Source: common/Texture.js

  1. /**
  2. * @class Texture
  3. * @memberof SQR
  4. *
  5. * @description Represents a WebGL texture created from an Image, Video or Canvas element.
  6. */
  7. SQR.Texture = function(_source, _options) {
  8. var t = {};
  9. var gl = SQR.gl;
  10. var source, options = _options || {};
  11. t.setSource = function(_source, _options) {
  12. if(!(
  13. _source instanceof HTMLVideoElement ||
  14. _source instanceof Image ||
  15. _source instanceof HTMLCanvasElement ||
  16. ('ImageBitmap' in window && _source instanceof window.ImageBitmap)
  17. )) {
  18. console.error('Invalid source: ' + _source);
  19. throw 'SQR.Texture > provided source is not a valid source for texture';
  20. }
  21. source = _source;
  22. options = _options || options;
  23. var wrapS = options.wrapS || options.wrap;
  24. var wrapT = options.wrapT || options.wrap;
  25. gl.bindTexture(gl.TEXTURE_2D, texture);
  26. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flip !== undefined ? options.flip : true);
  27. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha !== undefined ? options.premultiplyAlpha : false);
  28. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
  29. var mif, mgf;
  30. if(isPowerOfTwo()) {
  31. if(options.mipmap) gl.generateMipmap(gl.TEXTURE_2D);
  32. mif = options.mipmap ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR;
  33. mgf = gl.LINEAR;
  34. // if(!wrapS) wrapS = gl.REPEAT;
  35. // if(!wrapT) wrapT = gl.REPEAT;
  36. } else {
  37. // if(options.mipmap) console.warn('Only power-of-2 texture can use mipmaps\n', _source);
  38. mif = mgf = gl.LINEAR;
  39. // if(!wrapS) wrapS = gl.CLAMP_TO_EDGE;
  40. // if(!wrapT) wrapT = gl.CLAMP_TO_EDGE;
  41. }
  42. if(!wrapS) wrapS = gl.CLAMP_TO_EDGE;
  43. if(!wrapT) wrapT = gl.CLAMP_TO_EDGE;
  44. if(options.aniso) {
  45. var aniso = (
  46. gl.getExtension('EXT_texture_filter_anisotropic') ||
  47. gl.getExtension('MOZ_EXT_texture_filter_anisotropic') ||
  48. gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic')
  49. );
  50. if(aniso) {
  51. var m = gl.getParameter(aniso.MAX_TEXTURE_MAX_ANISOTROPY_EXT)
  52. var v = options.anisoLevel || 16;
  53. v = Math.min(m, v);
  54. gl.texParameterf(gl.TEXTURE_2D, aniso.TEXTURE_MAX_ANISOTROPY_EXT, v);
  55. }
  56. }
  57. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, options.magFilter || options.filter || mgf);
  58. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, options.minFilter || options.filter || mif);
  59. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
  60. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
  61. gl.bindTexture(gl.TEXTURE_2D, null);
  62. t.isAnimated = (options && options.isAnimated) || (_source instanceof HTMLVideoElement);
  63. return t;
  64. }
  65. var isPowerOfTwo = function() {
  66. var x = source.width, y = source.height;
  67. return x > 0 && y > 0 && (x & (x - 1)) == 0 && (y & (y - 1)) == 0;
  68. }
  69. t.getSource = function() {
  70. return source;
  71. }
  72. t.setParameter = function(key, value) {
  73. gl.bindTexture(gl.TEXTURE_2D, texture);
  74. gl.texParameteri(gl.TEXTURE_2D, key, value);
  75. gl.bindTexture(gl.TEXTURE_2D, null);
  76. }
  77. t.update = function() {
  78. var gl = SQR.gl;
  79. gl.bindTexture(gl.TEXTURE_2D, texture);
  80. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flip !== undefined ? options.flip : true);
  81. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha !== undefined ? options.premultiplyAlpha : false);
  82. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
  83. return t;
  84. }
  85. t.destroy = function() {
  86. gl.deleteTexture(t.tex);
  87. }
  88. var texture = gl.createTexture();
  89. t.tex = texture;
  90. if(_source) {
  91. t.setSource(_source, _options);
  92. }
  93. return t;
  94. }