forked from mrdoob/three.js
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c767592
commit 7b39d56
Showing
2 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
import { | ||
BoxGeometry, | ||
BufferAttribute, | ||
DoubleSide, | ||
Mesh, | ||
PlaneGeometry, | ||
ShaderMaterial, | ||
Vector3, | ||
} from 'three'; | ||
import { mergeGeometries } from '../utils/BufferGeometryUtils.js'; | ||
|
||
class TextureHelper extends Mesh { | ||
|
||
constructor( texture, width = 1, height = 1, depth = 1 ) { | ||
|
||
const material = new ShaderMaterial( { | ||
|
||
type: 'TextureHelperMaterial', | ||
|
||
side: DoubleSide, | ||
transparent: true, | ||
|
||
uniforms: { | ||
|
||
map: { value: texture }, | ||
alpha: { value: getAlpha( texture ) }, | ||
|
||
}, | ||
|
||
vertexShader: [ | ||
|
||
'attribute vec3 uvw;', | ||
|
||
'varying vec3 vUvw;', | ||
|
||
'void main() {', | ||
|
||
' vUvw = uvw;', | ||
|
||
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', | ||
|
||
'}', | ||
|
||
].join( '\n' ), | ||
|
||
fragmentShader: [ | ||
|
||
'precision highp float;', | ||
|
||
'precision highp sampler2DArray;', | ||
|
||
'precision highp sampler3D;', | ||
|
||
'uniform {samplerType} map;', | ||
|
||
'uniform float alpha;', | ||
|
||
'varying vec3 vUvw;', | ||
|
||
'vec4 textureHelper( in sampler2D map ) { return texture( map, vUvw.xy ); }', | ||
|
||
'vec4 textureHelper( in sampler2DArray map ) { return texture( map, vUvw ); }', | ||
|
||
'vec4 textureHelper( in sampler3D map ) { return texture( map, vUvw ); }', | ||
|
||
'vec4 textureHelper( in samplerCube map ) { return texture( map, vUvw ); }', | ||
|
||
'void main() {', | ||
|
||
' gl_FragColor = linearToOutputTexel( vec4( textureHelper( map ).xyz, alpha ) );', | ||
|
||
'}' | ||
|
||
].join( '\n' ).replace( '{samplerType}', getSamplerType( texture ) ) | ||
|
||
} ); | ||
|
||
const geometry = texture.isCubeTexture | ||
? createCubeGeometry( width, height, depth ) | ||
: createSliceGeometry( texture, width, height, depth ); | ||
|
||
super( geometry, material ); | ||
|
||
this.texture = texture; | ||
this.type = 'TextureHelper'; | ||
|
||
} | ||
|
||
dispose() { | ||
|
||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
|
||
} | ||
|
||
} | ||
|
||
function getSamplerType( texture ) { | ||
|
||
if ( texture.isCubeTexture ) { | ||
|
||
return 'samplerCube'; | ||
|
||
} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { | ||
|
||
return 'sampler2DArray'; | ||
|
||
} else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) { | ||
|
||
return 'sampler3D'; | ||
|
||
} else { | ||
|
||
return 'sampler2D'; | ||
|
||
} | ||
|
||
} | ||
|
||
function getImageCount( texture ) { | ||
|
||
if ( texture.isCubeTexture ) { | ||
|
||
return 6; | ||
|
||
} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { | ||
|
||
return texture.image.depth; | ||
|
||
} else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) { | ||
|
||
return texture.image.depth; | ||
|
||
} else { | ||
|
||
return 1; | ||
|
||
} | ||
|
||
} | ||
|
||
function getAlpha( texture ) { | ||
|
||
if ( texture.isCubeTexture ) { | ||
|
||
return 1; | ||
|
||
} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { | ||
|
||
return Math.max( 1 / texture.image.depth, 0.25 ); | ||
|
||
} else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) { | ||
|
||
return Math.max( 1 / texture.image.depth, 0.25 ); | ||
|
||
} else { | ||
|
||
return 1; | ||
|
||
} | ||
|
||
} | ||
|
||
function createCubeGeometry( width, height, depth ) { | ||
|
||
const geometry = new BoxGeometry( width, height, depth ); | ||
|
||
const position = geometry.attributes.position; | ||
const uv = geometry.attributes.uv; | ||
const uvw = new BufferAttribute( new Float32Array( uv.count * 3 ), 3 ); | ||
|
||
const _direction = new Vector3(); | ||
|
||
for ( let j = 0, jl = uv.count; j < jl; ++ j ) { | ||
|
||
_direction.fromBufferAttribute( position, j ).normalize(); | ||
|
||
const u = _direction.x; | ||
const v = _direction.y; | ||
const w = _direction.z; | ||
|
||
uvw.setXYZ( j, u, v, w ); | ||
|
||
} | ||
|
||
geometry.deleteAttribute( 'uv' ); | ||
geometry.setAttribute( 'uvw', uvw ); | ||
|
||
return geometry; | ||
|
||
} | ||
|
||
function createSliceGeometry( texture, width, height, depth ) { | ||
|
||
const sliceCount = getImageCount( texture ); | ||
|
||
const geometries = []; | ||
|
||
for ( let i = 0; i < sliceCount; ++ i ) { | ||
|
||
const geometry = new PlaneGeometry( width, height ); | ||
|
||
if ( sliceCount > 1 ) { | ||
|
||
geometry.translate( 0, 0, depth * ( i / ( sliceCount - 1 ) - 0.5 ) ); | ||
|
||
} | ||
|
||
const uv = geometry.attributes.uv; | ||
const uvw = new BufferAttribute( new Float32Array( uv.count * 3 ), 3 ); | ||
|
||
for ( let j = 0, jl = uv.count; j < jl; ++ j ) { | ||
|
||
const u = uv.getX( j ); | ||
const v = texture.flipY ? uv.getY( j ) : 1 - uv.getY( j ); | ||
const w = sliceCount === 1 | ||
? 1 | ||
: texture.isDataArrayTexture || texture.isCompressedArrayTexture | ||
? i | ||
: i / ( sliceCount - 1 ); | ||
|
||
uvw.setXYZ( j, u, v, w ); | ||
|
||
} | ||
|
||
geometry.deleteAttribute( 'uv' ); | ||
geometry.setAttribute( 'uvw', uvw ); | ||
|
||
geometries.push( geometry ); | ||
|
||
} | ||
|
||
return mergeGeometries( geometries ); | ||
|
||
} | ||
|
||
export { TextureHelper }; |