Vom Anderen PC aus hoch gespielt

This commit is contained in:
ChK
2026-02-01 13:40:05 +01:00
commit 60b1b7591c
1088 changed files with 452896 additions and 0 deletions

586
node_modules/three/examples/jsm/objects/BatchedMesh.js generated vendored Normal file
View File

@@ -0,0 +1,586 @@
import {
BufferAttribute,
BufferGeometry,
DataTexture,
FloatType,
MathUtils,
Matrix4,
Mesh,
RGBAFormat
} from 'three';
const ID_ATTR_NAME = '_batch_id_';
const _identityMatrix = new Matrix4();
const _zeroScaleMatrix = new Matrix4().set(
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1,
);
// Custom shaders
const batchingParsVertex = /* glsl */`
#ifdef BATCHING
attribute float ${ ID_ATTR_NAME };
uniform highp sampler2D batchingTexture;
uniform int batchingTextureSize;
mat4 getBatchingMatrix( const in float i ) {
float j = i * 4.0;
float x = mod( j, float( batchingTextureSize ) );
float y = floor( j / float( batchingTextureSize ) );
float dx = 1.0 / float( batchingTextureSize );
float dy = 1.0 / float( batchingTextureSize );
y = dy * ( y + 0.5 );
vec4 v1 = texture2D( batchingTexture, vec2( dx * ( x + 0.5 ), y ) );
vec4 v2 = texture2D( batchingTexture, vec2( dx * ( x + 1.5 ), y ) );
vec4 v3 = texture2D( batchingTexture, vec2( dx * ( x + 2.5 ), y ) );
vec4 v4 = texture2D( batchingTexture, vec2( dx * ( x + 3.5 ), y ) );
return mat4( v1, v2, v3, v4 );
}
#endif
`;
const batchingbaseVertex = /* glsl */`
#ifdef BATCHING
mat4 batchingMatrix = getBatchingMatrix( ${ ID_ATTR_NAME } );
#endif
`;
const batchingnormalVertex = /* glsl */`
#ifdef BATCHING
objectNormal = vec4( batchingMatrix * vec4( objectNormal, 0.0 ) ).xyz;
#ifdef USE_TANGENT
objectTangent = vec4( batchingMatrix * vec4( objectTangent, 0.0 ) ).xyz;
#endif
#endif
`;
const batchingVertex = /* glsl */`
#ifdef BATCHING
transformed = ( batchingMatrix * vec4( transformed, 1.0 ) ).xyz;
#endif
`;
// @TODO: SkinnedMesh support?
// @TODO: Future work if needed. Move into the core. Can be optimized more with WEBGL_multi_draw.
// copies data from attribute "src" into "target" starting at "targetOffset"
function copyAttributeData( src, target, targetOffset = 0 ) {
const itemSize = target.itemSize;
if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
// use the component getters and setters if the array data cannot
// be copied directly
const vertexCount = src.count;
for ( let i = 0; i < vertexCount; i ++ ) {
for ( let c = 0; c < itemSize; c ++ ) {
target.setComponent( i + targetOffset, c, src.getComponent( i, c ) );
}
}
} else {
// faster copy approach using typed array set function
target.array.set( src.array, targetOffset * itemSize );
}
target.needsUpdate = true;
}
class BatchedMesh extends Mesh {
constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
super( new BufferGeometry(), material );
this._vertexStarts = [];
this._vertexCounts = [];
this._indexStarts = [];
this._indexCounts = [];
this._visible = [];
this._active = [];
this._maxGeometryCount = maxGeometryCount;
this._maxVertexCount = maxVertexCount;
this._maxIndexCount = maxIndexCount;
this._geometryInitialized = false;
this._geometryCount = 0;
this._vertexCount = 0;
this._indexCount = 0;
// Local matrix per geometry by using data texture
// @TODO: Support uniform parameter per geometry
this._matrices = [];
this._matricesTexture = null;
// @TODO: Calculate the entire binding box and make frustumCulled true
this.frustumCulled = false;
this._customUniforms = {
batchingTexture: { value: null },
batchingTextureSize: { value: 0 }
};
this._initMatricesTexture();
this._initShader();
}
_initMatricesTexture() {
// layout (1 matrix = 4 pixels)
// RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
// with 8x8 pixel texture max 16 matrices * 4 pixels = (8 * 8)
// 16x16 pixel texture max 64 matrices * 4 pixels = (16 * 16)
// 32x32 pixel texture max 256 matrices * 4 pixels = (32 * 32)
// 64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix
size = MathUtils.ceilPowerOfTwo( size );
size = Math.max( size, 4 );
const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType );
this._matricesTexture = matricesTexture;
this._customUniforms.batchingTexture.value = this._matricesTexture;
this._customUniforms.batchingTextureSize.value = size;
}
_initShader() {
const material = this.material;
const currentOnBeforeCompile = material.onBeforeCompile;
const customUniforms = this._customUniforms;
material.onBeforeCompile = function onBeforeCompile( parameters, renderer ) {
// Is this replacement stable across any materials?
parameters.vertexShader = parameters.vertexShader
.replace(
'#include <skinning_pars_vertex>',
'#include <skinning_pars_vertex>\n'
+ batchingParsVertex
)
.replace(
'#include <skinnormal_vertex>',
'#include <skinnormal_vertex>\n'
+ batchingbaseVertex
+ batchingnormalVertex
)
.replace(
'#include <skinning_vertex>',
'#include <skinning_vertex>\n'
+ batchingVertex
);
for ( const uniformName in customUniforms ) {
parameters.uniforms[ uniformName ] = customUniforms[ uniformName ];
}
currentOnBeforeCompile.call( this, parameters, renderer );
};
material.defines = material.defines || {};
material.defines.BATCHING = false;
}
_initializeGeometry( reference ) {
// @TODO: geometry.groups support?
// @TODO: geometry.drawRange support?
// @TODO: geometry.morphAttributes support?
const geometry = this.geometry;
const maxVertexCount = this._maxVertexCount;
const maxGeometryCount = this._maxGeometryCount;
const maxIndexCount = this._maxIndexCount;
if ( this._geometryInitialized === false ) {
for ( const attributeName in reference.attributes ) {
const srcAttribute = reference.getAttribute( attributeName );
const { array, itemSize, normalized } = srcAttribute;
const dstArray = new array.constructor( maxVertexCount * itemSize );
const dstAttribute = new srcAttribute.constructor( dstArray, itemSize, normalized );
dstAttribute.setUsage( srcAttribute.usage );
geometry.setAttribute( attributeName, dstAttribute );
}
if ( reference.getIndex() !== null ) {
const indexArray = maxVertexCount > 65536
? new Uint32Array( maxIndexCount )
: new Uint16Array( maxIndexCount );
geometry.setIndex( new BufferAttribute( indexArray, 1 ) );
}
const idArray = maxGeometryCount > 65536
? new Uint32Array( maxVertexCount )
: new Uint16Array( maxVertexCount );
geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) );
this._geometryInitialized = true;
}
}
getGeometryCount() {
return this._geometryCount;
}
getVertexCount() {
return this._vertexCount;
}
getIndexCount() {
return this._indexCount;
}
applyGeometry( geometry ) {
this._initializeGeometry( geometry );
// ensure we're not over geometry
if ( this._geometryCount >= this._maxGeometryCount ) {
throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
}
// check that the geometry doesn't have a version of our reserved id attribute
if ( geometry.getAttribute( ID_ATTR_NAME ) ) {
throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` );
}
// check to ensure the geometries are using consistent attributes and indices
const batchGeometry = this.geometry;
if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
throw new Error( 'BatchedMesh: All geometries must consistently have "index".' );
}
for ( const attributeName in batchGeometry.attributes ) {
if ( attributeName === ID_ATTR_NAME ) {
continue;
}
if ( ! geometry.hasAttribute( attributeName ) ) {
throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
}
const srcAttribute = geometry.getAttribute( attributeName );
const dstAttribute = batchGeometry.getAttribute( attributeName );
if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
}
}
// Assuming geometry has position attribute
const srcPositionAttribute = geometry.getAttribute( 'position' );
const vertexCount = this._vertexCount;
const indexCount = this._indexCount;
const maxVertexCount = this._maxVertexCount;
const maxIndexCount = this._maxIndexCount;
// check if we're going over our maximum buffer capacity
if (
geometry.getIndex() !== null &&
indexCount + geometry.getIndex().count > maxIndexCount ||
vertexCount + srcPositionAttribute.count > maxVertexCount
) {
throw new Error( 'BatchedMesh: Added geometry is larger than available buffer capacity.' );
}
const visible = this._visible;
const active = this._active;
const matricesTexture = this._matricesTexture;
const matrices = this._matrices;
const matricesArray = this._matricesTexture.image.data;
const indexCounts = this._indexCounts;
const indexStarts = this._indexStarts;
const vertexCounts = this._vertexCounts;
const vertexStarts = this._vertexStarts;
const hasIndex = batchGeometry.getIndex() !== null;
const dstIndex = batchGeometry.getIndex();
const srcIndex = geometry.getIndex();
// push new geometry data range
vertexStarts.push( vertexCount );
vertexCounts.push( srcPositionAttribute.count );
// copy attribute data over
for ( const attributeName in batchGeometry.attributes ) {
if ( attributeName === ID_ATTR_NAME ) {
continue;
}
const srcAttribute = geometry.getAttribute( attributeName );
const dstAttribute = batchGeometry.getAttribute( attributeName );
copyAttributeData( srcAttribute, dstAttribute, vertexCount );
}
if ( hasIndex ) {
// push new index range
indexStarts.push( indexCount );
indexCounts.push( srcIndex.count );
// copy index data over
for ( let i = 0; i < srcIndex.count; i ++ ) {
dstIndex.setX( indexCount + i, vertexCount + srcIndex.getX( i ) );
}
this._indexCount += srcIndex.count;
dstIndex.needsUpdate = true;
}
// fill in the geometry ids
const geometryId = this._geometryCount;
this._geometryCount ++;
const idAttribute = batchGeometry.getAttribute( ID_ATTR_NAME );
for ( let i = 0; i < srcPositionAttribute.count; i ++ ) {
idAttribute.setX( this._vertexCount + i, geometryId );
}
idAttribute.needsUpdate = true;
// extend new range
this._vertexCount += srcPositionAttribute.count;
// push new visibility states
visible.push( true );
active.push( true );
// initialize matrix information
matrices.push( new Matrix4() );
_identityMatrix.toArray( matricesArray, geometryId * 16 );
matricesTexture.needsUpdate = true;
return geometryId;
}
deleteGeometry( geometryId ) {
// Note: User needs to call optimize() afterward to pack the data.
const active = this._active;
const matricesArray = this._matricesTexture.image.data;
const matricesTexture = this._matricesTexture;
if ( geometryId >= active.length || active[ geometryId ] === false ) {
return this;
}
active[ geometryId ] = false;
_zeroScaleMatrix.toArray( matricesArray, geometryId * 16 );
matricesTexture.needsUpdate = true;
return this;
}
optimize() {
throw new Error( 'BatchedMesh: Optimize function not implemented.' );
}
setMatrixAt( geometryId, matrix ) {
// @TODO: Map geometryId to index of the arrays because
// optimize() can make geometryId mismatch the index
const visible = this._visible;
const active = this._active;
const matricesTexture = this._matricesTexture;
const matrices = this._matrices;
const matricesArray = this._matricesTexture.image.data;
if ( geometryId >= matrices.length || active[ geometryId ] === false ) {
return this;
}
if ( visible[ geometryId ] === true ) {
matrix.toArray( matricesArray, geometryId * 16 );
matricesTexture.needsUpdate = true;
}
matrices[ geometryId ].copy( matrix );
return this;
}
getMatrixAt( geometryId, matrix ) {
const matrices = this._matrices;
const active = this._active;
if ( geometryId >= matrices.length || active[ geometryId ] === false ) {
return matrix;
}
return matrix.copy( matrices[ geometryId ] );
}
setVisibleAt( geometryId, value ) {
const visible = this._visible;
const active = this._active;
const matricesTexture = this._matricesTexture;
const matrices = this._matrices;
const matricesArray = this._matricesTexture.image.data;
// if the geometry is out of range, not active, or visibility state
// does not change then return early
if (
geometryId >= visible.length ||
active[ geometryId ] === false ||
visible[ geometryId ] === value
) {
return this;
}
// scale the matrix to zero if it's hidden
if ( value === true ) {
matrices[ geometryId ].toArray( matricesArray, geometryId * 16 );
} else {
_zeroScaleMatrix.toArray( matricesArray, geometryId * 16 );
}
matricesTexture.needsUpdate = true;
visible[ geometryId ] = value;
return this;
}
getVisibleAt( geometryId ) {
const visible = this._visible;
const active = this._active;
// return early if the geometry is out of range or not active
if ( geometryId >= visible.length || active[ geometryId ] === false ) {
return false;
}
return visible[ geometryId ];
}
raycast() {
console.warn( 'BatchedMesh: Raycast function not implemented.' );
}
copy() {
// super.copy( source );
throw new Error( 'BatchedMesh: Copy function not implemented.' );
}
toJSON() {
throw new Error( 'BatchedMesh: toJSON function not implemented.' );
}
dispose() {
// Assuming the geometry is not shared with other meshes
this.geometry.dispose();
this._matricesTexture.dispose();
this._matricesTexture = null;
return this;
}
onBeforeRender( _renderer, _scene, _camera, _geometry, material/*, _group*/ ) {
material.defines.BATCHING = true;
// @TODO: Implement frustum culling for each geometry
}
onAfterRender( _renderer, _scene, _camera, _geometry, material/*, _group*/ ) {
material.defines.BATCHING = false;
}
}
export { BatchedMesh };

View File

@@ -0,0 +1,172 @@
import { Mesh, IcosahedronGeometry, ShaderMaterial, DoubleSide } from 'three';
/**
* Ground projected env map adapted from @react-three/drei.
* https://github.com/pmndrs/drei/blob/master/src/core/Environment.tsx
*/
class GroundProjectedSkybox extends Mesh {
constructor( texture, options = {} ) {
const isCubeMap = texture.isCubeTexture;
const defines = [
isCubeMap ? '#define ENVMAP_TYPE_CUBE' : ''
];
const vertexShader = /* glsl */ `
varying vec3 vWorldPosition;
void main() {
vec4 worldPosition = ( modelMatrix * vec4( position, 1.0 ) );
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;
const fragmentShader = defines.join( '\n' ) + /* glsl */ `
varying vec3 vWorldPosition;
uniform float radius;
uniform float height;
uniform float angle;
#ifdef ENVMAP_TYPE_CUBE
uniform samplerCube map;
#else
uniform sampler2D map;
#endif
// From: https://www.shadertoy.com/view/4tsBD7
float diskIntersectWithBackFaceCulling( vec3 ro, vec3 rd, vec3 c, vec3 n, float r )
{
float d = dot ( rd, n );
if( d > 0.0 ) { return 1e6; }
vec3 o = ro - c;
float t = - dot( n, o ) / d;
vec3 q = o + rd * t;
return ( dot( q, q ) < r * r ) ? t : 1e6;
}
// From: https://www.iquilezles.org/www/articles/intersectors/intersectors.htm
float sphereIntersect( vec3 ro, vec3 rd, vec3 ce, float ra ) {
vec3 oc = ro - ce;
float b = dot( oc, rd );
float c = dot( oc, oc ) - ra * ra;
float h = b * b - c;
if( h < 0.0 ) { return -1.0; }
h = sqrt( h );
return - b + h;
}
vec3 project() {
vec3 p = normalize( vWorldPosition );
vec3 camPos = cameraPosition;
camPos.y -= height;
float intersection = sphereIntersect( camPos, p, vec3( 0.0 ), radius );
if( intersection > 0.0 ) {
vec3 h = vec3( 0.0, - height, 0.0 );
float intersection2 = diskIntersectWithBackFaceCulling( camPos, p, h, vec3( 0.0, 1.0, 0.0 ), radius );
p = ( camPos + min( intersection, intersection2 ) * p ) / radius;
} else {
p = vec3( 0.0, 1.0, 0.0 );
}
return p;
}
#include <common>
void main() {
vec3 projectedWorldPosition = project();
#ifdef ENVMAP_TYPE_CUBE
vec3 outcolor = textureCube( map, projectedWorldPosition ).rgb;
#else
vec3 direction = normalize( projectedWorldPosition );
vec2 uv = equirectUv( direction );
vec3 outcolor = texture2D( map, uv ).rgb;
#endif
gl_FragColor = vec4( outcolor, 1.0 );
#include <tonemapping_fragment>
#include <colorspace_fragment>
}
`;
const uniforms = {
map: { value: texture },
height: { value: options.height || 15 },
radius: { value: options.radius || 100 },
};
const geometry = new IcosahedronGeometry( 1, 16 );
const material = new ShaderMaterial( {
uniforms,
fragmentShader,
vertexShader,
side: DoubleSide,
} );
super( geometry, material );
}
set radius( radius ) {
this.material.uniforms.radius.value = radius;
}
get radius() {
return this.material.uniforms.radius.value;
}
set height( height ) {
this.material.uniforms.height.value = height;
}
get height() {
return this.material.uniforms.height.value;
}
}
export { GroundProjectedSkybox };

View File

@@ -0,0 +1,21 @@
import {
Mesh
} from 'three';
import InstancedPointsGeometry from '../geometries/InstancedPointsGeometry.js';
import InstancedPointsNodeMaterial from '../nodes/materials/InstancedPointsNodeMaterial.js';
class InstancedPoints extends Mesh {
constructor( geometry = new InstancedPointsGeometry(), material = new InstancedPointsNodeMaterial() ) {
super( geometry, material );
this.isInstancedPoints = true;
this.type = 'InstancedPoints';
}
}
export default InstancedPoints;

397
node_modules/three/examples/jsm/objects/Lensflare.js generated vendored Normal file
View File

@@ -0,0 +1,397 @@
import {
AdditiveBlending,
Box2,
BufferGeometry,
Color,
FramebufferTexture,
InterleavedBuffer,
InterleavedBufferAttribute,
Mesh,
MeshBasicMaterial,
RawShaderMaterial,
UnsignedByteType,
Vector2,
Vector3,
Vector4
} from 'three';
class Lensflare extends Mesh {
constructor() {
super( Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) );
this.isLensflare = true;
this.type = 'Lensflare';
this.frustumCulled = false;
this.renderOrder = Infinity;
//
const positionScreen = new Vector3();
const positionView = new Vector3();
// textures
const tempMap = new FramebufferTexture( 16, 16 );
const occlusionMap = new FramebufferTexture( 16, 16 );
let currentType = UnsignedByteType;
// material
const geometry = Lensflare.Geometry;
const material1a = new 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 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 Mesh( geometry, material1a );
//
const elements = [];
const shader = LensflareElement.Shader;
const material2 = new RawShaderMaterial( {
name: shader.name,
uniforms: {
'map': { value: null },
'occlusionMap': { value: occlusionMap },
'color': { value: new Color( 0xffffff ) },
'scale': { value: new Vector2() },
'screenPosition': { value: new Vector3() }
},
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader,
blending: AdditiveBlending,
transparent: true,
depthWrite: false
} );
const mesh2 = new Mesh( geometry, material2 );
this.addElement = function ( element ) {
elements.push( element );
};
//
const scale = new Vector2();
const screenPositionPixels = new Vector2();
const validArea = new Box2();
const viewport = new Vector4();
this.onBeforeRender = function ( renderer, scene, camera ) {
renderer.getCurrentViewport( viewport );
const renderTarget = renderer.getRenderTarget();
const type = ( renderTarget !== null ) ? renderTarget.texture.type : UnsignedByteType;
if ( currentType !== type ) {
tempMap.dispose();
occlusionMap.dispose();
tempMap.type = occlusionMap.type = type;
currentType = type;
}
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();
}
};
}
}
//
class LensflareElement {
constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) {
this.texture = texture;
this.size = size;
this.distance = distance;
this.color = color;
}
}
LensflareElement.Shader = {
name: 'LensflareElementShader',
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 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 InterleavedBuffer( float32Array, 5 );
geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
return geometry;
} )();
export { Lensflare, LensflareElement };

1176
node_modules/three/examples/jsm/objects/MarchingCubes.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

264
node_modules/three/examples/jsm/objects/Reflector.js generated vendored Normal file
View File

@@ -0,0 +1,264 @@
import {
Color,
Matrix4,
Mesh,
PerspectiveCamera,
Plane,
ShaderMaterial,
UniformsUtils,
Vector3,
Vector4,
WebGLRenderTarget,
HalfFloatType
} from 'three';
class Reflector extends Mesh {
constructor( geometry, options = {} ) {
super( geometry );
this.isReflector = true;
this.type = 'Reflector';
this.camera = new PerspectiveCamera();
const scope = this;
const color = ( options.color !== undefined ) ? new Color( options.color ) : new 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 Plane();
const normal = new Vector3();
const reflectorWorldPosition = new Vector3();
const cameraWorldPosition = new Vector3();
const rotationMatrix = new Matrix4();
const lookAtPosition = new Vector3( 0, 0, - 1 );
const clipPlane = new Vector4();
const view = new Vector3();
const target = new Vector3();
const q = new Vector4();
const textureMatrix = new Matrix4();
const virtualCamera = this.camera;
const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, { samples: multisample, type: HalfFloatType } );
const material = new ShaderMaterial( {
name: ( shader.name !== undefined ) ? shader.name : 'unspecified',
uniforms: 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
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.ReflectorShader = {
name: '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 );
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`
};
export { Reflector };

View File

@@ -0,0 +1,352 @@
import {
Color,
Matrix4,
Mesh,
PerspectiveCamera,
ShaderMaterial,
UniformsUtils,
Vector2,
Vector3,
WebGLRenderTarget,
DepthTexture,
UnsignedShortType,
NearestFilter,
Plane,
HalfFloatType
} from 'three';
class ReflectorForSSRPass extends Mesh {
constructor( geometry, options = {} ) {
super( geometry );
this.isReflectorForSSRPass = true;
this.type = 'ReflectorForSSRPass';
const scope = this;
const color = ( options.color !== undefined ) ? new Color( options.color ) : new 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 Vector3( 0, 1, 0 );
const vecTemp0 = new Vector3();
const vecTemp1 = new 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 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 Vector3();
const reflectorWorldPosition = new Vector3();
const cameraWorldPosition = new Vector3();
const rotationMatrix = new Matrix4();
const lookAtPosition = new Vector3( 0, 0, - 1 );
const view = new Vector3();
const target = new Vector3();
const textureMatrix = new Matrix4();
const virtualCamera = new PerspectiveCamera();
let depthTexture;
if ( useDepthTexture ) {
depthTexture = new DepthTexture();
depthTexture.type = UnsignedShortType;
depthTexture.minFilter = NearestFilter;
depthTexture.magFilter = NearestFilter;
}
const parameters = {
depthTexture: useDepthTexture ? depthTexture : null,
type: HalfFloatType
};
const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
const material = new ShaderMaterial( {
name: ( shader.name !== undefined ) ? shader.name : 'unspecified',
transparent: useDepthTexture,
defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
useDepthTexture
} ),
uniforms: 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 Plane( new 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 );
// 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.ReflectorShader = {
name: 'ReflectorShader',
defines: {
DISTANCE_ATTENUATION: true,
FRESNEL: true,
},
uniforms: {
color: { value: null },
tDiffuse: { value: null },
tDepth: { value: null },
textureMatrix: { value: new Matrix4() },
maxDistance: { value: 180 },
opacity: { value: 0.5 },
fresnelCoe: { value: null },
virtualCameraNear: { value: null },
virtualCameraFar: { value: null },
virtualCameraProjectionMatrix: { value: new Matrix4() },
virtualCameraMatrixWorld: { value: new Matrix4() },
virtualCameraProjectionMatrixInverse: { value: new Matrix4() },
resolution: { value: new 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
}
`,
};
export { ReflectorForSSRPass };

327
node_modules/three/examples/jsm/objects/Refractor.js generated vendored Normal file
View File

@@ -0,0 +1,327 @@
import {
Color,
Matrix4,
Mesh,
PerspectiveCamera,
Plane,
Quaternion,
ShaderMaterial,
UniformsUtils,
Vector3,
Vector4,
WebGLRenderTarget,
HalfFloatType
} from 'three';
class Refractor extends Mesh {
constructor( geometry, options = {} ) {
super( geometry );
this.isRefractor = true;
this.type = 'Refractor';
this.camera = new PerspectiveCamera();
const scope = this;
const color = ( options.color !== undefined ) ? new Color( options.color ) : new 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 = this.camera;
virtualCamera.matrixAutoUpdate = false;
virtualCamera.userData.refractor = true;
//
const refractorPlane = new Plane();
const textureMatrix = new Matrix4();
// render target
const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, { samples: multisample, type: HalfFloatType } );
// material
this.material = new ShaderMaterial( {
name: ( shader.name !== undefined ) ? shader.name : 'unspecified',
uniforms: 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 Vector3();
const cameraWorldPosition = new Vector3();
const rotationMatrix = new Matrix4();
const view = new Vector3();
const normal = new 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 Vector3();
const position = new Vector3();
const quaternion = new Quaternion();
const scale = new 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 Plane();
const clipVector = new Vector4();
const q = new 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. 516
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 ) {
// 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.RefractorShader = {
name: '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 );
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`
};
export { Refractor };

80
node_modules/three/examples/jsm/objects/ShadowMesh.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
import {
Matrix4,
Mesh,
MeshBasicMaterial,
EqualStencilFunc,
IncrementStencilOp
} from 'three';
/**
* A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane.
*/
const _shadowMatrix = new Matrix4();
class ShadowMesh extends Mesh {
constructor( mesh ) {
const shadowMaterial = new MeshBasicMaterial( {
color: 0x000000,
transparent: true,
opacity: 0.6,
depthWrite: false,
stencilWrite: true,
stencilFunc: EqualStencilFunc,
stencilRef: 0,
stencilZPass: IncrementStencilOp
} );
super( mesh.geometry, shadowMaterial );
this.isShadowMesh = true;
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 );
}
}
export { ShadowMesh };

219
node_modules/three/examples/jsm/objects/Sky.js generated vendored Normal file
View File

@@ -0,0 +1,219 @@
import {
BackSide,
BoxGeometry,
Mesh,
ShaderMaterial,
UniformsUtils,
Vector3
} from 'three';
/**
* 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 Mesh {
constructor() {
const shader = Sky.SkyShader;
const material = new ShaderMaterial( {
name: shader.name,
uniforms: UniformsUtils.clone( shader.uniforms ),
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader,
side: BackSide,
depthWrite: false
} );
super( new BoxGeometry( 1, 1, 1 ), material );
this.isSky = true;
}
}
Sky.SkyShader = {
name: 'SkyShader',
uniforms: {
'turbidity': { value: 2 },
'rayleigh': { value: 1 },
'mieCoefficient': { value: 0.005 },
'mieDirectionalG': { value: 0.8 },
'sunPosition': { value: new Vector3() },
'up': { value: new 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;
// 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 - cameraPosition );
// 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 <colorspace_fragment>
}`
};
export { Sky };

333
node_modules/three/examples/jsm/objects/Water.js generated vendored Normal file
View File

@@ -0,0 +1,333 @@
import {
Color,
FrontSide,
Matrix4,
Mesh,
PerspectiveCamera,
Plane,
ShaderMaterial,
UniformsLib,
UniformsUtils,
Vector3,
Vector4,
WebGLRenderTarget
} from 'three';
/**
* 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 Mesh {
constructor( geometry, options = {} ) {
super( geometry );
this.isWater = true;
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 Vector3( 0.70707, 0.70707, 0.0 );
const sunColor = new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
const waterColor = new Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
const eye = options.eye !== undefined ? options.eye : new Vector3( 0, 0, 0 );
const distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
const side = options.side !== undefined ? options.side : FrontSide;
const fog = options.fog !== undefined ? options.fog : false;
//
const mirrorPlane = new Plane();
const normal = new Vector3();
const mirrorWorldPosition = new Vector3();
const cameraWorldPosition = new Vector3();
const rotationMatrix = new Matrix4();
const lookAtPosition = new Vector3( 0, 0, - 1 );
const clipPlane = new Vector4();
const view = new Vector3();
const target = new Vector3();
const q = new Vector4();
const textureMatrix = new Matrix4();
const mirrorCamera = new PerspectiveCamera();
const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight );
const mirrorShader = {
name: 'MirrorShader',
uniforms: UniformsUtils.merge( [
UniformsLib[ 'fog' ],
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 Matrix4() },
'sunColor': { value: new Color( 0x7F7F7F ) },
'sunDirection': { value: new Vector3( 0.70707, 0.70707, 0 ) },
'eye': { value: new Vector3() },
'waterColor': { value: new 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 <colorspace_fragment>
#include <fog_fragment>
}`
};
const material = new ShaderMaterial( {
name: mirrorShader.name,
uniforms: UniformsUtils.clone( mirrorShader.uniforms ),
vertexShader: mirrorShader.vertexShader,
fragmentShader: mirrorShader.fragmentShader,
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 );
}
};
}
}
export { Water };

361
node_modules/three/examples/jsm/objects/Water2.js generated vendored Normal file
View File

@@ -0,0 +1,361 @@
import {
Clock,
Color,
Matrix4,
Mesh,
RepeatWrapping,
ShaderMaterial,
TextureLoader,
UniformsLib,
UniformsUtils,
Vector2,
Vector4
} from 'three';
import { Reflector } from '../objects/Reflector.js';
import { Refractor } from '../objects/Refractor.js';
/**
* References:
* https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf
* http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html
*
*/
class Water extends Mesh {
constructor( geometry, options = {} ) {
super( geometry );
this.isWater = true;
this.type = 'Water';
const scope = this;
const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0xFFFFFF );
const textureWidth = options.textureWidth || 512;
const textureHeight = options.textureHeight || 512;
const clipBias = options.clipBias || 0;
const flowDirection = options.flowDirection || new 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 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 Matrix4();
const clock = new Clock();
// internal components
if ( Reflector === undefined ) {
console.error( 'THREE.Water: Required component Reflector not found.' );
return;
}
if ( Refractor === undefined ) {
console.error( 'THREE.Water: Required component Refractor not found.' );
return;
}
const reflector = new Reflector( geometry, {
textureWidth: textureWidth,
textureHeight: textureHeight,
clipBias: clipBias
} );
const refractor = new Refractor( geometry, {
textureWidth: textureWidth,
textureHeight: textureHeight,
clipBias: clipBias
} );
reflector.matrixAutoUpdate = false;
refractor.matrixAutoUpdate = false;
// material
this.material = new ShaderMaterial( {
name: shader.name,
uniforms: UniformsUtils.merge( [
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 = RepeatWrapping;
normalMap1.wrapS = normalMap1.wrapT = 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.WaterShader = {
name: '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 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 <colorspace_fragment>
#include <fog_fragment>
}`
};
export { Water };