智慧水务管理系统 - 精河县供水工程综合管理平台

CubeMapFace.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. import Check from "../Core/Check.js";
  2. import defined from "../Core/defined.js";
  3. import DeveloperError from "../Core/DeveloperError.js";
  4. import PixelFormat from "../Core/PixelFormat.js";
  5. import PixelDatatype from "./PixelDatatype.js";
  6. /**
  7. * @private
  8. */
  9. function CubeMapFace(
  10. context,
  11. texture,
  12. textureTarget,
  13. targetFace,
  14. internalFormat,
  15. pixelFormat,
  16. pixelDatatype,
  17. size,
  18. preMultiplyAlpha,
  19. flipY,
  20. initialized,
  21. ) {
  22. this._context = context;
  23. this._texture = texture;
  24. this._textureTarget = textureTarget;
  25. this._targetFace = targetFace;
  26. this._pixelDatatype = pixelDatatype;
  27. this._internalFormat = internalFormat;
  28. this._pixelFormat = pixelFormat;
  29. this._size = size;
  30. this._preMultiplyAlpha = preMultiplyAlpha;
  31. this._flipY = flipY;
  32. this._initialized = initialized;
  33. }
  34. Object.defineProperties(CubeMapFace.prototype, {
  35. pixelFormat: {
  36. get: function () {
  37. return this._pixelFormat;
  38. },
  39. },
  40. pixelDatatype: {
  41. get: function () {
  42. return this._pixelDatatype;
  43. },
  44. },
  45. _target: {
  46. get: function () {
  47. return this._targetFace;
  48. },
  49. },
  50. });
  51. /**
  52. * Copies texels from the source to the cubemap's face.
  53. * @param {object} options Object with the following properties:
  54. * @param {object} options.source The source {@link ImageData}, {@link HTMLImageElement}, {@link HTMLCanvasElement}, {@link HTMLVideoElement},
  55. * or an object with a width, height, and arrayBufferView properties.
  56. * @param {number} [options.xOffset=0] An offset in the x direction in the cubemap where copying begins.
  57. * @param {number} [options.yOffset=0] An offset in the y direction in the cubemap where copying begins.
  58. * @param {boolean} [options.skipColorSpaceConversion=false] If true, any custom gamma or color profiles in the texture will be ignored.
  59. * @exception {DeveloperError} xOffset must be greater than or equal to zero.
  60. * @exception {DeveloperError} yOffset must be greater than or equal to zero.
  61. * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.
  62. * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.
  63. * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  64. *
  65. * @example
  66. * // Create a cubemap with 1x1 faces, and make the +x face red.
  67. * const cubeMap = new CubeMap({
  68. * context : context
  69. * width : 1,
  70. * height : 1
  71. * });
  72. * cubeMap.positiveX.copyFrom({
  73. * source: {
  74. * width : 1,
  75. * height : 1,
  76. * arrayBufferView : new Uint8Array([255, 0, 0, 255])
  77. * }
  78. * });
  79. */
  80. CubeMapFace.prototype.copyFrom = function (options) {
  81. //>>includeStart('debug', pragmas.debug);
  82. Check.defined("options", options);
  83. //>>includeEnd('debug');
  84. const {
  85. xOffset = 0,
  86. yOffset = 0,
  87. source,
  88. skipColorSpaceConversion = false,
  89. } = options;
  90. //>>includeStart('debug', pragmas.debug);
  91. Check.defined("options.source", source);
  92. Check.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
  93. Check.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
  94. if (xOffset + source.width > this._size) {
  95. throw new DeveloperError(
  96. "xOffset + options.source.width must be less than or equal to width.",
  97. );
  98. }
  99. if (yOffset + source.height > this._size) {
  100. throw new DeveloperError(
  101. "yOffset + options.source.height must be less than or equal to height.",
  102. );
  103. }
  104. //>>includeEnd('debug');
  105. const { width, height } = source;
  106. const gl = this._context._gl;
  107. const target = this._textureTarget;
  108. const targetFace = this._targetFace;
  109. gl.activeTexture(gl.TEXTURE0);
  110. gl.bindTexture(target, this._texture);
  111. let arrayBufferView = source.arrayBufferView;
  112. const size = this._size;
  113. const pixelFormat = this._pixelFormat;
  114. const internalFormat = this._internalFormat;
  115. const pixelDatatype = this._pixelDatatype;
  116. const preMultiplyAlpha = this._preMultiplyAlpha;
  117. const flipY = this._flipY;
  118. let unpackAlignment = 4;
  119. if (defined(arrayBufferView)) {
  120. unpackAlignment = PixelFormat.alignmentInBytes(
  121. pixelFormat,
  122. pixelDatatype,
  123. width,
  124. );
  125. }
  126. gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
  127. if (skipColorSpaceConversion) {
  128. gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
  129. } else {
  130. gl.pixelStorei(
  131. gl.UNPACK_COLORSPACE_CONVERSION_WEBGL,
  132. gl.BROWSER_DEFAULT_WEBGL,
  133. );
  134. }
  135. let uploaded = false;
  136. if (!this._initialized) {
  137. let pixels;
  138. if (xOffset === 0 && yOffset === 0 && width === size && height === size) {
  139. // initialize the entire texture
  140. if (defined(arrayBufferView)) {
  141. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  142. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  143. if (flipY) {
  144. arrayBufferView = PixelFormat.flipY(
  145. arrayBufferView,
  146. pixelFormat,
  147. pixelDatatype,
  148. size,
  149. size,
  150. );
  151. }
  152. pixels = arrayBufferView;
  153. } else {
  154. // Only valid for DOM-Element uploads
  155. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
  156. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
  157. pixels = source;
  158. }
  159. uploaded = true;
  160. } else {
  161. // initialize the entire texture to zero
  162. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  163. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  164. pixels = PixelFormat.createTypedArray(
  165. pixelFormat,
  166. pixelDatatype,
  167. size,
  168. size,
  169. );
  170. }
  171. gl.texImage2D(
  172. targetFace,
  173. 0,
  174. internalFormat,
  175. size,
  176. size,
  177. 0,
  178. pixelFormat,
  179. PixelDatatype.toWebGLConstant(pixelDatatype, this._context),
  180. pixels,
  181. );
  182. this._initialized = true;
  183. }
  184. if (!uploaded) {
  185. if (defined(arrayBufferView)) {
  186. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  187. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  188. if (flipY) {
  189. arrayBufferView = PixelFormat.flipY(
  190. arrayBufferView,
  191. pixelFormat,
  192. pixelDatatype,
  193. width,
  194. height,
  195. );
  196. }
  197. gl.texSubImage2D(
  198. targetFace,
  199. 0,
  200. xOffset,
  201. yOffset,
  202. width,
  203. height,
  204. pixelFormat,
  205. PixelDatatype.toWebGLConstant(pixelDatatype, this._context),
  206. arrayBufferView,
  207. );
  208. } else {
  209. // Only valid for DOM-Element uploads
  210. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
  211. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
  212. // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
  213. gl.texSubImage2D(
  214. targetFace,
  215. 0,
  216. xOffset,
  217. yOffset,
  218. pixelFormat,
  219. PixelDatatype.toWebGLConstant(pixelDatatype, this._context),
  220. source,
  221. );
  222. }
  223. }
  224. gl.bindTexture(target, null);
  225. };
  226. /**
  227. * Copies texels from the framebuffer to the cubemap's face.
  228. * @param {number} [xOffset=0] An offset in the x direction in the cubemap where copying begins.
  229. * @param {number} [yOffset=0] An offset in the y direction in the cubemap where copying begins.
  230. * @param {number} [framebufferXOffset=0] An offset in the x direction in the framebuffer where copying begins from.
  231. * @param {number} [framebufferYOffset=0] An offset in the y direction in the framebuffer where copying begins from.
  232. * @param {number} [width=CubeMap's width] The width of the subimage to copy.
  233. * @param {number} [height=CubeMap's height] The height of the subimage to copy.
  234. * @throws {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.
  235. * @throws {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.
  236. * @throws {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  237. * @throws {DeveloperError} xOffset must be greater than or equal to zero.
  238. * @throws {DeveloperError} yOffset must be greater than or equal to zero.
  239. * @throws {DeveloperError} framebufferXOffset must be greater than or equal to zero.
  240. * @throws {DeveloperError} framebufferYOffset must be greater than or equal to zero.
  241. * @throws {DeveloperError} xOffset + source.width must be less than or equal to width.
  242. * @throws {DeveloperError} yOffset + source.height must be less than or equal to height.
  243. * @throws {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  244. * @example
  245. * // Copy the framebuffer contents to the +x cube map face.
  246. * cubeMap.positiveX.copyFromFramebuffer();
  247. */
  248. CubeMapFace.prototype.copyFromFramebuffer = function (
  249. xOffset,
  250. yOffset,
  251. framebufferXOffset,
  252. framebufferYOffset,
  253. width,
  254. height,
  255. ) {
  256. xOffset = xOffset ?? 0;
  257. yOffset = yOffset ?? 0;
  258. framebufferXOffset = framebufferXOffset ?? 0;
  259. framebufferYOffset = framebufferYOffset ?? 0;
  260. width = width ?? this._size;
  261. height = height ?? this._size;
  262. //>>includeStart('debug', pragmas.debug);
  263. Check.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
  264. Check.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
  265. Check.typeOf.number.greaterThanOrEquals(
  266. "framebufferXOffset",
  267. framebufferXOffset,
  268. 0,
  269. );
  270. Check.typeOf.number.greaterThanOrEquals(
  271. "framebufferYOffset",
  272. framebufferYOffset,
  273. 0,
  274. );
  275. if (xOffset + width > this._size) {
  276. throw new DeveloperError(
  277. "xOffset + source.width must be less than or equal to width.",
  278. );
  279. }
  280. if (yOffset + height > this._size) {
  281. throw new DeveloperError(
  282. "yOffset + source.height must be less than or equal to height.",
  283. );
  284. }
  285. if (this._pixelDatatype === PixelDatatype.FLOAT) {
  286. throw new DeveloperError(
  287. "Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.",
  288. );
  289. }
  290. if (this._pixelDatatype === PixelDatatype.HALF_FLOAT) {
  291. throw new DeveloperError(
  292. "Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.",
  293. );
  294. }
  295. //>>includeEnd('debug');
  296. const gl = this._context._gl;
  297. const target = this._textureTarget;
  298. gl.activeTexture(gl.TEXTURE0);
  299. gl.bindTexture(target, this._texture);
  300. gl.copyTexSubImage2D(
  301. this._targetFace,
  302. 0,
  303. xOffset,
  304. yOffset,
  305. framebufferXOffset,
  306. framebufferYOffset,
  307. width,
  308. height,
  309. );
  310. gl.bindTexture(target, null);
  311. this._initialized = true;
  312. };
  313. /**
  314. * Copies texels from the framebuffer to the cubemap's face mipmap.
  315. * @param {number} [xOffset=0] An offset in the x direction in the framebuffer where copying begins from.
  316. * @param {number} [yOffset=0] An offset in the y direction in the framebuffer where copying begins from.
  317. * @param {number} [width=CubeMap's width] The width of the subimage to copy.
  318. * @param {number} [height=CubeMap's height] The height of the subimage to copy.
  319. * @param {number} [level=0] The level of detail. Level 0 is the base image level and level n is the n-th mipmap reduction level.
  320. * @throws {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.
  321. * @throws {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.
  322. * @throws {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  323. * @throws {DeveloperError} xOffset must be greater than or equal to zero.
  324. * @throws {DeveloperError} yOffset must be greater than or equal to zero.
  325. * @throws {DeveloperError} framebufferXOffset must be greater than or equal to zero.
  326. * @throws {DeveloperError} framebufferYOffset must be greater than or equal to zero.
  327. * @throws {DeveloperError} xOffset + source.width must be less than or equal to width.
  328. * @throws {DeveloperError} yOffset + source.height must be less than or equal to height.
  329. * @throws {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.
  330. *
  331. * @example
  332. * // Copy the framebuffer contents to the +x cube map face.
  333. * cubeMap.positiveX.copyFromFramebuffer();
  334. */
  335. CubeMapFace.prototype.copyMipmapFromFramebuffer = function (
  336. xOffset,
  337. yOffset,
  338. width,
  339. height,
  340. level,
  341. ) {
  342. xOffset = xOffset ?? 0;
  343. yOffset = yOffset ?? 0;
  344. width = width ?? this._size;
  345. height = height ?? this._size;
  346. level = level ?? 0;
  347. //>>includeStart('debug', pragmas.debug);
  348. Check.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
  349. Check.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
  350. if (xOffset + width > this._size) {
  351. throw new DeveloperError(
  352. "xOffset + source.width must be less than or equal to width.",
  353. );
  354. }
  355. if (yOffset + height > this._size) {
  356. throw new DeveloperError(
  357. "yOffset + source.height must be less than or equal to height.",
  358. );
  359. }
  360. if (this._pixelDatatype === PixelDatatype.FLOAT) {
  361. throw new DeveloperError(
  362. "Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.",
  363. );
  364. }
  365. if (this._pixelDatatype === PixelDatatype.HALF_FLOAT) {
  366. throw new DeveloperError(
  367. "Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.",
  368. );
  369. }
  370. //>>includeEnd('debug');
  371. const gl = this._context._gl;
  372. const target = this._textureTarget;
  373. gl.activeTexture(gl.TEXTURE0);
  374. gl.bindTexture(target, this._texture);
  375. gl.copyTexImage2D(
  376. this._targetFace,
  377. level,
  378. this._internalFormat,
  379. xOffset,
  380. yOffset,
  381. width,
  382. height,
  383. 0,
  384. );
  385. gl.bindTexture(target, null);
  386. this._initialized = true;
  387. };
  388. export default CubeMapFace;