SuperRender_10.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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) {
  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);
  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) {
  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. var yDataLength = width * height;
  206. var yData = i420Data.subarray(0, yDataLength);
  207. gl.activeTexture(gl.TEXTURE0);
  208. gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
  209. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
  210. var cbDataLength = width/2 * height/2;
  211. var cbData = i420Data.subarray(yDataLength, yDataLength + cbDataLength);
  212. gl.activeTexture(gl.TEXTURE1);
  213. gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
  214. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, cbData);
  215. var crDataLength = cbDataLength;
  216. var crData = i420Data.subarray(yDataLength + cbDataLength, yDataLength + cbDataLength + crDataLength);
  217. gl.activeTexture(gl.TEXTURE2);
  218. gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
  219. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width/2, height/2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, crData);
  220. };
  221. /**
  222. * 设置显示区域
  223. * @param stDisplayRect 显示区域
  224. */
  225. RenderManager.prototype.SR_SetDisplayRect = function(stDisplayRect) {
  226. var gl = this.contextGL;
  227. var nWindowWidth = this.nWindowWidth;
  228. var nWindowHeight = this.nWindowHeight;
  229. var texturePosValues = null;
  230. if(stDisplayRect && nWindowWidth > 0 && nWindowHeight > 0) {
  231. var fLeft = stDisplayRect.left / nWindowWidth;
  232. var fTop = stDisplayRect.top / nWindowHeight;
  233. var fRight = stDisplayRect.right / nWindowWidth;
  234. var fBottom = stDisplayRect.bottom / nWindowHeight;
  235. texturePosValues = new Float32Array([fRight, fTop, fLeft, fTop, fRight, fBottom, fLeft, fBottom]);
  236. }
  237. else {
  238. texturePosValues = new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]);
  239. }
  240. var texturePosBuffer = this.texturePosBuffer;
  241. gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
  242. gl.bufferSubData(gl.ARRAY_BUFFER, 0, texturePosValues);
  243. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  244. };
  245. /**
  246. * 释放显示资源
  247. */
  248. RenderManager.prototype.SR_Destroy = function() {
  249. var gl = this.contextGL;
  250. var YUVProgram = this.YUVProgram;
  251. gl.deleteProgram(YUVProgram);
  252. var vertexPosBuffer = this.vertexPosBuffer;
  253. var texturePosBuffer = this.texturePosBuffer;
  254. gl.deleteBuffer(vertexPosBuffer);
  255. gl.deleteBuffer(texturePosBuffer);
  256. var yTextureRef = this.yTextureRef;
  257. var uTextureRef = this.uTextureRef;
  258. var vTextureRef = this.vTextureRef;
  259. gl.deleteTexture(yTextureRef);
  260. gl.deleteTexture(uTextureRef);
  261. gl.deleteTexture(vTextureRef);
  262. };
  263. return RenderManager;
  264. }));