SuperRender_10.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. "use strict";
  2. //顶点着色器
  3. //attribute修饰符用于声明由浏览器(javascript)传输给顶点着色器的变量值;
  4. // vertexPos即我们定义的顶点坐标;
  5. // gl_Position是一个内建的传出变量。
  6. var vertexYUVShader = [
  7. 'attribute vec4 vertexPos;',
  8. 'attribute vec2 texturePos;',
  9. 'varying vec2 textureCoord;',
  10. 'void main()',
  11. '{',
  12. 'gl_Position = vertexPos;',
  13. 'textureCoord = texturePos;',
  14. '}'
  15. ].join('\n');
  16. //像素着色器(yuv->rgb)
  17. var fragmentYUVShader = [
  18. 'precision highp float;',
  19. 'varying highp vec2 textureCoord;',
  20. 'uniform sampler2D ySampler;',
  21. 'uniform sampler2D uSampler;',
  22. 'uniform sampler2D vSampler;',
  23. 'const mat4 YUV2RGB = mat4',
  24. '(',
  25. '1.1643828125, 0, 1.59602734375, -.87078515625,',
  26. '1.1643828125, -.39176171875, -.81296875, .52959375,',
  27. '1.1643828125, 2.017234375, 0, -1.081390625,',
  28. '0, 0, 0, 1',
  29. ');',
  30. 'void main(void) {',
  31. 'highp float y = texture2D(ySampler, textureCoord).r;',
  32. 'highp float u = texture2D(uSampler, textureCoord).r;',
  33. 'highp float v = texture2D(vSampler, textureCoord).r;',
  34. 'gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
  35. '}'
  36. ].join('\n');
  37. (function (root, factory) {
  38. root.SuperRender = factory();
  39. }(this, function () {
  40. function RenderManager(canvas) {
  41. this.canvasElement = document.getElementById(canvas);
  42. this.initContextGL();
  43. if(this.contextGL) {
  44. this.YUVProgram = this.initProgram(vertexYUVShader, fragmentYUVShader);
  45. this.initBuffers();
  46. this.initTextures();
  47. }
  48. };
  49. /**
  50. * 初始化WebGL上下文
  51. */
  52. RenderManager.prototype.initContextGL = function() {
  53. var canvas = this.canvasElement;
  54. var gl = null;
  55. try {
  56. gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
  57. } catch (e) {
  58. gl = null;
  59. }
  60. if(!gl || typeof gl.getParameter !== "function") {
  61. gl = null;
  62. }
  63. this.contextGL = gl;
  64. console.log("WebGL1.0");
  65. };
  66. /**
  67. * 初始化着色器程序
  68. * @param vertexShaderScript 顶点着色器脚本
  69. * @param fragmentShaderScript 片段着色器脚本
  70. */
  71. RenderManager.prototype.initProgram = function(vertexShaderScript, fragmentShaderScript) {
  72. var gl = this.contextGL;
  73. var vertexShader = gl.createShader(gl.VERTEX_SHADER); //创建定点着色器
  74. gl.shaderSource(vertexShader, vertexShaderScript);
  75. gl.compileShader(vertexShader);
  76. if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
  77. console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
  78. }
  79. var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  80. gl.shaderSource(fragmentShader, fragmentShaderScript);
  81. gl.compileShader(fragmentShader);
  82. if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
  83. console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
  84. }
  85. var program = gl.createProgram();
  86. gl.attachShader(program, vertexShader);
  87. gl.attachShader(program, fragmentShader);
  88. gl.linkProgram(program);
  89. if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  90. console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
  91. }
  92. gl.deleteShader(vertexShader);
  93. gl.deleteShader(fragmentShader);
  94. return program;
  95. };
  96. /**
  97. * 初始化数据缓存
  98. */
  99. RenderManager.prototype.initBuffers = function() {
  100. var gl = this.contextGL;
  101. var vertexPosBuffer = gl.createBuffer();
  102. gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
  103. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
  104. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  105. var texturePosBuffer = gl.createBuffer();
  106. gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
  107. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.DYNAMIC_DRAW);
  108. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  109. this.vertexPosBuffer = vertexPosBuffer;
  110. this.texturePosBuffer = texturePosBuffer;
  111. };
  112. /**
  113. * 创建纹理
  114. */
  115. RenderManager.prototype.initTexture = function() {
  116. var gl = this.contextGL;
  117. var textureRef = gl.createTexture();
  118. gl.bindTexture(gl.TEXTURE_2D, textureRef);
  119. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  120. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  121. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  122. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  123. gl.bindTexture(gl.TEXTURE_2D, null);
  124. return textureRef;
  125. };
  126. /**
  127. * 初始化YUV纹理
  128. */
  129. RenderManager.prototype.initTextures = function() {
  130. var gl = this.contextGL;
  131. var program = this.YUVProgram;
  132. gl.useProgram(program);
  133. var yTextureRef = this.initTexture();
  134. var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
  135. gl.uniform1i(ySamplerRef, 0);
  136. this.yTextureRef = yTextureRef;
  137. var uTextureRef = this.initTexture();
  138. var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
  139. gl.uniform1i(uSamplerRef, 1);
  140. this.uTextureRef = uTextureRef;
  141. var vTextureRef = this.initTexture();
  142. var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
  143. gl.uniform1i(vSamplerRef, 2);
  144. this.vTextureRef = vTextureRef;
  145. gl.useProgram(null);
  146. };
  147. /**
  148. * 显示帧数据
  149. * @param nWidth 宽度
  150. * @param nHeight 高度
  151. * @param nHeight 帧数据
  152. */
  153. RenderManager.prototype.SR_DisplayFrameData = function(nWidth, nHeight, pData,dWidth,dHeight) {
  154. if(nWidth <= 0 || nHeight <= 0)
  155. {
  156. return;
  157. }
  158. var gl = this.contextGL;
  159. if(null == pData)
  160. {
  161. gl.clearColor(0.0, 0.0, 0.0, 0.0);
  162. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  163. return;
  164. }
  165. var canvas = this.canvasElement;
  166. this.nWindowWidth = canvas.width;
  167. this.nWindowHeight = canvas.height;
  168. var nWindowWidth = this.nWindowWidth;
  169. var nWindowHeight = this.nWindowHeight;
  170. gl.clearColor(0.8, 0.8, 1.0, 1.0);
  171. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  172. gl.viewport(0, 0, nWindowWidth, nWindowHeight);
  173. this.updateFrameData(nWidth, nHeight, pData,dWidth,dHeight);
  174. var program = this.YUVProgram;
  175. gl.useProgram(program);
  176. var vertexPosBuffer = this.vertexPosBuffer;
  177. gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
  178. var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
  179. gl.enableVertexAttribArray(vertexPosRef);
  180. gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
  181. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  182. var texturePosBuffer = this.texturePosBuffer;
  183. gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
  184. var texturePosRef = gl.getAttribLocation(program, 'texturePos');
  185. gl.enableVertexAttribArray(texturePosRef);
  186. gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
  187. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  188. gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  189. gl.disableVertexAttribArray(vertexPosRef);
  190. gl.disableVertexAttribArray(texturePosRef);
  191. gl.useProgram(null);
  192. };
  193. /**
  194. * 上传YUV数据到纹理
  195. * @param nWidth 宽度
  196. * @param nHeight 高度
  197. * @param nHeight 帧数据
  198. */
  199. RenderManager.prototype.updateFrameData = function(width, height, data,dWidth,dHeight) {
  200. var gl = this.contextGL;
  201. var yTextureRef = this.yTextureRef;
  202. var uTextureRef = this.uTextureRef;
  203. var vTextureRef = this.vTextureRef;
  204. var i420Data = data;
  205. // debugger;
  206. if(width == dWidth && height == dHeight)
  207. {
  208. var yDataLength = width * height;
  209. var yData = i420Data.subarray(0, yDataLength);
  210. gl.activeTexture(gl.TEXTURE0);
  211. gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
  212. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
  213. var cbDataLength = width/2 * height/2;
  214. var cbData = i420Data.subarray(width*height, width*height + cbDataLength);
  215. gl.activeTexture(gl.TEXTURE1);
  216. gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
  217. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
  218. var crDataLength = cbDataLength;
  219. var crData = i420Data.subarray(width*height + width*height/4, width*height + width*height/4 + crDataLength);
  220. gl.activeTexture(gl.TEXTURE2);
  221. gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
  222. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
  223. }
  224. else
  225. {
  226. // //裁剪宽
  227. var yDataLength = dWidth * dHeight;
  228. var yData=new Uint8Array(yDataLength) ;
  229. for(var i=0;i<dHeight;i++)
  230. {
  231. //var ySonData=new Uint8Array(dWidth) ;
  232. var ySonData = i420Data.subarray(i*width, i*width+dWidth);
  233. for (var j = 0; j < dWidth; j++) {
  234. yData[i*dWidth + j] = ySonData[j];
  235. }
  236. }
  237. gl.activeTexture(gl.TEXTURE0);
  238. gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
  239. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth, dHeight, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
  240. yData=null;
  241. ySonData=null;
  242. var cbDataLength = dWidth/2 * dHeight/2;
  243. var cbData =new Uint8Array(cbDataLength);
  244. //var cbSonData=new Uint8Array(dWidth/2) ;
  245. for(var i=0;i<dHeight/2;i++)
  246. {
  247. var cbSonData = i420Data.subarray(width*height+i*width/2, width*height+i*width/2+dWidth/2);
  248. for (var j = 0; j < dWidth/2; j++) {
  249. cbData[i*dWidth/2 + j] = cbSonData[j];
  250. }
  251. }
  252. gl.activeTexture(gl.TEXTURE1);
  253. gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
  254. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth/2, dHeight/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
  255. cbData=null;
  256. cbSonData=null;
  257. var crDataLength = cbDataLength;
  258. var crData = new Uint8Array(crDataLength);
  259. for(var i=0;i<dHeight/2;i++)
  260. {
  261. var crSonData = i420Data.subarray(width*height*5/4+i*width/2, width*height*5/4+i*width/2+dWidth/2);
  262. for (var j = 0; j < dWidth/2; j++) {
  263. crData[i*dWidth/2 + j] = crSonData[j];
  264. }
  265. }
  266. gl.activeTexture(gl.TEXTURE2);
  267. gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
  268. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dWidth/2, dHeight/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
  269. crData=null;
  270. crSonData=null;
  271. }
  272. };
  273. /**
  274. * 设置显示区域
  275. * @param stDisplayRect 显示区域
  276. */
  277. RenderManager.prototype.SR_SetDisplayRect = function(stDisplayRect) {
  278. var gl = this.contextGL;
  279. var nWindowWidth = this.nWindowWidth;
  280. var nWindowHeight = this.nWindowHeight;
  281. var texturePosValues = null;
  282. if(stDisplayRect && nWindowWidth > 0 && nWindowHeight > 0) {
  283. var fLeft = stDisplayRect.left / nWindowWidth;
  284. var fTop = stDisplayRect.top / nWindowHeight;
  285. var fRight = stDisplayRect.right / nWindowWidth;
  286. var fBottom = stDisplayRect.bottom / nWindowHeight;
  287. texturePosValues = new Float32Array([fRight, fTop, fLeft, fTop, fRight, fBottom, fLeft, fBottom]);
  288. }
  289. else {
  290. texturePosValues = new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]);
  291. }
  292. var texturePosBuffer = this.texturePosBuffer;
  293. gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
  294. gl.bufferSubData(gl.ARRAY_BUFFER, 0, texturePosValues);
  295. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  296. };
  297. /**
  298. * 释放显示资源
  299. */
  300. RenderManager.prototype.SR_Destroy = function() {
  301. var gl = this.contextGL;
  302. var YUVProgram = this.YUVProgram;
  303. gl.deleteProgram(YUVProgram);
  304. var vertexPosBuffer = this.vertexPosBuffer;
  305. var texturePosBuffer = this.texturePosBuffer;
  306. gl.deleteBuffer(vertexPosBuffer);
  307. gl.deleteBuffer(texturePosBuffer);
  308. var yTextureRef = this.yTextureRef;
  309. var uTextureRef = this.uTextureRef;
  310. var vTextureRef = this.vTextureRef;
  311. gl.deleteTexture(yTextureRef);
  312. gl.deleteTexture(uTextureRef);
  313. gl.deleteTexture(vTextureRef);
  314. //gl.getExtension('WEBGL_lose_context').loseContext();
  315. };
  316. return RenderManager;
  317. }));