Initial commit
This commit is contained in:
347
HTML/ThreeJS/node_modules/three/examples/js/objects/Lensflare.js
generated
vendored
Normal file
347
HTML/ThreeJS/node_modules/three/examples/js/objects/Lensflare.js
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
( function () {
|
||||
|
||||
class Lensflare extends THREE.Mesh {
|
||||
|
||||
constructor() {
|
||||
|
||||
super( Lensflare.Geometry, new THREE.MeshBasicMaterial( {
|
||||
opacity: 0,
|
||||
transparent: true
|
||||
} ) );
|
||||
this.type = 'Lensflare';
|
||||
this.frustumCulled = false;
|
||||
this.renderOrder = Infinity; //
|
||||
|
||||
const positionScreen = new THREE.Vector3();
|
||||
const positionView = new THREE.Vector3(); // textures
|
||||
|
||||
const tempMap = new THREE.FramebufferTexture( 16, 16, THREE.RGBAFormat );
|
||||
const occlusionMap = new THREE.FramebufferTexture( 16, 16, THREE.RGBAFormat ); // material
|
||||
|
||||
const geometry = Lensflare.Geometry;
|
||||
const material1a = new THREE.RawShaderMaterial( {
|
||||
uniforms: {
|
||||
'scale': {
|
||||
value: null
|
||||
},
|
||||
'screenPosition': {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec3 screenPosition;
|
||||
uniform vec2 scale;
|
||||
|
||||
attribute vec3 position;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );
|
||||
|
||||
}`,
|
||||
depthTest: true,
|
||||
depthWrite: false,
|
||||
transparent: false
|
||||
} );
|
||||
const material1b = new THREE.RawShaderMaterial( {
|
||||
uniforms: {
|
||||
'map': {
|
||||
value: tempMap
|
||||
},
|
||||
'scale': {
|
||||
value: null
|
||||
},
|
||||
'screenPosition': {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec3 screenPosition;
|
||||
uniform vec2 scale;
|
||||
|
||||
attribute vec3 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUV;
|
||||
|
||||
void main() {
|
||||
|
||||
vUV = uv;
|
||||
|
||||
gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D map;
|
||||
|
||||
varying vec2 vUV;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_FragColor = texture2D( map, vUV );
|
||||
|
||||
}`,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
transparent: false
|
||||
} ); // the following object is used for occlusionMap generation
|
||||
|
||||
const mesh1 = new THREE.Mesh( geometry, material1a ); //
|
||||
|
||||
const elements = [];
|
||||
const shader = LensflareElement.Shader;
|
||||
const material2 = new THREE.RawShaderMaterial( {
|
||||
uniforms: {
|
||||
'map': {
|
||||
value: null
|
||||
},
|
||||
'occlusionMap': {
|
||||
value: occlusionMap
|
||||
},
|
||||
'color': {
|
||||
value: new THREE.Color( 0xffffff )
|
||||
},
|
||||
'scale': {
|
||||
value: new THREE.Vector2()
|
||||
},
|
||||
'screenPosition': {
|
||||
value: new THREE.Vector3()
|
||||
}
|
||||
},
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader,
|
||||
blending: THREE.AdditiveBlending,
|
||||
transparent: true,
|
||||
depthWrite: false
|
||||
} );
|
||||
const mesh2 = new THREE.Mesh( geometry, material2 );
|
||||
|
||||
this.addElement = function ( element ) {
|
||||
|
||||
elements.push( element );
|
||||
|
||||
}; //
|
||||
|
||||
|
||||
const scale = new THREE.Vector2();
|
||||
const screenPositionPixels = new THREE.Vector2();
|
||||
const validArea = new THREE.Box2();
|
||||
const viewport = new THREE.Vector4();
|
||||
|
||||
this.onBeforeRender = function ( renderer, scene, camera ) {
|
||||
|
||||
renderer.getCurrentViewport( viewport );
|
||||
const invAspect = viewport.w / viewport.z;
|
||||
const halfViewportWidth = viewport.z / 2.0;
|
||||
const halfViewportHeight = viewport.w / 2.0;
|
||||
let size = 16 / viewport.w;
|
||||
scale.set( size * invAspect, size );
|
||||
validArea.min.set( viewport.x, viewport.y );
|
||||
validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); // calculate position in screen space
|
||||
|
||||
positionView.setFromMatrixPosition( this.matrixWorld );
|
||||
positionView.applyMatrix4( camera.matrixWorldInverse );
|
||||
if ( positionView.z > 0 ) return; // lensflare is behind the camera
|
||||
|
||||
positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); // horizontal and vertical coordinate of the lower left corner of the pixels to copy
|
||||
|
||||
screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8;
|
||||
screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; // screen cull
|
||||
|
||||
if ( validArea.containsPoint( screenPositionPixels ) ) {
|
||||
|
||||
// save current RGB to temp texture
|
||||
renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); // render pink quad
|
||||
|
||||
let uniforms = material1a.uniforms;
|
||||
uniforms[ 'scale' ].value = scale;
|
||||
uniforms[ 'screenPosition' ].value = positionScreen;
|
||||
renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); // copy result to occlusionMap
|
||||
|
||||
renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); // restore graphics
|
||||
|
||||
uniforms = material1b.uniforms;
|
||||
uniforms[ 'scale' ].value = scale;
|
||||
uniforms[ 'screenPosition' ].value = positionScreen;
|
||||
renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); // render elements
|
||||
|
||||
const vecX = - positionScreen.x * 2;
|
||||
const vecY = - positionScreen.y * 2;
|
||||
|
||||
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
||||
|
||||
const element = elements[ i ];
|
||||
const uniforms = material2.uniforms;
|
||||
uniforms[ 'color' ].value.copy( element.color );
|
||||
uniforms[ 'map' ].value = element.texture;
|
||||
uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
|
||||
uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
|
||||
size = element.size / viewport.w;
|
||||
const invAspect = viewport.w / viewport.z;
|
||||
uniforms[ 'scale' ].value.set( size * invAspect, size );
|
||||
material2.uniformsNeedUpdate = true;
|
||||
renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.dispose = function () {
|
||||
|
||||
material1a.dispose();
|
||||
material1b.dispose();
|
||||
material2.dispose();
|
||||
tempMap.dispose();
|
||||
occlusionMap.dispose();
|
||||
|
||||
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
||||
|
||||
elements[ i ].texture.dispose();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Lensflare.prototype.isLensflare = true; //
|
||||
|
||||
class LensflareElement {
|
||||
|
||||
constructor( texture, size = 1, distance = 0, color = new THREE.Color( 0xffffff ) ) {
|
||||
|
||||
this.texture = texture;
|
||||
this.size = size;
|
||||
this.distance = distance;
|
||||
this.color = color;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LensflareElement.Shader = {
|
||||
uniforms: {
|
||||
'map': {
|
||||
value: null
|
||||
},
|
||||
'occlusionMap': {
|
||||
value: null
|
||||
},
|
||||
'color': {
|
||||
value: null
|
||||
},
|
||||
'scale': {
|
||||
value: null
|
||||
},
|
||||
'screenPosition': {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec3 screenPosition;
|
||||
uniform vec2 scale;
|
||||
|
||||
uniform sampler2D occlusionMap;
|
||||
|
||||
attribute vec3 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUV;
|
||||
varying float vVisibility;
|
||||
|
||||
void main() {
|
||||
|
||||
vUV = uv;
|
||||
|
||||
vec2 pos = position.xy;
|
||||
|
||||
vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );
|
||||
visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );
|
||||
|
||||
vVisibility = visibility.r / 9.0;
|
||||
vVisibility *= 1.0 - visibility.g / 9.0;
|
||||
vVisibility *= visibility.b / 9.0;
|
||||
|
||||
gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D map;
|
||||
uniform vec3 color;
|
||||
|
||||
varying vec2 vUV;
|
||||
varying float vVisibility;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 texture = texture2D( map, vUV );
|
||||
texture.a *= vVisibility;
|
||||
gl_FragColor = texture;
|
||||
gl_FragColor.rgb *= color;
|
||||
|
||||
}`
|
||||
};
|
||||
|
||||
Lensflare.Geometry = function () {
|
||||
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
const float32Array = new Float32Array( [ - 1, - 1, 0, 0, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1 ] );
|
||||
const interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );
|
||||
geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
|
||||
geometry.setAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
|
||||
geometry.setAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
|
||||
return geometry;
|
||||
|
||||
}();
|
||||
|
||||
THREE.Lensflare = Lensflare;
|
||||
THREE.LensflareElement = LensflareElement;
|
||||
|
||||
} )();
|
||||
210
HTML/ThreeJS/node_modules/three/examples/js/objects/LightningStorm.js
generated
vendored
Normal file
210
HTML/ThreeJS/node_modules/three/examples/js/objects/LightningStorm.js
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
( function () {
|
||||
|
||||
/**
|
||||
* @fileoverview Lightning strike object generator
|
||||
*
|
||||
*
|
||||
* Usage
|
||||
*
|
||||
* const myStorm = new LightningStorm( paramsObject );
|
||||
* myStorm.position.set( ... );
|
||||
* scene.add( myStorm );
|
||||
* ...
|
||||
* myStorm.update( currentTime );
|
||||
*
|
||||
* The "currentTime" can only go forwards or be stopped.
|
||||
*
|
||||
*
|
||||
* LightningStorm parameters:
|
||||
*
|
||||
* @param {double} size Size of the storm. If no 'onRayPosition' parameter is defined, it means the side of the rectangle the storm covers.
|
||||
*
|
||||
* @param {double} minHeight Minimum height a ray can start at. If no 'onRayPosition' parameter is defined, it means the height above plane y = 0.
|
||||
*
|
||||
* @param {double} maxHeight Maximum height a ray can start at. If no 'onRayPosition' parameter is defined, it means the height above plane y = 0.
|
||||
*
|
||||
* @param {double} maxSlope The maximum inclination slope of a ray. If no 'onRayPosition' parameter is defined, it means the slope relative to plane y = 0.
|
||||
*
|
||||
* @param {integer} maxLightnings Greater than 0. The maximum number of simultaneous rays.
|
||||
*
|
||||
* @param {double} lightningMinPeriod minimum time between two consecutive rays.
|
||||
*
|
||||
* @param {double} lightningMaxPeriod maximum time between two consecutive rays.
|
||||
*
|
||||
* @param {double} lightningMinDuration The minimum time a ray can last.
|
||||
*
|
||||
* @param {double} lightningMaxDuration The maximum time a ray can last.
|
||||
*
|
||||
* @param {Object} lightningParameters The parameters for created rays. See THREE.LightningStrike (geometry)
|
||||
*
|
||||
* @param {Material} lightningMaterial The THREE.Material used for the created rays.
|
||||
*
|
||||
* @param {function} onRayPosition Optional callback with two Vector3 parameters (source, dest). You can set here the start and end points for each created ray, using the standard size, minHeight, etc parameters and other values in your algorithm.
|
||||
*
|
||||
* @param {function} onLightningDown This optional callback is called with one parameter (lightningStrike) when a ray ends propagating, so it has hit the ground.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class LightningStorm extends THREE.Object3D {
|
||||
|
||||
constructor( stormParams = {} ) {
|
||||
|
||||
super(); // Parameters
|
||||
|
||||
this.stormParams = stormParams;
|
||||
stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0;
|
||||
stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0;
|
||||
stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0;
|
||||
stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1;
|
||||
stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3;
|
||||
stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0;
|
||||
stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0;
|
||||
stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0;
|
||||
stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5;
|
||||
this.lightningParameters = THREE.LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters );
|
||||
this.lightningParameters.isEternal = false;
|
||||
this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new THREE.MeshBasicMaterial( {
|
||||
color: 0xB0FFFF
|
||||
} );
|
||||
|
||||
if ( stormParams.onRayPosition !== undefined ) {
|
||||
|
||||
this.onRayPosition = stormParams.onRayPosition;
|
||||
|
||||
} else {
|
||||
|
||||
this.onRayPosition = function ( source, dest ) {
|
||||
|
||||
dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size );
|
||||
const height = THREE.MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() );
|
||||
source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this.onLightningDown = stormParams.onLightningDown; // Internal state
|
||||
|
||||
this.inited = false;
|
||||
this.nextLightningTime = 0;
|
||||
this.lightningsMeshes = [];
|
||||
this.deadLightningsMeshes = [];
|
||||
|
||||
for ( let i = 0; i < this.stormParams.maxLightnings; i ++ ) {
|
||||
|
||||
const lightning = new THREE.LightningStrike( THREE.LightningStrike.copyParameters( {}, this.lightningParameters ) );
|
||||
const mesh = new THREE.Mesh( lightning, this.lightningMaterial );
|
||||
this.deadLightningsMeshes.push( mesh );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
update( time ) {
|
||||
|
||||
if ( ! this.inited ) {
|
||||
|
||||
this.nextLightningTime = this.getNextLightningTime( time ) * Math.random();
|
||||
this.inited = true;
|
||||
|
||||
}
|
||||
|
||||
if ( time >= this.nextLightningTime ) {
|
||||
|
||||
// Lightning creation
|
||||
const lightningMesh = this.deadLightningsMeshes.pop();
|
||||
|
||||
if ( lightningMesh ) {
|
||||
|
||||
const lightningParams1 = THREE.LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters );
|
||||
lightningParams1.birthTime = time;
|
||||
lightningParams1.deathTime = time + THREE.MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() );
|
||||
this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset );
|
||||
lightningParams1.noiseSeed = Math.random();
|
||||
this.add( lightningMesh );
|
||||
this.lightningsMeshes.push( lightningMesh );
|
||||
|
||||
} // Schedule next lightning
|
||||
|
||||
|
||||
this.nextLightningTime = this.getNextLightningTime( time );
|
||||
|
||||
}
|
||||
|
||||
let i = 0,
|
||||
il = this.lightningsMeshes.length;
|
||||
|
||||
while ( i < il ) {
|
||||
|
||||
const mesh = this.lightningsMeshes[ i ];
|
||||
const lightning = mesh.geometry;
|
||||
const prevState = lightning.state;
|
||||
lightning.update( time );
|
||||
|
||||
if ( prevState === THREE.LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) {
|
||||
|
||||
if ( this.onLightningDown ) {
|
||||
|
||||
this.onLightningDown( lightning );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( lightning.state === THREE.LightningStrike.RAY_EXTINGUISHED ) {
|
||||
|
||||
// Lightning is to be destroyed
|
||||
this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 );
|
||||
this.deadLightningsMeshes.push( mesh );
|
||||
this.remove( mesh );
|
||||
il --;
|
||||
|
||||
} else {
|
||||
|
||||
i ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getNextLightningTime( currentTime ) {
|
||||
|
||||
return currentTime + THREE.MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
super.copy( source );
|
||||
this.stormParams.size = source.stormParams.size;
|
||||
this.stormParams.minHeight = source.stormParams.minHeight;
|
||||
this.stormParams.maxHeight = source.stormParams.maxHeight;
|
||||
this.stormParams.maxSlope = source.stormParams.maxSlope;
|
||||
this.stormParams.maxLightnings = source.stormParams.maxLightnings;
|
||||
this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod;
|
||||
this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod;
|
||||
this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration;
|
||||
this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration;
|
||||
this.lightningParameters = THREE.LightningStrike.copyParameters( {}, source.lightningParameters );
|
||||
this.lightningMaterial = source.stormParams.lightningMaterial;
|
||||
this.onLightningDown = source.onLightningDown;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor( this.stormParams ).copy( this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LightningStorm.prototype.isLightningStorm = true;
|
||||
|
||||
THREE.LightningStorm = LightningStorm;
|
||||
|
||||
} )();
|
||||
743
HTML/ThreeJS/node_modules/three/examples/js/objects/MarchingCubes.js
generated
vendored
Normal file
743
HTML/ThreeJS/node_modules/three/examples/js/objects/MarchingCubes.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
204
HTML/ThreeJS/node_modules/three/examples/js/objects/Reflector.js
generated
vendored
Normal file
204
HTML/ThreeJS/node_modules/three/examples/js/objects/Reflector.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
( function () {
|
||||
|
||||
class Reflector extends THREE.Mesh {
|
||||
|
||||
constructor( geometry, options = {} ) {
|
||||
|
||||
super( geometry );
|
||||
this.type = 'Reflector';
|
||||
const scope = this;
|
||||
const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
|
||||
const textureWidth = options.textureWidth || 512;
|
||||
const textureHeight = options.textureHeight || 512;
|
||||
const clipBias = options.clipBias || 0;
|
||||
const shader = options.shader || Reflector.ReflectorShader;
|
||||
const multisample = options.multisample !== undefined ? options.multisample : 4; //
|
||||
|
||||
const reflectorPlane = new THREE.Plane();
|
||||
const normal = new THREE.Vector3();
|
||||
const reflectorWorldPosition = new THREE.Vector3();
|
||||
const cameraWorldPosition = new THREE.Vector3();
|
||||
const rotationMatrix = new THREE.Matrix4();
|
||||
const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
|
||||
const clipPlane = new THREE.Vector4();
|
||||
const view = new THREE.Vector3();
|
||||
const target = new THREE.Vector3();
|
||||
const q = new THREE.Vector4();
|
||||
const textureMatrix = new THREE.Matrix4();
|
||||
const virtualCamera = new THREE.PerspectiveCamera();
|
||||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, {
|
||||
samples: multisample
|
||||
} );
|
||||
const material = new THREE.ShaderMaterial( {
|
||||
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
||||
fragmentShader: shader.fragmentShader,
|
||||
vertexShader: shader.vertexShader
|
||||
} );
|
||||
material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
|
||||
material.uniforms[ 'color' ].value = color;
|
||||
material.uniforms[ 'textureMatrix' ].value = textureMatrix;
|
||||
this.material = material;
|
||||
|
||||
this.onBeforeRender = function ( renderer, scene, camera ) {
|
||||
|
||||
reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
|
||||
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
|
||||
rotationMatrix.extractRotation( scope.matrixWorld );
|
||||
normal.set( 0, 0, 1 );
|
||||
normal.applyMatrix4( rotationMatrix );
|
||||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
|
||||
|
||||
if ( view.dot( normal ) > 0 ) return;
|
||||
view.reflect( normal ).negate();
|
||||
view.add( reflectorWorldPosition );
|
||||
rotationMatrix.extractRotation( camera.matrixWorld );
|
||||
lookAtPosition.set( 0, 0, - 1 );
|
||||
lookAtPosition.applyMatrix4( rotationMatrix );
|
||||
lookAtPosition.add( cameraWorldPosition );
|
||||
target.subVectors( reflectorWorldPosition, lookAtPosition );
|
||||
target.reflect( normal ).negate();
|
||||
target.add( reflectorWorldPosition );
|
||||
virtualCamera.position.copy( view );
|
||||
virtualCamera.up.set( 0, 1, 0 );
|
||||
virtualCamera.up.applyMatrix4( rotationMatrix );
|
||||
virtualCamera.up.reflect( normal );
|
||||
virtualCamera.lookAt( target );
|
||||
virtualCamera.far = camera.far; // Used in WebGLBackground
|
||||
|
||||
virtualCamera.updateMatrixWorld();
|
||||
virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix
|
||||
|
||||
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
|
||||
textureMatrix.multiply( virtualCamera.projectionMatrix );
|
||||
textureMatrix.multiply( virtualCamera.matrixWorldInverse );
|
||||
textureMatrix.multiply( scope.matrixWorld ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
|
||||
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
|
||||
|
||||
reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
|
||||
reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
|
||||
clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
|
||||
const projectionMatrix = virtualCamera.projectionMatrix;
|
||||
q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
|
||||
q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
|
||||
q.z = - 1.0;
|
||||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector
|
||||
|
||||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix
|
||||
|
||||
projectionMatrix.elements[ 2 ] = clipPlane.x;
|
||||
projectionMatrix.elements[ 6 ] = clipPlane.y;
|
||||
projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
|
||||
projectionMatrix.elements[ 14 ] = clipPlane.w; // Render
|
||||
|
||||
renderTarget.texture.encoding = renderer.outputEncoding;
|
||||
scope.visible = false;
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentXrEnabled = renderer.xr.enabled;
|
||||
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
||||
renderer.xr.enabled = false; // Avoid camera modification
|
||||
|
||||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
|
||||
|
||||
if ( renderer.autoClear === false ) renderer.clear();
|
||||
renderer.render( scene, virtualCamera );
|
||||
renderer.xr.enabled = currentXrEnabled;
|
||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
||||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
|
||||
|
||||
const viewport = camera.viewport;
|
||||
|
||||
if ( viewport !== undefined ) {
|
||||
|
||||
renderer.state.viewport( viewport );
|
||||
|
||||
}
|
||||
|
||||
scope.visible = true;
|
||||
|
||||
};
|
||||
|
||||
this.getRenderTarget = function () {
|
||||
|
||||
return renderTarget;
|
||||
|
||||
};
|
||||
|
||||
this.dispose = function () {
|
||||
|
||||
renderTarget.dispose();
|
||||
scope.material.dispose();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reflector.prototype.isReflector = true;
|
||||
Reflector.ReflectorShader = {
|
||||
uniforms: {
|
||||
'color': {
|
||||
value: null
|
||||
},
|
||||
'tDiffuse': {
|
||||
value: null
|
||||
},
|
||||
'textureMatrix': {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform mat4 textureMatrix;
|
||||
varying vec4 vUv;
|
||||
|
||||
#include <common>
|
||||
#include <logdepthbuf_pars_vertex>
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = textureMatrix * vec4( position, 1.0 );
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
#include <logdepthbuf_vertex>
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform vec3 color;
|
||||
uniform sampler2D tDiffuse;
|
||||
varying vec4 vUv;
|
||||
|
||||
#include <logdepthbuf_pars_fragment>
|
||||
|
||||
float blendOverlay( float base, float blend ) {
|
||||
|
||||
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
|
||||
|
||||
}
|
||||
|
||||
vec3 blendOverlay( vec3 base, vec3 blend ) {
|
||||
|
||||
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
#include <logdepthbuf_fragment>
|
||||
|
||||
vec4 base = texture2DProj( tDiffuse, vUv );
|
||||
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
|
||||
|
||||
}`
|
||||
};
|
||||
|
||||
THREE.Reflector = Reflector;
|
||||
|
||||
} )();
|
||||
320
HTML/ThreeJS/node_modules/three/examples/js/objects/ReflectorForSSRPass.js
generated
vendored
Normal file
320
HTML/ThreeJS/node_modules/three/examples/js/objects/ReflectorForSSRPass.js
generated
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
( function () {
|
||||
|
||||
class ReflectorForSSRPass extends THREE.Mesh {
|
||||
|
||||
constructor( geometry, options = {} ) {
|
||||
|
||||
super( geometry );
|
||||
this.type = 'ReflectorForSSRPass';
|
||||
const scope = this;
|
||||
const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
|
||||
const textureWidth = options.textureWidth || 512;
|
||||
const textureHeight = options.textureHeight || 512;
|
||||
const clipBias = options.clipBias || 0;
|
||||
const shader = options.shader || ReflectorForSSRPass.ReflectorShader;
|
||||
const useDepthTexture = options.useDepthTexture === true;
|
||||
const yAxis = new THREE.Vector3( 0, 1, 0 );
|
||||
const vecTemp0 = new THREE.Vector3();
|
||||
const vecTemp1 = new THREE.Vector3(); //
|
||||
|
||||
scope.needsUpdate = false;
|
||||
scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value;
|
||||
scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value;
|
||||
scope.color = color;
|
||||
scope.resolution = options.resolution || new THREE.Vector2( window.innerWidth, window.innerHeight );
|
||||
scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION;
|
||||
Object.defineProperty( scope, 'distanceAttenuation', {
|
||||
get() {
|
||||
|
||||
return scope._distanceAttenuation;
|
||||
|
||||
},
|
||||
|
||||
set( val ) {
|
||||
|
||||
if ( scope._distanceAttenuation === val ) return;
|
||||
scope._distanceAttenuation = val;
|
||||
scope.material.defines.DISTANCE_ATTENUATION = val;
|
||||
scope.material.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL;
|
||||
Object.defineProperty( scope, 'fresnel', {
|
||||
get() {
|
||||
|
||||
return scope._fresnel;
|
||||
|
||||
},
|
||||
|
||||
set( val ) {
|
||||
|
||||
if ( scope._fresnel === val ) return;
|
||||
scope._fresnel = val;
|
||||
scope.material.defines.FRESNEL = val;
|
||||
scope.material.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
const normal = new THREE.Vector3();
|
||||
const reflectorWorldPosition = new THREE.Vector3();
|
||||
const cameraWorldPosition = new THREE.Vector3();
|
||||
const rotationMatrix = new THREE.Matrix4();
|
||||
const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
|
||||
const view = new THREE.Vector3();
|
||||
const target = new THREE.Vector3();
|
||||
const textureMatrix = new THREE.Matrix4();
|
||||
const virtualCamera = new THREE.PerspectiveCamera();
|
||||
let depthTexture;
|
||||
|
||||
if ( useDepthTexture ) {
|
||||
|
||||
depthTexture = new THREE.DepthTexture();
|
||||
depthTexture.type = THREE.UnsignedShortType;
|
||||
depthTexture.minFilter = THREE.NearestFilter;
|
||||
depthTexture.magFilter = THREE.NearestFilter;
|
||||
|
||||
}
|
||||
|
||||
const parameters = {
|
||||
depthTexture: useDepthTexture ? depthTexture : null
|
||||
};
|
||||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
|
||||
const material = new THREE.ShaderMaterial( {
|
||||
transparent: useDepthTexture,
|
||||
defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
|
||||
useDepthTexture
|
||||
} ),
|
||||
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
||||
fragmentShader: shader.fragmentShader,
|
||||
vertexShader: shader.vertexShader
|
||||
} );
|
||||
material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
|
||||
material.uniforms[ 'color' ].value = scope.color;
|
||||
material.uniforms[ 'textureMatrix' ].value = textureMatrix;
|
||||
|
||||
if ( useDepthTexture ) {
|
||||
|
||||
material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture;
|
||||
|
||||
}
|
||||
|
||||
this.material = material;
|
||||
const globalPlane = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), clipBias );
|
||||
const globalPlanes = [ globalPlane ];
|
||||
|
||||
this.doRender = function ( renderer, scene, camera ) {
|
||||
|
||||
material.uniforms[ 'maxDistance' ].value = scope.maxDistance;
|
||||
material.uniforms[ 'color' ].value = scope.color;
|
||||
material.uniforms[ 'opacity' ].value = scope.opacity;
|
||||
vecTemp0.copy( camera.position ).normalize();
|
||||
vecTemp1.copy( vecTemp0 ).reflect( yAxis );
|
||||
material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel.
|
||||
|
||||
reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
|
||||
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
|
||||
rotationMatrix.extractRotation( scope.matrixWorld );
|
||||
normal.set( 0, 0, 1 );
|
||||
normal.applyMatrix4( rotationMatrix );
|
||||
view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
|
||||
|
||||
if ( view.dot( normal ) > 0 ) return;
|
||||
view.reflect( normal ).negate();
|
||||
view.add( reflectorWorldPosition );
|
||||
rotationMatrix.extractRotation( camera.matrixWorld );
|
||||
lookAtPosition.set( 0, 0, - 1 );
|
||||
lookAtPosition.applyMatrix4( rotationMatrix );
|
||||
lookAtPosition.add( cameraWorldPosition );
|
||||
target.subVectors( reflectorWorldPosition, lookAtPosition );
|
||||
target.reflect( normal ).negate();
|
||||
target.add( reflectorWorldPosition );
|
||||
virtualCamera.position.copy( view );
|
||||
virtualCamera.up.set( 0, 1, 0 );
|
||||
virtualCamera.up.applyMatrix4( rotationMatrix );
|
||||
virtualCamera.up.reflect( normal );
|
||||
virtualCamera.lookAt( target );
|
||||
virtualCamera.far = camera.far; // Used in WebGLBackground
|
||||
|
||||
virtualCamera.updateMatrixWorld();
|
||||
virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
|
||||
material.uniforms[ 'virtualCameraNear' ].value = camera.near;
|
||||
material.uniforms[ 'virtualCameraFar' ].value = camera.far;
|
||||
material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld;
|
||||
material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix;
|
||||
material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse;
|
||||
material.uniforms[ 'resolution' ].value = scope.resolution; // Update the texture matrix
|
||||
|
||||
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
|
||||
textureMatrix.multiply( virtualCamera.projectionMatrix );
|
||||
textureMatrix.multiply( virtualCamera.matrixWorldInverse );
|
||||
textureMatrix.multiply( scope.matrixWorld ); // Render
|
||||
|
||||
renderTarget.texture.encoding = renderer.outputEncoding; // scope.visible = false;
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentXrEnabled = renderer.xr.enabled;
|
||||
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
||||
const currentClippingPlanes = renderer.clippingPlanes;
|
||||
renderer.xr.enabled = false; // Avoid camera modification
|
||||
|
||||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
||||
|
||||
renderer.clippingPlanes = globalPlanes;
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
|
||||
|
||||
if ( renderer.autoClear === false ) renderer.clear();
|
||||
renderer.render( scene, virtualCamera );
|
||||
renderer.xr.enabled = currentXrEnabled;
|
||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
||||
renderer.clippingPlanes = currentClippingPlanes;
|
||||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
|
||||
|
||||
const viewport = camera.viewport;
|
||||
|
||||
if ( viewport !== undefined ) {
|
||||
|
||||
renderer.state.viewport( viewport );
|
||||
|
||||
} // scope.visible = true;
|
||||
|
||||
};
|
||||
|
||||
this.getRenderTarget = function () {
|
||||
|
||||
return renderTarget;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReflectorForSSRPass.prototype.isReflectorForSSRPass = true;
|
||||
ReflectorForSSRPass.ReflectorShader = {
|
||||
defines: {
|
||||
DISTANCE_ATTENUATION: true,
|
||||
FRESNEL: true
|
||||
},
|
||||
uniforms: {
|
||||
color: {
|
||||
value: null
|
||||
},
|
||||
tDiffuse: {
|
||||
value: null
|
||||
},
|
||||
tDepth: {
|
||||
value: null
|
||||
},
|
||||
textureMatrix: {
|
||||
value: new THREE.Matrix4()
|
||||
},
|
||||
maxDistance: {
|
||||
value: 180
|
||||
},
|
||||
opacity: {
|
||||
value: 0.5
|
||||
},
|
||||
fresnelCoe: {
|
||||
value: null
|
||||
},
|
||||
virtualCameraNear: {
|
||||
value: null
|
||||
},
|
||||
virtualCameraFar: {
|
||||
value: null
|
||||
},
|
||||
virtualCameraProjectionMatrix: {
|
||||
value: new THREE.Matrix4()
|
||||
},
|
||||
virtualCameraMatrixWorld: {
|
||||
value: new THREE.Matrix4()
|
||||
},
|
||||
virtualCameraProjectionMatrixInverse: {
|
||||
value: new THREE.Matrix4()
|
||||
},
|
||||
resolution: {
|
||||
value: new THREE.Vector2()
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform mat4 textureMatrix;
|
||||
varying vec4 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = textureMatrix * vec4( position, 1.0 );
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform vec3 color;
|
||||
uniform sampler2D tDiffuse;
|
||||
uniform sampler2D tDepth;
|
||||
uniform float maxDistance;
|
||||
uniform float opacity;
|
||||
uniform float fresnelCoe;
|
||||
uniform float virtualCameraNear;
|
||||
uniform float virtualCameraFar;
|
||||
uniform mat4 virtualCameraProjectionMatrix;
|
||||
uniform mat4 virtualCameraProjectionMatrixInverse;
|
||||
uniform mat4 virtualCameraMatrixWorld;
|
||||
uniform vec2 resolution;
|
||||
varying vec4 vUv;
|
||||
#include <packing>
|
||||
float blendOverlay( float base, float blend ) {
|
||||
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
|
||||
}
|
||||
vec3 blendOverlay( vec3 base, vec3 blend ) {
|
||||
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
|
||||
}
|
||||
float getDepth( const in vec2 uv ) {
|
||||
return texture2D( tDepth, uv ).x;
|
||||
}
|
||||
float getViewZ( const in float depth ) {
|
||||
return perspectiveDepthToViewZ( depth, virtualCameraNear, virtualCameraFar );
|
||||
}
|
||||
vec3 getViewPosition( const in vec2 uv, const in float depth/*clip space*/, const in float clipW ) {
|
||||
vec4 clipPosition = vec4( ( vec3( uv, depth ) - 0.5 ) * 2.0, 1.0 );//ndc
|
||||
clipPosition *= clipW; //clip
|
||||
return ( virtualCameraProjectionMatrixInverse * clipPosition ).xyz;//view
|
||||
}
|
||||
void main() {
|
||||
vec4 base = texture2DProj( tDiffuse, vUv );
|
||||
#ifdef useDepthTexture
|
||||
vec2 uv=(gl_FragCoord.xy-.5)/resolution.xy;
|
||||
uv.x=1.-uv.x;
|
||||
float depth = texture2DProj( tDepth, vUv ).r;
|
||||
float viewZ = getViewZ( depth );
|
||||
float clipW = virtualCameraProjectionMatrix[2][3] * viewZ+virtualCameraProjectionMatrix[3][3];
|
||||
vec3 viewPosition=getViewPosition( uv, depth, clipW );
|
||||
vec3 worldPosition=(virtualCameraMatrixWorld*vec4(viewPosition,1)).xyz;
|
||||
if(worldPosition.y>maxDistance) discard;
|
||||
float op=opacity;
|
||||
#ifdef DISTANCE_ATTENUATION
|
||||
float ratio=1.-(worldPosition.y/maxDistance);
|
||||
float attenuation=ratio*ratio;
|
||||
op=opacity*attenuation;
|
||||
#endif
|
||||
#ifdef FRESNEL
|
||||
op*=fresnelCoe;
|
||||
#endif
|
||||
gl_FragColor = vec4( blendOverlay( base.rgb, color ), op );
|
||||
#else
|
||||
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
|
||||
#endif
|
||||
}
|
||||
`
|
||||
};
|
||||
|
||||
THREE.ReflectorForSSRPass = ReflectorForSSRPass;
|
||||
|
||||
} )();
|
||||
252
HTML/ThreeJS/node_modules/three/examples/js/objects/Refractor.js
generated
vendored
Normal file
252
HTML/ThreeJS/node_modules/three/examples/js/objects/Refractor.js
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
( function () {
|
||||
|
||||
class Refractor extends THREE.Mesh {
|
||||
|
||||
constructor( geometry, options = {} ) {
|
||||
|
||||
super( geometry );
|
||||
this.type = 'Refractor';
|
||||
const scope = this;
|
||||
const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
|
||||
const textureWidth = options.textureWidth || 512;
|
||||
const textureHeight = options.textureHeight || 512;
|
||||
const clipBias = options.clipBias || 0;
|
||||
const shader = options.shader || Refractor.RefractorShader;
|
||||
const multisample = options.multisample !== undefined ? options.multisample : 4; //
|
||||
|
||||
const virtualCamera = new THREE.PerspectiveCamera();
|
||||
virtualCamera.matrixAutoUpdate = false;
|
||||
virtualCamera.userData.refractor = true; //
|
||||
|
||||
const refractorPlane = new THREE.Plane();
|
||||
const textureMatrix = new THREE.Matrix4(); // render target
|
||||
|
||||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, {
|
||||
samples: multisample
|
||||
} ); // material
|
||||
|
||||
this.material = new THREE.ShaderMaterial( {
|
||||
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader,
|
||||
transparent: true // ensures, refractors are drawn from farthest to closest
|
||||
|
||||
} );
|
||||
this.material.uniforms[ 'color' ].value = color;
|
||||
this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
|
||||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // functions
|
||||
|
||||
const visible = function () {
|
||||
|
||||
const refractorWorldPosition = new THREE.Vector3();
|
||||
const cameraWorldPosition = new THREE.Vector3();
|
||||
const rotationMatrix = new THREE.Matrix4();
|
||||
const view = new THREE.Vector3();
|
||||
const normal = new THREE.Vector3();
|
||||
return function visible( camera ) {
|
||||
|
||||
refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
|
||||
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
|
||||
view.subVectors( refractorWorldPosition, cameraWorldPosition );
|
||||
rotationMatrix.extractRotation( scope.matrixWorld );
|
||||
normal.set( 0, 0, 1 );
|
||||
normal.applyMatrix4( rotationMatrix );
|
||||
return view.dot( normal ) < 0;
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
const updateRefractorPlane = function () {
|
||||
|
||||
const normal = new THREE.Vector3();
|
||||
const position = new THREE.Vector3();
|
||||
const quaternion = new THREE.Quaternion();
|
||||
const scale = new THREE.Vector3();
|
||||
return function updateRefractorPlane() {
|
||||
|
||||
scope.matrixWorld.decompose( position, quaternion, scale );
|
||||
normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); // flip the normal because we want to cull everything above the plane
|
||||
|
||||
normal.negate();
|
||||
refractorPlane.setFromNormalAndCoplanarPoint( normal, position );
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
const updateVirtualCamera = function () {
|
||||
|
||||
const clipPlane = new THREE.Plane();
|
||||
const clipVector = new THREE.Vector4();
|
||||
const q = new THREE.Vector4();
|
||||
return function updateVirtualCamera( camera ) {
|
||||
|
||||
virtualCamera.matrixWorld.copy( camera.matrixWorld );
|
||||
virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert();
|
||||
virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
|
||||
virtualCamera.far = camera.far; // used in WebGLBackground
|
||||
// The following code creates an oblique view frustum for clipping.
|
||||
// see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”.
|
||||
// Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16
|
||||
|
||||
clipPlane.copy( refractorPlane );
|
||||
clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
|
||||
clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); // calculate the clip-space corner point opposite the clipping plane and
|
||||
// transform it into camera space by multiplying it by the inverse of the projection matrix
|
||||
|
||||
const projectionMatrix = virtualCamera.projectionMatrix;
|
||||
q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
|
||||
q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
|
||||
q.z = - 1.0;
|
||||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // calculate the scaled plane vector
|
||||
|
||||
clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); // replacing the third row of the projection matrix
|
||||
|
||||
projectionMatrix.elements[ 2 ] = clipVector.x;
|
||||
projectionMatrix.elements[ 6 ] = clipVector.y;
|
||||
projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias;
|
||||
projectionMatrix.elements[ 14 ] = clipVector.w;
|
||||
|
||||
};
|
||||
|
||||
}(); // This will update the texture matrix that is used for projective texture mapping in the shader.
|
||||
// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf
|
||||
|
||||
|
||||
function updateTextureMatrix( camera ) {
|
||||
|
||||
// this matrix does range mapping to [ 0, 1 ]
|
||||
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 ); // we use "Object Linear Texgen", so we need to multiply the texture matrix T
|
||||
// (matrix above) with the projection and view matrix of the virtual camera
|
||||
// and the model matrix of the refractor
|
||||
|
||||
textureMatrix.multiply( camera.projectionMatrix );
|
||||
textureMatrix.multiply( camera.matrixWorldInverse );
|
||||
textureMatrix.multiply( scope.matrixWorld );
|
||||
|
||||
} //
|
||||
|
||||
|
||||
function render( renderer, scene, camera ) {
|
||||
|
||||
scope.visible = false;
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentXrEnabled = renderer.xr.enabled;
|
||||
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
||||
renderer.xr.enabled = false; // avoid camera modification
|
||||
|
||||
renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
if ( renderer.autoClear === false ) renderer.clear();
|
||||
renderer.render( scene, virtualCamera );
|
||||
renderer.xr.enabled = currentXrEnabled;
|
||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
||||
renderer.setRenderTarget( currentRenderTarget ); // restore viewport
|
||||
|
||||
const viewport = camera.viewport;
|
||||
|
||||
if ( viewport !== undefined ) {
|
||||
|
||||
renderer.state.viewport( viewport );
|
||||
|
||||
}
|
||||
|
||||
scope.visible = true;
|
||||
|
||||
} //
|
||||
|
||||
|
||||
this.onBeforeRender = function ( renderer, scene, camera ) {
|
||||
|
||||
// Render
|
||||
renderTarget.texture.encoding = renderer.outputEncoding; // ensure refractors are rendered only once per frame
|
||||
|
||||
if ( camera.userData.refractor === true ) return; // avoid rendering when the refractor is viewed from behind
|
||||
|
||||
if ( ! visible( camera ) === true ) return; // update
|
||||
|
||||
updateRefractorPlane();
|
||||
updateTextureMatrix( camera );
|
||||
updateVirtualCamera( camera );
|
||||
render( renderer, scene, camera );
|
||||
|
||||
};
|
||||
|
||||
this.getRenderTarget = function () {
|
||||
|
||||
return renderTarget;
|
||||
|
||||
};
|
||||
|
||||
this.dispose = function () {
|
||||
|
||||
renderTarget.dispose();
|
||||
scope.material.dispose();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Refractor.prototype.isRefractor = true;
|
||||
Refractor.RefractorShader = {
|
||||
uniforms: {
|
||||
'color': {
|
||||
value: null
|
||||
},
|
||||
'tDiffuse': {
|
||||
value: null
|
||||
},
|
||||
'textureMatrix': {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
uniform mat4 textureMatrix;
|
||||
|
||||
varying vec4 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = textureMatrix * vec4( position, 1.0 );
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
uniform vec3 color;
|
||||
uniform sampler2D tDiffuse;
|
||||
|
||||
varying vec4 vUv;
|
||||
|
||||
float blendOverlay( float base, float blend ) {
|
||||
|
||||
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
|
||||
|
||||
}
|
||||
|
||||
vec3 blendOverlay( vec3 base, vec3 blend ) {
|
||||
|
||||
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 base = texture2DProj( tDiffuse, vUv );
|
||||
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
|
||||
|
||||
}`
|
||||
};
|
||||
|
||||
THREE.Refractor = Refractor;
|
||||
|
||||
} )();
|
||||
57
HTML/ThreeJS/node_modules/three/examples/js/objects/ShadowMesh.js
generated
vendored
Normal file
57
HTML/ThreeJS/node_modules/three/examples/js/objects/ShadowMesh.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
( function () {
|
||||
|
||||
/**
|
||||
* A shadow THREE.Mesh that follows a shadow-casting THREE.Mesh in the scene, but is confined to a single plane.
|
||||
*/
|
||||
|
||||
const _shadowMatrix = new THREE.Matrix4();
|
||||
|
||||
class ShadowMesh extends THREE.Mesh {
|
||||
|
||||
constructor( mesh ) {
|
||||
|
||||
const shadowMaterial = new THREE.MeshBasicMaterial( {
|
||||
color: 0x000000,
|
||||
transparent: true,
|
||||
opacity: 0.6,
|
||||
depthWrite: false
|
||||
} );
|
||||
super( mesh.geometry, shadowMaterial );
|
||||
this.meshMatrix = mesh.matrixWorld;
|
||||
this.frustumCulled = false;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
}
|
||||
|
||||
update( plane, lightPosition4D ) {
|
||||
|
||||
// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
|
||||
const dot = plane.normal.x * lightPosition4D.x + plane.normal.y * lightPosition4D.y + plane.normal.z * lightPosition4D.z + - plane.constant * lightPosition4D.w;
|
||||
const sme = _shadowMatrix.elements;
|
||||
sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x;
|
||||
sme[ 4 ] = - lightPosition4D.x * plane.normal.y;
|
||||
sme[ 8 ] = - lightPosition4D.x * plane.normal.z;
|
||||
sme[ 12 ] = - lightPosition4D.x * - plane.constant;
|
||||
sme[ 1 ] = - lightPosition4D.y * plane.normal.x;
|
||||
sme[ 5 ] = dot - lightPosition4D.y * plane.normal.y;
|
||||
sme[ 9 ] = - lightPosition4D.y * plane.normal.z;
|
||||
sme[ 13 ] = - lightPosition4D.y * - plane.constant;
|
||||
sme[ 2 ] = - lightPosition4D.z * plane.normal.x;
|
||||
sme[ 6 ] = - lightPosition4D.z * plane.normal.y;
|
||||
sme[ 10 ] = dot - lightPosition4D.z * plane.normal.z;
|
||||
sme[ 14 ] = - lightPosition4D.z * - plane.constant;
|
||||
sme[ 3 ] = - lightPosition4D.w * plane.normal.x;
|
||||
sme[ 7 ] = - lightPosition4D.w * plane.normal.y;
|
||||
sme[ 11 ] = - lightPosition4D.w * plane.normal.z;
|
||||
sme[ 15 ] = dot - lightPosition4D.w * - plane.constant;
|
||||
this.matrix.multiplyMatrices( _shadowMatrix, this.meshMatrix );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ShadowMesh.prototype.isShadowMesh = true;
|
||||
|
||||
THREE.ShadowMesh = ShadowMesh;
|
||||
|
||||
} )();
|
||||
223
HTML/ThreeJS/node_modules/three/examples/js/objects/Sky.js
generated
vendored
Normal file
223
HTML/ThreeJS/node_modules/three/examples/js/objects/Sky.js
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
( function () {
|
||||
|
||||
/**
|
||||
* Based on "A Practical Analytic Model for Daylight"
|
||||
* aka The Preetham Model, the de facto standard analytic skydome model
|
||||
* https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight
|
||||
*
|
||||
* First implemented by Simon Wallner
|
||||
* http://simonwallner.at/project/atmospheric-scattering/
|
||||
*
|
||||
* Improved by Martin Upitis
|
||||
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
|
||||
*
|
||||
* Three.js integration by zz85 http://twitter.com/blurspline
|
||||
*/
|
||||
|
||||
class Sky extends THREE.Mesh {
|
||||
|
||||
constructor() {
|
||||
|
||||
const shader = Sky.SkyShader;
|
||||
const material = new THREE.ShaderMaterial( {
|
||||
name: 'SkyShader',
|
||||
fragmentShader: shader.fragmentShader,
|
||||
vertexShader: shader.vertexShader,
|
||||
uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
||||
side: THREE.BackSide,
|
||||
depthWrite: false
|
||||
} );
|
||||
super( new THREE.BoxGeometry( 1, 1, 1 ), material );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Sky.prototype.isSky = true;
|
||||
Sky.SkyShader = {
|
||||
uniforms: {
|
||||
'turbidity': {
|
||||
value: 2
|
||||
},
|
||||
'rayleigh': {
|
||||
value: 1
|
||||
},
|
||||
'mieCoefficient': {
|
||||
value: 0.005
|
||||
},
|
||||
'mieDirectionalG': {
|
||||
value: 0.8
|
||||
},
|
||||
'sunPosition': {
|
||||
value: new THREE.Vector3()
|
||||
},
|
||||
'up': {
|
||||
value: new THREE.Vector3( 0, 1, 0 )
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform vec3 sunPosition;
|
||||
uniform float rayleigh;
|
||||
uniform float turbidity;
|
||||
uniform float mieCoefficient;
|
||||
uniform vec3 up;
|
||||
|
||||
varying vec3 vWorldPosition;
|
||||
varying vec3 vSunDirection;
|
||||
varying float vSunfade;
|
||||
varying vec3 vBetaR;
|
||||
varying vec3 vBetaM;
|
||||
varying float vSunE;
|
||||
|
||||
// constants for atmospheric scattering
|
||||
const float e = 2.71828182845904523536028747135266249775724709369995957;
|
||||
const float pi = 3.141592653589793238462643383279502884197169;
|
||||
|
||||
// wavelength of used primaries, according to preetham
|
||||
const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );
|
||||
// this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function:
|
||||
// (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn))
|
||||
const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );
|
||||
|
||||
// mie stuff
|
||||
// K coefficient for the primaries
|
||||
const float v = 4.0;
|
||||
const vec3 K = vec3( 0.686, 0.678, 0.666 );
|
||||
// MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K
|
||||
const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );
|
||||
|
||||
// earth shadow hack
|
||||
// cutoffAngle = pi / 1.95;
|
||||
const float cutoffAngle = 1.6110731556870734;
|
||||
const float steepness = 1.5;
|
||||
const float EE = 1000.0;
|
||||
|
||||
float sunIntensity( float zenithAngleCos ) {
|
||||
zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );
|
||||
return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );
|
||||
}
|
||||
|
||||
vec3 totalMie( float T ) {
|
||||
float c = ( 0.2 * T ) * 10E-18;
|
||||
return 0.434 * c * MieConst;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
|
||||
vWorldPosition = worldPosition.xyz;
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
gl_Position.z = gl_Position.w; // set z to camera.far
|
||||
|
||||
vSunDirection = normalize( sunPosition );
|
||||
|
||||
vSunE = sunIntensity( dot( vSunDirection, up ) );
|
||||
|
||||
vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );
|
||||
|
||||
float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );
|
||||
|
||||
// extinction (absorbtion + out scattering)
|
||||
// rayleigh coefficients
|
||||
vBetaR = totalRayleigh * rayleighCoefficient;
|
||||
|
||||
// mie coefficients
|
||||
vBetaM = totalMie( turbidity ) * mieCoefficient;
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
varying vec3 vWorldPosition;
|
||||
varying vec3 vSunDirection;
|
||||
varying float vSunfade;
|
||||
varying vec3 vBetaR;
|
||||
varying vec3 vBetaM;
|
||||
varying float vSunE;
|
||||
|
||||
uniform float mieDirectionalG;
|
||||
uniform vec3 up;
|
||||
|
||||
const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );
|
||||
|
||||
// constants for atmospheric scattering
|
||||
const float pi = 3.141592653589793238462643383279502884197169;
|
||||
|
||||
const float n = 1.0003; // refractive index of air
|
||||
const float N = 2.545E25; // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius)
|
||||
|
||||
// optical length at zenith for molecules
|
||||
const float rayleighZenithLength = 8.4E3;
|
||||
const float mieZenithLength = 1.25E3;
|
||||
// 66 arc seconds -> degrees, and the cosine of that
|
||||
const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;
|
||||
|
||||
// 3.0 / ( 16.0 * pi )
|
||||
const float THREE_OVER_SIXTEENPI = 0.05968310365946075;
|
||||
// 1.0 / ( 4.0 * pi )
|
||||
const float ONE_OVER_FOURPI = 0.07957747154594767;
|
||||
|
||||
float rayleighPhase( float cosTheta ) {
|
||||
return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );
|
||||
}
|
||||
|
||||
float hgPhase( float cosTheta, float g ) {
|
||||
float g2 = pow( g, 2.0 );
|
||||
float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );
|
||||
return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 direction = normalize( vWorldPosition - cameraPos );
|
||||
|
||||
// optical length
|
||||
// cutoff angle at 90 to avoid singularity in next formula.
|
||||
float zenithAngle = acos( max( 0.0, dot( up, direction ) ) );
|
||||
float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );
|
||||
float sR = rayleighZenithLength * inverse;
|
||||
float sM = mieZenithLength * inverse;
|
||||
|
||||
// combined extinction factor
|
||||
vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );
|
||||
|
||||
// in scattering
|
||||
float cosTheta = dot( direction, vSunDirection );
|
||||
|
||||
float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );
|
||||
vec3 betaRTheta = vBetaR * rPhase;
|
||||
|
||||
float mPhase = hgPhase( cosTheta, mieDirectionalG );
|
||||
vec3 betaMTheta = vBetaM * mPhase;
|
||||
|
||||
vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );
|
||||
Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) );
|
||||
|
||||
// nightsky
|
||||
float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]
|
||||
float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]
|
||||
vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );
|
||||
vec3 L0 = vec3( 0.1 ) * Fex;
|
||||
|
||||
// composition + solar disc
|
||||
float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );
|
||||
L0 += ( vSunE * 19000.0 * Fex ) * sundisk;
|
||||
|
||||
vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );
|
||||
|
||||
vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );
|
||||
|
||||
gl_FragColor = vec4( retColor, 1.0 );
|
||||
|
||||
#include <tonemapping_fragment>
|
||||
#include <encodings_fragment>
|
||||
|
||||
}`
|
||||
};
|
||||
|
||||
THREE.Sky = Sky;
|
||||
|
||||
} )();
|
||||
288
HTML/ThreeJS/node_modules/three/examples/js/objects/Water.js
generated
vendored
Normal file
288
HTML/ThreeJS/node_modules/three/examples/js/objects/Water.js
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
( function () {
|
||||
|
||||
/**
|
||||
* Work based on :
|
||||
* https://github.com/Slayvin: Flat mirror for three.js
|
||||
* https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror
|
||||
* http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
|
||||
*/
|
||||
|
||||
class Water extends THREE.Mesh {
|
||||
|
||||
constructor( geometry, options = {} ) {
|
||||
|
||||
super( geometry );
|
||||
const scope = this;
|
||||
const textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
|
||||
const textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
|
||||
const clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
|
||||
const alpha = options.alpha !== undefined ? options.alpha : 1.0;
|
||||
const time = options.time !== undefined ? options.time : 0.0;
|
||||
const normalSampler = options.waterNormals !== undefined ? options.waterNormals : null;
|
||||
const sunDirection = options.sunDirection !== undefined ? options.sunDirection : new THREE.Vector3( 0.70707, 0.70707, 0.0 );
|
||||
const sunColor = new THREE.Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
|
||||
const waterColor = new THREE.Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
|
||||
const eye = options.eye !== undefined ? options.eye : new THREE.Vector3( 0, 0, 0 );
|
||||
const distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
|
||||
const side = options.side !== undefined ? options.side : THREE.FrontSide;
|
||||
const fog = options.fog !== undefined ? options.fog : false; //
|
||||
|
||||
const mirrorPlane = new THREE.Plane();
|
||||
const normal = new THREE.Vector3();
|
||||
const mirrorWorldPosition = new THREE.Vector3();
|
||||
const cameraWorldPosition = new THREE.Vector3();
|
||||
const rotationMatrix = new THREE.Matrix4();
|
||||
const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
|
||||
const clipPlane = new THREE.Vector4();
|
||||
const view = new THREE.Vector3();
|
||||
const target = new THREE.Vector3();
|
||||
const q = new THREE.Vector4();
|
||||
const textureMatrix = new THREE.Matrix4();
|
||||
const mirrorCamera = new THREE.PerspectiveCamera();
|
||||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight );
|
||||
const mirrorShader = {
|
||||
uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], THREE.UniformsLib[ 'lights' ], {
|
||||
'normalSampler': {
|
||||
value: null
|
||||
},
|
||||
'mirrorSampler': {
|
||||
value: null
|
||||
},
|
||||
'alpha': {
|
||||
value: 1.0
|
||||
},
|
||||
'time': {
|
||||
value: 0.0
|
||||
},
|
||||
'size': {
|
||||
value: 1.0
|
||||
},
|
||||
'distortionScale': {
|
||||
value: 20.0
|
||||
},
|
||||
'textureMatrix': {
|
||||
value: new THREE.Matrix4()
|
||||
},
|
||||
'sunColor': {
|
||||
value: new THREE.Color( 0x7F7F7F )
|
||||
},
|
||||
'sunDirection': {
|
||||
value: new THREE.Vector3( 0.70707, 0.70707, 0 )
|
||||
},
|
||||
'eye': {
|
||||
value: new THREE.Vector3()
|
||||
},
|
||||
'waterColor': {
|
||||
value: new THREE.Color( 0x555555 )
|
||||
}
|
||||
} ] ),
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform mat4 textureMatrix;
|
||||
uniform float time;
|
||||
|
||||
varying vec4 mirrorCoord;
|
||||
varying vec4 worldPosition;
|
||||
|
||||
#include <common>
|
||||
#include <fog_pars_vertex>
|
||||
#include <shadowmap_pars_vertex>
|
||||
#include <logdepthbuf_pars_vertex>
|
||||
|
||||
void main() {
|
||||
mirrorCoord = modelMatrix * vec4( position, 1.0 );
|
||||
worldPosition = mirrorCoord.xyzw;
|
||||
mirrorCoord = textureMatrix * mirrorCoord;
|
||||
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
|
||||
#include <beginnormal_vertex>
|
||||
#include <defaultnormal_vertex>
|
||||
#include <logdepthbuf_vertex>
|
||||
#include <fog_vertex>
|
||||
#include <shadowmap_vertex>
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
uniform sampler2D mirrorSampler;
|
||||
uniform float alpha;
|
||||
uniform float time;
|
||||
uniform float size;
|
||||
uniform float distortionScale;
|
||||
uniform sampler2D normalSampler;
|
||||
uniform vec3 sunColor;
|
||||
uniform vec3 sunDirection;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 waterColor;
|
||||
|
||||
varying vec4 mirrorCoord;
|
||||
varying vec4 worldPosition;
|
||||
|
||||
vec4 getNoise( vec2 uv ) {
|
||||
vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);
|
||||
vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );
|
||||
vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );
|
||||
vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );
|
||||
vec4 noise = texture2D( normalSampler, uv0 ) +
|
||||
texture2D( normalSampler, uv1 ) +
|
||||
texture2D( normalSampler, uv2 ) +
|
||||
texture2D( normalSampler, uv3 );
|
||||
return noise * 0.5 - 1.0;
|
||||
}
|
||||
|
||||
void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {
|
||||
vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );
|
||||
float direction = max( 0.0, dot( eyeDirection, reflection ) );
|
||||
specularColor += pow( direction, shiny ) * sunColor * spec;
|
||||
diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;
|
||||
}
|
||||
|
||||
#include <common>
|
||||
#include <packing>
|
||||
#include <bsdfs>
|
||||
#include <fog_pars_fragment>
|
||||
#include <logdepthbuf_pars_fragment>
|
||||
#include <lights_pars_begin>
|
||||
#include <shadowmap_pars_fragment>
|
||||
#include <shadowmask_pars_fragment>
|
||||
|
||||
void main() {
|
||||
|
||||
#include <logdepthbuf_fragment>
|
||||
vec4 noise = getNoise( worldPosition.xz * size );
|
||||
vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );
|
||||
|
||||
vec3 diffuseLight = vec3(0.0);
|
||||
vec3 specularLight = vec3(0.0);
|
||||
|
||||
vec3 worldToEye = eye-worldPosition.xyz;
|
||||
vec3 eyeDirection = normalize( worldToEye );
|
||||
sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );
|
||||
|
||||
float distance = length(worldToEye);
|
||||
|
||||
vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;
|
||||
vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) );
|
||||
|
||||
float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );
|
||||
float rf0 = 0.3;
|
||||
float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );
|
||||
vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;
|
||||
vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);
|
||||
vec3 outgoingLight = albedo;
|
||||
gl_FragColor = vec4( outgoingLight, alpha );
|
||||
|
||||
#include <tonemapping_fragment>
|
||||
#include <fog_fragment>
|
||||
}`
|
||||
};
|
||||
const material = new THREE.ShaderMaterial( {
|
||||
fragmentShader: mirrorShader.fragmentShader,
|
||||
vertexShader: mirrorShader.vertexShader,
|
||||
uniforms: THREE.UniformsUtils.clone( mirrorShader.uniforms ),
|
||||
lights: true,
|
||||
side: side,
|
||||
fog: fog
|
||||
} );
|
||||
material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture;
|
||||
material.uniforms[ 'textureMatrix' ].value = textureMatrix;
|
||||
material.uniforms[ 'alpha' ].value = alpha;
|
||||
material.uniforms[ 'time' ].value = time;
|
||||
material.uniforms[ 'normalSampler' ].value = normalSampler;
|
||||
material.uniforms[ 'sunColor' ].value = sunColor;
|
||||
material.uniforms[ 'waterColor' ].value = waterColor;
|
||||
material.uniforms[ 'sunDirection' ].value = sunDirection;
|
||||
material.uniforms[ 'distortionScale' ].value = distortionScale;
|
||||
material.uniforms[ 'eye' ].value = eye;
|
||||
scope.material = material;
|
||||
|
||||
scope.onBeforeRender = function ( renderer, scene, camera ) {
|
||||
|
||||
mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
|
||||
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
|
||||
rotationMatrix.extractRotation( scope.matrixWorld );
|
||||
normal.set( 0, 0, 1 );
|
||||
normal.applyMatrix4( rotationMatrix );
|
||||
view.subVectors( mirrorWorldPosition, cameraWorldPosition ); // Avoid rendering when mirror is facing away
|
||||
|
||||
if ( view.dot( normal ) > 0 ) return;
|
||||
view.reflect( normal ).negate();
|
||||
view.add( mirrorWorldPosition );
|
||||
rotationMatrix.extractRotation( camera.matrixWorld );
|
||||
lookAtPosition.set( 0, 0, - 1 );
|
||||
lookAtPosition.applyMatrix4( rotationMatrix );
|
||||
lookAtPosition.add( cameraWorldPosition );
|
||||
target.subVectors( mirrorWorldPosition, lookAtPosition );
|
||||
target.reflect( normal ).negate();
|
||||
target.add( mirrorWorldPosition );
|
||||
mirrorCamera.position.copy( view );
|
||||
mirrorCamera.up.set( 0, 1, 0 );
|
||||
mirrorCamera.up.applyMatrix4( rotationMatrix );
|
||||
mirrorCamera.up.reflect( normal );
|
||||
mirrorCamera.lookAt( target );
|
||||
mirrorCamera.far = camera.far; // Used in WebGLBackground
|
||||
|
||||
mirrorCamera.updateMatrixWorld();
|
||||
mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix
|
||||
|
||||
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
|
||||
textureMatrix.multiply( mirrorCamera.projectionMatrix );
|
||||
textureMatrix.multiply( mirrorCamera.matrixWorldInverse ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
|
||||
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
|
||||
|
||||
mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition );
|
||||
mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse );
|
||||
clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant );
|
||||
const projectionMatrix = mirrorCamera.projectionMatrix;
|
||||
q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
|
||||
q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
|
||||
q.z = - 1.0;
|
||||
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector
|
||||
|
||||
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix
|
||||
|
||||
projectionMatrix.elements[ 2 ] = clipPlane.x;
|
||||
projectionMatrix.elements[ 6 ] = clipPlane.y;
|
||||
projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
|
||||
projectionMatrix.elements[ 14 ] = clipPlane.w;
|
||||
eye.setFromMatrixPosition( camera.matrixWorld ); // Render
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentXrEnabled = renderer.xr.enabled;
|
||||
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
||||
scope.visible = false;
|
||||
renderer.xr.enabled = false; // Avoid camera modification and recursion
|
||||
|
||||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
|
||||
|
||||
if ( renderer.autoClear === false ) renderer.clear();
|
||||
renderer.render( scene, mirrorCamera );
|
||||
scope.visible = true;
|
||||
renderer.xr.enabled = currentXrEnabled;
|
||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
||||
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
|
||||
|
||||
const viewport = camera.viewport;
|
||||
|
||||
if ( viewport !== undefined ) {
|
||||
|
||||
renderer.state.viewport( viewport );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Water.prototype.isWater = true;
|
||||
|
||||
THREE.Water = Water;
|
||||
|
||||
} )();
|
||||
306
HTML/ThreeJS/node_modules/three/examples/js/objects/Water2.js
generated
vendored
Normal file
306
HTML/ThreeJS/node_modules/three/examples/js/objects/Water2.js
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
( function () {
|
||||
|
||||
/**
|
||||
* References:
|
||||
* https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf
|
||||
* http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html
|
||||
*
|
||||
*/
|
||||
|
||||
class Water extends THREE.Mesh {
|
||||
|
||||
constructor( geometry, options = {} ) {
|
||||
|
||||
super( geometry );
|
||||
this.type = 'Water';
|
||||
const scope = this;
|
||||
const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0xFFFFFF );
|
||||
const textureWidth = options.textureWidth || 512;
|
||||
const textureHeight = options.textureHeight || 512;
|
||||
const clipBias = options.clipBias || 0;
|
||||
const flowDirection = options.flowDirection || new THREE.Vector2( 1, 0 );
|
||||
const flowSpeed = options.flowSpeed || 0.03;
|
||||
const reflectivity = options.reflectivity || 0.02;
|
||||
const scale = options.scale || 1;
|
||||
const shader = options.shader || Water.WaterShader;
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
const flowMap = options.flowMap || undefined;
|
||||
const normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
|
||||
const normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
|
||||
const cycle = 0.15; // a cycle of a flow map phase
|
||||
|
||||
const halfCycle = cycle * 0.5;
|
||||
const textureMatrix = new THREE.Matrix4();
|
||||
const clock = new THREE.Clock(); // internal components
|
||||
|
||||
if ( THREE.Reflector === undefined ) {
|
||||
|
||||
console.error( 'THREE.Water: Required component THREE.Reflector not found.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if ( THREE.Refractor === undefined ) {
|
||||
|
||||
console.error( 'THREE.Water: Required component THREE.Refractor not found.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
const reflector = new THREE.Reflector( geometry, {
|
||||
textureWidth: textureWidth,
|
||||
textureHeight: textureHeight,
|
||||
clipBias: clipBias
|
||||
} );
|
||||
const refractor = new THREE.Refractor( geometry, {
|
||||
textureWidth: textureWidth,
|
||||
textureHeight: textureHeight,
|
||||
clipBias: clipBias
|
||||
} );
|
||||
reflector.matrixAutoUpdate = false;
|
||||
refractor.matrixAutoUpdate = false; // material
|
||||
|
||||
this.material = new THREE.ShaderMaterial( {
|
||||
uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], shader.uniforms ] ),
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader,
|
||||
transparent: true,
|
||||
fog: true
|
||||
} );
|
||||
|
||||
if ( flowMap !== undefined ) {
|
||||
|
||||
this.material.defines.USE_FLOWMAP = '';
|
||||
this.material.uniforms[ 'tFlowMap' ] = {
|
||||
type: 't',
|
||||
value: flowMap
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
this.material.uniforms[ 'flowDirection' ] = {
|
||||
type: 'v2',
|
||||
value: flowDirection
|
||||
};
|
||||
|
||||
} // maps
|
||||
|
||||
|
||||
normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping;
|
||||
normalMap1.wrapS = normalMap1.wrapT = THREE.RepeatWrapping;
|
||||
this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture;
|
||||
this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture;
|
||||
this.material.uniforms[ 'tNormalMap0' ].value = normalMap0;
|
||||
this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; // water
|
||||
|
||||
this.material.uniforms[ 'color' ].value = color;
|
||||
this.material.uniforms[ 'reflectivity' ].value = reflectivity;
|
||||
this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // inital values
|
||||
|
||||
this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0
|
||||
|
||||
this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1
|
||||
|
||||
this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle
|
||||
|
||||
this.material.uniforms[ 'config' ].value.w = scale; // scale
|
||||
// functions
|
||||
|
||||
function updateTextureMatrix( camera ) {
|
||||
|
||||
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
|
||||
textureMatrix.multiply( camera.projectionMatrix );
|
||||
textureMatrix.multiply( camera.matrixWorldInverse );
|
||||
textureMatrix.multiply( scope.matrixWorld );
|
||||
|
||||
}
|
||||
|
||||
function updateFlow() {
|
||||
|
||||
const delta = clock.getDelta();
|
||||
const config = scope.material.uniforms[ 'config' ];
|
||||
config.value.x += flowSpeed * delta; // flowMapOffset0
|
||||
|
||||
config.value.y = config.value.x + halfCycle; // flowMapOffset1
|
||||
// Important: The distance between offsets should be always the value of "halfCycle".
|
||||
// Moreover, both offsets should be in the range of [ 0, cycle ].
|
||||
// This approach ensures a smooth water flow and avoids "reset" effects.
|
||||
|
||||
if ( config.value.x >= cycle ) {
|
||||
|
||||
config.value.x = 0;
|
||||
config.value.y = halfCycle;
|
||||
|
||||
} else if ( config.value.y >= cycle ) {
|
||||
|
||||
config.value.y = config.value.y - cycle;
|
||||
|
||||
}
|
||||
|
||||
} //
|
||||
|
||||
|
||||
this.onBeforeRender = function ( renderer, scene, camera ) {
|
||||
|
||||
updateTextureMatrix( camera );
|
||||
updateFlow();
|
||||
scope.visible = false;
|
||||
reflector.matrixWorld.copy( scope.matrixWorld );
|
||||
refractor.matrixWorld.copy( scope.matrixWorld );
|
||||
reflector.onBeforeRender( renderer, scene, camera );
|
||||
refractor.onBeforeRender( renderer, scene, camera );
|
||||
scope.visible = true;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Water.prototype.isWater = true;
|
||||
Water.WaterShader = {
|
||||
uniforms: {
|
||||
'color': {
|
||||
type: 'c',
|
||||
value: null
|
||||
},
|
||||
'reflectivity': {
|
||||
type: 'f',
|
||||
value: 0
|
||||
},
|
||||
'tReflectionMap': {
|
||||
type: 't',
|
||||
value: null
|
||||
},
|
||||
'tRefractionMap': {
|
||||
type: 't',
|
||||
value: null
|
||||
},
|
||||
'tNormalMap0': {
|
||||
type: 't',
|
||||
value: null
|
||||
},
|
||||
'tNormalMap1': {
|
||||
type: 't',
|
||||
value: null
|
||||
},
|
||||
'textureMatrix': {
|
||||
type: 'm4',
|
||||
value: null
|
||||
},
|
||||
'config': {
|
||||
type: 'v4',
|
||||
value: new THREE.Vector4()
|
||||
}
|
||||
},
|
||||
vertexShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
#include <common>
|
||||
#include <fog_pars_vertex>
|
||||
#include <logdepthbuf_pars_vertex>
|
||||
|
||||
uniform mat4 textureMatrix;
|
||||
|
||||
varying vec4 vCoord;
|
||||
varying vec2 vUv;
|
||||
varying vec3 vToEye;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
vCoord = textureMatrix * vec4( position, 1.0 );
|
||||
|
||||
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
|
||||
vToEye = cameraPosition - worldPosition.xyz;
|
||||
|
||||
vec4 mvPosition = viewMatrix * worldPosition; // used in fog_vertex
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
|
||||
#include <logdepthbuf_vertex>
|
||||
#include <fog_vertex>
|
||||
|
||||
}`,
|
||||
fragmentShader:
|
||||
/* glsl */
|
||||
`
|
||||
|
||||
#include <common>
|
||||
#include <fog_pars_fragment>
|
||||
#include <logdepthbuf_pars_fragment>
|
||||
|
||||
uniform sampler2D tReflectionMap;
|
||||
uniform sampler2D tRefractionMap;
|
||||
uniform sampler2D tNormalMap0;
|
||||
uniform sampler2D tNormalMap1;
|
||||
|
||||
#ifdef USE_FLOWMAP
|
||||
uniform sampler2D tFlowMap;
|
||||
#else
|
||||
uniform vec2 flowDirection;
|
||||
#endif
|
||||
|
||||
uniform vec3 color;
|
||||
uniform float reflectivity;
|
||||
uniform vec4 config;
|
||||
|
||||
varying vec4 vCoord;
|
||||
varying vec2 vUv;
|
||||
varying vec3 vToEye;
|
||||
|
||||
void main() {
|
||||
|
||||
#include <logdepthbuf_fragment>
|
||||
|
||||
float flowMapOffset0 = config.x;
|
||||
float flowMapOffset1 = config.y;
|
||||
float halfCycle = config.z;
|
||||
float scale = config.w;
|
||||
|
||||
vec3 toEye = normalize( vToEye );
|
||||
|
||||
// determine flow direction
|
||||
vec2 flow;
|
||||
#ifdef USE_FLOWMAP
|
||||
flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0;
|
||||
#else
|
||||
flow = flowDirection;
|
||||
#endif
|
||||
flow.x *= - 1.0;
|
||||
|
||||
// sample normal maps (distort uvs with flowdata)
|
||||
vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 );
|
||||
vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 );
|
||||
|
||||
// linear interpolate to get the final normal color
|
||||
float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;
|
||||
vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );
|
||||
|
||||
// calculate normal vector
|
||||
vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );
|
||||
|
||||
// calculate the fresnel term to blend reflection and refraction maps
|
||||
float theta = max( dot( toEye, normal ), 0.0 );
|
||||
float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 );
|
||||
|
||||
// calculate final uv coords
|
||||
vec3 coord = vCoord.xyz / vCoord.w;
|
||||
vec2 uv = coord.xy + coord.z * normal.xz * 0.05;
|
||||
|
||||
vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) );
|
||||
vec4 refractColor = texture2D( tRefractionMap, uv );
|
||||
|
||||
// multiply water color with the mix of both textures
|
||||
gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );
|
||||
|
||||
#include <tonemapping_fragment>
|
||||
#include <encodings_fragment>
|
||||
#include <fog_fragment>
|
||||
|
||||
}`
|
||||
};
|
||||
|
||||
THREE.Water = Water;
|
||||
|
||||
} )();
|
||||
Reference in New Issue
Block a user