123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- "use strict";
- var vertexYUVShader = [
- 'attribute vec4 vertexPos;',
- 'attribute vec2 texturePos;',
- 'varying vec2 textureCoord;',
- 'void main()',
- '{',
- 'gl_Position = vertexPos;',
- 'textureCoord = texturePos;',
- '}'
- ].join('\n');
- var fragmentYUVShader = [
- 'precision highp float;',
- 'varying highp vec2 textureCoord;',
- 'uniform sampler2D ySampler;',
- 'uniform sampler2D uSampler;',
- 'uniform sampler2D vSampler;',
- '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) {',
- 'highp float y = texture2D(ySampler, textureCoord).r;',
- 'highp float u = texture2D(uSampler, textureCoord).r;',
- 'highp float v = texture2D(vSampler, textureCoord).r;',
- 'gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
- '}'
- ].join('\n');
- (function (root, factory) {
- root.SuperRender = factory();
- }(this, function () {
-
- function RenderManager(canvas) {
- this.canvasElement = document.getElementById(canvas);
- this.initContextGL();
- if(this.contextGL) {
- this.YUVProgram = this.initProgram(vertexYUVShader, fragmentYUVShader);
- this.initBuffers();
- this.initTextures();
- }
- };
- /**
- * 初始化WebGL上下文
- */
- RenderManager.prototype.initContextGL = function() {
-
- var canvas = this.canvasElement;
- var gl = null;
- try {
- gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
- } catch (e) {
- gl = null;
- }
- if(!gl || typeof gl.getParameter !== "function") {
- gl = null;
- }
- this.contextGL = gl;
- console.log("WebGL1.0");
- };
- /**
- * 初始化着色器程序
- * @param vertexShaderScript 顶点着色器脚本
- * @param fragmentShaderScript 片段着色器脚本
- */
- RenderManager.prototype.initProgram = function(vertexShaderScript, fragmentShaderScript) {
-
- var gl = this.contextGL;
-
- var vertexShader = gl.createShader(gl.VERTEX_SHADER);
- gl.shaderSource(vertexShader, vertexShaderScript);
- gl.compileShader(vertexShader);
- if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
- console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
- }
- var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
- gl.shaderSource(fragmentShader, fragmentShaderScript);
- gl.compileShader(fragmentShader);
- if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
- console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
- }
- var program = gl.createProgram();
- gl.attachShader(program, vertexShader);
- gl.attachShader(program, fragmentShader);
- gl.linkProgram(program);
- if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
- console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
- }
-
- gl.deleteShader(vertexShader);
- gl.deleteShader(fragmentShader);
- return program;
- };
- /**
- * 初始化数据缓存
- */
- RenderManager.prototype.initBuffers = function() {
-
- var gl = this.contextGL;
-
- var vertexPosBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- var texturePosBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.DYNAMIC_DRAW);
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- this.vertexPosBuffer = vertexPosBuffer;
- this.texturePosBuffer = texturePosBuffer;
- };
- /**
- * 初始化YUV纹理
- */
- RenderManager.prototype.initTextures = function() {
-
- var gl = this.contextGL;
-
- var program = this.YUVProgram;
- gl.useProgram(program);
-
- var yTextureRef = this.initTexture();
- var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
- gl.uniform1i(ySamplerRef, 0);
- this.yTextureRef = yTextureRef;
- var uTextureRef = this.initTexture();
- var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
- gl.uniform1i(uSamplerRef, 1);
- this.uTextureRef = uTextureRef;
- var vTextureRef = this.initTexture();
- var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
- gl.uniform1i(vSamplerRef, 2);
- this.vTextureRef = vTextureRef;
-
- gl.useProgram(null);
- };
- /**
- * 创建纹理
- */
- RenderManager.prototype.initTexture = function() {
-
- var gl = this.contextGL;
- var textureRef = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, textureRef);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.bindTexture(gl.TEXTURE_2D, null);
- return textureRef;
- };
- /**
- * 显示帧数据
- * @param nWidth 宽度
- * @param nHeight 高度
- * @param nHeight 帧数据
- */
- RenderManager.prototype.SR_DisplayFrameData = function(nWidth, nHeight, pData) {
- if(nWidth <= 0 || nHeight <= 0)
- {
- return;
- }
- var gl = this.contextGL;
- if(null == pData)
- {
- gl.clearColor(0.0, 0.0, 0.0, 0.0);
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
- return;
- }
- var canvas = this.canvasElement;
- this.nWindowWidth = canvas.width;
- this.nWindowHeight = canvas.height;
-
- var nWindowWidth = this.nWindowWidth;
- var nWindowHeight = this.nWindowHeight;
- gl.clearColor(0.8, 0.8, 1.0, 1.0);
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
- gl.viewport(0, 0, nWindowWidth, nWindowHeight);
- this.updateFrameData(nWidth, nHeight, pData);
- var program = this.YUVProgram;
- gl.useProgram(program);
- var vertexPosBuffer = this.vertexPosBuffer;
- gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
- var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
- gl.enableVertexAttribArray(vertexPosRef);
- gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- var texturePosBuffer = this.texturePosBuffer;
- gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
- var texturePosRef = gl.getAttribLocation(program, 'texturePos');
- gl.enableVertexAttribArray(texturePosRef);
- gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.disableVertexAttribArray(vertexPosRef);
- gl.disableVertexAttribArray(texturePosRef);
- gl.useProgram(null);
- };
- /**
- * 上传YUV数据到纹理
- * @param nWidth 宽度
- * @param nHeight 高度
- * @param nHeight 帧数据
- */
- RenderManager.prototype.updateFrameData = function(width, height, data) {
- var gl = this.contextGL;
- var yTextureRef = this.yTextureRef;
- var uTextureRef = this.uTextureRef;
- var vTextureRef = this.vTextureRef;
- var i420Data = data;
- var yDataLength = width * height;
- var yData = i420Data.subarray(0, yDataLength);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
- var cbDataLength = width/2 * height/2;
- var cbData = i420Data.subarray(yDataLength, yDataLength + cbDataLength);
- gl.activeTexture(gl.TEXTURE1);
- gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
- var crDataLength = cbDataLength;
- var crData = i420Data.subarray(yDataLength + cbDataLength, yDataLength + cbDataLength + crDataLength);
- gl.activeTexture(gl.TEXTURE2);
- gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
- };
- /**
- * 设置显示区域
- * @param stDisplayRect 显示区域
- */
- RenderManager.prototype.SR_SetDisplayRect = function(stDisplayRect) {
- var gl = this.contextGL;
- var nWindowWidth = this.nWindowWidth;
- var nWindowHeight = this.nWindowHeight;
-
- var texturePosValues = null;
-
- if(stDisplayRect && nWindowWidth > 0 && nWindowHeight > 0) {
- var fLeft = stDisplayRect.left / nWindowWidth;
- var fTop = stDisplayRect.top / nWindowHeight;
- var fRight = stDisplayRect.right / nWindowWidth;
- var fBottom = stDisplayRect.bottom / nWindowHeight;
- texturePosValues = new Float32Array([fRight, fTop, fLeft, fTop, fRight, fBottom, fLeft, fBottom]);
- }
- else {
- texturePosValues = new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]);
- }
- var texturePosBuffer = this.texturePosBuffer;
- gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
- gl.bufferSubData(gl.ARRAY_BUFFER, 0, texturePosValues);
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- };
- /**
- * 释放显示资源
- */
- RenderManager.prototype.SR_Destroy = function() {
- var gl = this.contextGL;
-
- var YUVProgram = this.YUVProgram;
- gl.deleteProgram(YUVProgram);
- var vertexPosBuffer = this.vertexPosBuffer;
- var texturePosBuffer = this.texturePosBuffer;
-
- gl.deleteBuffer(vertexPosBuffer);
- gl.deleteBuffer(texturePosBuffer);
- var yTextureRef = this.yTextureRef;
- var uTextureRef = this.uTextureRef;
- var vTextureRef = this.vTextureRef;
- gl.deleteTexture(yTextureRef);
- gl.deleteTexture(uTextureRef);
- gl.deleteTexture(vTextureRef);
- };
- return RenderManager;
- }));
|