Source: Core/Resources/Engine_Textures.js

  1. /*
  2. * File: EngineCore_Texture.js
  3. * Provides support for loading and unloading of textures (images)
  4. */
  5. /*jslint node: true, vars: true */
  6. /*global Image, Uint8Array, alert */
  7. /* find out more about jslint: http://www.jslint.com/help.html */
  8. "use strict"; // Operate in Strict mode such that variables must be declared before used!
  9. /**
  10. * Static refrence to gEngine
  11. * @type gEngine
  12. */
  13. var gEngine = gEngine || { };
  14. /**
  15. * Texture meta data
  16. * @class TextureInfo
  17. * @param {String} name Name of Texture
  18. * @param {Number} w Width of Texture
  19. * @param {Number} h Height of Texture
  20. * @param {Number} id ID of Texture
  21. * @returns {TextureInfo} New instance of TextureInfo
  22. */
  23. function TextureInfo(name, w, h, id) {
  24. this.mName = name;
  25. this.mWidth = w;
  26. this.mHeight = h;
  27. this.mGLTexID = id;
  28. this.mColorArray = null;
  29. }
  30. /**
  31. * Provides support for loading and unloading of textures (images)
  32. * @class gEngine.Textures
  33. * @type gEngine.Textures
  34. */
  35. gEngine.Textures = (function () {
  36. /**
  37. * This converts an image to the webGL texture format. <p>
  38. * This should only be called once the texture is loaded.
  39. * @memberOf gEngine.Textures
  40. * @param {String} textureName name of the texture to be stored
  41. * @param {String} image Image file path
  42. * @returns {void}
  43. */
  44. var _processLoadedImage = function (textureName, image) {
  45. var gl = gEngine.Core.getGL();
  46. // Generate a texture reference to the webGL context
  47. var textureID = gl.createTexture();
  48. // bind the texture reference with the current texture functionality in the webGL
  49. gl.bindTexture(gl.TEXTURE_2D, textureID);
  50. // Load the texture into the texture data structure with descriptive info.
  51. // Parameters:
  52. // 1: Which "binding point" or target the texture is being loaded to.
  53. // 2: Level of detail. Used for mipmapping. 0 is base texture level.
  54. // 3: Internal format. The composition of each element. i.e. pixels.
  55. // 4: Format of texel data. Must match internal format.
  56. // 5: The data type of the texel data.
  57. // 6: Texture Data.
  58. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  59. // Creates a mipmap for this texture.
  60. gl.generateMipmap(gl.TEXTURE_2D);
  61. // Tells WebGL that we are done manipulating data at the mGL.TEXTURE_2D target.
  62. gl.bindTexture(gl.TEXTURE_2D, null);
  63. var texInfo = new TextureInfo(textureName, image.naturalWidth, image.naturalHeight, textureID);
  64. gEngine.ResourceMap.asyncLoadCompleted(textureName, texInfo);
  65. };
  66. /**
  67. * Loads an texture so that it can be drawn.<p>
  68. * If already in the map, will do nothing.
  69. * @memberOf gEngine.Textures
  70. * @param {String} textureName Texture to load from ResourceMap
  71. * @returns {void}
  72. */
  73. var loadTexture = function (textureName) {
  74. if (!(gEngine.ResourceMap.isAssetLoaded(textureName))) {
  75. // Create new Texture object.
  76. var img = new Image();
  77. // Update resources in loading counter.
  78. gEngine.ResourceMap.asyncLoadRequested(textureName);
  79. // When the texture loads, convert it to the WebGL format then put
  80. // it back into the mTextureMap.
  81. img.onload = function () {
  82. _processLoadedImage(textureName, img);
  83. };
  84. img.src = textureName;
  85. } else {
  86. gEngine.ResourceMap.incAssetRefCount(textureName);
  87. }
  88. };
  89. /**
  90. * Remove the reference to allow associated memory <p>
  91. * be available for subsequent garbage collection
  92. * @memberOf gEngine.Textures
  93. * @param {String} textureName Texture to unload from ResourceMap
  94. * @returns {void}
  95. */
  96. var unloadTexture = function (textureName) {
  97. var gl = gEngine.Core.getGL();
  98. var texInfo = gEngine.ResourceMap.retrieveAsset(textureName);
  99. gl.deleteTexture(texInfo.mGLTexID);
  100. gEngine.ResourceMap.unloadAsset(textureName);
  101. };
  102. /**
  103. * Activate gl.LINEAR_MIPMAP_LINEAR for texture <p>
  104. * @memberOf gEngine.Textures
  105. * @param {String} textureName Name of Texture
  106. * @returns {void}
  107. */
  108. var activateTexture = function (textureName) {
  109. var gl = gEngine.Core.getGL();
  110. var texInfo = gEngine.ResourceMap.retrieveAsset(textureName);
  111. // Binds our texture reference to the current webGL texture functionality
  112. gl.activeTexture(gl.TEXTURE0);
  113. gl.bindTexture(gl.TEXTURE_2D, texInfo.mGLTexID);
  114. // To prevent texture wrappings
  115. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  116. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  117. // Handles how magnification and minimization filters will work.
  118. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  119. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
  120. // For pixel-graphics where you want the texture to look "sharp" do the following:
  121. // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  122. // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  123. };
  124. /**
  125. * Activate gl.LINEAR_MIPMAP_LINEAR for texture <p>
  126. * texture 1 is always normal map for this game engine
  127. * @memberOf gEngine.Textures
  128. * @param {String} textureName Name of Texture
  129. * @returns {void}
  130. */
  131. var activateNormalMap = function (textureName) {
  132. var gl = gEngine.Core.getGL();
  133. var texInfo = gEngine.ResourceMap.retrieveAsset(textureName);
  134. // Binds our texture reference to the current webGL texture functionality
  135. gl.activeTexture(gl.TEXTURE1);
  136. gl.bindTexture(gl.TEXTURE_2D, texInfo.mGLTexID);
  137. // To prevent texture wrappings
  138. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  139. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  140. // Handles how magnification and minimization filters will work.
  141. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  142. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
  143. };
  144. /**
  145. * Deactivate the Textures and remove them from the GPU
  146. * @memberOf gEngine.Textures
  147. * @returns {void}
  148. */
  149. var deactivateTexture = function () {
  150. var gl = gEngine.Core.getGL();
  151. gl.bindTexture(gl.TEXTURE_2D, null);
  152. };
  153. /**
  154. * Return the TextureInfo of Texture
  155. * @memberOf gEngine.Textures
  156. * @param {String} textureName Name of Texture
  157. * @returns {TextureInfo} TextureInto of Texture to get TexttureInfo
  158. */
  159. var getTextureInfo = function (textureName) {
  160. return gEngine.ResourceMap.retrieveAsset(textureName);
  161. };
  162. /**
  163. * Return the Color Array of a texture
  164. * @memberOf gEngine.Textures
  165. * @param {String} textureName Name of Texture to get Color Array
  166. * @returns {Float[]}
  167. */
  168. var getColorArray = function (textureName) {
  169. var texInfo = getTextureInfo(textureName);
  170. if (texInfo.mColorArray === null) {
  171. // create a framebuffer bind it to the texture, and read the color content
  172. // Hint from: http://stackoverflow.com/questions/13626606/read-pixels-from-a-webgl-texture
  173. var gl = gEngine.Core.getGL();
  174. var fb = gl.createFramebuffer();
  175. gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  176. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texInfo.mGLTexID, 0);
  177. if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
  178. var pixels = new Uint8Array(texInfo.mWidth * texInfo.mHeight * 4);
  179. gl.readPixels(0, 0, texInfo.mWidth, texInfo.mHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  180. texInfo.mColorArray = pixels;
  181. } else {
  182. alert("WARNING: Engine.Textures.getColorArray() failed!");
  183. }
  184. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  185. gl.deleteFramebuffer(fb);
  186. }
  187. return texInfo.mColorArray;
  188. };
  189. // Public interface for this object. Anything not in here will
  190. // not be accessable.
  191. var mPublic = {
  192. loadTexture: loadTexture,
  193. unloadTexture: unloadTexture,
  194. activateTexture: activateTexture,
  195. activateNormalMap: activateNormalMap,
  196. deactivateTexture: deactivateTexture,
  197. getTextureInfo: getTextureInfo,
  198. getColorArray: getColorArray
  199. };
  200. return mPublic;
  201. }());