JeelizCanvas2DHelper.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. Usage: JeelizCanvas2DHelper(spec) where spec is the returned object of the initialization function (callbackReady)
  3. Return an object width these properties:
  4. - canvas: the CANVAS element
  5. - ctx: the canvas drawing context
  6. - update_canvasTexture: function to launch each time the canvas has been updated (somethink has been drawn on it)
  7. - draw: draw the video with the canvas above
  8. - getCoordinates: transform the detectedState relative 2D viewport coords into canvas 2D pixel coordinates
  9. - resize: to call if the HTML canvas size has changed
  10. */
  11. const JeelizCanvas2DHelper = function(spec){
  12. // some globalz:
  13. let CV = null, CANVAS2D = null, CTX = null, GL = null, CANVASTEXTURE = null, CANVASTEXTURENEEDSUPDATE = null, SHADERCOPY = null, VIDEOTEXTURE = null;
  14. let VIDEOTEXTURETRANSFORMMAT2 = null, UUVTRANSFORM = null;
  15. const COORDINATES = {
  16. x:0, y:0, s:0
  17. };
  18. //BEGIN WEBGL HELPERS
  19. // compile a shader:
  20. function compile_shader(source, glType, typeString) {
  21. const glShader = GL.createShader(glType);
  22. GL.shaderSource(glShader, source);
  23. GL.compileShader(glShader);
  24. if (!GL.getShaderParameter(glShader, GL.COMPILE_STATUS)) {
  25. alert("ERROR IN " + typeString + " SHADER: " + GL.getShaderInfoLog(glShader));
  26. return null;
  27. }
  28. return glShader;
  29. };
  30. // helper function to build the shader program:
  31. function build_shaderProgram(shaderVertexSource, shaderFragmentSource, id) {
  32. // compile both shader separately:
  33. const glShaderVertex = compile_shader(shaderVertexSource, GL.VERTEX_SHADER, "VERTEX " + id);
  34. const glShaderFragment = compile_shader(shaderFragmentSource, GL.FRAGMENT_SHADER, "FRAGMENT " + id);
  35. const glShaderProgram = GL.createProgram();
  36. GL.attachShader(glShaderProgram, glShaderVertex);
  37. GL.attachShader(glShaderProgram, glShaderFragment);
  38. // start the linking stage:
  39. GL.linkProgram(glShaderProgram);
  40. return glShaderProgram;
  41. }
  42. //END WEBGL HELPERS
  43. // affect some globalz:
  44. GL = spec.GL;
  45. CV = spec.canvasElement;
  46. VIDEOTEXTURE = spec.videoTexture;
  47. VIDEOTEXTURETRANSFORMMAT2 = spec.videoTransformMat2;
  48. // create and size the 2D canvas and its drawing context:
  49. CANVAS2D = document.createElement('canvas');
  50. CANVAS2D.width = CV.width;
  51. CANVAS2D.height = CV.height;
  52. CTX = CANVAS2D.getContext('2d');
  53. // create the WebGL texture with the canvas:
  54. CANVASTEXTURE = GL.createTexture();
  55. GL.bindTexture(GL.TEXTURE_2D, CANVASTEXTURE);
  56. GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, CANVAS2D);
  57. GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR);
  58. GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR);
  59. GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
  60. GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
  61. // build the copy shader program:
  62. const copyVertexShaderSource = "attribute vec2 position;\n\
  63. uniform mat2 UVTransformMat2;\n\
  64. varying vec2 vUV;\n\
  65. void main(void){\n\
  66. gl_Position = vec4(position, 0., 1.);\n\
  67. vUV = vec2(0.5,0.5) + UVTransformMat2 * position;\n\
  68. }";
  69. const copyFragmentShaderSource = "precision lowp float;\n\
  70. uniform sampler2D samplerImage;\n\
  71. varying vec2 vUV;\n\
  72. \n\
  73. void main(void){\n\
  74. gl_FragColor = texture2D(samplerImage, vUV);\n\
  75. }";
  76. SHADERCOPY = build_shaderProgram(copyVertexShaderSource, copyFragmentShaderSource, 'VIDEO');
  77. const uSampler = GL.getUniformLocation(SHADERCOPY, 'samplerImage');
  78. UUVTRANSFORM = GL.getUniformLocation(SHADERCOPY, 'UVTransformMat2');
  79. GL.useProgram(SHADERCOPY);
  80. GL.uniform1i(uSampler, 0);
  81. return {
  82. canvas: CANVAS2D,
  83. ctx: CTX,
  84. update_canvasTexture: function(){
  85. CANVASTEXTURENEEDSUPDATE = true;
  86. },
  87. draw: function(){ // draw the video and the canvas above
  88. GL.viewport(0, 0, CV.width, CV.height);
  89. GL.useProgram(SHADERCOPY);
  90. // enable blending:
  91. GL.enable(GL.BLEND);
  92. GL.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);
  93. // draw the video first:
  94. GL.bindTexture(GL.TEXTURE_2D, VIDEOTEXTURE);
  95. GL.uniformMatrix2fv(UUVTRANSFORM, false, VIDEOTEXTURETRANSFORMMAT2);
  96. GL.drawElements(GL.TRIANGLES, 3, GL.UNSIGNED_SHORT, 0);
  97. // then draw the canvas:
  98. GL.bindTexture(GL.TEXTURE_2D, CANVASTEXTURE);
  99. GL.uniformMatrix2fv(UUVTRANSFORM, false, [0.5, 0, 0, 0.5]);
  100. if (CANVASTEXTURENEEDSUPDATE) {
  101. GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, CANVAS2D);
  102. }
  103. GL.drawElements(GL.TRIANGLES, 3, GL.UNSIGNED_SHORT, 0);
  104. GL.disable(GL.BLEND);
  105. },
  106. getCoordinates: function(detectedState){
  107. COORDINATES.x = Math.round((0.5+0.5*detectedState.x-0.5*detectedState.s)*CV.width);
  108. COORDINATES.y = Math.round((0.5+0.5*detectedState.y-0.5*detectedState.s)*CV.height);
  109. COORDINATES.w = Math.round(detectedState.s*CV.width);
  110. COORDINATES.h = COORDINATES.w;
  111. return COORDINATES;
  112. },
  113. resize: function(){
  114. CANVAS2D.width = CV.width;
  115. CANVAS2D.height = CV.height;
  116. }
  117. }; //end Canvas2DDisplay return value
  118. } //end JeelizCanvas2DHelper()
  119. // const JeelizCanvas2DHelper = JeelizCanvas2DHelper();
  120. if(typeof(module) !== 'undefined') {
  121. module.exports = JeelizCanvas2DHelper;
  122. }