Anlegen vom Raum-Scanner

This commit is contained in:
chk
2026-06-16 10:06:05 +02:00
commit 792022d1fb
1836 changed files with 773869 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
function WebGLAnimation() {
let context = null;
let isAnimating = false;
let animationLoop = null;
let requestId = null;
function onAnimationFrame( time, frame ) {
animationLoop( time, frame );
requestId = context.requestAnimationFrame( onAnimationFrame );
}
return {
start: function () {
if ( isAnimating === true ) return;
if ( animationLoop === null ) return;
requestId = context.requestAnimationFrame( onAnimationFrame );
isAnimating = true;
},
stop: function () {
context.cancelAnimationFrame( requestId );
isAnimating = false;
},
setAnimationLoop: function ( callback ) {
animationLoop = callback;
},
setContext: function ( value ) {
context = value;
}
};
}
export { WebGLAnimation };

View File

@@ -0,0 +1,237 @@
function WebGLAttributes( gl ) {
const buffers = new WeakMap();
function createBuffer( attribute, bufferType ) {
const array = attribute.array;
const usage = attribute.usage;
const size = array.byteLength;
const buffer = gl.createBuffer();
gl.bindBuffer( bufferType, buffer );
gl.bufferData( bufferType, array, usage );
attribute.onUploadCallback();
let type;
if ( array instanceof Float32Array ) {
type = gl.FLOAT;
} else if ( typeof Float16Array !== 'undefined' && array instanceof Float16Array ) {
type = gl.HALF_FLOAT;
} else if ( array instanceof Uint16Array ) {
if ( attribute.isFloat16BufferAttribute ) {
type = gl.HALF_FLOAT;
} else {
type = gl.UNSIGNED_SHORT;
}
} else if ( array instanceof Int16Array ) {
type = gl.SHORT;
} else if ( array instanceof Uint32Array ) {
type = gl.UNSIGNED_INT;
} else if ( array instanceof Int32Array ) {
type = gl.INT;
} else if ( array instanceof Int8Array ) {
type = gl.BYTE;
} else if ( array instanceof Uint8Array ) {
type = gl.UNSIGNED_BYTE;
} else if ( array instanceof Uint8ClampedArray ) {
type = gl.UNSIGNED_BYTE;
} else {
throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
}
return {
buffer: buffer,
type: type,
bytesPerElement: array.BYTES_PER_ELEMENT,
version: attribute.version,
size: size
};
}
function updateBuffer( buffer, attribute, bufferType ) {
const array = attribute.array;
const updateRanges = attribute.updateRanges;
gl.bindBuffer( bufferType, buffer );
if ( updateRanges.length === 0 ) {
// Not using update ranges
gl.bufferSubData( bufferType, 0, array );
} else {
// Before applying update ranges, we merge any adjacent / overlapping
// ranges to reduce load on `gl.bufferSubData`. Empirically, this has led
// to performance improvements for applications which make heavy use of
// update ranges. Likely due to GPU command overhead.
//
// Note that to reduce garbage collection between frames, we merge the
// update ranges in-place. This is safe because this method will clear the
// update ranges once updated.
updateRanges.sort( ( a, b ) => a.start - b.start );
// To merge the update ranges in-place, we work from left to right in the
// existing updateRanges array, merging ranges. This may result in a final
// array which is smaller than the original. This index tracks the last
// index representing a merged range, any data after this index can be
// trimmed once the merge algorithm is completed.
let mergeIndex = 0;
for ( let i = 1; i < updateRanges.length; i ++ ) {
const previousRange = updateRanges[ mergeIndex ];
const range = updateRanges[ i ];
// We add one here to merge adjacent ranges. This is safe because ranges
// operate over positive integers.
if ( range.start <= previousRange.start + previousRange.count + 1 ) {
previousRange.count = Math.max(
previousRange.count,
range.start + range.count - previousRange.start
);
} else {
++ mergeIndex;
updateRanges[ mergeIndex ] = range;
}
}
// Trim the array to only contain the merged ranges.
updateRanges.length = mergeIndex + 1;
for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
const range = updateRanges[ i ];
gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
array, range.start, range.count );
}
attribute.clearUpdateRanges();
}
attribute.onUploadCallback();
}
//
function get( attribute ) {
if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
return buffers.get( attribute );
}
function remove( attribute ) {
if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
const data = buffers.get( attribute );
if ( data ) {
gl.deleteBuffer( data.buffer );
buffers.delete( attribute );
}
}
function update( attribute, bufferType ) {
if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
if ( attribute.isGLBufferAttribute ) {
const cached = buffers.get( attribute );
if ( ! cached || cached.version < attribute.version ) {
buffers.set( attribute, {
buffer: attribute.buffer,
type: attribute.type,
bytesPerElement: attribute.elementSize,
version: attribute.version
} );
}
return;
}
const data = buffers.get( attribute );
if ( data === undefined ) {
buffers.set( attribute, createBuffer( attribute, bufferType ) );
} else if ( data.version < attribute.version ) {
if ( data.size !== attribute.array.byteLength ) {
throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' );
}
updateBuffer( data.buffer, attribute, bufferType );
data.version = attribute.version;
}
}
return {
get: get,
remove: remove,
update: update
};
}
export { WebGLAttributes };

View File

@@ -0,0 +1,303 @@
import { BackSide, FrontSide, CubeUVReflectionMapping, SRGBTransfer } from '../../constants.js';
import { BoxGeometry } from '../../geometries/BoxGeometry.js';
import { PlaneGeometry } from '../../geometries/PlaneGeometry.js';
import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
import { Color } from '../../math/Color.js';
import { ColorManagement } from '../../math/ColorManagement.js';
import { Euler } from '../../math/Euler.js';
import { Matrix4 } from '../../math/Matrix4.js';
import { Mesh } from '../../objects/Mesh.js';
import { ShaderLib } from '../shaders/ShaderLib.js';
import { cloneUniforms, getUnlitUniformColorSpace } from '../shaders/UniformsUtils.js';
const _rgb = { r: 0, b: 0, g: 0 };
const _e1 = /*@__PURE__*/ new Euler();
const _m1 = /*@__PURE__*/ new Matrix4();
function WebGLBackground( renderer, environments, state, objects, alpha, premultipliedAlpha ) {
const clearColor = new Color( 0x000000 );
let clearAlpha = alpha === true ? 0 : 1;
let planeMesh;
let boxMesh;
let currentBackground = null;
let currentBackgroundVersion = 0;
let currentTonemapping = null;
function getBackground( scene ) {
let background = scene.isScene === true ? scene.background : null;
if ( background && background.isTexture ) {
const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
background = environments.get( background, usePMREM );
}
return background;
}
function render( scene ) {
let forceClear = false;
const background = getBackground( scene );
if ( background === null ) {
setClear( clearColor, clearAlpha );
} else if ( background && background.isColor ) {
setClear( background, 1 );
forceClear = true;
}
const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
if ( environmentBlendMode === 'additive' ) {
state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
} else if ( environmentBlendMode === 'alpha-blend' ) {
state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
}
if ( renderer.autoClear || forceClear ) {
// buffers might not be writable which is required to ensure a correct clear
state.buffers.depth.setTest( true );
state.buffers.depth.setMask( true );
state.buffers.color.setMask( true );
renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
}
}
function addToRenderList( renderList, scene ) {
const background = getBackground( scene );
if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
if ( boxMesh === undefined ) {
boxMesh = new Mesh(
new BoxGeometry( 1, 1, 1 ),
new ShaderMaterial( {
name: 'BackgroundCubeMaterial',
uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ),
vertexShader: ShaderLib.backgroundCube.vertexShader,
fragmentShader: ShaderLib.backgroundCube.fragmentShader,
side: BackSide,
depthTest: false,
depthWrite: false,
fog: false,
allowOverride: false
} )
);
boxMesh.geometry.deleteAttribute( 'normal' );
boxMesh.geometry.deleteAttribute( 'uv' );
boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
this.matrixWorld.copyPosition( camera.matrixWorld );
};
// add "envMap" material property so the renderer can evaluate it like for built-in materials
Object.defineProperty( boxMesh.material, 'envMap', {
get: function () {
return this.uniforms.envMap.value;
}
} );
objects.update( boxMesh );
}
_e1.copy( scene.backgroundRotation );
// accommodate left-handed frame
_e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
// environment maps which are not cube render targets or PMREMs follow a different convention
_e1.y *= - 1;
_e1.z *= - 1;
}
boxMesh.material.uniforms.envMap.value = background;
boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
if ( currentBackground !== background ||
currentBackgroundVersion !== background.version ||
currentTonemapping !== renderer.toneMapping ) {
boxMesh.material.needsUpdate = true;
currentBackground = background;
currentBackgroundVersion = background.version;
currentTonemapping = renderer.toneMapping;
}
boxMesh.layers.enableAll();
// push to the pre-sorted opaque render list
renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
} else if ( background && background.isTexture ) {
if ( planeMesh === undefined ) {
planeMesh = new Mesh(
new PlaneGeometry( 2, 2 ),
new ShaderMaterial( {
name: 'BackgroundMaterial',
uniforms: cloneUniforms( ShaderLib.background.uniforms ),
vertexShader: ShaderLib.background.vertexShader,
fragmentShader: ShaderLib.background.fragmentShader,
side: FrontSide,
depthTest: false,
depthWrite: false,
fog: false,
allowOverride: false
} )
);
planeMesh.geometry.deleteAttribute( 'normal' );
// add "map" material property so the renderer can evaluate it like for built-in materials
Object.defineProperty( planeMesh.material, 'map', {
get: function () {
return this.uniforms.t2D.value;
}
} );
objects.update( planeMesh );
}
planeMesh.material.uniforms.t2D.value = background;
planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
if ( background.matrixAutoUpdate === true ) {
background.updateMatrix();
}
planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
if ( currentBackground !== background ||
currentBackgroundVersion !== background.version ||
currentTonemapping !== renderer.toneMapping ) {
planeMesh.material.needsUpdate = true;
currentBackground = background;
currentBackgroundVersion = background.version;
currentTonemapping = renderer.toneMapping;
}
planeMesh.layers.enableAll();
// push to the pre-sorted opaque render list
renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
}
}
function setClear( color, alpha ) {
color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
}
function dispose() {
if ( boxMesh !== undefined ) {
boxMesh.geometry.dispose();
boxMesh.material.dispose();
boxMesh = undefined;
}
if ( planeMesh !== undefined ) {
planeMesh.geometry.dispose();
planeMesh.material.dispose();
planeMesh = undefined;
}
}
return {
getClearColor: function () {
return clearColor;
},
setClearColor: function ( color, alpha = 1 ) {
clearColor.set( color );
clearAlpha = alpha;
setClear( clearColor, clearAlpha );
},
getClearAlpha: function () {
return clearAlpha;
},
setClearAlpha: function ( alpha ) {
clearAlpha = alpha;
setClear( clearColor, clearAlpha );
},
render: render,
addToRenderList: addToRenderList,
dispose: dispose
};
}
export { WebGLBackground };

View File

@@ -0,0 +1,666 @@
import { IntType } from '../../constants.js';
function WebGLBindingStates( gl, attributes ) {
const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
const bindingStates = {};
const defaultState = createBindingState( null );
let currentState = defaultState;
let forceUpdate = false;
function setup( object, material, program, geometry, index ) {
let updateBuffers = false;
const state = getBindingState( object, geometry, program, material );
if ( currentState !== state ) {
currentState = state;
bindVertexArrayObject( currentState.object );
}
updateBuffers = needsUpdate( object, geometry, program, index );
if ( updateBuffers ) saveCache( object, geometry, program, index );
if ( index !== null ) {
attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
}
if ( updateBuffers || forceUpdate ) {
forceUpdate = false;
setupVertexAttributes( object, material, program, geometry );
if ( index !== null ) {
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer );
}
}
}
function createVertexArrayObject() {
return gl.createVertexArray();
}
function bindVertexArrayObject( vao ) {
return gl.bindVertexArray( vao );
}
function deleteVertexArrayObject( vao ) {
return gl.deleteVertexArray( vao );
}
function getBindingState( object, geometry, program, material ) {
const wireframe = ( material.wireframe === true );
let objectMap = bindingStates[ geometry.id ];
if ( objectMap === undefined ) {
objectMap = {};
bindingStates[ geometry.id ] = objectMap;
}
// Each InstancedMesh requires unique binding states because it contains instanced attributes.
const objectId = ( object.isInstancedMesh === true ) ? object.id : 0;
let programMap = objectMap[ objectId ];
if ( programMap === undefined ) {
programMap = {};
objectMap[ objectId ] = programMap;
}
let stateMap = programMap[ program.id ];
if ( stateMap === undefined ) {
stateMap = {};
programMap[ program.id ] = stateMap;
}
let state = stateMap[ wireframe ];
if ( state === undefined ) {
state = createBindingState( createVertexArrayObject() );
stateMap[ wireframe ] = state;
}
return state;
}
function createBindingState( vao ) {
const newAttributes = [];
const enabledAttributes = [];
const attributeDivisors = [];
for ( let i = 0; i < maxVertexAttributes; i ++ ) {
newAttributes[ i ] = 0;
enabledAttributes[ i ] = 0;
attributeDivisors[ i ] = 0;
}
return {
// for backward compatibility on non-VAO support browser
geometry: null,
program: null,
wireframe: false,
newAttributes: newAttributes,
enabledAttributes: enabledAttributes,
attributeDivisors: attributeDivisors,
object: vao,
attributes: {},
index: null
};
}
function needsUpdate( object, geometry, program, index ) {
const cachedAttributes = currentState.attributes;
const geometryAttributes = geometry.attributes;
let attributesNum = 0;
const programAttributes = program.getAttributes();
for ( const name in programAttributes ) {
const programAttribute = programAttributes[ name ];
if ( programAttribute.location >= 0 ) {
const cachedAttribute = cachedAttributes[ name ];
let geometryAttribute = geometryAttributes[ name ];
if ( geometryAttribute === undefined ) {
if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
}
if ( cachedAttribute === undefined ) return true;
if ( cachedAttribute.attribute !== geometryAttribute ) return true;
if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true;
attributesNum ++;
}
}
if ( currentState.attributesNum !== attributesNum ) return true;
if ( currentState.index !== index ) return true;
return false;
}
function saveCache( object, geometry, program, index ) {
const cache = {};
const attributes = geometry.attributes;
let attributesNum = 0;
const programAttributes = program.getAttributes();
for ( const name in programAttributes ) {
const programAttribute = programAttributes[ name ];
if ( programAttribute.location >= 0 ) {
let attribute = attributes[ name ];
if ( attribute === undefined ) {
if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix;
if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor;
}
const data = {};
data.attribute = attribute;
if ( attribute && attribute.data ) {
data.data = attribute.data;
}
cache[ name ] = data;
attributesNum ++;
}
}
currentState.attributes = cache;
currentState.attributesNum = attributesNum;
currentState.index = index;
}
function initAttributes() {
const newAttributes = currentState.newAttributes;
for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
newAttributes[ i ] = 0;
}
}
function enableAttribute( attribute ) {
enableAttributeAndDivisor( attribute, 0 );
}
function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
const newAttributes = currentState.newAttributes;
const enabledAttributes = currentState.enabledAttributes;
const attributeDivisors = currentState.attributeDivisors;
newAttributes[ attribute ] = 1;
if ( enabledAttributes[ attribute ] === 0 ) {
gl.enableVertexAttribArray( attribute );
enabledAttributes[ attribute ] = 1;
}
if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
gl.vertexAttribDivisor( attribute, meshPerAttribute );
attributeDivisors[ attribute ] = meshPerAttribute;
}
}
function disableUnusedAttributes() {
const newAttributes = currentState.newAttributes;
const enabledAttributes = currentState.enabledAttributes;
for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
gl.disableVertexAttribArray( i );
enabledAttributes[ i ] = 0;
}
}
}
function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) {
if ( integer === true ) {
gl.vertexAttribIPointer( index, size, type, stride, offset );
} else {
gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
}
}
function setupVertexAttributes( object, material, program, geometry ) {
initAttributes();
const geometryAttributes = geometry.attributes;
const programAttributes = program.getAttributes();
const materialDefaultAttributeValues = material.defaultAttributeValues;
for ( const name in programAttributes ) {
const programAttribute = programAttributes[ name ];
if ( programAttribute.location >= 0 ) {
let geometryAttribute = geometryAttributes[ name ];
if ( geometryAttribute === undefined ) {
if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
}
if ( geometryAttribute !== undefined ) {
const normalized = geometryAttribute.normalized;
const size = geometryAttribute.itemSize;
const attribute = attributes.get( geometryAttribute );
// TODO Attribute may not be available on context restore
if ( attribute === undefined ) continue;
const buffer = attribute.buffer;
const type = attribute.type;
const bytesPerElement = attribute.bytesPerElement;
// check for integer attributes
const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType );
if ( geometryAttribute.isInterleavedBufferAttribute ) {
const data = geometryAttribute.data;
const stride = data.stride;
const offset = geometryAttribute.offset;
if ( data.isInstancedInterleavedBuffer ) {
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
}
if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
geometry._maxInstanceCount = data.meshPerAttribute * data.count;
}
} else {
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
enableAttribute( programAttribute.location + i );
}
}
gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
vertexAttribPointer(
programAttribute.location + i,
size / programAttribute.locationSize,
type,
normalized,
stride * bytesPerElement,
( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement,
integer
);
}
} else {
if ( geometryAttribute.isInstancedBufferAttribute ) {
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
}
if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
}
} else {
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
enableAttribute( programAttribute.location + i );
}
}
gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
vertexAttribPointer(
programAttribute.location + i,
size / programAttribute.locationSize,
type,
normalized,
size * bytesPerElement,
( size / programAttribute.locationSize ) * i * bytesPerElement,
integer
);
}
}
} else if ( materialDefaultAttributeValues !== undefined ) {
const value = materialDefaultAttributeValues[ name ];
if ( value !== undefined ) {
switch ( value.length ) {
case 2:
gl.vertexAttrib2fv( programAttribute.location, value );
break;
case 3:
gl.vertexAttrib3fv( programAttribute.location, value );
break;
case 4:
gl.vertexAttrib4fv( programAttribute.location, value );
break;
default:
gl.vertexAttrib1fv( programAttribute.location, value );
}
}
}
}
}
disableUnusedAttributes();
}
function dispose() {
reset();
for ( const geometryId in bindingStates ) {
const objectMap = bindingStates[ geometryId ];
for ( const objectId in objectMap ) {
const programMap = objectMap[ objectId ];
for ( const programId in programMap ) {
const stateMap = programMap[ programId ];
for ( const wireframe in stateMap ) {
deleteVertexArrayObject( stateMap[ wireframe ].object );
delete stateMap[ wireframe ];
}
delete programMap[ programId ];
}
}
delete bindingStates[ geometryId ];
}
}
function releaseStatesOfGeometry( geometry ) {
if ( bindingStates[ geometry.id ] === undefined ) return;
const objectMap = bindingStates[ geometry.id ];
for ( const objectId in objectMap ) {
const programMap = objectMap[ objectId ];
for ( const programId in programMap ) {
const stateMap = programMap[ programId ];
for ( const wireframe in stateMap ) {
deleteVertexArrayObject( stateMap[ wireframe ].object );
delete stateMap[ wireframe ];
}
delete programMap[ programId ];
}
}
delete bindingStates[ geometry.id ];
}
function releaseStatesOfProgram( program ) {
for ( const geometryId in bindingStates ) {
const objectMap = bindingStates[ geometryId ];
for ( const objectId in objectMap ) {
const programMap = objectMap[ objectId ];
if ( programMap[ program.id ] === undefined ) continue;
const stateMap = programMap[ program.id ];
for ( const wireframe in stateMap ) {
deleteVertexArrayObject( stateMap[ wireframe ].object );
delete stateMap[ wireframe ];
}
delete programMap[ program.id ];
}
}
}
function releaseStatesOfObject( object ) {
for ( const geometryId in bindingStates ) {
const objectMap = bindingStates[ geometryId ];
const objectId = ( object.isInstancedMesh === true ) ? object.id : 0;
const programMap = objectMap[ objectId ];
if ( programMap === undefined ) continue;
for ( const programId in programMap ) {
const stateMap = programMap[ programId ];
for ( const wireframe in stateMap ) {
deleteVertexArrayObject( stateMap[ wireframe ].object );
delete stateMap[ wireframe ];
}
delete programMap[ programId ];
}
delete objectMap[ objectId ];
if ( Object.keys( objectMap ).length === 0 ) {
delete bindingStates[ geometryId ];
}
}
}
function reset() {
resetDefaultState();
forceUpdate = true;
if ( currentState === defaultState ) return;
currentState = defaultState;
bindVertexArrayObject( currentState.object );
}
// for backward-compatibility
function resetDefaultState() {
defaultState.geometry = null;
defaultState.program = null;
defaultState.wireframe = false;
}
return {
setup: setup,
reset: reset,
resetDefaultState: resetDefaultState,
dispose: dispose,
releaseStatesOfGeometry: releaseStatesOfGeometry,
releaseStatesOfObject: releaseStatesOfObject,
releaseStatesOfProgram: releaseStatesOfProgram,
initAttributes: initAttributes,
enableAttribute: enableAttribute,
disableUnusedAttributes: disableUnusedAttributes
};
}
export { WebGLBindingStates };

View File

@@ -0,0 +1,89 @@
function WebGLBufferRenderer( gl, extensions, info ) {
let mode;
function setMode( value ) {
mode = value;
}
function render( start, count ) {
gl.drawArrays( mode, start, count );
info.update( count, mode, 1 );
}
function renderInstances( start, count, primcount ) {
if ( primcount === 0 ) return;
gl.drawArraysInstanced( mode, start, count, primcount );
info.update( count, mode, primcount );
}
function renderMultiDraw( starts, counts, drawCount ) {
if ( drawCount === 0 ) return;
const extension = extensions.get( 'WEBGL_multi_draw' );
extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount );
let elementCount = 0;
for ( let i = 0; i < drawCount; i ++ ) {
elementCount += counts[ i ];
}
info.update( elementCount, mode, 1 );
}
function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
if ( drawCount === 0 ) return;
const extension = extensions.get( 'WEBGL_multi_draw' );
if ( extension === null ) {
for ( let i = 0; i < starts.length; i ++ ) {
renderInstances( starts[ i ], counts[ i ], primcount[ i ] );
}
} else {
extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount );
let elementCount = 0;
for ( let i = 0; i < drawCount; i ++ ) {
elementCount += counts[ i ] * primcount[ i ];
}
info.update( elementCount, mode, 1 );
}
}
//
this.setMode = setMode;
this.render = render;
this.renderInstances = renderInstances;
this.renderMultiDraw = renderMultiDraw;
this.renderMultiDrawInstances = renderMultiDrawInstances;
}
export { WebGLBufferRenderer };

View File

@@ -0,0 +1,144 @@
import { FloatType, HalfFloatType, RGBAFormat, UnsignedByteType } from '../../constants.js';
import { warn } from '../../utils.js';
function WebGLCapabilities( gl, extensions, parameters, utils ) {
let maxAnisotropy;
function getMaxAnisotropy() {
if ( maxAnisotropy !== undefined ) return maxAnisotropy;
if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
} else {
maxAnisotropy = 0;
}
return maxAnisotropy;
}
function textureFormatReadable( textureFormat ) {
if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
return false;
}
return true;
}
function textureTypeReadable( textureType ) {
const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) );
if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513)
textureType !== FloatType && ! halfFloatSupportedByExt ) {
return false;
}
return true;
}
function getMaxPrecision( precision ) {
if ( precision === 'highp' ) {
if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
return 'highp';
}
precision = 'mediump';
}
if ( precision === 'mediump' ) {
if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
return 'mediump';
}
}
return 'lowp';
}
let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
const maxPrecision = getMaxPrecision( precision );
if ( maxPrecision !== precision ) {
warn( 'WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
precision = maxPrecision;
}
const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
const reversedDepthBuffer = parameters.reversedDepthBuffer === true && extensions.has( 'EXT_clip_control' );
const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
const maxSamples = gl.getParameter( gl.MAX_SAMPLES );
const samples = gl.getParameter( gl.SAMPLES );
return {
isWebGL2: true, // keeping this for backwards compatibility
getMaxAnisotropy: getMaxAnisotropy,
getMaxPrecision: getMaxPrecision,
textureFormatReadable: textureFormatReadable,
textureTypeReadable: textureTypeReadable,
precision: precision,
logarithmicDepthBuffer: logarithmicDepthBuffer,
reversedDepthBuffer: reversedDepthBuffer,
maxTextures: maxTextures,
maxVertexTextures: maxVertexTextures,
maxTextureSize: maxTextureSize,
maxCubemapSize: maxCubemapSize,
maxAttributes: maxAttributes,
maxVertexUniforms: maxVertexUniforms,
maxVaryings: maxVaryings,
maxFragmentUniforms: maxFragmentUniforms,
maxSamples: maxSamples,
samples: samples
};
}
export { WebGLCapabilities };

171
node_modules/three/src/renderers/webgl/WebGLClipping.js generated vendored Normal file
View File

@@ -0,0 +1,171 @@
import { Matrix3 } from '../../math/Matrix3.js';
import { Plane } from '../../math/Plane.js';
function WebGLClipping( properties ) {
const scope = this;
let globalState = null,
numGlobalPlanes = 0,
localClippingEnabled = false,
renderingShadows = false;
const plane = new Plane(),
viewNormalMatrix = new Matrix3(),
uniform = { value: null, needsUpdate: false };
this.uniform = uniform;
this.numPlanes = 0;
this.numIntersection = 0;
this.init = function ( planes, enableLocalClipping ) {
const enabled =
planes.length !== 0 ||
enableLocalClipping ||
// enable state of previous frame - the clipping code has to
// run another frame in order to reset the state:
numGlobalPlanes !== 0 ||
localClippingEnabled;
localClippingEnabled = enableLocalClipping;
numGlobalPlanes = planes.length;
return enabled;
};
this.beginShadows = function () {
renderingShadows = true;
projectPlanes( null );
};
this.endShadows = function () {
renderingShadows = false;
};
this.setGlobalState = function ( planes, camera ) {
globalState = projectPlanes( planes, camera, 0 );
};
this.setState = function ( material, camera, useCache ) {
const planes = material.clippingPlanes,
clipIntersection = material.clipIntersection,
clipShadows = material.clipShadows;
const materialProperties = properties.get( material );
if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
// there's no local clipping
if ( renderingShadows ) {
// there's no global clipping
projectPlanes( null );
} else {
resetGlobalState();
}
} else {
const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
lGlobal = nGlobal * 4;
let dstArray = materialProperties.clippingState || null;
uniform.value = dstArray; // ensure unique state
dstArray = projectPlanes( planes, camera, lGlobal, useCache );
for ( let i = 0; i !== lGlobal; ++ i ) {
dstArray[ i ] = globalState[ i ];
}
materialProperties.clippingState = dstArray;
this.numIntersection = clipIntersection ? this.numPlanes : 0;
this.numPlanes += nGlobal;
}
};
function resetGlobalState() {
if ( uniform.value !== globalState ) {
uniform.value = globalState;
uniform.needsUpdate = numGlobalPlanes > 0;
}
scope.numPlanes = numGlobalPlanes;
scope.numIntersection = 0;
}
function projectPlanes( planes, camera, dstOffset, skipTransform ) {
const nPlanes = planes !== null ? planes.length : 0;
let dstArray = null;
if ( nPlanes !== 0 ) {
dstArray = uniform.value;
if ( skipTransform !== true || dstArray === null ) {
const flatSize = dstOffset + nPlanes * 4,
viewMatrix = camera.matrixWorldInverse;
viewNormalMatrix.getNormalMatrix( viewMatrix );
if ( dstArray === null || dstArray.length < flatSize ) {
dstArray = new Float32Array( flatSize );
}
for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
plane.normal.toArray( dstArray, i4 );
dstArray[ i4 + 3 ] = plane.constant;
}
}
uniform.value = dstArray;
uniform.needsUpdate = true;
}
scope.numPlanes = nPlanes;
scope.numIntersection = 0;
return dstArray;
}
}
export { WebGLClipping };

View File

@@ -0,0 +1,228 @@
import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from '../../constants.js';
import { PMREMGenerator } from '../../extras/PMREMGenerator.js';
import { WebGLCubeRenderTarget } from '../WebGLCubeRenderTarget.js';
function WebGLEnvironments( renderer ) {
let cubeMaps = new WeakMap();
let pmremMaps = new WeakMap();
let pmremGenerator = null;
function get( texture, usePMREM = false ) {
if ( texture === null || texture === undefined ) return null;
if ( usePMREM ) {
return getPMREM( texture );
}
return getCube( texture );
}
function getCube( texture ) {
if ( texture && texture.isTexture ) {
const mapping = texture.mapping;
if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
if ( cubeMaps.has( texture ) ) {
const cubemap = cubeMaps.get( texture ).texture;
return mapTextureMapping( cubemap, texture.mapping );
} else {
const image = texture.image;
if ( image && image.height > 0 ) {
const renderTarget = new WebGLCubeRenderTarget( image.height );
renderTarget.fromEquirectangularTexture( renderer, texture );
cubeMaps.set( texture, renderTarget );
texture.addEventListener( 'dispose', onCubemapDispose );
return mapTextureMapping( renderTarget.texture, texture.mapping );
} else {
// image not yet ready. try the conversion next frame
return null;
}
}
}
}
return texture;
}
function getPMREM( texture ) {
if ( texture && texture.isTexture ) {
const mapping = texture.mapping;
const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
// equirect/cube map to cubeUV conversion
if ( isEquirectMap || isCubeMap ) {
let renderTarget = pmremMaps.get( texture );
const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0;
if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) {
if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget );
renderTarget.texture.pmremVersion = texture.pmremVersion;
pmremMaps.set( texture, renderTarget );
return renderTarget.texture;
} else {
if ( renderTarget !== undefined ) {
return renderTarget.texture;
} else {
const image = texture.image;
if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
renderTarget.texture.pmremVersion = texture.pmremVersion;
pmremMaps.set( texture, renderTarget );
texture.addEventListener( 'dispose', onPMREMDispose );
return renderTarget.texture;
} else {
// image not yet ready. try the conversion next frame
return null;
}
}
}
}
}
return texture;
}
function mapTextureMapping( texture, mapping ) {
if ( mapping === EquirectangularReflectionMapping ) {
texture.mapping = CubeReflectionMapping;
} else if ( mapping === EquirectangularRefractionMapping ) {
texture.mapping = CubeRefractionMapping;
}
return texture;
}
function isCubeTextureComplete( image ) {
let count = 0;
const length = 6;
for ( let i = 0; i < length; i ++ ) {
if ( image[ i ] !== undefined ) count ++;
}
return count === length;
}
function onCubemapDispose( event ) {
const texture = event.target;
texture.removeEventListener( 'dispose', onCubemapDispose );
const cubemap = cubeMaps.get( texture );
if ( cubemap !== undefined ) {
cubeMaps.delete( texture );
cubemap.dispose();
}
}
function onPMREMDispose( event ) {
const texture = event.target;
texture.removeEventListener( 'dispose', onPMREMDispose );
const pmrem = pmremMaps.get( texture );
if ( pmrem !== undefined ) {
pmremMaps.delete( texture );
pmrem.dispose();
}
}
function dispose() {
cubeMaps = new WeakMap();
pmremMaps = new WeakMap();
if ( pmremGenerator !== null ) {
pmremGenerator.dispose();
pmremGenerator = null;
}
}
return {
get: get,
dispose: dispose
};
}
export { WebGLEnvironments };

View File

@@ -0,0 +1,61 @@
import { warnOnce } from '../../utils.js';
function WebGLExtensions( gl ) {
const extensions = {};
function getExtension( name ) {
if ( extensions[ name ] !== undefined ) {
return extensions[ name ];
}
const extension = gl.getExtension( name );
extensions[ name ] = extension;
return extension;
}
return {
has: function ( name ) {
return getExtension( name ) !== null;
},
init: function () {
getExtension( 'EXT_color_buffer_float' );
getExtension( 'WEBGL_clip_cull_distance' );
getExtension( 'OES_texture_float_linear' );
getExtension( 'EXT_color_buffer_half_float' );
getExtension( 'WEBGL_multisampled_render_to_texture' );
getExtension( 'WEBGL_render_shared_exponent' );
},
get: function ( name ) {
const extension = getExtension( name );
if ( extension === null ) {
warnOnce( 'WebGLRenderer: ' + name + ' extension not supported.' );
}
return extension;
}
};
}
export { WebGLExtensions };

View File

@@ -0,0 +1,186 @@
import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js';
function WebGLGeometries( gl, attributes, info, bindingStates ) {
const geometries = {};
const wireframeAttributes = new WeakMap();
function onGeometryDispose( event ) {
const geometry = event.target;
if ( geometry.index !== null ) {
attributes.remove( geometry.index );
}
for ( const name in geometry.attributes ) {
attributes.remove( geometry.attributes[ name ] );
}
geometry.removeEventListener( 'dispose', onGeometryDispose );
delete geometries[ geometry.id ];
const attribute = wireframeAttributes.get( geometry );
if ( attribute ) {
attributes.remove( attribute );
wireframeAttributes.delete( geometry );
}
bindingStates.releaseStatesOfGeometry( geometry );
if ( geometry.isInstancedBufferGeometry === true ) {
delete geometry._maxInstanceCount;
}
//
info.memory.geometries --;
}
function get( object, geometry ) {
if ( geometries[ geometry.id ] === true ) return geometry;
geometry.addEventListener( 'dispose', onGeometryDispose );
geometries[ geometry.id ] = true;
info.memory.geometries ++;
return geometry;
}
function update( geometry ) {
const geometryAttributes = geometry.attributes;
// Updating index buffer in VAO now. See WebGLBindingStates.
for ( const name in geometryAttributes ) {
attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
}
}
function updateWireframeAttribute( geometry ) {
const indices = [];
const geometryIndex = geometry.index;
const geometryPosition = geometry.attributes.position;
let version = 0;
if ( geometryPosition === undefined ) {
return;
}
if ( geometryIndex !== null ) {
const array = geometryIndex.array;
version = geometryIndex.version;
for ( let i = 0, l = array.length; i < l; i += 3 ) {
const a = array[ i + 0 ];
const b = array[ i + 1 ];
const c = array[ i + 2 ];
indices.push( a, b, b, c, c, a );
}
} else {
const array = geometryPosition.array;
version = geometryPosition.version;
for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
const a = i + 0;
const b = i + 1;
const c = i + 2;
indices.push( a, b, b, c, c, a );
}
}
// check whether a 32 bit or 16 bit buffer is required to store the indices
// account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
const attribute = new ( geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
attribute.version = version;
// Updating index buffer in VAO now. See WebGLBindingStates
//
const previousAttribute = wireframeAttributes.get( geometry );
if ( previousAttribute ) attributes.remove( previousAttribute );
//
wireframeAttributes.set( geometry, attribute );
}
function getWireframeAttribute( geometry ) {
const currentAttribute = wireframeAttributes.get( geometry );
if ( currentAttribute ) {
const geometryIndex = geometry.index;
if ( geometryIndex !== null ) {
// if the attribute is obsolete, create a new one
if ( currentAttribute.version < geometryIndex.version ) {
updateWireframeAttribute( geometry );
}
}
} else {
updateWireframeAttribute( geometry );
}
return wireframeAttributes.get( geometry );
}
return {
get: get,
update: update,
getWireframeAttribute: getWireframeAttribute
};
}
export { WebGLGeometries };

View File

@@ -0,0 +1,100 @@
function WebGLIndexedBufferRenderer( gl, extensions, info ) {
let mode;
function setMode( value ) {
mode = value;
}
let type, bytesPerElement;
function setIndex( value ) {
type = value.type;
bytesPerElement = value.bytesPerElement;
}
function render( start, count ) {
gl.drawElements( mode, count, type, start * bytesPerElement );
info.update( count, mode, 1 );
}
function renderInstances( start, count, primcount ) {
if ( primcount === 0 ) return;
gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount );
info.update( count, mode, primcount );
}
function renderMultiDraw( starts, counts, drawCount ) {
if ( drawCount === 0 ) return;
const extension = extensions.get( 'WEBGL_multi_draw' );
extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount );
let elementCount = 0;
for ( let i = 0; i < drawCount; i ++ ) {
elementCount += counts[ i ];
}
info.update( elementCount, mode, 1 );
}
function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
if ( drawCount === 0 ) return;
const extension = extensions.get( 'WEBGL_multi_draw' );
if ( extension === null ) {
for ( let i = 0; i < starts.length; i ++ ) {
renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] );
}
} else {
extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount );
let elementCount = 0;
for ( let i = 0; i < drawCount; i ++ ) {
elementCount += counts[ i ] * primcount[ i ];
}
info.update( elementCount, mode, 1 );
}
}
//
this.setMode = setMode;
this.setIndex = setIndex;
this.render = render;
this.renderInstances = renderInstances;
this.renderMultiDraw = renderMultiDraw;
this.renderMultiDrawInstances = renderMultiDrawInstances;
}
export { WebGLIndexedBufferRenderer };

73
node_modules/three/src/renderers/webgl/WebGLInfo.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
import { error } from '../../utils.js';
function WebGLInfo( gl ) {
const memory = {
geometries: 0,
textures: 0
};
const render = {
frame: 0,
calls: 0,
triangles: 0,
points: 0,
lines: 0
};
function update( count, mode, instanceCount ) {
render.calls ++;
switch ( mode ) {
case gl.TRIANGLES:
render.triangles += instanceCount * ( count / 3 );
break;
case gl.LINES:
render.lines += instanceCount * ( count / 2 );
break;
case gl.LINE_STRIP:
render.lines += instanceCount * ( count - 1 );
break;
case gl.LINE_LOOP:
render.lines += instanceCount * count;
break;
case gl.POINTS:
render.points += instanceCount * count;
break;
default:
error( 'WebGLInfo: Unknown draw mode:', mode );
break;
}
}
function reset() {
render.calls = 0;
render.triangles = 0;
render.points = 0;
render.lines = 0;
}
return {
memory: memory,
render: render,
programs: null,
autoReset: true,
reset: reset,
update: update
};
}
export { WebGLInfo };

584
node_modules/three/src/renderers/webgl/WebGLLights.js generated vendored Normal file
View File

@@ -0,0 +1,584 @@
import { Color } from '../../math/Color.js';
import { Matrix4 } from '../../math/Matrix4.js';
import { Vector2 } from '../../math/Vector2.js';
import { Vector3 } from '../../math/Vector3.js';
import { UniformsLib } from '../shaders/UniformsLib.js';
import { RGFormat } from '../../constants.js';
function UniformsCache() {
const lights = {};
return {
get: function ( light ) {
if ( lights[ light.id ] !== undefined ) {
return lights[ light.id ];
}
let uniforms;
switch ( light.type ) {
case 'DirectionalLight':
uniforms = {
direction: new Vector3(),
color: new Color()
};
break;
case 'SpotLight':
uniforms = {
position: new Vector3(),
direction: new Vector3(),
color: new Color(),
distance: 0,
coneCos: 0,
penumbraCos: 0,
decay: 0
};
break;
case 'PointLight':
uniforms = {
position: new Vector3(),
color: new Color(),
distance: 0,
decay: 0
};
break;
case 'HemisphereLight':
uniforms = {
direction: new Vector3(),
skyColor: new Color(),
groundColor: new Color()
};
break;
case 'RectAreaLight':
uniforms = {
color: new Color(),
position: new Vector3(),
halfWidth: new Vector3(),
halfHeight: new Vector3()
};
break;
}
lights[ light.id ] = uniforms;
return uniforms;
}
};
}
function ShadowUniformsCache() {
const lights = {};
return {
get: function ( light ) {
if ( lights[ light.id ] !== undefined ) {
return lights[ light.id ];
}
let uniforms;
switch ( light.type ) {
case 'DirectionalLight':
uniforms = {
shadowIntensity: 1,
shadowBias: 0,
shadowNormalBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2()
};
break;
case 'SpotLight':
uniforms = {
shadowIntensity: 1,
shadowBias: 0,
shadowNormalBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2()
};
break;
case 'PointLight':
uniforms = {
shadowIntensity: 1,
shadowBias: 0,
shadowNormalBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2(),
shadowCameraNear: 1,
shadowCameraFar: 1000
};
break;
// TODO (abelnation): set RectAreaLight shadow uniforms
}
lights[ light.id ] = uniforms;
return uniforms;
}
};
}
let nextVersion = 0;
function shadowCastingAndTexturingLightsFirst( lightA, lightB ) {
return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 );
}
function WebGLLights( extensions ) {
const cache = new UniformsCache();
const shadowCache = ShadowUniformsCache();
const state = {
version: 0,
hash: {
directionalLength: - 1,
pointLength: - 1,
spotLength: - 1,
rectAreaLength: - 1,
hemiLength: - 1,
numDirectionalShadows: - 1,
numPointShadows: - 1,
numSpotShadows: - 1,
numSpotMaps: - 1,
numLightProbes: - 1
},
ambient: [ 0, 0, 0 ],
probe: [],
directional: [],
directionalShadow: [],
directionalShadowMap: [],
directionalShadowMatrix: [],
spot: [],
spotLightMap: [],
spotShadow: [],
spotShadowMap: [],
spotLightMatrix: [],
rectArea: [],
rectAreaLTC1: null,
rectAreaLTC2: null,
point: [],
pointShadow: [],
pointShadowMap: [],
pointShadowMatrix: [],
hemi: [],
numSpotLightShadowsWithMaps: 0,
numLightProbes: 0
};
for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
const vector3 = new Vector3();
const matrix4 = new Matrix4();
const matrix42 = new Matrix4();
function setup( lights ) {
let r = 0, g = 0, b = 0;
for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
let directionalLength = 0;
let pointLength = 0;
let spotLength = 0;
let rectAreaLength = 0;
let hemiLength = 0;
let numDirectionalShadows = 0;
let numPointShadows = 0;
let numSpotShadows = 0;
let numSpotMaps = 0;
let numSpotShadowsWithMaps = 0;
let numLightProbes = 0;
// ordering : [shadow casting + map texturing, map texturing, shadow casting, none ]
lights.sort( shadowCastingAndTexturingLightsFirst );
for ( let i = 0, l = lights.length; i < l; i ++ ) {
const light = lights[ i ];
const color = light.color;
const intensity = light.intensity;
const distance = light.distance;
let shadowMap = null;
if ( light.shadow && light.shadow.map ) {
if ( light.shadow.map.texture.format === RGFormat ) {
// VSM uses color texture with blurred mean/std_dev
shadowMap = light.shadow.map.texture;
} else {
// Other types use depth texture
shadowMap = light.shadow.map.depthTexture || light.shadow.map.texture;
}
}
if ( light.isAmbientLight ) {
r += color.r * intensity;
g += color.g * intensity;
b += color.b * intensity;
} else if ( light.isLightProbe ) {
for ( let j = 0; j < 9; j ++ ) {
state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
}
numLightProbes ++;
} else if ( light.isDirectionalLight ) {
const uniforms = cache.get( light );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
if ( light.castShadow ) {
const shadow = light.shadow;
const shadowUniforms = shadowCache.get( light );
shadowUniforms.shadowIntensity = shadow.intensity;
shadowUniforms.shadowBias = shadow.bias;
shadowUniforms.shadowNormalBias = shadow.normalBias;
shadowUniforms.shadowRadius = shadow.radius;
shadowUniforms.shadowMapSize = shadow.mapSize;
state.directionalShadow[ directionalLength ] = shadowUniforms;
state.directionalShadowMap[ directionalLength ] = shadowMap;
state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
numDirectionalShadows ++;
}
state.directional[ directionalLength ] = uniforms;
directionalLength ++;
} else if ( light.isSpotLight ) {
const uniforms = cache.get( light );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.color.copy( color ).multiplyScalar( intensity );
uniforms.distance = distance;
uniforms.coneCos = Math.cos( light.angle );
uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
uniforms.decay = light.decay;
state.spot[ spotLength ] = uniforms;
const shadow = light.shadow;
if ( light.map ) {
state.spotLightMap[ numSpotMaps ] = light.map;
numSpotMaps ++;
// make sure the lightMatrix is up to date
// TODO : do it if required only
shadow.updateMatrices( light );
if ( light.castShadow ) numSpotShadowsWithMaps ++;
}
state.spotLightMatrix[ spotLength ] = shadow.matrix;
if ( light.castShadow ) {
const shadowUniforms = shadowCache.get( light );
shadowUniforms.shadowIntensity = shadow.intensity;
shadowUniforms.shadowBias = shadow.bias;
shadowUniforms.shadowNormalBias = shadow.normalBias;
shadowUniforms.shadowRadius = shadow.radius;
shadowUniforms.shadowMapSize = shadow.mapSize;
state.spotShadow[ spotLength ] = shadowUniforms;
state.spotShadowMap[ spotLength ] = shadowMap;
numSpotShadows ++;
}
spotLength ++;
} else if ( light.isRectAreaLight ) {
const uniforms = cache.get( light );
uniforms.color.copy( color ).multiplyScalar( intensity );
uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
state.rectArea[ rectAreaLength ] = uniforms;
rectAreaLength ++;
} else if ( light.isPointLight ) {
const uniforms = cache.get( light );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
uniforms.distance = light.distance;
uniforms.decay = light.decay;
if ( light.castShadow ) {
const shadow = light.shadow;
const shadowUniforms = shadowCache.get( light );
shadowUniforms.shadowIntensity = shadow.intensity;
shadowUniforms.shadowBias = shadow.bias;
shadowUniforms.shadowNormalBias = shadow.normalBias;
shadowUniforms.shadowRadius = shadow.radius;
shadowUniforms.shadowMapSize = shadow.mapSize;
shadowUniforms.shadowCameraNear = shadow.camera.near;
shadowUniforms.shadowCameraFar = shadow.camera.far;
state.pointShadow[ pointLength ] = shadowUniforms;
state.pointShadowMap[ pointLength ] = shadowMap;
state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
numPointShadows ++;
}
state.point[ pointLength ] = uniforms;
pointLength ++;
} else if ( light.isHemisphereLight ) {
const uniforms = cache.get( light );
uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
state.hemi[ hemiLength ] = uniforms;
hemiLength ++;
}
}
if ( rectAreaLength > 0 ) {
if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
} else {
state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
}
}
state.ambient[ 0 ] = r;
state.ambient[ 1 ] = g;
state.ambient[ 2 ] = b;
const hash = state.hash;
if ( hash.directionalLength !== directionalLength ||
hash.pointLength !== pointLength ||
hash.spotLength !== spotLength ||
hash.rectAreaLength !== rectAreaLength ||
hash.hemiLength !== hemiLength ||
hash.numDirectionalShadows !== numDirectionalShadows ||
hash.numPointShadows !== numPointShadows ||
hash.numSpotShadows !== numSpotShadows ||
hash.numSpotMaps !== numSpotMaps ||
hash.numLightProbes !== numLightProbes ) {
state.directional.length = directionalLength;
state.spot.length = spotLength;
state.rectArea.length = rectAreaLength;
state.point.length = pointLength;
state.hemi.length = hemiLength;
state.directionalShadow.length = numDirectionalShadows;
state.directionalShadowMap.length = numDirectionalShadows;
state.pointShadow.length = numPointShadows;
state.pointShadowMap.length = numPointShadows;
state.spotShadow.length = numSpotShadows;
state.spotShadowMap.length = numSpotShadows;
state.directionalShadowMatrix.length = numDirectionalShadows;
state.pointShadowMatrix.length = numPointShadows;
state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
state.spotLightMap.length = numSpotMaps;
state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
state.numLightProbes = numLightProbes;
hash.directionalLength = directionalLength;
hash.pointLength = pointLength;
hash.spotLength = spotLength;
hash.rectAreaLength = rectAreaLength;
hash.hemiLength = hemiLength;
hash.numDirectionalShadows = numDirectionalShadows;
hash.numPointShadows = numPointShadows;
hash.numSpotShadows = numSpotShadows;
hash.numSpotMaps = numSpotMaps;
hash.numLightProbes = numLightProbes;
state.version = nextVersion ++;
}
}
function setupView( lights, camera ) {
let directionalLength = 0;
let pointLength = 0;
let spotLength = 0;
let rectAreaLength = 0;
let hemiLength = 0;
const viewMatrix = camera.matrixWorldInverse;
for ( let i = 0, l = lights.length; i < l; i ++ ) {
const light = lights[ i ];
if ( light.isDirectionalLight ) {
const uniforms = state.directional[ directionalLength ];
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( vector3 );
uniforms.direction.transformDirection( viewMatrix );
directionalLength ++;
} else if ( light.isSpotLight ) {
const uniforms = state.spot[ spotLength ];
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( vector3 );
uniforms.direction.transformDirection( viewMatrix );
spotLength ++;
} else if ( light.isRectAreaLight ) {
const uniforms = state.rectArea[ rectAreaLength ];
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
// extract local rotation of light to derive width/height half vectors
matrix42.identity();
matrix4.copy( light.matrixWorld );
matrix4.premultiply( viewMatrix );
matrix42.extractRotation( matrix4 );
uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
uniforms.halfWidth.applyMatrix4( matrix42 );
uniforms.halfHeight.applyMatrix4( matrix42 );
rectAreaLength ++;
} else if ( light.isPointLight ) {
const uniforms = state.point[ pointLength ];
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
pointLength ++;
} else if ( light.isHemisphereLight ) {
const uniforms = state.hemi[ hemiLength ];
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
uniforms.direction.transformDirection( viewMatrix );
hemiLength ++;
}
}
}
return {
setup: setup,
setupView: setupView,
state: state
};
}
export { WebGLLights };

View File

@@ -0,0 +1,603 @@
import { BackSide } from '../../constants.js';
import { getUnlitUniformColorSpace } from '../shaders/UniformsUtils.js';
import { Euler } from '../../math/Euler.js';
import { Matrix4 } from '../../math/Matrix4.js';
const _e1 = /*@__PURE__*/ new Euler();
const _m1 = /*@__PURE__*/ new Matrix4();
function WebGLMaterials( renderer, properties ) {
function refreshTransformUniform( map, uniform ) {
if ( map.matrixAutoUpdate === true ) {
map.updateMatrix();
}
uniform.value.copy( map.matrix );
}
function refreshFogUniforms( uniforms, fog ) {
fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) );
if ( fog.isFog ) {
uniforms.fogNear.value = fog.near;
uniforms.fogFar.value = fog.far;
} else if ( fog.isFogExp2 ) {
uniforms.fogDensity.value = fog.density;
}
}
function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
if ( material.isMeshBasicMaterial ) {
refreshUniformsCommon( uniforms, material );
} else if ( material.isMeshLambertMaterial ) {
refreshUniformsCommon( uniforms, material );
if ( material.envMap ) {
uniforms.envMapIntensity.value = material.envMapIntensity;
}
} else if ( material.isMeshToonMaterial ) {
refreshUniformsCommon( uniforms, material );
refreshUniformsToon( uniforms, material );
} else if ( material.isMeshPhongMaterial ) {
refreshUniformsCommon( uniforms, material );
refreshUniformsPhong( uniforms, material );
if ( material.envMap ) {
uniforms.envMapIntensity.value = material.envMapIntensity;
}
} else if ( material.isMeshStandardMaterial ) {
refreshUniformsCommon( uniforms, material );
refreshUniformsStandard( uniforms, material );
if ( material.isMeshPhysicalMaterial ) {
refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
}
} else if ( material.isMeshMatcapMaterial ) {
refreshUniformsCommon( uniforms, material );
refreshUniformsMatcap( uniforms, material );
} else if ( material.isMeshDepthMaterial ) {
refreshUniformsCommon( uniforms, material );
} else if ( material.isMeshDistanceMaterial ) {
refreshUniformsCommon( uniforms, material );
refreshUniformsDistance( uniforms, material );
} else if ( material.isMeshNormalMaterial ) {
refreshUniformsCommon( uniforms, material );
} else if ( material.isLineBasicMaterial ) {
refreshUniformsLine( uniforms, material );
if ( material.isLineDashedMaterial ) {
refreshUniformsDash( uniforms, material );
}
} else if ( material.isPointsMaterial ) {
refreshUniformsPoints( uniforms, material, pixelRatio, height );
} else if ( material.isSpriteMaterial ) {
refreshUniformsSprites( uniforms, material );
} else if ( material.isShadowMaterial ) {
uniforms.color.value.copy( material.color );
uniforms.opacity.value = material.opacity;
} else if ( material.isShaderMaterial ) {
material.uniformsNeedUpdate = false; // #15581
}
}
function refreshUniformsCommon( uniforms, material ) {
uniforms.opacity.value = material.opacity;
if ( material.color ) {
uniforms.diffuse.value.copy( material.color );
}
if ( material.emissive ) {
uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
}
if ( material.map ) {
uniforms.map.value = material.map;
refreshTransformUniform( material.map, uniforms.mapTransform );
}
if ( material.alphaMap ) {
uniforms.alphaMap.value = material.alphaMap;
refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
}
if ( material.bumpMap ) {
uniforms.bumpMap.value = material.bumpMap;
refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform );
uniforms.bumpScale.value = material.bumpScale;
if ( material.side === BackSide ) {
uniforms.bumpScale.value *= - 1;
}
}
if ( material.normalMap ) {
uniforms.normalMap.value = material.normalMap;
refreshTransformUniform( material.normalMap, uniforms.normalMapTransform );
uniforms.normalScale.value.copy( material.normalScale );
if ( material.side === BackSide ) {
uniforms.normalScale.value.negate();
}
}
if ( material.displacementMap ) {
uniforms.displacementMap.value = material.displacementMap;
refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform );
uniforms.displacementScale.value = material.displacementScale;
uniforms.displacementBias.value = material.displacementBias;
}
if ( material.emissiveMap ) {
uniforms.emissiveMap.value = material.emissiveMap;
refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform );
}
if ( material.specularMap ) {
uniforms.specularMap.value = material.specularMap;
refreshTransformUniform( material.specularMap, uniforms.specularMapTransform );
}
if ( material.alphaTest > 0 ) {
uniforms.alphaTest.value = material.alphaTest;
}
const materialProperties = properties.get( material );
const envMap = materialProperties.envMap;
const envMapRotation = materialProperties.envMapRotation;
if ( envMap ) {
uniforms.envMap.value = envMap;
_e1.copy( envMapRotation );
// accommodate left-handed frame
_e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) {
// environment maps which are not cube render targets or PMREMs follow a different convention
_e1.y *= - 1;
_e1.z *= - 1;
}
uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
uniforms.reflectivity.value = material.reflectivity;
uniforms.ior.value = material.ior;
uniforms.refractionRatio.value = material.refractionRatio;
}
if ( material.lightMap ) {
uniforms.lightMap.value = material.lightMap;
uniforms.lightMapIntensity.value = material.lightMapIntensity;
refreshTransformUniform( material.lightMap, uniforms.lightMapTransform );
}
if ( material.aoMap ) {
uniforms.aoMap.value = material.aoMap;
uniforms.aoMapIntensity.value = material.aoMapIntensity;
refreshTransformUniform( material.aoMap, uniforms.aoMapTransform );
}
}
function refreshUniformsLine( uniforms, material ) {
uniforms.diffuse.value.copy( material.color );
uniforms.opacity.value = material.opacity;
if ( material.map ) {
uniforms.map.value = material.map;
refreshTransformUniform( material.map, uniforms.mapTransform );
}
}
function refreshUniformsDash( uniforms, material ) {
uniforms.dashSize.value = material.dashSize;
uniforms.totalSize.value = material.dashSize + material.gapSize;
uniforms.scale.value = material.scale;
}
function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
uniforms.diffuse.value.copy( material.color );
uniforms.opacity.value = material.opacity;
uniforms.size.value = material.size * pixelRatio;
uniforms.scale.value = height * 0.5;
if ( material.map ) {
uniforms.map.value = material.map;
refreshTransformUniform( material.map, uniforms.uvTransform );
}
if ( material.alphaMap ) {
uniforms.alphaMap.value = material.alphaMap;
refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
}
if ( material.alphaTest > 0 ) {
uniforms.alphaTest.value = material.alphaTest;
}
}
function refreshUniformsSprites( uniforms, material ) {
uniforms.diffuse.value.copy( material.color );
uniforms.opacity.value = material.opacity;
uniforms.rotation.value = material.rotation;
if ( material.map ) {
uniforms.map.value = material.map;
refreshTransformUniform( material.map, uniforms.mapTransform );
}
if ( material.alphaMap ) {
uniforms.alphaMap.value = material.alphaMap;
refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
}
if ( material.alphaTest > 0 ) {
uniforms.alphaTest.value = material.alphaTest;
}
}
function refreshUniformsPhong( uniforms, material ) {
uniforms.specular.value.copy( material.specular );
uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
}
function refreshUniformsToon( uniforms, material ) {
if ( material.gradientMap ) {
uniforms.gradientMap.value = material.gradientMap;
}
}
function refreshUniformsStandard( uniforms, material ) {
uniforms.metalness.value = material.metalness;
if ( material.metalnessMap ) {
uniforms.metalnessMap.value = material.metalnessMap;
refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform );
}
uniforms.roughness.value = material.roughness;
if ( material.roughnessMap ) {
uniforms.roughnessMap.value = material.roughnessMap;
refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform );
}
if ( material.envMap ) {
//uniforms.envMap.value = material.envMap; // part of uniforms common
uniforms.envMapIntensity.value = material.envMapIntensity;
}
}
function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
uniforms.ior.value = material.ior; // also part of uniforms common
if ( material.sheen > 0 ) {
uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
uniforms.sheenRoughness.value = material.sheenRoughness;
if ( material.sheenColorMap ) {
uniforms.sheenColorMap.value = material.sheenColorMap;
refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform );
}
if ( material.sheenRoughnessMap ) {
uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform );
}
}
if ( material.clearcoat > 0 ) {
uniforms.clearcoat.value = material.clearcoat;
uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
if ( material.clearcoatMap ) {
uniforms.clearcoatMap.value = material.clearcoatMap;
refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform );
}
if ( material.clearcoatRoughnessMap ) {
uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform );
}
if ( material.clearcoatNormalMap ) {
uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform );
uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
if ( material.side === BackSide ) {
uniforms.clearcoatNormalScale.value.negate();
}
}
}
if ( material.dispersion > 0 ) {
uniforms.dispersion.value = material.dispersion;
}
if ( material.iridescence > 0 ) {
uniforms.iridescence.value = material.iridescence;
uniforms.iridescenceIOR.value = material.iridescenceIOR;
uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
if ( material.iridescenceMap ) {
uniforms.iridescenceMap.value = material.iridescenceMap;
refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform );
}
if ( material.iridescenceThicknessMap ) {
uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform );
}
}
if ( material.transmission > 0 ) {
uniforms.transmission.value = material.transmission;
uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
if ( material.transmissionMap ) {
uniforms.transmissionMap.value = material.transmissionMap;
refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform );
}
uniforms.thickness.value = material.thickness;
if ( material.thicknessMap ) {
uniforms.thicknessMap.value = material.thicknessMap;
refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform );
}
uniforms.attenuationDistance.value = material.attenuationDistance;
uniforms.attenuationColor.value.copy( material.attenuationColor );
}
if ( material.anisotropy > 0 ) {
uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );
if ( material.anisotropyMap ) {
uniforms.anisotropyMap.value = material.anisotropyMap;
refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform );
}
}
uniforms.specularIntensity.value = material.specularIntensity;
uniforms.specularColor.value.copy( material.specularColor );
if ( material.specularColorMap ) {
uniforms.specularColorMap.value = material.specularColorMap;
refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform );
}
if ( material.specularIntensityMap ) {
uniforms.specularIntensityMap.value = material.specularIntensityMap;
refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform );
}
}
function refreshUniformsMatcap( uniforms, material ) {
if ( material.matcap ) {
uniforms.matcap.value = material.matcap;
}
}
function refreshUniformsDistance( uniforms, material ) {
const light = properties.get( material ).light;
uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld );
uniforms.nearDistance.value = light.shadow.camera.near;
uniforms.farDistance.value = light.shadow.camera.far;
}
return {
refreshFogUniforms: refreshFogUniforms,
refreshMaterialUniforms: refreshMaterialUniforms
};
}
export { WebGLMaterials };

View File

@@ -0,0 +1,168 @@
import { FloatType } from '../../constants.js';
import { DataArrayTexture } from '../../textures/DataArrayTexture.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector2 } from '../../math/Vector2.js';
function WebGLMorphtargets( gl, capabilities, textures ) {
const morphTextures = new WeakMap();
const morph = new Vector4();
function update( object, geometry, program ) {
const objectInfluences = object.morphTargetInfluences;
// the following encodes morph targets into an array of data textures. Each layer represents a single morph target.
const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
let entry = morphTextures.get( geometry );
if ( entry === undefined || entry.count !== morphTargetsCount ) {
if ( entry !== undefined ) entry.texture.dispose();
const hasMorphPosition = geometry.morphAttributes.position !== undefined;
const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
const hasMorphColors = geometry.morphAttributes.color !== undefined;
const morphTargets = geometry.morphAttributes.position || [];
const morphNormals = geometry.morphAttributes.normal || [];
const morphColors = geometry.morphAttributes.color || [];
let vertexDataCount = 0;
if ( hasMorphPosition === true ) vertexDataCount = 1;
if ( hasMorphNormals === true ) vertexDataCount = 2;
if ( hasMorphColors === true ) vertexDataCount = 3;
let width = geometry.attributes.position.count * vertexDataCount;
let height = 1;
if ( width > capabilities.maxTextureSize ) {
height = Math.ceil( width / capabilities.maxTextureSize );
width = capabilities.maxTextureSize;
}
const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
texture.type = FloatType;
texture.needsUpdate = true;
// fill buffer
const vertexDataStride = vertexDataCount * 4;
for ( let i = 0; i < morphTargetsCount; i ++ ) {
const morphTarget = morphTargets[ i ];
const morphNormal = morphNormals[ i ];
const morphColor = morphColors[ i ];
const offset = width * height * 4 * i;
for ( let j = 0; j < morphTarget.count; j ++ ) {
const stride = j * vertexDataStride;
if ( hasMorphPosition === true ) {
morph.fromBufferAttribute( morphTarget, j );
buffer[ offset + stride + 0 ] = morph.x;
buffer[ offset + stride + 1 ] = morph.y;
buffer[ offset + stride + 2 ] = morph.z;
buffer[ offset + stride + 3 ] = 0;
}
if ( hasMorphNormals === true ) {
morph.fromBufferAttribute( morphNormal, j );
buffer[ offset + stride + 4 ] = morph.x;
buffer[ offset + stride + 5 ] = morph.y;
buffer[ offset + stride + 6 ] = morph.z;
buffer[ offset + stride + 7 ] = 0;
}
if ( hasMorphColors === true ) {
morph.fromBufferAttribute( morphColor, j );
buffer[ offset + stride + 8 ] = morph.x;
buffer[ offset + stride + 9 ] = morph.y;
buffer[ offset + stride + 10 ] = morph.z;
buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
}
}
}
entry = {
count: morphTargetsCount,
texture: texture,
size: new Vector2( width, height )
};
morphTextures.set( geometry, entry );
function disposeTexture() {
texture.dispose();
morphTextures.delete( geometry );
geometry.removeEventListener( 'dispose', disposeTexture );
}
geometry.addEventListener( 'dispose', disposeTexture );
}
//
if ( object.isInstancedMesh === true && object.morphTexture !== null ) {
program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures );
} else {
let morphInfluencesSum = 0;
for ( let i = 0; i < objectInfluences.length; i ++ ) {
morphInfluencesSum += objectInfluences[ i ];
}
const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
}
program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
}
return {
update: update
};
}
export { WebGLMorphtargets };

94
node_modules/three/src/renderers/webgl/WebGLObjects.js generated vendored Normal file
View File

@@ -0,0 +1,94 @@
function WebGLObjects( gl, geometries, attributes, bindingStates, info ) {
let updateMap = new WeakMap();
function update( object ) {
const frame = info.render.frame;
const geometry = object.geometry;
const buffergeometry = geometries.get( object, geometry );
// Update once per frame
if ( updateMap.get( buffergeometry ) !== frame ) {
geometries.update( buffergeometry );
updateMap.set( buffergeometry, frame );
}
if ( object.isInstancedMesh ) {
if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
object.addEventListener( 'dispose', onInstancedMeshDispose );
}
if ( updateMap.get( object ) !== frame ) {
attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );
if ( object.instanceColor !== null ) {
attributes.update( object.instanceColor, gl.ARRAY_BUFFER );
}
updateMap.set( object, frame );
}
}
if ( object.isSkinnedMesh ) {
const skeleton = object.skeleton;
if ( updateMap.get( skeleton ) !== frame ) {
skeleton.update();
updateMap.set( skeleton, frame );
}
}
return buffergeometry;
}
function dispose() {
updateMap = new WeakMap();
}
function onInstancedMeshDispose( event ) {
const instancedMesh = event.target;
instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
bindingStates.releaseStatesOfObject( instancedMesh );
attributes.remove( instancedMesh.instanceMatrix );
if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
}
return {
update: update,
dispose: dispose
};
}
export { WebGLObjects };

267
node_modules/three/src/renderers/webgl/WebGLOutput.js generated vendored Normal file
View File

@@ -0,0 +1,267 @@
import {
NoToneMapping,
LinearToneMapping,
ReinhardToneMapping,
CineonToneMapping,
ACESFilmicToneMapping,
AgXToneMapping,
NeutralToneMapping,
CustomToneMapping,
SRGBTransfer,
HalfFloatType
} from '../../constants.js';
import { BufferGeometry } from '../../core/BufferGeometry.js';
import { Float32BufferAttribute } from '../../core/BufferAttribute.js';
import { RawShaderMaterial } from '../../materials/RawShaderMaterial.js';
import { Mesh } from '../../objects/Mesh.js';
import { OrthographicCamera } from '../../cameras/OrthographicCamera.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { ColorManagement } from '../../math/ColorManagement.js';
const toneMappingMap = {
[ LinearToneMapping ]: 'LINEAR_TONE_MAPPING',
[ ReinhardToneMapping ]: 'REINHARD_TONE_MAPPING',
[ CineonToneMapping ]: 'CINEON_TONE_MAPPING',
[ ACESFilmicToneMapping ]: 'ACES_FILMIC_TONE_MAPPING',
[ AgXToneMapping ]: 'AGX_TONE_MAPPING',
[ NeutralToneMapping ]: 'NEUTRAL_TONE_MAPPING',
[ CustomToneMapping ]: 'CUSTOM_TONE_MAPPING'
};
function WebGLOutput( type, width, height, depth, stencil ) {
// render targets for scene and post-processing
const targetA = new WebGLRenderTarget( width, height, {
type: type,
depthBuffer: depth,
stencilBuffer: stencil
} );
const targetB = new WebGLRenderTarget( width, height, {
type: HalfFloatType,
depthBuffer: false,
stencilBuffer: false
} );
// create fullscreen triangle geometry
const geometry = new BufferGeometry();
geometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) );
geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) );
// create output material with tone mapping support
const material = new RawShaderMaterial( {
uniforms: {
tDiffuse: { value: null }
},
vertexShader: /* glsl */`
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: /* glsl */`
precision highp float;
uniform sampler2D tDiffuse;
varying vec2 vUv;
#include <tonemapping_pars_fragment>
#include <colorspace_pars_fragment>
void main() {
gl_FragColor = texture2D( tDiffuse, vUv );
#ifdef LINEAR_TONE_MAPPING
gl_FragColor.rgb = LinearToneMapping( gl_FragColor.rgb );
#elif defined( REINHARD_TONE_MAPPING )
gl_FragColor.rgb = ReinhardToneMapping( gl_FragColor.rgb );
#elif defined( CINEON_TONE_MAPPING )
gl_FragColor.rgb = CineonToneMapping( gl_FragColor.rgb );
#elif defined( ACES_FILMIC_TONE_MAPPING )
gl_FragColor.rgb = ACESFilmicToneMapping( gl_FragColor.rgb );
#elif defined( AGX_TONE_MAPPING )
gl_FragColor.rgb = AgXToneMapping( gl_FragColor.rgb );
#elif defined( NEUTRAL_TONE_MAPPING )
gl_FragColor.rgb = NeutralToneMapping( gl_FragColor.rgb );
#elif defined( CUSTOM_TONE_MAPPING )
gl_FragColor.rgb = CustomToneMapping( gl_FragColor.rgb );
#endif
#ifdef SRGB_TRANSFER
gl_FragColor = sRGBTransferOETF( gl_FragColor );
#endif
}`,
depthTest: false,
depthWrite: false
} );
const mesh = new Mesh( geometry, material );
const camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
let _outputColorSpace = null;
let _outputToneMapping = null;
let _isCompositing = false;
let _savedToneMapping;
let _savedRenderTarget = null;
let _effects = [];
let _hasRenderPass = false;
this.setSize = function ( width, height ) {
targetA.setSize( width, height );
targetB.setSize( width, height );
for ( let i = 0; i < _effects.length; i ++ ) {
const effect = _effects[ i ];
if ( effect.setSize ) effect.setSize( width, height );
}
};
this.setEffects = function ( effects ) {
_effects = effects;
_hasRenderPass = _effects.length > 0 && _effects[ 0 ].isRenderPass === true;
const width = targetA.width;
const height = targetA.height;
for ( let i = 0; i < _effects.length; i ++ ) {
const effect = _effects[ i ];
if ( effect.setSize ) effect.setSize( width, height );
}
};
this.begin = function ( renderer, renderTarget ) {
// Don't begin during compositing phase (post-processing effects call render())
if ( _isCompositing ) return false;
if ( renderer.toneMapping === NoToneMapping && _effects.length === 0 ) return false;
_savedRenderTarget = renderTarget;
// resize internal buffers to match render target (e.g. XR resolution)
if ( renderTarget !== null ) {
const width = renderTarget.width;
const height = renderTarget.height;
if ( targetA.width !== width || targetA.height !== height ) {
this.setSize( width, height );
}
}
// if first effect is a RenderPass, it will set its own render target
if ( _hasRenderPass === false ) {
renderer.setRenderTarget( targetA );
}
// disable tone mapping during render - it will be applied in end()
_savedToneMapping = renderer.toneMapping;
renderer.toneMapping = NoToneMapping;
return true;
};
this.hasRenderPass = function () {
return _hasRenderPass;
};
this.end = function ( renderer, deltaTime ) {
// restore tone mapping
renderer.toneMapping = _savedToneMapping;
_isCompositing = true;
// run post-processing effects
let readBuffer = targetA;
let writeBuffer = targetB;
for ( let i = 0; i < _effects.length; i ++ ) {
const effect = _effects[ i ];
if ( effect.enabled === false ) continue;
effect.render( renderer, writeBuffer, readBuffer, deltaTime );
if ( effect.needsSwap !== false ) {
const temp = readBuffer;
readBuffer = writeBuffer;
writeBuffer = temp;
}
}
// update output material defines if settings changed
if ( _outputColorSpace !== renderer.outputColorSpace || _outputToneMapping !== renderer.toneMapping ) {
_outputColorSpace = renderer.outputColorSpace;
_outputToneMapping = renderer.toneMapping;
material.defines = {};
if ( ColorManagement.getTransfer( _outputColorSpace ) === SRGBTransfer ) material.defines.SRGB_TRANSFER = '';
const toneMapping = toneMappingMap[ _outputToneMapping ];
if ( toneMapping ) material.defines[ toneMapping ] = '';
material.needsUpdate = true;
}
// final output to canvas (or XR render target)
material.uniforms.tDiffuse.value = readBuffer.texture;
renderer.setRenderTarget( _savedRenderTarget );
renderer.render( mesh, camera );
_savedRenderTarget = null;
_isCompositing = false;
};
this.isCompositing = function () {
return _isCompositing;
};
this.dispose = function () {
targetA.dispose();
targetB.dispose();
geometry.dispose();
material.dispose();
};
}
export { WebGLOutput };

1027
node_modules/three/src/renderers/webgl/WebGLProgram.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

663
node_modules/three/src/renderers/webgl/WebGLPrograms.js generated vendored Normal file
View File

@@ -0,0 +1,663 @@
import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, NormalBlending, LinearSRGBColorSpace, SRGBTransfer } from '../../constants.js';
import { Layers } from '../../core/Layers.js';
import { WebGLProgram } from './WebGLProgram.js';
import { WebGLShaderCache } from './WebGLShaderCache.js';
import { ShaderLib } from '../shaders/ShaderLib.js';
import { UniformsUtils } from '../shaders/UniformsUtils.js';
import { ColorManagement } from '../../math/ColorManagement.js';
import { warn } from '../../utils.js';
function WebGLPrograms( renderer, environments, extensions, capabilities, bindingStates, clipping ) {
const _programLayers = new Layers();
const _customShaders = new WebGLShaderCache();
const _activeChannels = new Set();
const programs = [];
const programsMap = new Map();
const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
let precision = capabilities.precision;
const shaderIDs = {
MeshDepthMaterial: 'depth',
MeshDistanceMaterial: 'distance',
MeshNormalMaterial: 'normal',
MeshBasicMaterial: 'basic',
MeshLambertMaterial: 'lambert',
MeshPhongMaterial: 'phong',
MeshToonMaterial: 'toon',
MeshStandardMaterial: 'physical',
MeshPhysicalMaterial: 'physical',
MeshMatcapMaterial: 'matcap',
LineBasicMaterial: 'basic',
LineDashedMaterial: 'dashed',
PointsMaterial: 'points',
ShadowMaterial: 'shadow',
SpriteMaterial: 'sprite'
};
function getChannel( value ) {
_activeChannels.add( value );
if ( value === 0 ) return 'uv';
return `uv${ value }`;
}
function getParameters( material, lights, shadows, scene, object ) {
const fog = scene.fog;
const geometry = object.geometry;
const environment = ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) ? scene.environment : null;
const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap );
const envMap = environments.get( material.envMap || environment, usePMREM );
const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null;
const shaderID = shaderIDs[ material.type ];
// heuristics to create shader parameters according to lights in the scene
// (not to blow over maxLights budget)
if ( material.precision !== null ) {
precision = capabilities.getMaxPrecision( material.precision );
if ( precision !== material.precision ) {
warn( 'WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
}
}
//
const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
let morphTextureStride = 0;
if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1;
if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2;
if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3;
//
let vertexShader, fragmentShader;
let customVertexShaderID, customFragmentShaderID;
if ( shaderID ) {
const shader = ShaderLib[ shaderID ];
vertexShader = shader.vertexShader;
fragmentShader = shader.fragmentShader;
} else {
vertexShader = material.vertexShader;
fragmentShader = material.fragmentShader;
_customShaders.update( material );
customVertexShaderID = _customShaders.getVertexShaderID( material );
customFragmentShaderID = _customShaders.getFragmentShaderID( material );
}
const currentRenderTarget = renderer.getRenderTarget();
const reversedDepthBuffer = renderer.state.buffers.depth.getReversed();
const IS_INSTANCEDMESH = object.isInstancedMesh === true;
const IS_BATCHEDMESH = object.isBatchedMesh === true;
const HAS_MAP = !! material.map;
const HAS_MATCAP = !! material.matcap;
const HAS_ENVMAP = !! envMap;
const HAS_AOMAP = !! material.aoMap;
const HAS_LIGHTMAP = !! material.lightMap;
const HAS_BUMPMAP = !! material.bumpMap;
const HAS_NORMALMAP = !! material.normalMap;
const HAS_DISPLACEMENTMAP = !! material.displacementMap;
const HAS_EMISSIVEMAP = !! material.emissiveMap;
const HAS_METALNESSMAP = !! material.metalnessMap;
const HAS_ROUGHNESSMAP = !! material.roughnessMap;
const HAS_ANISOTROPY = material.anisotropy > 0;
const HAS_CLEARCOAT = material.clearcoat > 0;
const HAS_DISPERSION = material.dispersion > 0;
const HAS_IRIDESCENCE = material.iridescence > 0;
const HAS_SHEEN = material.sheen > 0;
const HAS_TRANSMISSION = material.transmission > 0;
const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap;
const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap;
const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap;
const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap;
const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap;
const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap;
const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap;
const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap;
const HAS_SPECULARMAP = !! material.specularMap;
const HAS_SPECULAR_COLORMAP = !! material.specularColorMap;
const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap;
const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap;
const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap;
const HAS_GRADIENTMAP = !! material.gradientMap;
const HAS_ALPHAMAP = !! material.alphaMap;
const HAS_ALPHATEST = material.alphaTest > 0;
const HAS_ALPHAHASH = !! material.alphaHash;
const HAS_EXTENSIONS = !! material.extensions;
let toneMapping = NoToneMapping;
if ( material.toneMapped ) {
if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) {
toneMapping = renderer.toneMapping;
}
}
const parameters = {
shaderID: shaderID,
shaderType: material.type,
shaderName: material.name,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
defines: material.defines,
customVertexShaderID: customVertexShaderID,
customFragmentShaderID: customFragmentShaderID,
isRawShaderMaterial: material.isRawShaderMaterial === true,
glslVersion: material.glslVersion,
precision: precision,
batching: IS_BATCHEDMESH,
batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null,
instancing: IS_INSTANCEDMESH,
instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null,
instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null,
outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ),
alphaToCoverage: !! material.alphaToCoverage,
map: HAS_MAP,
matcap: HAS_MATCAP,
envMap: HAS_ENVMAP,
envMapMode: HAS_ENVMAP && envMap.mapping,
envMapCubeUVHeight: envMapCubeUVHeight,
aoMap: HAS_AOMAP,
lightMap: HAS_LIGHTMAP,
bumpMap: HAS_BUMPMAP,
normalMap: HAS_NORMALMAP,
displacementMap: HAS_DISPLACEMENTMAP,
emissiveMap: HAS_EMISSIVEMAP,
normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
metalnessMap: HAS_METALNESSMAP,
roughnessMap: HAS_ROUGHNESSMAP,
anisotropy: HAS_ANISOTROPY,
anisotropyMap: HAS_ANISOTROPYMAP,
clearcoat: HAS_CLEARCOAT,
clearcoatMap: HAS_CLEARCOATMAP,
clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
dispersion: HAS_DISPERSION,
iridescence: HAS_IRIDESCENCE,
iridescenceMap: HAS_IRIDESCENCEMAP,
iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP,
sheen: HAS_SHEEN,
sheenColorMap: HAS_SHEEN_COLORMAP,
sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP,
specularMap: HAS_SPECULARMAP,
specularColorMap: HAS_SPECULAR_COLORMAP,
specularIntensityMap: HAS_SPECULAR_INTENSITYMAP,
transmission: HAS_TRANSMISSION,
transmissionMap: HAS_TRANSMISSIONMAP,
thicknessMap: HAS_THICKNESSMAP,
gradientMap: HAS_GRADIENTMAP,
opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false,
alphaMap: HAS_ALPHAMAP,
alphaTest: HAS_ALPHATEST,
alphaHash: HAS_ALPHAHASH,
combine: material.combine,
//
mapUv: HAS_MAP && getChannel( material.map.channel ),
aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ),
lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ),
bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ),
normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ),
displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ),
emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ),
metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ),
roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ),
anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ),
clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ),
clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ),
clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ),
iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ),
iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ),
sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ),
sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ),
specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ),
specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ),
specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ),
transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ),
thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ),
alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ),
//
vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ),
vertexColors: material.vertexColors,
vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ),
fog: !! fog,
useFog: material.fog === true,
fogExp2: ( !! fog && fog.isFogExp2 ),
flatShading: material.wireframe === false && (
material.flatShading === true ||
( geometry.attributes.normal === undefined && HAS_NORMALMAP === false &&
( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isMeshPhysicalMaterial )
)
),
sizeAttenuation: material.sizeAttenuation === true,
logarithmicDepthBuffer: logarithmicDepthBuffer,
reversedDepthBuffer: reversedDepthBuffer,
skinning: object.isSkinnedMesh === true,
morphTargets: geometry.morphAttributes.position !== undefined,
morphNormals: geometry.morphAttributes.normal !== undefined,
morphColors: geometry.morphAttributes.color !== undefined,
morphTargetsCount: morphTargetsCount,
morphTextureStride: morphTextureStride,
numDirLights: lights.directional.length,
numPointLights: lights.point.length,
numSpotLights: lights.spot.length,
numSpotLightMaps: lights.spotLightMap.length,
numRectAreaLights: lights.rectArea.length,
numHemiLights: lights.hemi.length,
numDirLightShadows: lights.directionalShadowMap.length,
numPointLightShadows: lights.pointShadowMap.length,
numSpotLightShadows: lights.spotShadowMap.length,
numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
numLightProbes: lights.numLightProbes,
numClippingPlanes: clipping.numPlanes,
numClipIntersection: clipping.numIntersection,
dithering: material.dithering,
shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
shadowMapType: renderer.shadowMap.type,
toneMapping: toneMapping,
decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ),
decodeVideoTextureEmissive: HAS_EMISSIVEMAP && ( material.emissiveMap.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.emissiveMap.colorSpace ) === SRGBTransfer ),
premultipliedAlpha: material.premultipliedAlpha,
doubleSided: material.side === DoubleSide,
flipSided: material.side === BackSide,
useDepthPacking: material.depthPacking >= 0,
depthPacking: material.depthPacking || 0,
index0AttributeName: material.index0AttributeName,
extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ),
extensionMultiDraw: ( HAS_EXTENSIONS && material.extensions.multiDraw === true || IS_BATCHEDMESH ) && extensions.has( 'WEBGL_multi_draw' ),
rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
customProgramCacheKey: material.customProgramCacheKey()
};
// the usage of getChannel() determines the active texture channels for this shader
parameters.vertexUv1s = _activeChannels.has( 1 );
parameters.vertexUv2s = _activeChannels.has( 2 );
parameters.vertexUv3s = _activeChannels.has( 3 );
_activeChannels.clear();
return parameters;
}
function getProgramCacheKey( parameters ) {
const array = [];
if ( parameters.shaderID ) {
array.push( parameters.shaderID );
} else {
array.push( parameters.customVertexShaderID );
array.push( parameters.customFragmentShaderID );
}
if ( parameters.defines !== undefined ) {
for ( const name in parameters.defines ) {
array.push( name );
array.push( parameters.defines[ name ] );
}
}
if ( parameters.isRawShaderMaterial === false ) {
getProgramCacheKeyParameters( array, parameters );
getProgramCacheKeyBooleans( array, parameters );
array.push( renderer.outputColorSpace );
}
array.push( parameters.customProgramCacheKey );
return array.join();
}
function getProgramCacheKeyParameters( array, parameters ) {
array.push( parameters.precision );
array.push( parameters.outputColorSpace );
array.push( parameters.envMapMode );
array.push( parameters.envMapCubeUVHeight );
array.push( parameters.mapUv );
array.push( parameters.alphaMapUv );
array.push( parameters.lightMapUv );
array.push( parameters.aoMapUv );
array.push( parameters.bumpMapUv );
array.push( parameters.normalMapUv );
array.push( parameters.displacementMapUv );
array.push( parameters.emissiveMapUv );
array.push( parameters.metalnessMapUv );
array.push( parameters.roughnessMapUv );
array.push( parameters.anisotropyMapUv );
array.push( parameters.clearcoatMapUv );
array.push( parameters.clearcoatNormalMapUv );
array.push( parameters.clearcoatRoughnessMapUv );
array.push( parameters.iridescenceMapUv );
array.push( parameters.iridescenceThicknessMapUv );
array.push( parameters.sheenColorMapUv );
array.push( parameters.sheenRoughnessMapUv );
array.push( parameters.specularMapUv );
array.push( parameters.specularColorMapUv );
array.push( parameters.specularIntensityMapUv );
array.push( parameters.transmissionMapUv );
array.push( parameters.thicknessMapUv );
array.push( parameters.combine );
array.push( parameters.fogExp2 );
array.push( parameters.sizeAttenuation );
array.push( parameters.morphTargetsCount );
array.push( parameters.morphAttributeCount );
array.push( parameters.numDirLights );
array.push( parameters.numPointLights );
array.push( parameters.numSpotLights );
array.push( parameters.numSpotLightMaps );
array.push( parameters.numHemiLights );
array.push( parameters.numRectAreaLights );
array.push( parameters.numDirLightShadows );
array.push( parameters.numPointLightShadows );
array.push( parameters.numSpotLightShadows );
array.push( parameters.numSpotLightShadowsWithMaps );
array.push( parameters.numLightProbes );
array.push( parameters.shadowMapType );
array.push( parameters.toneMapping );
array.push( parameters.numClippingPlanes );
array.push( parameters.numClipIntersection );
array.push( parameters.depthPacking );
}
function getProgramCacheKeyBooleans( array, parameters ) {
_programLayers.disableAll();
if ( parameters.instancing )
_programLayers.enable( 0 );
if ( parameters.instancingColor )
_programLayers.enable( 1 );
if ( parameters.instancingMorph )
_programLayers.enable( 2 );
if ( parameters.matcap )
_programLayers.enable( 3 );
if ( parameters.envMap )
_programLayers.enable( 4 );
if ( parameters.normalMapObjectSpace )
_programLayers.enable( 5 );
if ( parameters.normalMapTangentSpace )
_programLayers.enable( 6 );
if ( parameters.clearcoat )
_programLayers.enable( 7 );
if ( parameters.iridescence )
_programLayers.enable( 8 );
if ( parameters.alphaTest )
_programLayers.enable( 9 );
if ( parameters.vertexColors )
_programLayers.enable( 10 );
if ( parameters.vertexAlphas )
_programLayers.enable( 11 );
if ( parameters.vertexUv1s )
_programLayers.enable( 12 );
if ( parameters.vertexUv2s )
_programLayers.enable( 13 );
if ( parameters.vertexUv3s )
_programLayers.enable( 14 );
if ( parameters.vertexTangents )
_programLayers.enable( 15 );
if ( parameters.anisotropy )
_programLayers.enable( 16 );
if ( parameters.alphaHash )
_programLayers.enable( 17 );
if ( parameters.batching )
_programLayers.enable( 18 );
if ( parameters.dispersion )
_programLayers.enable( 19 );
if ( parameters.batchingColor )
_programLayers.enable( 20 );
if ( parameters.gradientMap )
_programLayers.enable( 21 );
array.push( _programLayers.mask );
_programLayers.disableAll();
if ( parameters.fog )
_programLayers.enable( 0 );
if ( parameters.useFog )
_programLayers.enable( 1 );
if ( parameters.flatShading )
_programLayers.enable( 2 );
if ( parameters.logarithmicDepthBuffer )
_programLayers.enable( 3 );
if ( parameters.reversedDepthBuffer )
_programLayers.enable( 4 );
if ( parameters.skinning )
_programLayers.enable( 5 );
if ( parameters.morphTargets )
_programLayers.enable( 6 );
if ( parameters.morphNormals )
_programLayers.enable( 7 );
if ( parameters.morphColors )
_programLayers.enable( 8 );
if ( parameters.premultipliedAlpha )
_programLayers.enable( 9 );
if ( parameters.shadowMapEnabled )
_programLayers.enable( 10 );
if ( parameters.doubleSided )
_programLayers.enable( 11 );
if ( parameters.flipSided )
_programLayers.enable( 12 );
if ( parameters.useDepthPacking )
_programLayers.enable( 13 );
if ( parameters.dithering )
_programLayers.enable( 14 );
if ( parameters.transmission )
_programLayers.enable( 15 );
if ( parameters.sheen )
_programLayers.enable( 16 );
if ( parameters.opaque )
_programLayers.enable( 17 );
if ( parameters.pointsUvs )
_programLayers.enable( 18 );
if ( parameters.decodeVideoTexture )
_programLayers.enable( 19 );
if ( parameters.decodeVideoTextureEmissive )
_programLayers.enable( 20 );
if ( parameters.alphaToCoverage )
_programLayers.enable( 21 );
array.push( _programLayers.mask );
}
function getUniforms( material ) {
const shaderID = shaderIDs[ material.type ];
let uniforms;
if ( shaderID ) {
const shader = ShaderLib[ shaderID ];
uniforms = UniformsUtils.clone( shader.uniforms );
} else {
uniforms = material.uniforms;
}
return uniforms;
}
function acquireProgram( parameters, cacheKey ) {
let program = programsMap.get( cacheKey );
if ( program !== undefined ) {
++ program.usedTimes;
} else {
program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
programs.push( program );
programsMap.set( cacheKey, program );
}
return program;
}
function releaseProgram( program ) {
if ( -- program.usedTimes === 0 ) {
// Remove from unordered set
const i = programs.indexOf( program );
programs[ i ] = programs[ programs.length - 1 ];
programs.pop();
// Remove from map
programsMap.delete( program.cacheKey );
// Free WebGL resources
program.destroy();
}
}
function releaseShaderCache( material ) {
_customShaders.remove( material );
}
function dispose() {
_customShaders.dispose();
}
return {
getParameters: getParameters,
getProgramCacheKey: getProgramCacheKey,
getUniforms: getUniforms,
acquireProgram: acquireProgram,
releaseProgram: releaseProgram,
releaseShaderCache: releaseShaderCache,
// Exposed for resource monitoring & error feedback via renderer.info:
programs: programs,
dispose: dispose
};
}
export { WebGLPrograms };

View File

@@ -0,0 +1,55 @@
function WebGLProperties() {
let properties = new WeakMap();
function has( object ) {
return properties.has( object );
}
function get( object ) {
let map = properties.get( object );
if ( map === undefined ) {
map = {};
properties.set( object, map );
}
return map;
}
function remove( object ) {
properties.delete( object );
}
function update( object, key, value ) {
properties.get( object )[ key ] = value;
}
function dispose() {
properties = new WeakMap();
}
return {
has: has,
get: get,
remove: remove,
update: update,
dispose: dispose
};
}
export { WebGLProperties };

View File

@@ -0,0 +1,253 @@
function painterSortStable( a, b ) {
if ( a.groupOrder !== b.groupOrder ) {
return a.groupOrder - b.groupOrder;
} else if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.material.id !== b.material.id ) {
return a.material.id - b.material.id;
} else if ( a.materialVariant !== b.materialVariant ) {
return a.materialVariant - b.materialVariant;
} else if ( a.z !== b.z ) {
return a.z - b.z;
} else {
return a.id - b.id;
}
}
function reversePainterSortStable( a, b ) {
if ( a.groupOrder !== b.groupOrder ) {
return a.groupOrder - b.groupOrder;
} else if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.z !== b.z ) {
return b.z - a.z;
} else {
return a.id - b.id;
}
}
function WebGLRenderList() {
const renderItems = [];
let renderItemsIndex = 0;
const opaque = [];
const transmissive = [];
const transparent = [];
function init() {
renderItemsIndex = 0;
opaque.length = 0;
transmissive.length = 0;
transparent.length = 0;
}
function materialVariant( object ) {
let variant = 0;
if ( object.isInstancedMesh ) variant += 2;
if ( object.isSkinnedMesh ) variant += 1;
return variant;
}
function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
let renderItem = renderItems[ renderItemsIndex ];
if ( renderItem === undefined ) {
renderItem = {
id: object.id,
object: object,
geometry: geometry,
material: material,
materialVariant: materialVariant( object ),
groupOrder: groupOrder,
renderOrder: object.renderOrder,
z: z,
group: group
};
renderItems[ renderItemsIndex ] = renderItem;
} else {
renderItem.id = object.id;
renderItem.object = object;
renderItem.geometry = geometry;
renderItem.material = material;
renderItem.materialVariant = materialVariant( object );
renderItem.groupOrder = groupOrder;
renderItem.renderOrder = object.renderOrder;
renderItem.z = z;
renderItem.group = group;
}
renderItemsIndex ++;
return renderItem;
}
function push( object, geometry, material, groupOrder, z, group ) {
const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
if ( material.transmission > 0.0 ) {
transmissive.push( renderItem );
} else if ( material.transparent === true ) {
transparent.push( renderItem );
} else {
opaque.push( renderItem );
}
}
function unshift( object, geometry, material, groupOrder, z, group ) {
const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
if ( material.transmission > 0.0 ) {
transmissive.unshift( renderItem );
} else if ( material.transparent === true ) {
transparent.unshift( renderItem );
} else {
opaque.unshift( renderItem );
}
}
function sort( customOpaqueSort, customTransparentSort ) {
if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
}
function finish() {
// Clear references from inactive renderItems in the list
for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
const renderItem = renderItems[ i ];
if ( renderItem.id === null ) break;
renderItem.id = null;
renderItem.object = null;
renderItem.geometry = null;
renderItem.material = null;
renderItem.group = null;
}
}
return {
opaque: opaque,
transmissive: transmissive,
transparent: transparent,
init: init,
push: push,
unshift: unshift,
finish: finish,
sort: sort
};
}
function WebGLRenderLists() {
let lists = new WeakMap();
function get( scene, renderCallDepth ) {
const listArray = lists.get( scene );
let list;
if ( listArray === undefined ) {
list = new WebGLRenderList();
lists.set( scene, [ list ] );
} else {
if ( renderCallDepth >= listArray.length ) {
list = new WebGLRenderList();
listArray.push( list );
} else {
list = listArray[ renderCallDepth ];
}
}
return list;
}
function dispose() {
lists = new WeakMap();
}
return {
get: get,
dispose: dispose
};
}
export { WebGLRenderLists, WebGLRenderList };

View File

@@ -0,0 +1,113 @@
import { WebGLLights } from './WebGLLights.js';
function WebGLRenderState( extensions ) {
const lights = new WebGLLights( extensions );
const lightsArray = [];
const shadowsArray = [];
function init( camera ) {
state.camera = camera;
lightsArray.length = 0;
shadowsArray.length = 0;
}
function pushLight( light ) {
lightsArray.push( light );
}
function pushShadow( shadowLight ) {
shadowsArray.push( shadowLight );
}
function setupLights() {
lights.setup( lightsArray );
}
function setupLightsView( camera ) {
lights.setupView( lightsArray, camera );
}
const state = {
lightsArray: lightsArray,
shadowsArray: shadowsArray,
camera: null,
lights: lights,
transmissionRenderTarget: {}
};
return {
init: init,
state: state,
setupLights: setupLights,
setupLightsView: setupLightsView,
pushLight: pushLight,
pushShadow: pushShadow
};
}
function WebGLRenderStates( extensions ) {
let renderStates = new WeakMap();
function get( scene, renderCallDepth = 0 ) {
const renderStateArray = renderStates.get( scene );
let renderState;
if ( renderStateArray === undefined ) {
renderState = new WebGLRenderState( extensions );
renderStates.set( scene, [ renderState ] );
} else {
if ( renderCallDepth >= renderStateArray.length ) {
renderState = new WebGLRenderState( extensions );
renderStateArray.push( renderState );
} else {
renderState = renderStateArray[ renderCallDepth ];
}
}
return renderState;
}
function dispose() {
renderStates = new WeakMap();
}
return {
get: get,
dispose: dispose
};
}
export { WebGLRenderStates };

12
node_modules/three/src/renderers/webgl/WebGLShader.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
function WebGLShader( gl, type, string ) {
const shader = gl.createShader( type );
gl.shaderSource( shader, string );
gl.compileShader( shader );
return shader;
}
export { WebGLShader };

View File

@@ -0,0 +1,124 @@
let _id = 0;
class WebGLShaderCache {
constructor() {
this.shaderCache = new Map();
this.materialCache = new Map();
}
update( material ) {
const vertexShader = material.vertexShader;
const fragmentShader = material.fragmentShader;
const vertexShaderStage = this._getShaderStage( vertexShader );
const fragmentShaderStage = this._getShaderStage( fragmentShader );
const materialShaders = this._getShaderCacheForMaterial( material );
if ( materialShaders.has( vertexShaderStage ) === false ) {
materialShaders.add( vertexShaderStage );
vertexShaderStage.usedTimes ++;
}
if ( materialShaders.has( fragmentShaderStage ) === false ) {
materialShaders.add( fragmentShaderStage );
fragmentShaderStage.usedTimes ++;
}
return this;
}
remove( material ) {
const materialShaders = this.materialCache.get( material );
for ( const shaderStage of materialShaders ) {
shaderStage.usedTimes --;
if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code );
}
this.materialCache.delete( material );
return this;
}
getVertexShaderID( material ) {
return this._getShaderStage( material.vertexShader ).id;
}
getFragmentShaderID( material ) {
return this._getShaderStage( material.fragmentShader ).id;
}
dispose() {
this.shaderCache.clear();
this.materialCache.clear();
}
_getShaderCacheForMaterial( material ) {
const cache = this.materialCache;
let set = cache.get( material );
if ( set === undefined ) {
set = new Set();
cache.set( material, set );
}
return set;
}
_getShaderStage( code ) {
const cache = this.shaderCache;
let stage = cache.get( code );
if ( stage === undefined ) {
stage = new WebGLShaderStage( code );
cache.set( code, stage );
}
return stage;
}
}
class WebGLShaderStage {
constructor( code ) {
this.id = _id ++;
this.code = code;
this.usedTimes = 0;
}
}
export { WebGLShaderCache };

View File

@@ -0,0 +1,600 @@
import { FrontSide, BackSide, DoubleSide, NearestFilter, LinearFilter, PCFShadowMap, VSMShadowMap, NoBlending, LessEqualCompare, GreaterEqualCompare, DepthFormat, UnsignedIntType, RGFormat, HalfFloatType, FloatType, PCFSoftShadowMap } from '../../constants.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { WebGLCubeRenderTarget } from '../WebGLCubeRenderTarget.js';
import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
import { BufferAttribute } from '../../core/BufferAttribute.js';
import { BufferGeometry } from '../../core/BufferGeometry.js';
import { Mesh } from '../../objects/Mesh.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector2 } from '../../math/Vector2.js';
import { Matrix4 } from '../../math/Matrix4.js';
import { Frustum } from '../../math/Frustum.js';
import { DepthTexture } from '../../textures/DepthTexture.js';
import { CubeDepthTexture } from '../../textures/CubeDepthTexture.js';
import * as vsm from '../shaders/ShaderLib/vsm.glsl.js';
import { warn } from '../../utils.js';
import { Vector3 } from '../../math/Vector3.js';
const _cubeDirections = [
/*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ),
/*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 )
];
const _cubeUps = [
/*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ),
/*@__PURE__*/ new Vector3( 0, 0, - 1 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 )
];
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
const _lightPositionWorld = /*@__PURE__*/ new Vector3();
const _lookTarget = /*@__PURE__*/ new Vector3();
function WebGLShadowMap( renderer, objects, capabilities ) {
let _frustum = new Frustum();
const _shadowMapSize = new Vector2(),
_viewportSize = new Vector2(),
_viewport = new Vector4(),
_depthMaterial = new MeshDepthMaterial(),
_distanceMaterial = new MeshDistanceMaterial(),
_materialCache = {},
_maxTextureSize = capabilities.maxTextureSize;
const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide };
const shadowMaterialVertical = new ShaderMaterial( {
defines: {
VSM_SAMPLES: 8
},
uniforms: {
shadow_pass: { value: null },
resolution: { value: new Vector2() },
radius: { value: 4.0 }
},
vertexShader: vsm.vertex,
fragmentShader: vsm.fragment
} );
const shadowMaterialHorizontal = shadowMaterialVertical.clone();
shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
const fullScreenTri = new BufferGeometry();
fullScreenTri.setAttribute(
'position',
new BufferAttribute(
new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
3
)
);
const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
const scope = this;
this.enabled = false;
this.autoUpdate = true;
this.needsUpdate = false;
this.type = PCFShadowMap;
let _previousType = this.type;
this.render = function ( lights, scene, camera ) {
if ( scope.enabled === false ) return;
if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
if ( lights.length === 0 ) return;
if ( this.type === PCFSoftShadowMap ) {
warn( 'WebGLShadowMap: PCFSoftShadowMap has been deprecated. Using PCFShadowMap instead.' );
this.type = PCFShadowMap;
}
const currentRenderTarget = renderer.getRenderTarget();
const activeCubeFace = renderer.getActiveCubeFace();
const activeMipmapLevel = renderer.getActiveMipmapLevel();
const _state = renderer.state;
// Set GL state for depth map.
_state.setBlending( NoBlending );
if ( _state.buffers.depth.getReversed() === true ) {
_state.buffers.color.setClear( 0, 0, 0, 0 );
} else {
_state.buffers.color.setClear( 1, 1, 1, 1 );
}
_state.buffers.depth.setTest( true );
_state.setScissorTest( false );
// check for shadow map type changes
const typeChanged = _previousType !== this.type;
// When shadow map type changes, materials need recompilation because sampler types change
// (sampler2DShadow for PCF vs sampler2D for Basic)
if ( typeChanged ) {
scene.traverse( function ( object ) {
if ( object.material ) {
if ( Array.isArray( object.material ) ) {
object.material.forEach( mat => mat.needsUpdate = true );
} else {
object.material.needsUpdate = true;
}
}
} );
}
// render depth map
for ( let i = 0, il = lights.length; i < il; i ++ ) {
const light = lights[ i ];
const shadow = light.shadow;
if ( shadow === undefined ) {
warn( 'WebGLShadowMap:', light, 'has no shadow.' );
continue;
}
if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
_shadowMapSize.copy( shadow.mapSize );
const shadowFrameExtents = shadow.getFrameExtents();
_shadowMapSize.multiply( shadowFrameExtents );
_viewportSize.copy( shadow.mapSize );
if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
if ( _shadowMapSize.x > _maxTextureSize ) {
_viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x );
_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
shadow.mapSize.x = _viewportSize.x;
}
if ( _shadowMapSize.y > _maxTextureSize ) {
_viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y );
_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
shadow.mapSize.y = _viewportSize.y;
}
}
const reversedDepthBuffer = renderer.state.buffers.depth.getReversed();
shadow.camera._reversedDepth = reversedDepthBuffer;
if ( shadow.map === null || typeChanged === true ) {
if ( shadow.map !== null ) {
if ( shadow.map.depthTexture !== null ) {
shadow.map.depthTexture.dispose();
shadow.map.depthTexture = null;
}
shadow.map.dispose();
}
if ( this.type === VSMShadowMap ) {
if ( light.isPointLight ) {
warn( 'WebGLShadowMap: VSM shadow maps are not supported for PointLights. Use PCF or BasicShadowMap instead.' );
continue;
}
shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, {
format: RGFormat,
type: HalfFloatType,
minFilter: LinearFilter,
magFilter: LinearFilter,
generateMipmaps: false
} );
shadow.map.texture.name = light.name + '.shadowMap';
// Native depth texture for VSM - depth is captured here, then blurred into the color texture
shadow.map.depthTexture = new DepthTexture( _shadowMapSize.x, _shadowMapSize.y, FloatType );
shadow.map.depthTexture.name = light.name + '.shadowMapDepth';
shadow.map.depthTexture.format = DepthFormat;
shadow.map.depthTexture.compareFunction = null; // For regular sampling (not shadow comparison)
shadow.map.depthTexture.minFilter = NearestFilter;
shadow.map.depthTexture.magFilter = NearestFilter;
} else {
if ( light.isPointLight ) {
shadow.map = new WebGLCubeRenderTarget( _shadowMapSize.x );
shadow.map.depthTexture = new CubeDepthTexture( _shadowMapSize.x, UnsignedIntType );
} else {
shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y );
shadow.map.depthTexture = new DepthTexture( _shadowMapSize.x, _shadowMapSize.y, UnsignedIntType );
}
shadow.map.depthTexture.name = light.name + '.shadowMap';
shadow.map.depthTexture.format = DepthFormat;
if ( this.type === PCFShadowMap ) {
shadow.map.depthTexture.compareFunction = reversedDepthBuffer ? GreaterEqualCompare : LessEqualCompare;
shadow.map.depthTexture.minFilter = LinearFilter;
shadow.map.depthTexture.magFilter = LinearFilter;
} else {
shadow.map.depthTexture.compareFunction = null;
shadow.map.depthTexture.minFilter = NearestFilter;
shadow.map.depthTexture.magFilter = NearestFilter;
}
}
shadow.camera.updateProjectionMatrix();
}
// For cube render targets (PointLights), render all 6 faces. Otherwise, render once.
const faceCount = shadow.map.isWebGLCubeRenderTarget ? 6 : 1;
for ( let face = 0; face < faceCount; face ++ ) {
// For cube render targets, render to each face separately
if ( shadow.map.isWebGLCubeRenderTarget ) {
renderer.setRenderTarget( shadow.map, face );
renderer.clear();
} else {
// For 2D render targets, use viewports
if ( face === 0 ) {
renderer.setRenderTarget( shadow.map );
renderer.clear();
}
const viewport = shadow.getViewport( face );
_viewport.set(
_viewportSize.x * viewport.x,
_viewportSize.y * viewport.y,
_viewportSize.x * viewport.z,
_viewportSize.y * viewport.w
);
_state.viewport( _viewport );
}
if ( light.isPointLight ) {
const camera = shadow.camera;
const shadowMatrix = shadow.matrix;
const far = light.distance || camera.far;
if ( far !== camera.far ) {
camera.far = far;
camera.updateProjectionMatrix();
}
_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
camera.position.copy( _lightPositionWorld );
_lookTarget.copy( camera.position );
_lookTarget.add( _cubeDirections[ face ] );
camera.up.copy( _cubeUps[ face ] );
camera.lookAt( _lookTarget );
camera.updateMatrixWorld();
shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
shadow._frustum.setFromProjectionMatrix( _projScreenMatrix, camera.coordinateSystem, camera.reversedDepth );
} else {
shadow.updateMatrices( light );
}
_frustum = shadow.getFrustum();
renderObject( scene, camera, shadow.camera, light, this.type );
}
// do blur pass for VSM
if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) {
VSMPass( shadow, camera );
}
shadow.needsUpdate = false;
}
_previousType = this.type;
scope.needsUpdate = false;
renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
};
function VSMPass( shadow, camera ) {
const geometry = objects.update( fullScreenMesh );
if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
shadowMaterialVertical.needsUpdate = true;
shadowMaterialHorizontal.needsUpdate = true;
}
if ( shadow.mapPass === null ) {
shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, {
format: RGFormat,
type: HalfFloatType
} );
}
// vertical pass - read from native depth texture
shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.depthTexture;
shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
shadowMaterialVertical.uniforms.radius.value = shadow.radius;
renderer.setRenderTarget( shadow.mapPass );
renderer.clear();
renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
// horizontal pass
shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
renderer.setRenderTarget( shadow.map );
renderer.clear();
renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
}
function getDepthMaterial( object, material, light, type ) {
let result = null;
const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial;
if ( customMaterial !== undefined ) {
result = customMaterial;
} else {
result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) ||
( material.displacementMap && material.displacementScale !== 0 ) ||
( material.alphaMap && material.alphaTest > 0 ) ||
( material.map && material.alphaTest > 0 ) ||
( material.alphaToCoverage === true ) ) {
// in this case we need a unique material instance reflecting the
// appropriate state
const keyA = result.uuid, keyB = material.uuid;
let materialsForVariant = _materialCache[ keyA ];
if ( materialsForVariant === undefined ) {
materialsForVariant = {};
_materialCache[ keyA ] = materialsForVariant;
}
let cachedMaterial = materialsForVariant[ keyB ];
if ( cachedMaterial === undefined ) {
cachedMaterial = result.clone();
materialsForVariant[ keyB ] = cachedMaterial;
material.addEventListener( 'dispose', onMaterialDispose );
}
result = cachedMaterial;
}
}
result.visible = material.visible;
result.wireframe = material.wireframe;
if ( type === VSMShadowMap ) {
result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
} else {
result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
}
result.alphaMap = material.alphaMap;
result.alphaTest = ( material.alphaToCoverage === true ) ? 0.5 : material.alphaTest; // approximate alphaToCoverage by using a fixed alphaTest value
result.map = material.map;
result.clipShadows = material.clipShadows;
result.clippingPlanes = material.clippingPlanes;
result.clipIntersection = material.clipIntersection;
result.displacementMap = material.displacementMap;
result.displacementScale = material.displacementScale;
result.displacementBias = material.displacementBias;
result.wireframeLinewidth = material.wireframeLinewidth;
result.linewidth = material.linewidth;
if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
const materialProperties = renderer.properties.get( result );
materialProperties.light = light;
}
return result;
}
function renderObject( object, camera, shadowCamera, light, type ) {
if ( object.visible === false ) return;
const visible = object.layers.test( camera.layers );
if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
const geometry = objects.update( object );
const material = object.material;
if ( Array.isArray( material ) ) {
const groups = geometry.groups;
for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
const group = groups[ k ];
const groupMaterial = material[ group.materialIndex ];
if ( groupMaterial && groupMaterial.visible ) {
const depthMaterial = getDepthMaterial( object, groupMaterial, light, type );
object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
}
}
} else if ( material.visible ) {
const depthMaterial = getDepthMaterial( object, material, light, type );
object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
}
}
}
const children = object.children;
for ( let i = 0, l = children.length; i < l; i ++ ) {
renderObject( children[ i ], camera, shadowCamera, light, type );
}
}
function onMaterialDispose( event ) {
const material = event.target;
material.removeEventListener( 'dispose', onMaterialDispose );
// make sure to remove the unique distance/depth materials used for shadow map rendering
for ( const id in _materialCache ) {
const cache = _materialCache[ id ];
const uuid = event.target.uuid;
if ( uuid in cache ) {
const shadowMaterial = cache[ uuid ];
shadowMaterial.dispose();
delete cache[ uuid ];
}
}
}
}
export { WebGLShadowMap };

1327
node_modules/three/src/renderers/webgl/WebGLState.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2403
node_modules/three/src/renderers/webgl/WebGLTextures.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1203
node_modules/three/src/renderers/webgl/WebGLUniforms.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,394 @@
import { error, warn } from '../../utils.js';
function WebGLUniformsGroups( gl, info, capabilities, state ) {
let buffers = {};
let updateList = {};
let allocatedBindingPoints = [];
const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program
function bind( uniformsGroup, program ) {
const webglProgram = program.program;
state.uniformBlockBinding( uniformsGroup, webglProgram );
}
function update( uniformsGroup, program ) {
let buffer = buffers[ uniformsGroup.id ];
if ( buffer === undefined ) {
prepareUniformsGroup( uniformsGroup );
buffer = createBuffer( uniformsGroup );
buffers[ uniformsGroup.id ] = buffer;
uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose );
}
// ensure to update the binding points/block indices mapping for this program
const webglProgram = program.program;
state.updateUBOMapping( uniformsGroup, webglProgram );
// update UBO once per frame
const frame = info.render.frame;
if ( updateList[ uniformsGroup.id ] !== frame ) {
updateBufferData( uniformsGroup );
updateList[ uniformsGroup.id ] = frame;
}
}
function createBuffer( uniformsGroup ) {
// the setup of an UBO is independent of a particular shader program but global
const bindingPointIndex = allocateBindingPointIndex();
uniformsGroup.__bindingPointIndex = bindingPointIndex;
const buffer = gl.createBuffer();
const size = uniformsGroup.__size;
const usage = uniformsGroup.usage;
gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
gl.bufferData( gl.UNIFORM_BUFFER, size, usage );
gl.bindBuffer( gl.UNIFORM_BUFFER, null );
gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer );
return buffer;
}
function allocateBindingPointIndex() {
for ( let i = 0; i < maxBindingPoints; i ++ ) {
if ( allocatedBindingPoints.indexOf( i ) === - 1 ) {
allocatedBindingPoints.push( i );
return i;
}
}
error( 'WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
return 0;
}
function updateBufferData( uniformsGroup ) {
const buffer = buffers[ uniformsGroup.id ];
const uniforms = uniformsGroup.uniforms;
const cache = uniformsGroup.__cache;
gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
for ( let i = 0, il = uniforms.length; i < il; i ++ ) {
const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
const uniform = uniformArray[ j ];
if ( hasUniformChanged( uniform, i, j, cache ) === true ) {
const offset = uniform.__offset;
const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
let arrayOffset = 0;
for ( let k = 0; k < values.length; k ++ ) {
const value = values[ k ];
const info = getUniformSize( value );
// TODO add integer and struct support
if ( typeof value === 'number' || typeof value === 'boolean' ) {
uniform.__data[ 0 ] = value;
gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data );
} else if ( value.isMatrix3 ) {
// manually converting 3x3 to 3x4
uniform.__data[ 0 ] = value.elements[ 0 ];
uniform.__data[ 1 ] = value.elements[ 1 ];
uniform.__data[ 2 ] = value.elements[ 2 ];
uniform.__data[ 3 ] = 0;
uniform.__data[ 4 ] = value.elements[ 3 ];
uniform.__data[ 5 ] = value.elements[ 4 ];
uniform.__data[ 6 ] = value.elements[ 5 ];
uniform.__data[ 7 ] = 0;
uniform.__data[ 8 ] = value.elements[ 6 ];
uniform.__data[ 9 ] = value.elements[ 7 ];
uniform.__data[ 10 ] = value.elements[ 8 ];
uniform.__data[ 11 ] = 0;
} else {
value.toArray( uniform.__data, arrayOffset );
arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
}
}
gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
}
}
}
gl.bindBuffer( gl.UNIFORM_BUFFER, null );
}
function hasUniformChanged( uniform, index, indexArray, cache ) {
const value = uniform.value;
const indexString = index + '_' + indexArray;
if ( cache[ indexString ] === undefined ) {
// cache entry does not exist so far
if ( typeof value === 'number' || typeof value === 'boolean' ) {
cache[ indexString ] = value;
} else {
cache[ indexString ] = value.clone();
}
return true;
} else {
const cachedObject = cache[ indexString ];
// compare current value with cached entry
if ( typeof value === 'number' || typeof value === 'boolean' ) {
if ( cachedObject !== value ) {
cache[ indexString ] = value;
return true;
}
} else {
if ( cachedObject.equals( value ) === false ) {
cachedObject.copy( value );
return true;
}
}
}
return false;
}
function prepareUniformsGroup( uniformsGroup ) {
// determine total buffer size according to the STD140 layout
// Hint: STD140 is the only supported layout in WebGL 2
const uniforms = uniformsGroup.uniforms;
let offset = 0; // global buffer offset in bytes
const chunkSize = 16; // size of a chunk in bytes
for ( let i = 0, l = uniforms.length; i < l; i ++ ) {
const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
const uniform = uniformArray[ j ];
const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
for ( let k = 0, kl = values.length; k < kl; k ++ ) {
const value = values[ k ];
const info = getUniformSize( value );
const chunkOffset = offset % chunkSize; // offset in the current chunk
const chunkPadding = chunkOffset % info.boundary; // required padding to match boundary
const chunkStart = chunkOffset + chunkPadding; // the start position in the current chunk for the data
offset += chunkPadding;
// Check for chunk overflow
if ( chunkStart !== 0 && ( chunkSize - chunkStart ) < info.storage ) {
// Add padding and adjust offset
offset += ( chunkSize - chunkStart );
}
// the following two properties will be used for partial buffer updates
uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT );
uniform.__offset = offset;
// Update the global offset
offset += info.storage;
}
}
}
// ensure correct final padding
const chunkOffset = offset % chunkSize;
if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset );
//
uniformsGroup.__size = offset;
uniformsGroup.__cache = {};
return this;
}
function getUniformSize( value ) {
const info = {
boundary: 0, // bytes
storage: 0 // bytes
};
// determine sizes according to STD140
if ( typeof value === 'number' || typeof value === 'boolean' ) {
// float/int/bool
info.boundary = 4;
info.storage = 4;
} else if ( value.isVector2 ) {
// vec2
info.boundary = 8;
info.storage = 8;
} else if ( value.isVector3 || value.isColor ) {
// vec3
info.boundary = 16;
info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes
} else if ( value.isVector4 ) {
// vec4
info.boundary = 16;
info.storage = 16;
} else if ( value.isMatrix3 ) {
// mat3 (in STD140 a 3x3 matrix is represented as 3x4)
info.boundary = 48;
info.storage = 48;
} else if ( value.isMatrix4 ) {
// mat4
info.boundary = 64;
info.storage = 64;
} else if ( value.isTexture ) {
warn( 'WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
} else {
warn( 'WebGLRenderer: Unsupported uniform value type.', value );
}
return info;
}
function onUniformsGroupsDispose( event ) {
const uniformsGroup = event.target;
uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose );
const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
allocatedBindingPoints.splice( index, 1 );
gl.deleteBuffer( buffers[ uniformsGroup.id ] );
delete buffers[ uniformsGroup.id ];
delete updateList[ uniformsGroup.id ];
}
function dispose() {
for ( const id in buffers ) {
gl.deleteBuffer( buffers[ id ] );
}
allocatedBindingPoints = [];
buffers = {};
updateList = {};
}
return {
bind: bind,
update: update,
dispose: dispose
};
}
export { WebGLUniformsGroups };

217
node_modules/three/src/renderers/webgl/WebGLUtils.js generated vendored Normal file
View File

@@ -0,0 +1,217 @@
import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, RG11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, RedFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, NoColorSpace, SRGBTransfer, UnsignedInt5999Type, RGBFormat, UnsignedInt101111Type } from '../../constants.js';
import { ColorManagement } from '../../math/ColorManagement.js';
function WebGLUtils( gl, extensions ) {
function convert( p, colorSpace = NoColorSpace ) {
let extension;
const transfer = ColorManagement.getTransfer( colorSpace );
if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV;
if ( p === UnsignedInt101111Type ) return gl.UNSIGNED_INT_10F_11F_11F_REV;
if ( p === ByteType ) return gl.BYTE;
if ( p === ShortType ) return gl.SHORT;
if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
if ( p === IntType ) return gl.INT;
if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
if ( p === FloatType ) return gl.FLOAT;
if ( p === HalfFloatType ) return gl.HALF_FLOAT;
if ( p === AlphaFormat ) return gl.ALPHA;
if ( p === RGBFormat ) return gl.RGB;
if ( p === RGBAFormat ) return gl.RGBA;
if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
// WebGL2 formats.
if ( p === RedFormat ) return gl.RED;
if ( p === RedIntegerFormat ) return gl.RED_INTEGER;
if ( p === RGFormat ) return gl.RG;
if ( p === RGIntegerFormat ) return gl.RG_INTEGER;
if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER;
// S3TC
if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
if ( transfer === SRGBTransfer ) {
extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' );
if ( extension !== null ) {
if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
} else {
return null;
}
} else {
extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
if ( extension !== null ) {
if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
} else {
return null;
}
}
}
// PVRTC
if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
if ( extension !== null ) {
if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
} else {
return null;
}
}
// ETC
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format || p === R11_EAC_Format || p === SIGNED_R11_EAC_Format || p === RG11_EAC_Format || p === SIGNED_RG11_EAC_Format ) {
extension = extensions.get( 'WEBGL_compressed_texture_etc' );
if ( extension !== null ) {
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
if ( p === R11_EAC_Format ) return extension.COMPRESSED_R11_EAC;
if ( p === SIGNED_R11_EAC_Format ) return extension.COMPRESSED_SIGNED_R11_EAC;
if ( p === RG11_EAC_Format ) return extension.COMPRESSED_RG11_EAC;
if ( p === SIGNED_RG11_EAC_Format ) return extension.COMPRESSED_SIGNED_RG11_EAC;
} else {
return null;
}
}
// ASTC
if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
extension = extensions.get( 'WEBGL_compressed_texture_astc' );
if ( extension !== null ) {
if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
} else {
return null;
}
}
// BPTC
if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) {
extension = extensions.get( 'EXT_texture_compression_bptc' );
if ( extension !== null ) {
if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
} else {
return null;
}
}
// RGTC
if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) {
extension = extensions.get( 'EXT_texture_compression_rgtc' );
if ( extension !== null ) {
if ( p === RED_RGTC1_Format ) return extension.COMPRESSED_RED_RGTC1_EXT;
if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
} else {
return null;
}
}
//
if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8;
// if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
return ( gl[ p ] !== undefined ) ? gl[ p ] : null;
}
return { convert: convert };
}
export { WebGLUtils };