初始化
This commit is contained in:
145
vendor/tinyh264/YUVSurfaceShader.ts
vendored
Normal file
145
vendor/tinyh264/YUVSurfaceShader.ts
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import ShaderProgram from './ShaderProgram';
|
||||
import ShaderCompiler from './ShaderCompiler';
|
||||
import { fragmentYUV, vertexQuad } from './ShaderSources';
|
||||
import Texture from '../h264-live-player/Texture';
|
||||
|
||||
type ShaderArguments = {
|
||||
yTexture: WebGLUniformLocation | null;
|
||||
uTexture: WebGLUniformLocation | null;
|
||||
vTexture: WebGLUniformLocation | null;
|
||||
u_projection: WebGLUniformLocation | null;
|
||||
a_position: number;
|
||||
a_texCoord: number;
|
||||
};
|
||||
|
||||
export default class YUVSurfaceShader {
|
||||
/**
|
||||
*
|
||||
* @param {WebGLRenderingContext} gl
|
||||
* @returns {YUVSurfaceShader}
|
||||
*/
|
||||
static create(gl: WebGLRenderingContext): YUVSurfaceShader {
|
||||
const program = this._initShaders(gl);
|
||||
const shaderArgs = this._initShaderArgs(gl, program);
|
||||
const vertexBuffer = this._initBuffers(gl);
|
||||
|
||||
return new YUVSurfaceShader(gl, vertexBuffer as WebGLBuffer, shaderArgs, program);
|
||||
}
|
||||
|
||||
static _initShaders(gl: WebGLRenderingContext): ShaderProgram {
|
||||
const program = new ShaderProgram(gl);
|
||||
program.attach(ShaderCompiler.compile(gl, vertexQuad) as WebGLShader);
|
||||
program.attach(ShaderCompiler.compile(gl, fragmentYUV) as WebGLShader);
|
||||
program.link();
|
||||
program.use();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
static _initShaderArgs(gl: WebGLRenderingContext, program: ShaderProgram): ShaderArguments {
|
||||
// find shader arguments
|
||||
const shaderArgs: ShaderArguments = {
|
||||
yTexture: program.getUniformLocation('yTexture'),
|
||||
uTexture: program.getUniformLocation('uTexture'),
|
||||
vTexture: program.getUniformLocation('vTexture'),
|
||||
u_projection: program.getUniformLocation('u_projection'),
|
||||
a_position: program.getAttributeLocation('a_position'),
|
||||
a_texCoord: program.getAttributeLocation('a_texCoord'),
|
||||
};
|
||||
|
||||
gl.enableVertexAttribArray(shaderArgs.a_position);
|
||||
gl.enableVertexAttribArray(shaderArgs.a_texCoord);
|
||||
|
||||
return shaderArgs;
|
||||
}
|
||||
|
||||
static _initBuffers(gl: WebGLRenderingContext): WebGLBuffer | null {
|
||||
// Create vertex buffer object.
|
||||
return gl.createBuffer();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private gl: WebGLRenderingContext,
|
||||
private vertexBuffer: WebGLBuffer,
|
||||
private shaderArgs: ShaderArguments,
|
||||
private program: ShaderProgram,
|
||||
) {}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Texture} textureY
|
||||
* @param {Texture} textureU
|
||||
* @param {Texture} textureV
|
||||
*/
|
||||
setTexture(textureY: Texture, textureU: Texture, textureV: Texture): void {
|
||||
const gl = this.gl;
|
||||
|
||||
gl.uniform1i(this.shaderArgs.yTexture, 0);
|
||||
gl.uniform1i(this.shaderArgs.uTexture, 1);
|
||||
gl.uniform1i(this.shaderArgs.vTexture, 2);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, textureY.texture);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, textureU.texture);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE2);
|
||||
gl.bindTexture(gl.TEXTURE_2D, textureV.texture);
|
||||
}
|
||||
|
||||
use(): void {
|
||||
this.program.use();
|
||||
}
|
||||
|
||||
release(): void {
|
||||
this.gl.useProgram(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{w:number, h:number}}encodedFrameSize
|
||||
* @param {{maxXTexCoord:number, maxYTexCoord:number}} h264RenderState
|
||||
*/
|
||||
updateShaderData(
|
||||
encodedFrameSize: { w: number; h: number },
|
||||
h264RenderState: { maxXTexCoord: number; maxYTexCoord: number },
|
||||
): void {
|
||||
const { w, h } = encodedFrameSize;
|
||||
this.gl.viewport(0, 0, w, h);
|
||||
// prettier-ignore
|
||||
this.program.setUniformM4(this.shaderArgs.u_projection as WebGLUniformLocation, [
|
||||
2.0 / w, 0, 0, 0,
|
||||
0, 2.0 / -h, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 1, 0, 1
|
||||
])
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
// prettier-ignore
|
||||
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([
|
||||
// First triangle
|
||||
// top left:
|
||||
0, 0, 0, 0,
|
||||
// top right:
|
||||
w, 0, h264RenderState.maxXTexCoord, 0,
|
||||
// bottom right:
|
||||
w, h, h264RenderState.maxXTexCoord, h264RenderState.maxYTexCoord,
|
||||
|
||||
// Second triangle
|
||||
// bottom right:
|
||||
w, h, h264RenderState.maxXTexCoord, h264RenderState.maxYTexCoord,
|
||||
// bottom left:
|
||||
0, h, 0, h264RenderState.maxYTexCoord,
|
||||
// top left:
|
||||
0, 0, 0, 0
|
||||
]), this.gl.DYNAMIC_DRAW);
|
||||
this.gl.vertexAttribPointer(this.shaderArgs.a_position, 2, this.gl.FLOAT, false, 16, 0);
|
||||
this.gl.vertexAttribPointer(this.shaderArgs.a_texCoord, 2, this.gl.FLOAT, false, 16, 8);
|
||||
}
|
||||
|
||||
draw(): void {
|
||||
const gl = this.gl;
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
||||
gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 6);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user