PixelFormat.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. import PixelDatatype from "../Renderer/PixelDatatype.js";
  2. import WebGLConstants from "./WebGLConstants.js";
  3. /**
  4. * The format of a pixel, i.e., the number of components it has and what they represent.
  5. *
  6. * @enum {Number}
  7. */
  8. const PixelFormat = {
  9. /**
  10. * A pixel format containing a depth value.
  11. *
  12. * @type {Number}
  13. * @constant
  14. */
  15. DEPTH_COMPONENT: WebGLConstants.DEPTH_COMPONENT,
  16. /**
  17. * A pixel format containing a depth and stencil value, most often used with {@link PixelDatatype.UNSIGNED_INT_24_8}.
  18. *
  19. * @type {Number}
  20. * @constant
  21. */
  22. DEPTH_STENCIL: WebGLConstants.DEPTH_STENCIL,
  23. /**
  24. * A pixel format containing an alpha channel.
  25. *
  26. * @type {Number}
  27. * @constant
  28. */
  29. ALPHA: WebGLConstants.ALPHA,
  30. /**
  31. * A pixel format containing red, green, and blue channels.
  32. *
  33. * @type {Number}
  34. * @constant
  35. */
  36. RGB: WebGLConstants.RGB,
  37. /**
  38. * A pixel format containing red, green, blue, and alpha channels.
  39. *
  40. * @type {Number}
  41. * @constant
  42. */
  43. RGBA: WebGLConstants.RGBA,
  44. /**
  45. * A pixel format containing a luminance (intensity) channel.
  46. *
  47. * @type {Number}
  48. * @constant
  49. */
  50. LUMINANCE: WebGLConstants.LUMINANCE,
  51. /**
  52. * A pixel format containing luminance (intensity) and alpha channels.
  53. *
  54. * @type {Number}
  55. * @constant
  56. */
  57. LUMINANCE_ALPHA: WebGLConstants.LUMINANCE_ALPHA,
  58. /**
  59. * A pixel format containing red, green, and blue channels that is DXT1 compressed.
  60. *
  61. * @type {Number}
  62. * @constant
  63. */
  64. RGB_DXT1: WebGLConstants.COMPRESSED_RGB_S3TC_DXT1_EXT,
  65. /**
  66. * A pixel format containing red, green, blue, and alpha channels that is DXT1 compressed.
  67. *
  68. * @type {Number}
  69. * @constant
  70. */
  71. RGBA_DXT1: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT1_EXT,
  72. /**
  73. * A pixel format containing red, green, blue, and alpha channels that is DXT3 compressed.
  74. *
  75. * @type {Number}
  76. * @constant
  77. */
  78. RGBA_DXT3: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT3_EXT,
  79. /**
  80. * A pixel format containing red, green, blue, and alpha channels that is DXT5 compressed.
  81. *
  82. * @type {Number}
  83. * @constant
  84. */
  85. RGBA_DXT5: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT5_EXT,
  86. /**
  87. * A pixel format containing red, green, and blue channels that is PVR 4bpp compressed.
  88. *
  89. * @type {Number}
  90. * @constant
  91. */
  92. RGB_PVRTC_4BPPV1: WebGLConstants.COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
  93. /**
  94. * A pixel format containing red, green, and blue channels that is PVR 2bpp compressed.
  95. *
  96. * @type {Number}
  97. * @constant
  98. */
  99. RGB_PVRTC_2BPPV1: WebGLConstants.COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
  100. /**
  101. * A pixel format containing red, green, blue, and alpha channels that is PVR 4bpp compressed.
  102. *
  103. * @type {Number}
  104. * @constant
  105. */
  106. RGBA_PVRTC_4BPPV1: WebGLConstants.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
  107. /**
  108. * A pixel format containing red, green, blue, and alpha channels that is PVR 2bpp compressed.
  109. *
  110. * @type {Number}
  111. * @constant
  112. */
  113. RGBA_PVRTC_2BPPV1: WebGLConstants.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,
  114. /**
  115. * A pixel format containing red, green, blue, and alpha channels that is ASTC compressed.
  116. *
  117. * @type {Number}
  118. * @constant
  119. */
  120. RGBA_ASTC: WebGLConstants.COMPRESSED_RGBA_ASTC_4x4_WEBGL,
  121. /**
  122. * A pixel format containing red, green, and blue channels that is ETC1 compressed.
  123. *
  124. * @type {Number}
  125. * @constant
  126. */
  127. RGB_ETC1: WebGLConstants.COMPRESSED_RGB_ETC1_WEBGL,
  128. /**
  129. * A pixel format containing red, green, and blue channels that is ETC2 compressed.
  130. *
  131. * @type {Number}
  132. * @constant
  133. */
  134. RGB8_ETC2: WebGLConstants.COMPRESSED_RGB8_ETC2,
  135. /**
  136. * A pixel format containing red, green, blue, and alpha channels that is ETC2 compressed.
  137. *
  138. * @type {Number}
  139. * @constant
  140. */
  141. RGBA8_ETC2_EAC: WebGLConstants.COMPRESSED_RGBA8_ETC2_EAC,
  142. /**
  143. * A pixel format containing red, green, blue, and alpha channels that is BC7 compressed.
  144. *
  145. * @type {Number}
  146. * @constant
  147. */
  148. RGBA_BC7: WebGLConstants.COMPRESSED_RGBA_BPTC_UNORM,
  149. };
  150. /**
  151. * @private
  152. */
  153. PixelFormat.componentsLength = function (pixelFormat) {
  154. switch (pixelFormat) {
  155. case PixelFormat.RGB:
  156. return 3;
  157. case PixelFormat.RGBA:
  158. return 4;
  159. case PixelFormat.LUMINANCE_ALPHA:
  160. return 2;
  161. case PixelFormat.ALPHA:
  162. case PixelFormat.LUMINANCE:
  163. return 1;
  164. default:
  165. return 1;
  166. }
  167. };
  168. /**
  169. * @private
  170. */
  171. PixelFormat.validate = function (pixelFormat) {
  172. return (
  173. pixelFormat === PixelFormat.DEPTH_COMPONENT ||
  174. pixelFormat === PixelFormat.DEPTH_STENCIL ||
  175. pixelFormat === PixelFormat.ALPHA ||
  176. pixelFormat === PixelFormat.RGB ||
  177. pixelFormat === PixelFormat.RGBA ||
  178. pixelFormat === PixelFormat.LUMINANCE ||
  179. pixelFormat === PixelFormat.LUMINANCE_ALPHA ||
  180. pixelFormat === PixelFormat.RGB_DXT1 ||
  181. pixelFormat === PixelFormat.RGBA_DXT1 ||
  182. pixelFormat === PixelFormat.RGBA_DXT3 ||
  183. pixelFormat === PixelFormat.RGBA_DXT5 ||
  184. pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||
  185. pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||
  186. pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||
  187. pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 ||
  188. pixelFormat === PixelFormat.RGBA_ASTC ||
  189. pixelFormat === PixelFormat.RGB_ETC1 ||
  190. pixelFormat === PixelFormat.RGB8_ETC2 ||
  191. pixelFormat === PixelFormat.RGBA8_ETC2_EAC ||
  192. pixelFormat === PixelFormat.RGBA_BC7
  193. );
  194. };
  195. /**
  196. * @private
  197. */
  198. PixelFormat.isColorFormat = function (pixelFormat) {
  199. return (
  200. pixelFormat === PixelFormat.ALPHA ||
  201. pixelFormat === PixelFormat.RGB ||
  202. pixelFormat === PixelFormat.RGBA ||
  203. pixelFormat === PixelFormat.LUMINANCE ||
  204. pixelFormat === PixelFormat.LUMINANCE_ALPHA
  205. );
  206. };
  207. /**
  208. * @private
  209. */
  210. PixelFormat.isDepthFormat = function (pixelFormat) {
  211. return (
  212. pixelFormat === PixelFormat.DEPTH_COMPONENT ||
  213. pixelFormat === PixelFormat.DEPTH_STENCIL
  214. );
  215. };
  216. /**
  217. * @private
  218. */
  219. PixelFormat.isCompressedFormat = function (pixelFormat) {
  220. return (
  221. pixelFormat === PixelFormat.RGB_DXT1 ||
  222. pixelFormat === PixelFormat.RGBA_DXT1 ||
  223. pixelFormat === PixelFormat.RGBA_DXT3 ||
  224. pixelFormat === PixelFormat.RGBA_DXT5 ||
  225. pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||
  226. pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||
  227. pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||
  228. pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 ||
  229. pixelFormat === PixelFormat.RGBA_ASTC ||
  230. pixelFormat === PixelFormat.RGB_ETC1 ||
  231. pixelFormat === PixelFormat.RGB8_ETC2 ||
  232. pixelFormat === PixelFormat.RGBA8_ETC2_EAC ||
  233. pixelFormat === PixelFormat.RGBA_BC7
  234. );
  235. };
  236. /**
  237. * @private
  238. */
  239. PixelFormat.isDXTFormat = function (pixelFormat) {
  240. return (
  241. pixelFormat === PixelFormat.RGB_DXT1 ||
  242. pixelFormat === PixelFormat.RGBA_DXT1 ||
  243. pixelFormat === PixelFormat.RGBA_DXT3 ||
  244. pixelFormat === PixelFormat.RGBA_DXT5
  245. );
  246. };
  247. /**
  248. * @private
  249. */
  250. PixelFormat.isPVRTCFormat = function (pixelFormat) {
  251. return (
  252. pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||
  253. pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||
  254. pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||
  255. pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1
  256. );
  257. };
  258. /**
  259. * @private
  260. */
  261. PixelFormat.isASTCFormat = function (pixelFormat) {
  262. return pixelFormat === PixelFormat.RGBA_ASTC;
  263. };
  264. /**
  265. * @private
  266. */
  267. PixelFormat.isETC1Format = function (pixelFormat) {
  268. return pixelFormat === PixelFormat.RGB_ETC1;
  269. };
  270. /**
  271. * @private
  272. */
  273. PixelFormat.isETC2Format = function (pixelFormat) {
  274. return (
  275. pixelFormat === PixelFormat.RGB8_ETC2 ||
  276. pixelFormat === PixelFormat.RGBA8_ETC2_EAC
  277. );
  278. };
  279. /**
  280. * @private
  281. */
  282. PixelFormat.isBC7Format = function (pixelFormat) {
  283. return pixelFormat === PixelFormat.RGBA_BC7;
  284. };
  285. /**
  286. * @private
  287. */
  288. PixelFormat.compressedTextureSizeInBytes = function (
  289. pixelFormat,
  290. width,
  291. height
  292. ) {
  293. switch (pixelFormat) {
  294. case PixelFormat.RGB_DXT1:
  295. case PixelFormat.RGBA_DXT1:
  296. case PixelFormat.RGB_ETC1:
  297. case PixelFormat.RGB8_ETC2:
  298. return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
  299. case PixelFormat.RGBA_DXT3:
  300. case PixelFormat.RGBA_DXT5:
  301. case PixelFormat.RGBA_ASTC:
  302. case PixelFormat.RGBA8_ETC2_EAC:
  303. return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
  304. case PixelFormat.RGB_PVRTC_4BPPV1:
  305. case PixelFormat.RGBA_PVRTC_4BPPV1:
  306. return Math.floor((Math.max(width, 8) * Math.max(height, 8) * 4 + 7) / 8);
  307. case PixelFormat.RGB_PVRTC_2BPPV1:
  308. case PixelFormat.RGBA_PVRTC_2BPPV1:
  309. return Math.floor(
  310. (Math.max(width, 16) * Math.max(height, 8) * 2 + 7) / 8
  311. );
  312. case PixelFormat.RGBA_BC7:
  313. return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
  314. default:
  315. return 0;
  316. }
  317. };
  318. /**
  319. * @private
  320. */
  321. PixelFormat.textureSizeInBytes = function (
  322. pixelFormat,
  323. pixelDatatype,
  324. width,
  325. height
  326. ) {
  327. let componentsLength = PixelFormat.componentsLength(pixelFormat);
  328. if (PixelDatatype.isPacked(pixelDatatype)) {
  329. componentsLength = 1;
  330. }
  331. return (
  332. componentsLength * PixelDatatype.sizeInBytes(pixelDatatype) * width * height
  333. );
  334. };
  335. /**
  336. * @private
  337. */
  338. PixelFormat.alignmentInBytes = function (pixelFormat, pixelDatatype, width) {
  339. const mod =
  340. PixelFormat.textureSizeInBytes(pixelFormat, pixelDatatype, width, 1) % 4;
  341. return mod === 0 ? 4 : mod === 2 ? 2 : 1;
  342. };
  343. /**
  344. * @private
  345. */
  346. PixelFormat.createTypedArray = function (
  347. pixelFormat,
  348. pixelDatatype,
  349. width,
  350. height
  351. ) {
  352. let constructor;
  353. const sizeInBytes = PixelDatatype.sizeInBytes(pixelDatatype);
  354. if (sizeInBytes === Uint8Array.BYTES_PER_ELEMENT) {
  355. constructor = Uint8Array;
  356. } else if (sizeInBytes === Uint16Array.BYTES_PER_ELEMENT) {
  357. constructor = Uint16Array;
  358. } else if (
  359. sizeInBytes === Float32Array.BYTES_PER_ELEMENT &&
  360. pixelDatatype === PixelDatatype.FLOAT
  361. ) {
  362. constructor = Float32Array;
  363. } else {
  364. constructor = Uint32Array;
  365. }
  366. const size = PixelFormat.componentsLength(pixelFormat) * width * height;
  367. return new constructor(size);
  368. };
  369. /**
  370. * @private
  371. */
  372. PixelFormat.flipY = function (
  373. bufferView,
  374. pixelFormat,
  375. pixelDatatype,
  376. width,
  377. height
  378. ) {
  379. if (height === 1) {
  380. return bufferView;
  381. }
  382. const flipped = PixelFormat.createTypedArray(
  383. pixelFormat,
  384. pixelDatatype,
  385. width,
  386. height
  387. );
  388. const numberOfComponents = PixelFormat.componentsLength(pixelFormat);
  389. const textureWidth = width * numberOfComponents;
  390. for (let i = 0; i < height; ++i) {
  391. const row = i * width * numberOfComponents;
  392. const flippedRow = (height - i - 1) * width * numberOfComponents;
  393. for (let j = 0; j < textureWidth; ++j) {
  394. flipped[flippedRow + j] = bufferView[row + j];
  395. }
  396. }
  397. return flipped;
  398. };
  399. /**
  400. * @private
  401. */
  402. PixelFormat.toInternalFormat = function (pixelFormat, pixelDatatype, context) {
  403. // WebGL 1 require internalFormat to be the same as PixelFormat
  404. if (!context.webgl2) {
  405. return pixelFormat;
  406. }
  407. // Convert pixelFormat to correct internalFormat for WebGL 2
  408. if (pixelFormat === PixelFormat.DEPTH_STENCIL) {
  409. return WebGLConstants.DEPTH24_STENCIL8;
  410. }
  411. if (pixelFormat === PixelFormat.DEPTH_COMPONENT) {
  412. if (pixelDatatype === PixelDatatype.UNSIGNED_SHORT) {
  413. return WebGLConstants.DEPTH_COMPONENT16;
  414. } else if (pixelDatatype === PixelDatatype.UNSIGNED_INT) {
  415. return WebGLConstants.DEPTH_COMPONENT24;
  416. }
  417. }
  418. if (pixelDatatype === PixelDatatype.FLOAT) {
  419. switch (pixelFormat) {
  420. case PixelFormat.RGBA:
  421. return WebGLConstants.RGBA32F;
  422. case PixelFormat.RGB:
  423. return WebGLConstants.RGB32F;
  424. case PixelFormat.RG:
  425. return WebGLConstants.RG32F;
  426. case PixelFormat.R:
  427. return WebGLConstants.R32F;
  428. }
  429. }
  430. if (pixelDatatype === PixelDatatype.HALF_FLOAT) {
  431. switch (pixelFormat) {
  432. case PixelFormat.RGBA:
  433. return WebGLConstants.RGBA16F;
  434. case PixelFormat.RGB:
  435. return WebGLConstants.RGB16F;
  436. case PixelFormat.RG:
  437. return WebGLConstants.RG16F;
  438. case PixelFormat.R:
  439. return WebGLConstants.R16F;
  440. }
  441. }
  442. return pixelFormat;
  443. };
  444. export default Object.freeze(PixelFormat);