threepipe
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

texture.ts 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import {
  2. ColorSpace,
  3. DataTexture,
  4. DataUtils,
  5. FloatType,
  6. HalfFloatType,
  7. LinearSRGBColorSpace,
  8. Texture,
  9. TextureDataType,
  10. UnsignedByteType,
  11. WebGLRenderer,
  12. } from 'three'
  13. import {TextureImageData} from 'three/src/textures/types'
  14. import {LinearToSRGB} from 'ts-browser-helpers'
  15. export function getTextureDataType(renderer?: WebGLRenderer): TextureDataType {
  16. if (!renderer) return UnsignedByteType
  17. const halfFloatSupport = renderer.extensions.has('EXT_color_buffer_half_float') || renderer.capabilities.isWebGL2 && renderer.extensions.has('EXT_color_buffer_float')
  18. const floatSupport = renderer.capabilities.isWebGL2 || renderer.extensions.has('OES_texture_float') || renderer.extensions.has('WEBGL_color_buffer_float')
  19. return halfFloatSupport ? HalfFloatType : floatSupport ? FloatType : UnsignedByteType
  20. }
  21. export function textureDataToImageData(imgData: TextureImageData | ImageData | {data: Float32Array|Uint16Array|Uint8Array, width: number, height: number}, colorSpace?: ColorSpace, outData?: ImageData) {
  22. const data = outData?.data ?? new Uint8ClampedArray(imgData.height * imgData.width * 4)
  23. const isFloat32 = imgData.data instanceof Float32Array
  24. const isUint16 = imgData.data instanceof Uint16Array
  25. for (let i = 0; i < data.length; i++) {
  26. if (isFloat32) { // Float32
  27. data[i] = imgData.data[i] * 255
  28. } else if (isUint16) { // Uint16 (half float)
  29. data[i] = DataUtils.fromHalfFloat(imgData.data[i]) * 255
  30. } else { // Uint8
  31. data[i] = imgData.data[i]
  32. }
  33. if (colorSpace === LinearSRGBColorSpace) {
  34. data[i] = LinearToSRGB(data[i] / 255.0) * 255
  35. }
  36. // todo: rgbm?
  37. }
  38. return outData ?? new ImageData(data, imgData.width, imgData.height)
  39. }
  40. /**
  41. *
  42. * @param texture
  43. * @param maxWidth
  44. * @param flipY
  45. * @param canvas
  46. */
  47. export function textureToCanvas(texture: Texture|DataTexture, maxWidth: number, flipY = false, canvas?: HTMLCanvasElement) {
  48. let img
  49. if ((texture as DataTexture).isDataTexture) img = textureDataToImageData(texture.image, texture.colorSpace)
  50. else img = texture.image
  51. return imageToCanvas(img, maxWidth, flipY, canvas)
  52. }
  53. export function imageToCanvas(image: TexImageSource, maxWidth: number, flipY = false, canvas?: HTMLCanvasElement) {
  54. canvas = canvas || document.createElement('canvas')
  55. // resize it to the size of our image
  56. canvas.width = Math.min(maxWidth, image.width as number)
  57. canvas.height = Math.floor(1.0 + canvas.width * (image.height as number) / (image.width as number))
  58. const ctx = canvas.getContext('2d')
  59. if (!ctx) {
  60. console.error('textureToDataUrl: could not get canvas context')
  61. return canvas
  62. }
  63. if (flipY === true) {
  64. ctx.translate(0, canvas.height)
  65. ctx.scale(1, -1)
  66. }
  67. if ((image as ImageData).data !== undefined) { // THREE.DataTexture
  68. const imageData = image as ImageData
  69. if (image.width !== canvas.width || image.height !== canvas.height) {
  70. const tempCanvas = document.createElement('canvas')
  71. tempCanvas.width = image.width
  72. tempCanvas.height = image.height
  73. const tempCtx = tempCanvas.getContext('2d')
  74. if (!tempCtx) {
  75. console.error('textureToDataUrl: could not get temp canvas context')
  76. ctx.putImageData(imageData, 0, 0)
  77. } else {
  78. tempCtx.putImageData(imageData, 0, 0)
  79. ctx.drawImage(tempCanvas, 0, 0, canvas.width, canvas.height)
  80. }
  81. } else {
  82. ctx.putImageData(imageData, 0, 0)
  83. }
  84. } else {
  85. ctx.drawImage(image as any, 0, 0, canvas.width, canvas.height)
  86. }
  87. return canvas
  88. }
  89. export function textureToDataUrl(texture: Texture|DataTexture, maxWidth: number, flipY: boolean, mimeType?: string, quality?: number) {
  90. return textureToCanvas(texture, maxWidth, flipY).toDataURL(mimeType, quality)
  91. }