1+ import {
2+ BoxGeometry ,
3+ BufferAttribute ,
4+ DoubleSide ,
5+ Mesh ,
6+ PlaneGeometry ,
7+ ShaderMaterial ,
8+ Vector3 ,
9+ } from 'three' ;
10+ import { mergeGeometries } from '../utils/BufferGeometryUtils.js' ;
11+
12+ class TextureHelper extends Mesh {
13+
14+ constructor ( texture , width = 1 , height = 1 , depth = 1 ) {
15+
16+ const material = new ShaderMaterial ( {
17+
18+ type : 'TextureHelperMaterial' ,
19+
20+ side : DoubleSide ,
21+ transparent : true ,
22+
23+ uniforms : {
24+
25+ map : { value : texture } ,
26+ alpha : { value : getAlpha ( texture ) } ,
27+
28+ } ,
29+
30+ vertexShader : [
31+
32+ 'attribute vec3 uvw;' ,
33+
34+ 'varying vec3 vUvw;' ,
35+
36+ 'void main() {' ,
37+
38+ ' vUvw = uvw;' ,
39+
40+ ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );' ,
41+
42+ '}' ,
43+
44+ ] . join ( '\n' ) ,
45+
46+ fragmentShader : [
47+
48+ 'precision highp float;' ,
49+
50+ 'precision highp sampler2DArray;' ,
51+
52+ 'precision highp sampler3D;' ,
53+
54+ 'uniform {samplerType} map;' ,
55+
56+ 'uniform float alpha;' ,
57+
58+ 'varying vec3 vUvw;' ,
59+
60+ 'vec4 textureHelper( in sampler2D map ) { return texture( map, vUvw.xy ); }' ,
61+
62+ 'vec4 textureHelper( in sampler2DArray map ) { return texture( map, vUvw ); }' ,
63+
64+ 'vec4 textureHelper( in sampler3D map ) { return texture( map, vUvw ); }' ,
65+
66+ 'vec4 textureHelper( in samplerCube map ) { return texture( map, vUvw ); }' ,
67+
68+ 'void main() {' ,
69+
70+ ' gl_FragColor = linearToOutputTexel( vec4( textureHelper( map ).xyz, alpha ) );' ,
71+
72+ '}'
73+
74+ ] . join ( '\n' ) . replace ( '{samplerType}' , getSamplerType ( texture ) )
75+
76+ } ) ;
77+
78+ const geometry = texture . isCubeTexture
79+ ? createCubeGeometry ( width , height , depth )
80+ : createSliceGeometry ( texture , width , height , depth ) ;
81+
82+ super ( geometry , material ) ;
83+
84+ this . texture = texture ;
85+ this . type = 'TextureHelper' ;
86+
87+ }
88+
89+ dispose ( ) {
90+
91+ this . geometry . dispose ( ) ;
92+ this . material . dispose ( ) ;
93+
94+ }
95+
96+ }
97+
98+ function getSamplerType ( texture ) {
99+
100+ if ( texture . isCubeTexture ) {
101+
102+ return 'samplerCube' ;
103+
104+ } else if ( texture . isDataArrayTexture || texture . isCompressedArrayTexture ) {
105+
106+ return 'sampler2DArray' ;
107+
108+ } else if ( texture . isData3DTexture || texture . isCompressed3DTexture ) {
109+
110+ return 'sampler3D' ;
111+
112+ } else {
113+
114+ return 'sampler2D' ;
115+
116+ }
117+
118+ }
119+
120+ function getImageCount ( texture ) {
121+
122+ if ( texture . isCubeTexture ) {
123+
124+ return 6 ;
125+
126+ } else if ( texture . isDataArrayTexture || texture . isCompressedArrayTexture ) {
127+
128+ return texture . image . depth ;
129+
130+ } else if ( texture . isData3DTexture || texture . isCompressed3DTexture ) {
131+
132+ return texture . image . depth ;
133+
134+ } else {
135+
136+ return 1 ;
137+
138+ }
139+
140+ }
141+
142+ function getAlpha ( texture ) {
143+
144+ if ( texture . isCubeTexture ) {
145+
146+ return 1 ;
147+
148+ } else if ( texture . isDataArrayTexture || texture . isCompressedArrayTexture ) {
149+
150+ return Math . max ( 1 / texture . image . depth , 0.25 ) ;
151+
152+ } else if ( texture . isData3DTexture || texture . isCompressed3DTexture ) {
153+
154+ return Math . max ( 1 / texture . image . depth , 0.25 ) ;
155+
156+ } else {
157+
158+ return 1 ;
159+
160+ }
161+
162+ }
163+
164+ function createCubeGeometry ( width , height , depth ) {
165+
166+ const geometry = new BoxGeometry ( width , height , depth ) ;
167+
168+ const position = geometry . attributes . position ;
169+ const uv = geometry . attributes . uv ;
170+ const uvw = new BufferAttribute ( new Float32Array ( uv . count * 3 ) , 3 ) ;
171+
172+ const _direction = new Vector3 ( ) ;
173+
174+ for ( let j = 0 , jl = uv . count ; j < jl ; ++ j ) {
175+
176+ _direction . fromBufferAttribute ( position , j ) . normalize ( ) ;
177+
178+ const u = _direction . x ;
179+ const v = _direction . y ;
180+ const w = _direction . z ;
181+
182+ uvw . setXYZ ( j , u , v , w ) ;
183+
184+ }
185+
186+ geometry . deleteAttribute ( 'uv' ) ;
187+ geometry . setAttribute ( 'uvw' , uvw ) ;
188+
189+ return geometry ;
190+
191+ }
192+
193+ function createSliceGeometry ( texture , width , height , depth ) {
194+
195+ const sliceCount = getImageCount ( texture ) ;
196+
197+ const geometries = [ ] ;
198+
199+ for ( let i = 0 ; i < sliceCount ; ++ i ) {
200+
201+ const geometry = new PlaneGeometry ( width , height ) ;
202+
203+ if ( sliceCount > 1 ) {
204+
205+ geometry . translate ( 0 , 0 , depth * ( i / ( sliceCount - 1 ) - 0.5 ) ) ;
206+
207+ }
208+
209+ const uv = geometry . attributes . uv ;
210+ const uvw = new BufferAttribute ( new Float32Array ( uv . count * 3 ) , 3 ) ;
211+
212+ for ( let j = 0 , jl = uv . count ; j < jl ; ++ j ) {
213+
214+ const u = uv . getX ( j ) ;
215+ const v = texture . flipY ? uv . getY ( j ) : 1 - uv . getY ( j ) ;
216+ const w = sliceCount === 1
217+ ? 1
218+ : texture . isDataArrayTexture || texture . isCompressedArrayTexture
219+ ? i
220+ : i / ( sliceCount - 1 ) ;
221+
222+ uvw . setXYZ ( j , u , v , w ) ;
223+
224+ }
225+
226+ geometry . deleteAttribute ( 'uv' ) ;
227+ geometry . setAttribute ( 'uvw' , uvw ) ;
228+
229+ geometries . push ( geometry ) ;
230+
231+ }
232+
233+ return mergeGeometries ( geometries ) ;
234+
235+ }
236+
237+ export { TextureHelper } ;
0 commit comments