SuperRender_10.js 11 KB

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