Skip to content

Commit ec09a96

Browse files
authored
Add TextureHelper (mrdoob#27151)
1 parent bf7d99e commit ec09a96

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

examples/jsm/Addons.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export * from './helpers/LightProbeHelper.js';
6060
export * from './helpers/OctreeHelper.js';
6161
export * from './helpers/PositionalAudioHelper.js';
6262
export * from './helpers/RectAreaLightHelper.js';
63+
export * from './helpers/TextureHelper.js';
6364
export * from './helpers/VertexNormalsHelper.js';
6465
export * from './helpers/VertexTangentsHelper.js';
6566
export * from './helpers/ViewHelper.js';

examples/jsm/helpers/TextureHelper.js

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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

Comments
 (0)