| | |
| | | Texture.prototype.fill = function(width, height, data) { |
| | | var gl = this.gl |
| | | gl.bindTexture(gl.TEXTURE_2D, this.texture) |
| | | gl.texImage2D( |
| | | gl.TEXTURE_2D, |
| | | 0, |
| | | gl.LUMINANCE, |
| | | width, |
| | | height, |
| | | 0, |
| | | gl.LUMINANCE, |
| | | gl.UNSIGNED_BYTE, |
| | | data |
| | | ) |
| | | gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data) |
| | | } |
| | | |
| | | export function WebGLPlayer(canvas) { |
| | | this.canvas = canvas |
| | | this.gl = |
| | | canvas.getContext('webgl') || canvas.getContext('experimental-webgl') |
| | | this.gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl") |
| | | this.initGL() |
| | | } |
| | | |
| | | WebGLPlayer.prototype.initGL = function() { |
| | | if (!this.gl) { |
| | | console.log('[ER] WebGL not supported.') |
| | | console.log("[ER] WebGL not supported.") |
| | | return |
| | | } |
| | | |
| | |
| | | gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1) |
| | | var program = gl.createProgram() |
| | | var vertexShaderSource = [ |
| | | 'attribute highp vec4 aVertexPosition;', |
| | | 'attribute vec2 aTextureCoord;', |
| | | 'varying highp vec2 vTextureCoord;', |
| | | 'void main(void) {', |
| | | ' gl_Position = aVertexPosition;', |
| | | ' vTextureCoord = aTextureCoord;', |
| | | '}', |
| | | ].join('\n') |
| | | "attribute highp vec4 aVertexPosition;", |
| | | "attribute vec2 aTextureCoord;", |
| | | "varying highp vec2 vTextureCoord;", |
| | | "void main(void) {", |
| | | " gl_Position = aVertexPosition;", |
| | | " vTextureCoord = aTextureCoord;", |
| | | "}" |
| | | ].join("\n") |
| | | var vertexShader = gl.createShader(gl.VERTEX_SHADER) |
| | | gl.shaderSource(vertexShader, vertexShaderSource) |
| | | gl.compileShader(vertexShader) |
| | | var fragmentShaderSource = [ |
| | | 'precision highp float;', |
| | | 'varying lowp vec2 vTextureCoord;', |
| | | 'uniform sampler2D YTexture;', |
| | | 'uniform sampler2D UTexture;', |
| | | 'uniform sampler2D VTexture;', |
| | | 'const mat4 YUV2RGB = mat4', |
| | | '(', |
| | | ' 1.1643828125, 0, 1.59602734375, -.87078515625,', |
| | | ' 1.1643828125, -.39176171875, -.81296875, .52959375,', |
| | | ' 1.1643828125, 2.017234375, 0, -1.081390625,', |
| | | ' 0, 0, 0, 1', |
| | | ');', |
| | | 'void main(void) {', |
| | | ' gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;', |
| | | '}', |
| | | ].join('\n') |
| | | "precision highp float;", |
| | | "varying lowp vec2 vTextureCoord;", |
| | | "uniform sampler2D YTexture;", |
| | | "uniform sampler2D UTexture;", |
| | | "uniform sampler2D VTexture;", |
| | | "const mat4 YUV2RGB = mat4", |
| | | "(", |
| | | " 1.1643828125, 0, 1.59602734375, -.87078515625,", |
| | | " 1.1643828125, -.39176171875, -.81296875, .52959375,", |
| | | " 1.1643828125, 2.017234375, 0, -1.081390625,", |
| | | " 0, 0, 0, 1", |
| | | ");", |
| | | "void main(void) {", |
| | | " gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;", |
| | | "}" |
| | | ].join("\n") |
| | | |
| | | var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) |
| | | gl.shaderSource(fragmentShader, fragmentShaderSource) |
| | |
| | | gl.linkProgram(program) |
| | | gl.useProgram(program) |
| | | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { |
| | | console.log('[ER] Shader link failed.') |
| | | console.log("[ER] Shader link failed.") |
| | | } |
| | | var vertexPositionAttribute = gl.getAttribLocation(program, 'aVertexPosition') |
| | | var vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition") |
| | | gl.enableVertexAttribArray(vertexPositionAttribute) |
| | | var textureCoordAttribute = gl.getAttribLocation(program, 'aTextureCoord') |
| | | var textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord") |
| | | gl.enableVertexAttribArray(textureCoordAttribute) |
| | | |
| | | var verticesBuffer = gl.createBuffer() |
| | | gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer) |
| | | gl.bufferData( |
| | | gl.ARRAY_BUFFER, |
| | | new Float32Array([ |
| | | 1.0, |
| | | 1.0, |
| | | 0.0, |
| | | -1.0, |
| | | 1.0, |
| | | 0.0, |
| | | 1.0, |
| | | -1.0, |
| | | 0.0, |
| | | -1.0, |
| | | -1.0, |
| | | 0.0, |
| | | ]), |
| | | new Float32Array([1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0]), |
| | | gl.STATIC_DRAW |
| | | ) |
| | | gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0) |
| | | var texCoordBuffer = gl.createBuffer() |
| | | gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer) |
| | | gl.bufferData( |
| | | gl.ARRAY_BUFFER, |
| | | new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]), |
| | | gl.STATIC_DRAW |
| | | ) |
| | | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW) |
| | | gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0) |
| | | |
| | | gl.y = new Texture(gl) |
| | | gl.u = new Texture(gl) |
| | | gl.v = new Texture(gl) |
| | | gl.y.bind(0, program, 'YTexture') |
| | | gl.u.bind(1, program, 'UTexture') |
| | | gl.v.bind(2, program, 'VTexture') |
| | | gl.y.bind(0, program, "YTexture") |
| | | gl.u.bind(1, program, "UTexture") |
| | | gl.v.bind(2, program, "VTexture") |
| | | } |
| | | |
| | | WebGLPlayer.prototype.renderFrame = function(videoFrame, width, height) { |
| | | if (!this.gl) { |
| | | console.log('[ER] Render frame failed due to WebGL not supported.') |
| | | console.log("[ER] Render frame failed due to WebGL not supported.") |
| | | return |
| | | } |
| | | |
| | |
| | | gl.clear(gl.COLOR_BUFFER_BIT) |
| | | |
| | | gl.y.fill(width, height, videoFrame.subarray(0, width * height)) |
| | | gl.u.fill( |
| | | width >> 1, |
| | | height >> 1, |
| | | videoFrame.subarray(width * height, (width * height * 5) / 4) |
| | | ) |
| | | gl.v.fill( |
| | | width >> 1, |
| | | height >> 1, |
| | | videoFrame.subarray((width * height * 5) / 4, (width * height * 3) / 2) |
| | | ) |
| | | gl.u.fill(width >> 1, height >> 1, videoFrame.subarray(width * height, (width * height * 5) / 4)) |
| | | gl.v.fill(width >> 1, height >> 1, videoFrame.subarray((width * height * 5) / 4, (width * height * 3) / 2)) |
| | | |
| | | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) |
| | | } |
| | | |
| | | WebGLPlayer.prototype.fullscreen = function() { |
| | | var canvas = this.canvas |
| | | let canvas = this.canvas.parentNode.parentNode.parentNode |
| | | if (canvas.RequestFullScreen) { |
| | | canvas.RequestFullScreen() |
| | | } else if (canvas.webkitRequestFullScreen) { |