Source: dependencies/pixi-gl-core/GLTexture.js

dependencies/pixi-gl-core/GLTexture.js

  1. /**
  2. * Helper class to create a WebGL Texture
  3. *
  4. * @class
  5. * @memberof PIXI.glCore
  6. * @param gl {WebGLRenderingContext} The current WebGL context
  7. * @param width {number} the width of the texture
  8. * @param height {number} the height of the texture
  9. * @param format {number} the pixel format of the texture. defaults to gl.RGBA
  10. * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE
  11. */
  12. var Texture = function(gl, width, height, format, type)
  13. {
  14. /**
  15. * The current WebGL rendering context
  16. *
  17. * @member {WebGLRenderingContext}
  18. */
  19. this.gl = gl;
  20. /**
  21. * The WebGL texture
  22. *
  23. * @member {WebGLTexture}
  24. */
  25. this.texture = gl.createTexture();
  26. /**
  27. * If mipmapping was used for this texture, enable and disable with enableMipmap()
  28. *
  29. * @member {Boolean}
  30. */
  31. // some settings..
  32. this.mipmap = false;
  33. /**
  34. * Set to true to enable pre-multiplied alpha
  35. *
  36. * @member {Boolean}
  37. */
  38. this.premultiplyAlpha = false;
  39. /**
  40. * The width of texture
  41. *
  42. * @member {Number}
  43. */
  44. this.width = width || -1;
  45. /**
  46. * The height of texture
  47. *
  48. * @member {Number}
  49. */
  50. this.height = height || -1;
  51. /**
  52. * The pixel format of the texture. defaults to gl.RGBA
  53. *
  54. * @member {Number}
  55. */
  56. this.format = format || gl.RGBA;
  57. /**
  58. * The gl type of the texture. defaults to gl.UNSIGNED_BYTE
  59. *
  60. * @member {Number}
  61. */
  62. this.type = type || gl.UNSIGNED_BYTE;
  63. };
  64. /**
  65. * Uploads this texture to the GPU
  66. * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture
  67. */
  68. Texture.prototype.upload = function(source)
  69. {
  70. this.bind();
  71. var gl = this.gl;
  72. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);
  73. var newWidth = source.videoWidth || source.width;
  74. var newHeight = source.videoHeight || source.height;
  75. if(newHeight !== this.height || newWidth !== this.width)
  76. {
  77. gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source);
  78. }
  79. else
  80. {
  81. gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.format, this.type, source);
  82. }
  83. // if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect.
  84. this.width = newWidth;
  85. this.height = newHeight;
  86. };
  87. var FLOATING_POINT_AVAILABLE = false;
  88. /**
  89. * Use a data source and uploads this texture to the GPU
  90. * @param data {TypedArray} the data to upload to the texture
  91. * @param width {number} the new width of the texture
  92. * @param height {number} the new height of the texture
  93. */
  94. Texture.prototype.uploadData = function(data, width, height)
  95. {
  96. this.bind();
  97. var gl = this.gl;
  98. if(data instanceof Float32Array)
  99. {
  100. if(!FLOATING_POINT_AVAILABLE)
  101. {
  102. var ext = gl.getExtension("OES_texture_float");
  103. if(ext)
  104. {
  105. FLOATING_POINT_AVAILABLE = true;
  106. }
  107. else
  108. {
  109. throw new Error('floating point textures not available');
  110. }
  111. }
  112. this.type = gl.FLOAT;
  113. }
  114. else
  115. {
  116. // TODO support for other types
  117. this.type = this.type || gl.UNSIGNED_BYTE;
  118. }
  119. // what type of data?
  120. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);
  121. if(width !== this.width || height !== this.height)
  122. {
  123. gl.texImage2D(gl.TEXTURE_2D, 0, this.format, width, height, 0, this.format, this.type, data || null);
  124. }
  125. else
  126. {
  127. gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, this.format, this.type, data || null);
  128. }
  129. this.width = width;
  130. this.height = height;
  131. // texSubImage2D
  132. };
  133. /**
  134. * Binds the texture
  135. * @param location
  136. */
  137. Texture.prototype.bind = function(location)
  138. {
  139. var gl = this.gl;
  140. if(location !== undefined)
  141. {
  142. gl.activeTexture(gl.TEXTURE0 + location);
  143. }
  144. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  145. };
  146. /**
  147. * Unbinds the texture
  148. */
  149. Texture.prototype.unbind = function()
  150. {
  151. var gl = this.gl;
  152. gl.bindTexture(gl.TEXTURE_2D, null);
  153. };
  154. /**
  155. * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation
  156. */
  157. Texture.prototype.minFilter = function( linear )
  158. {
  159. var gl = this.gl;
  160. this.bind();
  161. if(this.mipmap)
  162. {
  163. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);
  164. }
  165. else
  166. {
  167. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST);
  168. }
  169. };
  170. /**
  171. * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation
  172. */
  173. Texture.prototype.magFilter = function( linear )
  174. {
  175. var gl = this.gl;
  176. this.bind();
  177. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST);
  178. };
  179. /**
  180. * Enables mipmapping
  181. */
  182. Texture.prototype.enableMipmap = function()
  183. {
  184. var gl = this.gl;
  185. this.bind();
  186. this.mipmap = true;
  187. gl.generateMipmap(gl.TEXTURE_2D);
  188. };
  189. /**
  190. * Enables linear filtering
  191. */
  192. Texture.prototype.enableLinearScaling = function()
  193. {
  194. this.minFilter(true);
  195. this.magFilter(true);
  196. };
  197. /**
  198. * Enables nearest neighbour interpolation
  199. */
  200. Texture.prototype.enableNearestScaling = function()
  201. {
  202. this.minFilter(false);
  203. this.magFilter(false);
  204. };
  205. /**
  206. * Enables clamping on the texture so WebGL will not repeat it
  207. */
  208. Texture.prototype.enableWrapClamp = function()
  209. {
  210. var gl = this.gl;
  211. this.bind();
  212. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  213. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  214. };
  215. /**
  216. * Enable tiling on the texture
  217. */
  218. Texture.prototype.enableWrapRepeat = function()
  219. {
  220. var gl = this.gl;
  221. this.bind();
  222. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  223. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  224. };
  225. Texture.prototype.enableWrapMirrorRepeat = function()
  226. {
  227. var gl = this.gl;
  228. this.bind();
  229. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
  230. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
  231. };
  232. /**
  233. * Destroys this texture
  234. */
  235. Texture.prototype.destroy = function()
  236. {
  237. var gl = this.gl;
  238. //TODO
  239. gl.deleteTexture(this.texture);
  240. };
  241. /**
  242. * @static
  243. * @param gl {WebGLRenderingContext} The current WebGL context
  244. * @param source {HTMLImageElement|ImageData} the source image of the texture
  245. * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha
  246. */
  247. Texture.fromSource = function(gl, source, premultiplyAlpha)
  248. {
  249. var texture = new Texture(gl);
  250. texture.premultiplyAlpha = premultiplyAlpha || false;
  251. texture.upload(source);
  252. return texture;
  253. };
  254. /**
  255. * @static
  256. * @param gl {WebGLRenderingContext} The current WebGL context
  257. * @param data {TypedArray} the data to upload to the texture
  258. * @param width {number} the new width of the texture
  259. * @param height {number} the new height of the texture
  260. */
  261. Texture.fromData = function(gl, data, width, height)
  262. {
  263. //console.log(data, width, height);
  264. var texture = new Texture(gl);
  265. texture.uploadData(data, width, height);
  266. return texture;
  267. };
  268. module.exports = Texture;