const yuvBehavior = Behavior({ methods: { initShader() { const gl = this.gl = this.renderer.getContext() const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM) const vs = ` attribute vec2 a_position; attribute vec2 a_texCoord; uniform mat3 displayTransform; varying vec2 v_texCoord; void main() { vec3 p = displayTransform * vec3(a_position, 0); gl_Position = vec4(p, 1); v_texCoord = a_texCoord; } ` const fs = ` precision highp float; uniform sampler2D y_texture; uniform sampler2D uv_texture; varying vec2 v_texCoord; void main() { vec4 y_color = texture2D(y_texture, v_texCoord); vec4 uv_color = texture2D(uv_texture, v_texCoord); float Y, U, V; float R ,G, B; Y = y_color.r; U = uv_color.r - 0.5; V = uv_color.a - 0.5; R = Y + 1.402 * V; G = Y - 0.344 * U - 0.714 * V; B = Y + 1.772 * U; gl_FragColor = vec4(R, G, B, 1.0); } ` const vertShader = gl.createShader(gl.VERTEX_SHADER) gl.shaderSource(vertShader, vs) gl.compileShader(vertShader) const fragShader = gl.createShader(gl.FRAGMENT_SHADER) gl.shaderSource(fragShader, fs) gl.compileShader(fragShader) const program = this._program = gl.createProgram() this._program.gl = gl gl.attachShader(program, vertShader) gl.attachShader(program, fragShader) gl.deleteShader(vertShader) gl.deleteShader(fragShader) gl.linkProgram(program) gl.useProgram(program) const uniformYTexture = gl.getUniformLocation(program, 'y_texture') gl.uniform1i(uniformYTexture, 5) const uniformUVTexture = gl.getUniformLocation(program, 'uv_texture') gl.uniform1i(uniformUVTexture, 6) this._dt = gl.getUniformLocation(program, 'displayTransform') gl.useProgram(currentProgram) }, initVAO() { const gl = this.renderer.getContext() const ext = gl.getExtension('OES_vertex_array_object') this.ext = ext const currentVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING) const vao = ext.createVertexArrayOES() ext.bindVertexArrayOES(vao) const posAttr = gl.getAttribLocation(this._program, 'a_position') const pos = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, pos) gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW) gl.vertexAttribPointer(posAttr, 2, gl.FLOAT, false, 0, 0) gl.enableVertexAttribArray(posAttr) vao.posBuffer = pos const texcoordAttr = gl.getAttribLocation(this._program, 'a_texCoord') const texcoord = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, texcoord) gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, 0, 1, 1, 0, 0, 0]), gl.STATIC_DRAW) gl.vertexAttribPointer(texcoordAttr, 2, gl.FLOAT, false, 0, 0) gl.enableVertexAttribArray(texcoordAttr) vao.texcoordBuffer = texcoord ext.bindVertexArrayOES(currentVAO) this._vao = vao }, initGL() { this.initShader() this.initVAO() }, renderGL(frame) { const gl = this.renderer.getContext() gl.disable(gl.DEPTH_TEST) const { yTexture, uvTexture } = frame.getCameraTexture(gl, 'yuv') const displayTransform = frame.getDisplayTransform() if (yTexture && uvTexture) { const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM) const currentActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE) const currentVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING) gl.useProgram(this._program) this.ext.bindVertexArrayOES(this._vao) gl.uniformMatrix3fv(this._dt, false, displayTransform) gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.activeTexture(gl.TEXTURE0 + 5) const bindingTexture5 = gl.getParameter(gl.TEXTURE_BINDING_2D) gl.bindTexture(gl.TEXTURE_2D, yTexture) gl.activeTexture(gl.TEXTURE0 + 6) const bindingTexture6 = gl.getParameter(gl.TEXTURE_BINDING_2D) gl.bindTexture(gl.TEXTURE_2D, uvTexture) gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.bindTexture(gl.TEXTURE_2D, bindingTexture6) gl.activeTexture(gl.TEXTURE0 + 5) gl.bindTexture(gl.TEXTURE_2D, bindingTexture5) gl.useProgram(currentProgram) gl.activeTexture(currentActiveTexture) this.ext.bindVertexArrayOES(currentVAO) } }, }, }) export default yuvBehavior