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