TextureHelperGPU.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import {
  2. NodeMaterial,
  3. BoxGeometry,
  4. BufferAttribute,
  5. Mesh,
  6. PlaneGeometry,
  7. DoubleSide,
  8. Vector3,
  9. } from 'three';
  10. import { texture as textureNode, cubeTexture, texture3D, float, vec4, attribute } from 'three/tsl';
  11. import { mergeGeometries } from '../utils/BufferGeometryUtils.js';
  12. class TextureHelper extends Mesh {
  13. constructor( texture, width = 1, height = 1, depth = 1 ) {
  14. const material = new NodeMaterial();
  15. material.side = DoubleSide;
  16. material.transparent = true;
  17. material.name = 'TextureHelper';
  18. let colorNode;
  19. const uvw = attribute( 'uvw' );
  20. if ( texture.isCubeTexture ) {
  21. colorNode = cubeTexture( texture ).sample( uvw );
  22. } else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) {
  23. colorNode = texture3D( texture ).sample( uvw );
  24. } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
  25. colorNode = textureNode( texture ).sample( uvw.xy ).depth( uvw.z );
  26. } else {
  27. colorNode = textureNode( texture );
  28. }
  29. const alphaNode = float( getAlpha( texture ) );
  30. material.colorNode = vec4( colorNode.rgb, alphaNode );
  31. const geometry = texture.isCubeTexture
  32. ? createCubeGeometry( width, height, depth )
  33. : createSliceGeometry( texture, width, height, depth );
  34. super( geometry, material );
  35. this.texture = texture;
  36. this.type = 'TextureHelper';
  37. }
  38. dispose() {
  39. this.geometry.dispose();
  40. this.material.dispose();
  41. }
  42. }
  43. function getImageCount( texture ) {
  44. if ( texture.isCubeTexture ) {
  45. return 6;
  46. } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
  47. return texture.image.depth;
  48. } else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) {
  49. return texture.image.depth;
  50. } else {
  51. return 1;
  52. }
  53. }
  54. function getAlpha( texture ) {
  55. if ( texture.isCubeTexture ) {
  56. return 1;
  57. } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
  58. return Math.max( 1 / texture.image.depth, 0.25 );
  59. } else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) {
  60. return Math.max( 1 / texture.image.depth, 0.25 );
  61. } else {
  62. return 1;
  63. }
  64. }
  65. function createCubeGeometry( width, height, depth ) {
  66. const geometry = new BoxGeometry( width, height, depth );
  67. const position = geometry.attributes.position;
  68. const uv = geometry.attributes.uv;
  69. const uvw = new BufferAttribute( new Float32Array( uv.count * 3 ), 3 );
  70. const _direction = new Vector3();
  71. for ( let j = 0, jl = uv.count; j < jl; ++ j ) {
  72. _direction.fromBufferAttribute( position, j ).normalize();
  73. const u = _direction.x;
  74. const v = _direction.y;
  75. const w = _direction.z;
  76. uvw.setXYZ( j, u, v, w );
  77. }
  78. geometry.deleteAttribute( 'uv' );
  79. geometry.setAttribute( 'uvw', uvw );
  80. return geometry;
  81. }
  82. function createSliceGeometry( texture, width, height, depth ) {
  83. const sliceCount = getImageCount( texture );
  84. const geometries = [];
  85. for ( let i = 0; i < sliceCount; ++ i ) {
  86. const geometry = new PlaneGeometry( width, height );
  87. if ( sliceCount > 1 ) {
  88. geometry.translate( 0, 0, depth * ( i / ( sliceCount - 1 ) - 0.5 ) );
  89. }
  90. const uv = geometry.attributes.uv;
  91. const uvw = new BufferAttribute( new Float32Array( uv.count * 3 ), 3 );
  92. for ( let j = 0, jl = uv.count; j < jl; ++ j ) {
  93. const u = uv.getX( j );
  94. const v = texture.flipY ? uv.getY( j ) : 1 - uv.getY( j );
  95. const w = sliceCount === 1
  96. ? 1
  97. : texture.isDataArrayTexture || texture.isCompressedArrayTexture
  98. ? i
  99. : i / ( sliceCount - 1 );
  100. uvw.setXYZ( j, u, v, w );
  101. }
  102. geometry.deleteAttribute( 'uv' );
  103. geometry.setAttribute( 'uvw', uvw );
  104. geometries.push( geometry );
  105. }
  106. return mergeGeometries( geometries );
  107. }
  108. export { TextureHelper };
粤ICP备19079148号