CubeMapFace.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import Check from '../Core/Check.js';
  2. import defaultValue from '../Core/defaultValue.js';
  3. import defined from '../Core/defined.js';
  4. import defineProperties from '../Core/defineProperties.js';
  5. import DeveloperError from '../Core/DeveloperError.js';
  6. import PixelFormat from '../Core/PixelFormat.js';
  7. import PixelDatatype from './PixelDatatype.js';
  8. /**
  9. * @private
  10. */
  11. function CubeMapFace(gl, texture, textureTarget, targetFace, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized) {
  12. this._gl = gl;
  13. this._texture = texture;
  14. this._textureTarget = textureTarget;
  15. this._targetFace = targetFace;
  16. this._pixelFormat = pixelFormat;
  17. this._pixelDatatype = pixelDatatype;
  18. this._size = size;
  19. this._preMultiplyAlpha = preMultiplyAlpha;
  20. this._flipY = flipY;
  21. this._initialized = initialized;
  22. }
  23. defineProperties(CubeMapFace.prototype, {
  24. pixelFormat : {
  25. get : function() {
  26. return this._pixelFormat;
  27. }
  28. },
  29. pixelDatatype : {
  30. get : function() {
  31. return this._pixelDatatype;
  32. }
  33. },
  34. _target : {
  35. get : function() {
  36. return this._targetFace;
  37. }
  38. }
  39. });
  40. /**
  41. * Copies texels from the source to the cubemap's face.
  42. *
  43. * @param {Object} source The source ImageData, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, or an object with a width, height, and typed array as shown in the example.
  44. * @param {Number} [xOffset=0] An offset in the x direction in the cubemap where copying begins.
  45. * @param {Number} [yOffset=0] An offset in the y direction in the cubemap where copying begins.
  46. *
  47. * @exception {DeveloperError} xOffset must be greater than or equal to zero.
  48. * @exception {DeveloperError} yOffset must be greater than or equal to zero.
  49. * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.
  50. * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.
  51. * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  52. *
  53. * @example
  54. * // Create a cubemap with 1x1 faces, and make the +x face red.
  55. * var cubeMap = new CubeMap({
  56. * context : context
  57. * width : 1,
  58. * height : 1
  59. * });
  60. * cubeMap.positiveX.copyFrom({
  61. * width : 1,
  62. * height : 1,
  63. * arrayBufferView : new Uint8Array([255, 0, 0, 255])
  64. * });
  65. */
  66. CubeMapFace.prototype.copyFrom = function(source, xOffset, yOffset) {
  67. xOffset = defaultValue(xOffset, 0);
  68. yOffset = defaultValue(yOffset, 0);
  69. //>>includeStart('debug', pragmas.debug);
  70. Check.defined('source', source);
  71. Check.typeOf.number.greaterThanOrEquals('xOffset', xOffset, 0);
  72. Check.typeOf.number.greaterThanOrEquals('yOffset', yOffset, 0);
  73. if (xOffset + source.width > this._size) {
  74. throw new DeveloperError('xOffset + source.width must be less than or equal to width.');
  75. }
  76. if (yOffset + source.height > this._size) {
  77. throw new DeveloperError('yOffset + source.height must be less than or equal to height.');
  78. }
  79. //>>includeEnd('debug');
  80. var gl = this._gl;
  81. var target = this._textureTarget;
  82. var targetFace = this._targetFace;
  83. gl.activeTexture(gl.TEXTURE0);
  84. gl.bindTexture(target, this._texture);
  85. var width = source.width;
  86. var height = source.height;
  87. var arrayBufferView = source.arrayBufferView;
  88. var size = this._size;
  89. var pixelFormat = this._pixelFormat;
  90. var pixelDatatype = this._pixelDatatype;
  91. var preMultiplyAlpha = this._preMultiplyAlpha;
  92. var flipY = this._flipY;
  93. var unpackAlignment = 4;
  94. if (defined(arrayBufferView)) {
  95. unpackAlignment = PixelFormat.alignmentInBytes(pixelFormat, pixelDatatype, width);
  96. }
  97. gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
  98. var uploaded = false;
  99. if (!this._initialized) {
  100. if (xOffset === 0 && yOffset === 0 && width === size && height === size) {
  101. // initialize the entire texture
  102. if (defined(arrayBufferView)) {
  103. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  104. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  105. if (flipY) {
  106. arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, size, size);
  107. }
  108. gl.texImage2D(targetFace, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, arrayBufferView);
  109. } else {
  110. // Only valid for DOM-Element uploads
  111. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
  112. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
  113. gl.texImage2D(targetFace, 0, pixelFormat, pixelFormat, pixelDatatype, source);
  114. }
  115. uploaded = true;
  116. } else {
  117. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  118. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  119. // initialize the entire texture to zero
  120. var bufferView = PixelFormat.createTypedArray(pixelFormat, pixelDatatype, size, size);
  121. gl.texImage2D(targetFace, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, bufferView);
  122. }
  123. this._initialized = true;
  124. }
  125. if (!uploaded) {
  126. if (defined(arrayBufferView)) {
  127. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  128. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  129. if (flipY) {
  130. arrayBufferView = PixelFormat.flipY(arrayBufferView, pixelFormat, pixelDatatype, width, height);
  131. }
  132. gl.texSubImage2D(targetFace, 0, xOffset, yOffset, width, height, pixelFormat, pixelDatatype, arrayBufferView);
  133. } else {
  134. // Only valid for DOM-Element uploads
  135. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
  136. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
  137. // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
  138. gl.texSubImage2D(targetFace, 0, xOffset, yOffset, pixelFormat, pixelDatatype, source);
  139. }
  140. }
  141. gl.bindTexture(target, null);
  142. };
  143. /**
  144. * Copies texels from the framebuffer to the cubemap's face.
  145. *
  146. * @param {Number} [xOffset=0] An offset in the x direction in the cubemap where copying begins.
  147. * @param {Number} [yOffset=0] An offset in the y direction in the cubemap where copying begins.
  148. * @param {Number} [framebufferXOffset=0] An offset in the x direction in the framebuffer where copying begins from.
  149. * @param {Number} [framebufferYOffset=0] An offset in the y direction in the framebuffer where copying begins from.
  150. * @param {Number} [width=CubeMap's width] The width of the subimage to copy.
  151. * @param {Number} [height=CubeMap's height] The height of the subimage to copy.
  152. *
  153. * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.
  154. * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.
  155. * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  156. * @exception {DeveloperError} xOffset must be greater than or equal to zero.
  157. * @exception {DeveloperError} yOffset must be greater than or equal to zero.
  158. * @exception {DeveloperError} framebufferXOffset must be greater than or equal to zero.
  159. * @exception {DeveloperError} framebufferYOffset must be greater than or equal to zero.
  160. * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.
  161. * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.
  162. * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  163. *
  164. * @example
  165. * // Copy the framebuffer contents to the +x cube map face.
  166. * cubeMap.positiveX.copyFromFramebuffer();
  167. */
  168. CubeMapFace.prototype.copyFromFramebuffer = function(xOffset, yOffset, framebufferXOffset, framebufferYOffset, width, height) {
  169. xOffset = defaultValue(xOffset, 0);
  170. yOffset = defaultValue(yOffset, 0);
  171. framebufferXOffset = defaultValue(framebufferXOffset, 0);
  172. framebufferYOffset = defaultValue(framebufferYOffset, 0);
  173. width = defaultValue(width, this._size);
  174. height = defaultValue(height, this._size);
  175. //>>includeStart('debug', pragmas.debug);
  176. Check.typeOf.number.greaterThanOrEquals('xOffset', xOffset, 0);
  177. Check.typeOf.number.greaterThanOrEquals('yOffset', yOffset, 0);
  178. Check.typeOf.number.greaterThanOrEquals('framebufferXOffset', framebufferXOffset, 0);
  179. Check.typeOf.number.greaterThanOrEquals('framebufferYOffset', framebufferYOffset, 0);
  180. if (xOffset + width > this._size) {
  181. throw new DeveloperError('xOffset + source.width must be less than or equal to width.');
  182. }
  183. if (yOffset + height > this._size) {
  184. throw new DeveloperError('yOffset + source.height must be less than or equal to height.');
  185. }
  186. if (this._pixelDatatype === PixelDatatype.FLOAT) {
  187. throw new DeveloperError('Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.');
  188. }
  189. if (this._pixelDatatype === PixelDatatype.HALF_FLOAT) {
  190. throw new DeveloperError('Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.');
  191. }
  192. //>>includeEnd('debug');
  193. var gl = this._gl;
  194. var target = this._textureTarget;
  195. gl.activeTexture(gl.TEXTURE0);
  196. gl.bindTexture(target, this._texture);
  197. gl.copyTexSubImage2D(this._targetFace, 0, xOffset, yOffset, framebufferXOffset, framebufferYOffset, width, height);
  198. gl.bindTexture(target, null);
  199. this._initialized = true;
  200. };
  201. export default CubeMapFace;