|
@@ -9091,15 +9091,13 @@ Object.assign( Frustum.prototype, {
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
|
*/
|
|
|
|
|
|
-function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
|
|
|
+function WebGLShadowMap( _renderer, _shadows, _objects, capabilities ) {
|
|
|
|
|
|
var _gl = _renderer.context,
|
|
|
_state = _renderer.state,
|
|
|
_frustum = new Frustum(),
|
|
|
_projScreenMatrix = new Matrix4(),
|
|
|
|
|
|
- _lightShadows = _lights.shadows,
|
|
|
-
|
|
|
_shadowMapSize = new Vector2(),
|
|
|
_maxShadowMapSize = new Vector2( capabilities.maxTextureSize, capabilities.maxTextureSize ),
|
|
|
|
|
@@ -9186,7 +9184,7 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
|
|
|
if ( scope.enabled === false ) return;
|
|
|
if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
|
|
|
|
|
|
- if ( _lightShadows.length === 0 ) return;
|
|
|
+ if ( _shadows.length === 0 ) return;
|
|
|
|
|
|
// Set GL state for depth map.
|
|
|
_state.disable( _gl.BLEND );
|
|
@@ -9198,9 +9196,9 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
|
|
|
|
|
|
var faceCount;
|
|
|
|
|
|
- for ( var i = 0, il = _lightShadows.length; i < il; i ++ ) {
|
|
|
+ for ( var i = 0, il = _shadows.length; i < il; i ++ ) {
|
|
|
|
|
|
- var light = _lightShadows[ i ];
|
|
|
+ var light = _shadows[ i ];
|
|
|
var shadow = light.shadow;
|
|
|
var isPointLight = light && light.isPointLight;
|
|
|
|
|
@@ -16848,7 +16846,7 @@ function WebGLGeometries( gl, attributes, infoMemory ) {
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
|
*/
|
|
|
|
|
|
-function WebGLLights() {
|
|
|
+function UniformsCache() {
|
|
|
|
|
|
var lights = {};
|
|
|
|
|
@@ -16941,6 +16939,232 @@ function WebGLLights() {
|
|
|
|
|
|
}
|
|
|
|
|
|
+function WebGLLights() {
|
|
|
+
|
|
|
+ var cache = new UniformsCache();
|
|
|
+
|
|
|
+ var state = {
|
|
|
+
|
|
|
+ hash: '',
|
|
|
+
|
|
|
+ ambient: [ 0, 0, 0 ],
|
|
|
+ directional: [],
|
|
|
+ directionalShadowMap: [],
|
|
|
+ directionalShadowMatrix: [],
|
|
|
+ spot: [],
|
|
|
+ spotShadowMap: [],
|
|
|
+ spotShadowMatrix: [],
|
|
|
+ rectArea: [],
|
|
|
+ point: [],
|
|
|
+ pointShadowMap: [],
|
|
|
+ pointShadowMatrix: [],
|
|
|
+ hemi: []
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var vector3 = new Vector3();
|
|
|
+ var matrix4 = new Matrix4();
|
|
|
+ var matrix42 = new Matrix4();
|
|
|
+
|
|
|
+ function setup( lights, shadows, camera ) {
|
|
|
+
|
|
|
+ var r = 0, g = 0, b = 0;
|
|
|
+
|
|
|
+ var directionalLength = 0;
|
|
|
+ var pointLength = 0;
|
|
|
+ var spotLength = 0;
|
|
|
+ var rectAreaLength = 0;
|
|
|
+ var hemiLength = 0;
|
|
|
+
|
|
|
+ var viewMatrix = camera.matrixWorldInverse;
|
|
|
+
|
|
|
+ for ( var i = 0, l = lights.length; i < l; i ++ ) {
|
|
|
+
|
|
|
+ var light = lights[ i ];
|
|
|
+
|
|
|
+ var color = light.color;
|
|
|
+ var intensity = light.intensity;
|
|
|
+ var distance = light.distance;
|
|
|
+
|
|
|
+ var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
|
|
|
+
|
|
|
+ if ( light.isAmbientLight ) {
|
|
|
+
|
|
|
+ r += color.r * intensity;
|
|
|
+ g += color.g * intensity;
|
|
|
+ b += color.b * intensity;
|
|
|
+
|
|
|
+ } else if ( light.isDirectionalLight ) {
|
|
|
+
|
|
|
+ var uniforms = cache.get( light );
|
|
|
+
|
|
|
+ uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
|
|
|
+ uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ vector3.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
+ uniforms.direction.sub( vector3 );
|
|
|
+ uniforms.direction.transformDirection( viewMatrix );
|
|
|
+
|
|
|
+ uniforms.shadow = light.castShadow;
|
|
|
+
|
|
|
+ if ( light.castShadow ) {
|
|
|
+
|
|
|
+ var shadow = light.shadow;
|
|
|
+
|
|
|
+ uniforms.shadowBias = shadow.bias;
|
|
|
+ uniforms.shadowRadius = shadow.radius;
|
|
|
+ uniforms.shadowMapSize = shadow.mapSize;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.directionalShadowMap[ directionalLength ] = shadowMap;
|
|
|
+ state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
|
|
|
+ state.directional[ directionalLength ] = uniforms;
|
|
|
+
|
|
|
+ directionalLength ++;
|
|
|
+
|
|
|
+ } else if ( light.isSpotLight ) {
|
|
|
+
|
|
|
+ var uniforms = cache.get( light );
|
|
|
+
|
|
|
+ uniforms.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ uniforms.position.applyMatrix4( viewMatrix );
|
|
|
+
|
|
|
+ uniforms.color.copy( color ).multiplyScalar( intensity );
|
|
|
+ uniforms.distance = distance;
|
|
|
+
|
|
|
+ uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ vector3.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
+ uniforms.direction.sub( vector3 );
|
|
|
+ uniforms.direction.transformDirection( viewMatrix );
|
|
|
+
|
|
|
+ uniforms.coneCos = Math.cos( light.angle );
|
|
|
+ uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
|
|
|
+ uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
|
|
|
+
|
|
|
+ uniforms.shadow = light.castShadow;
|
|
|
+
|
|
|
+ if ( light.castShadow ) {
|
|
|
+
|
|
|
+ var shadow = light.shadow;
|
|
|
+
|
|
|
+ uniforms.shadowBias = shadow.bias;
|
|
|
+ uniforms.shadowRadius = shadow.radius;
|
|
|
+ uniforms.shadowMapSize = shadow.mapSize;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.spotShadowMap[ spotLength ] = shadowMap;
|
|
|
+ state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
|
|
|
+ state.spot[ spotLength ] = uniforms;
|
|
|
+
|
|
|
+ spotLength ++;
|
|
|
+
|
|
|
+ } else if ( light.isRectAreaLight ) {
|
|
|
+
|
|
|
+ var uniforms = cache.get( light );
|
|
|
+
|
|
|
+ // (a) intensity controls irradiance of entire light
|
|
|
+ uniforms.color
|
|
|
+ .copy( color )
|
|
|
+ .multiplyScalar( intensity / ( light.width * light.height ) );
|
|
|
+
|
|
|
+ // (b) intensity controls the radiance per light area
|
|
|
+ // uniforms.color.copy( color ).multiplyScalar( intensity );
|
|
|
+
|
|
|
+ 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 );
|
|
|
+
|
|
|
+ // TODO (abelnation): RectAreaLight distance?
|
|
|
+ // uniforms.distance = distance;
|
|
|
+
|
|
|
+ state.rectArea[ rectAreaLength ] = uniforms;
|
|
|
+
|
|
|
+ rectAreaLength ++;
|
|
|
+
|
|
|
+ } else if ( light.isPointLight ) {
|
|
|
+
|
|
|
+ var uniforms = cache.get( light );
|
|
|
+
|
|
|
+ uniforms.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ uniforms.position.applyMatrix4( viewMatrix );
|
|
|
+
|
|
|
+ uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
|
|
|
+ uniforms.distance = light.distance;
|
|
|
+ uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
|
|
|
+
|
|
|
+ uniforms.shadow = light.castShadow;
|
|
|
+
|
|
|
+ if ( light.castShadow ) {
|
|
|
+
|
|
|
+ var shadow = light.shadow;
|
|
|
+
|
|
|
+ uniforms.shadowBias = shadow.bias;
|
|
|
+ uniforms.shadowRadius = shadow.radius;
|
|
|
+ uniforms.shadowMapSize = shadow.mapSize;
|
|
|
+ uniforms.shadowCameraNear = shadow.camera.near;
|
|
|
+ uniforms.shadowCameraFar = shadow.camera.far;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.pointShadowMap[ pointLength ] = shadowMap;
|
|
|
+ state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
|
|
|
+ state.point[ pointLength ] = uniforms;
|
|
|
+
|
|
|
+ pointLength ++;
|
|
|
+
|
|
|
+ } else if ( light.isHemisphereLight ) {
|
|
|
+
|
|
|
+ var uniforms = cache.get( light );
|
|
|
+
|
|
|
+ uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ uniforms.direction.transformDirection( viewMatrix );
|
|
|
+ uniforms.direction.normalize();
|
|
|
+
|
|
|
+ uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
|
|
|
+ uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
|
|
|
+
|
|
|
+ state.hemi[ hemiLength ] = uniforms;
|
|
|
+
|
|
|
+ hemiLength ++;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ state.ambient[ 0 ] = r;
|
|
|
+ state.ambient[ 1 ] = g;
|
|
|
+ state.ambient[ 2 ] = b;
|
|
|
+
|
|
|
+ state.directional.length = directionalLength;
|
|
|
+ state.spot.length = spotLength;
|
|
|
+ state.rectArea.length = rectAreaLength;
|
|
|
+ state.point.length = pointLength;
|
|
|
+ state.hemi.length = hemiLength;
|
|
|
+
|
|
|
+ // TODO (sam-g-steel) why aren't we using join
|
|
|
+ state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ setup: setup,
|
|
|
+ state: state
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
|
*/
|
|
@@ -17805,7 +18029,7 @@ function WebGLPrograms( renderer, capabilities ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- this.getParameters = function ( material, lights, fog, nClipPlanes, nClipIntersection, object ) {
|
|
|
+ this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
|
|
|
|
|
|
var shaderID = shaderIDs[ material.type ];
|
|
|
|
|
@@ -17889,7 +18113,7 @@ function WebGLPrograms( renderer, capabilities ) {
|
|
|
|
|
|
dithering: material.dithering,
|
|
|
|
|
|
- shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0,
|
|
|
+ shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
|
|
|
shadowMapType: renderer.shadowMap.type,
|
|
|
|
|
|
toneMapping: renderer.toneMapping,
|
|
@@ -20371,7 +20595,8 @@ function WebGLRenderer( parameters ) {
|
|
|
_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
|
|
|
_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false;
|
|
|
|
|
|
- var lights = [];
|
|
|
+ var lightsArray = [];
|
|
|
+ var shadowsArray = [];
|
|
|
|
|
|
var currentRenderList = null;
|
|
|
|
|
@@ -20472,31 +20697,6 @@ function WebGLRenderer( parameters ) {
|
|
|
_projScreenMatrix = new Matrix4(),
|
|
|
|
|
|
_vector3 = new Vector3(),
|
|
|
- _matrix4 = new Matrix4(),
|
|
|
- _matrix42 = new Matrix4(),
|
|
|
-
|
|
|
- // light arrays cache
|
|
|
-
|
|
|
- _lights = {
|
|
|
-
|
|
|
- hash: '',
|
|
|
-
|
|
|
- ambient: [ 0, 0, 0 ],
|
|
|
- directional: [],
|
|
|
- directionalShadowMap: [],
|
|
|
- directionalShadowMatrix: [],
|
|
|
- spot: [],
|
|
|
- spotShadowMap: [],
|
|
|
- spotShadowMatrix: [],
|
|
|
- rectArea: [],
|
|
|
- point: [],
|
|
|
- pointShadowMap: [],
|
|
|
- pointShadowMatrix: [],
|
|
|
- hemi: [],
|
|
|
-
|
|
|
- shadows: []
|
|
|
-
|
|
|
- },
|
|
|
|
|
|
// info
|
|
|
|
|
@@ -20577,8 +20777,8 @@ function WebGLRenderer( parameters ) {
|
|
|
}
|
|
|
|
|
|
var extensions, capabilities, state;
|
|
|
- var properties, textures, attributes, geometries, objects;
|
|
|
- var programCache, lightCache, renderLists;
|
|
|
+ var properties, textures, attributes, geometries, objects, lights;
|
|
|
+ var programCache, renderLists;
|
|
|
|
|
|
var background, bufferRenderer, indexedBufferRenderer;
|
|
|
|
|
@@ -20611,7 +20811,7 @@ function WebGLRenderer( parameters ) {
|
|
|
geometries = new WebGLGeometries( _gl, attributes, _infoMemory );
|
|
|
objects = new WebGLObjects( _gl, geometries, _infoRender );
|
|
|
programCache = new WebGLPrograms( _this, capabilities );
|
|
|
- lightCache = new WebGLLights();
|
|
|
+ lights = new WebGLLights();
|
|
|
renderLists = new WebGLRenderLists();
|
|
|
|
|
|
background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
|
|
@@ -20645,7 +20845,7 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
// shadow map
|
|
|
|
|
|
- var shadowMap = new WebGLShadowMap( this, _lights, objects, capabilities );
|
|
|
+ var shadowMap = new WebGLShadowMap( this, shadowsArray, objects, capabilities );
|
|
|
|
|
|
this.shadowMap = shadowMap;
|
|
|
|
|
@@ -21364,19 +21564,26 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
this.compile = function ( scene, camera ) {
|
|
|
|
|
|
- lights = [];
|
|
|
+ lightsArray.length = 0;
|
|
|
+ shadowsArray.length = 0;
|
|
|
|
|
|
scene.traverse( function ( object ) {
|
|
|
|
|
|
if ( object.isLight ) {
|
|
|
|
|
|
- lights.push( object );
|
|
|
+ lightsArray.push( object );
|
|
|
+
|
|
|
+ if ( object.castShadow ) {
|
|
|
+
|
|
|
+ shadowsArray.push( object );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
} );
|
|
|
|
|
|
- setupLights( lights, camera );
|
|
|
+ lights.setup( lightsArray, shadowsArray, camera );
|
|
|
|
|
|
scene.traverse( function ( object ) {
|
|
|
|
|
@@ -21452,7 +21659,9 @@ function WebGLRenderer( parameters ) {
|
|
|
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
|
|
|
_frustum.setFromMatrix( _projScreenMatrix );
|
|
|
|
|
|
- lights.length = 0;
|
|
|
+ lightsArray.length = 0;
|
|
|
+ shadowsArray.length = 0;
|
|
|
+
|
|
|
sprites.length = 0;
|
|
|
lensFlares.length = 0;
|
|
|
|
|
@@ -21476,11 +21685,9 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
if ( _clippingEnabled ) _clipping.beginShadows();
|
|
|
|
|
|
- setupShadows( lights );
|
|
|
-
|
|
|
shadowMap.render( scene, camera );
|
|
|
|
|
|
- setupLights( lights, camera );
|
|
|
+ lights.setup( lightsArray, shadowsArray, camera );
|
|
|
|
|
|
if ( _clippingEnabled ) _clipping.endShadows();
|
|
|
|
|
@@ -21622,7 +21829,13 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
if ( object.isLight ) {
|
|
|
|
|
|
- lights.push( object );
|
|
|
+ lightsArray.push( object );
|
|
|
+
|
|
|
+ if ( object.castShadow ) {
|
|
|
+
|
|
|
+ shadowsArray.push( object );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
} else if ( object.isSprite ) {
|
|
|
|
|
@@ -21790,7 +22003,7 @@ function WebGLRenderer( parameters ) {
|
|
|
var materialProperties = properties.get( material );
|
|
|
|
|
|
var parameters = programCache.getParameters(
|
|
|
- material, _lights, fog, _clipping.numPlanes, _clipping.numIntersection, object );
|
|
|
+ material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
|
|
|
|
|
|
var code = programCache.getProgramCode( material, parameters );
|
|
|
|
|
@@ -21902,25 +22115,25 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
// store the light setup it was created for
|
|
|
|
|
|
- materialProperties.lightsHash = _lights.hash;
|
|
|
+ materialProperties.lightsHash = lights.state.hash;
|
|
|
|
|
|
if ( material.lights ) {
|
|
|
|
|
|
// wire up the material to this renderer's lighting state
|
|
|
|
|
|
- uniforms.ambientLightColor.value = _lights.ambient;
|
|
|
- uniforms.directionalLights.value = _lights.directional;
|
|
|
- uniforms.spotLights.value = _lights.spot;
|
|
|
- uniforms.rectAreaLights.value = _lights.rectArea;
|
|
|
- uniforms.pointLights.value = _lights.point;
|
|
|
- uniforms.hemisphereLights.value = _lights.hemi;
|
|
|
-
|
|
|
- uniforms.directionalShadowMap.value = _lights.directionalShadowMap;
|
|
|
- uniforms.directionalShadowMatrix.value = _lights.directionalShadowMatrix;
|
|
|
- uniforms.spotShadowMap.value = _lights.spotShadowMap;
|
|
|
- uniforms.spotShadowMatrix.value = _lights.spotShadowMatrix;
|
|
|
- uniforms.pointShadowMap.value = _lights.pointShadowMap;
|
|
|
- uniforms.pointShadowMatrix.value = _lights.pointShadowMatrix;
|
|
|
+ uniforms.ambientLightColor.value = lights.state.ambient;
|
|
|
+ uniforms.directionalLights.value = lights.state.directional;
|
|
|
+ uniforms.spotLights.value = lights.state.spot;
|
|
|
+ uniforms.rectAreaLights.value = lights.state.rectArea;
|
|
|
+ uniforms.pointLights.value = lights.state.point;
|
|
|
+ uniforms.hemisphereLights.value = lights.state.hemi;
|
|
|
+
|
|
|
+ uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
|
|
|
+ uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
|
|
|
+ uniforms.spotShadowMap.value = lights.state.spotShadowMap;
|
|
|
+ uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
|
|
|
+ uniforms.pointShadowMap.value = lights.state.pointShadowMap;
|
|
|
+ uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
|
|
|
// TODO (abelnation): add area lights shadow info to uniforms
|
|
|
|
|
|
}
|
|
@@ -21968,7 +22181,7 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
material.needsUpdate = true;
|
|
|
|
|
|
- } else if ( material.lights && materialProperties.lightsHash !== _lights.hash ) {
|
|
|
+ } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) {
|
|
|
|
|
|
material.needsUpdate = true;
|
|
|
|
|
@@ -22559,226 +22772,6 @@ function WebGLRenderer( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Lighting
|
|
|
-
|
|
|
- function setupShadows( lights ) {
|
|
|
-
|
|
|
- var lightShadowsLength = 0;
|
|
|
-
|
|
|
- for ( var i = 0, l = lights.length; i < l; i ++ ) {
|
|
|
-
|
|
|
- var light = lights[ i ];
|
|
|
-
|
|
|
- if ( light.castShadow ) {
|
|
|
-
|
|
|
- _lights.shadows[ lightShadowsLength ] = light;
|
|
|
- lightShadowsLength ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _lights.shadows.length = lightShadowsLength;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function setupLights( lights, camera ) {
|
|
|
-
|
|
|
- var l, ll, light, shadow,
|
|
|
- r = 0, g = 0, b = 0,
|
|
|
- color,
|
|
|
- intensity,
|
|
|
- distance,
|
|
|
- shadowMap,
|
|
|
-
|
|
|
- viewMatrix = camera.matrixWorldInverse,
|
|
|
-
|
|
|
- directionalLength = 0,
|
|
|
- pointLength = 0,
|
|
|
- spotLength = 0,
|
|
|
- rectAreaLength = 0,
|
|
|
- hemiLength = 0;
|
|
|
-
|
|
|
- for ( l = 0, ll = lights.length; l < ll; l ++ ) {
|
|
|
-
|
|
|
- light = lights[ l ];
|
|
|
-
|
|
|
- color = light.color;
|
|
|
- intensity = light.intensity;
|
|
|
- distance = light.distance;
|
|
|
-
|
|
|
- shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
|
|
|
-
|
|
|
- if ( light.isAmbientLight ) {
|
|
|
-
|
|
|
- r += color.r * intensity;
|
|
|
- g += color.g * intensity;
|
|
|
- b += color.b * intensity;
|
|
|
-
|
|
|
- } else if ( light.isDirectionalLight ) {
|
|
|
-
|
|
|
- var uniforms = lightCache.get( light );
|
|
|
-
|
|
|
- uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
|
|
|
- uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
- _vector3.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
- uniforms.direction.sub( _vector3 );
|
|
|
- uniforms.direction.transformDirection( viewMatrix );
|
|
|
-
|
|
|
- uniforms.shadow = light.castShadow;
|
|
|
-
|
|
|
- if ( light.castShadow ) {
|
|
|
-
|
|
|
- shadow = light.shadow;
|
|
|
-
|
|
|
- uniforms.shadowBias = shadow.bias;
|
|
|
- uniforms.shadowRadius = shadow.radius;
|
|
|
- uniforms.shadowMapSize = shadow.mapSize;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _lights.directionalShadowMap[ directionalLength ] = shadowMap;
|
|
|
- _lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
|
|
|
- _lights.directional[ directionalLength ] = uniforms;
|
|
|
-
|
|
|
- directionalLength ++;
|
|
|
-
|
|
|
- } else if ( light.isSpotLight ) {
|
|
|
-
|
|
|
- var uniforms = lightCache.get( light );
|
|
|
-
|
|
|
- uniforms.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
- uniforms.position.applyMatrix4( viewMatrix );
|
|
|
-
|
|
|
- uniforms.color.copy( color ).multiplyScalar( intensity );
|
|
|
- uniforms.distance = distance;
|
|
|
-
|
|
|
- uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
- _vector3.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
- uniforms.direction.sub( _vector3 );
|
|
|
- uniforms.direction.transformDirection( viewMatrix );
|
|
|
-
|
|
|
- uniforms.coneCos = Math.cos( light.angle );
|
|
|
- uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
|
|
|
- uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
|
|
|
-
|
|
|
- uniforms.shadow = light.castShadow;
|
|
|
-
|
|
|
- if ( light.castShadow ) {
|
|
|
-
|
|
|
- shadow = light.shadow;
|
|
|
-
|
|
|
- uniforms.shadowBias = shadow.bias;
|
|
|
- uniforms.shadowRadius = shadow.radius;
|
|
|
- uniforms.shadowMapSize = shadow.mapSize;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _lights.spotShadowMap[ spotLength ] = shadowMap;
|
|
|
- _lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
|
|
|
- _lights.spot[ spotLength ] = uniforms;
|
|
|
-
|
|
|
- spotLength ++;
|
|
|
-
|
|
|
- } else if ( light.isRectAreaLight ) {
|
|
|
-
|
|
|
- var uniforms = lightCache.get( light );
|
|
|
-
|
|
|
- // (a) intensity controls irradiance of entire light
|
|
|
- uniforms.color
|
|
|
- .copy( color )
|
|
|
- .multiplyScalar( intensity / ( light.width * light.height ) );
|
|
|
-
|
|
|
- // (b) intensity controls the radiance per light area
|
|
|
- // uniforms.color.copy( color ).multiplyScalar( intensity );
|
|
|
-
|
|
|
- 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 );
|
|
|
-
|
|
|
- // TODO (abelnation): RectAreaLight distance?
|
|
|
- // uniforms.distance = distance;
|
|
|
-
|
|
|
- _lights.rectArea[ rectAreaLength ] = uniforms;
|
|
|
-
|
|
|
- rectAreaLength ++;
|
|
|
-
|
|
|
- } else if ( light.isPointLight ) {
|
|
|
-
|
|
|
- var uniforms = lightCache.get( light );
|
|
|
-
|
|
|
- uniforms.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
- uniforms.position.applyMatrix4( viewMatrix );
|
|
|
-
|
|
|
- uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
|
|
|
- uniforms.distance = light.distance;
|
|
|
- uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
|
|
|
-
|
|
|
- uniforms.shadow = light.castShadow;
|
|
|
-
|
|
|
- if ( light.castShadow ) {
|
|
|
-
|
|
|
- shadow = light.shadow;
|
|
|
-
|
|
|
- uniforms.shadowBias = shadow.bias;
|
|
|
- uniforms.shadowRadius = shadow.radius;
|
|
|
- uniforms.shadowMapSize = shadow.mapSize;
|
|
|
- uniforms.shadowCameraNear = shadow.camera.near;
|
|
|
- uniforms.shadowCameraFar = shadow.camera.far;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _lights.pointShadowMap[ pointLength ] = shadowMap;
|
|
|
- _lights.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
|
|
|
- _lights.point[ pointLength ] = uniforms;
|
|
|
-
|
|
|
- pointLength ++;
|
|
|
-
|
|
|
- } else if ( light.isHemisphereLight ) {
|
|
|
-
|
|
|
- var uniforms = lightCache.get( light );
|
|
|
-
|
|
|
- uniforms.direction.setFromMatrixPosition( light.matrixWorld );
|
|
|
- uniforms.direction.transformDirection( viewMatrix );
|
|
|
- uniforms.direction.normalize();
|
|
|
-
|
|
|
- uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
|
|
|
- uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
|
|
|
-
|
|
|
- _lights.hemi[ hemiLength ] = uniforms;
|
|
|
-
|
|
|
- hemiLength ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- _lights.ambient[ 0 ] = r;
|
|
|
- _lights.ambient[ 1 ] = g;
|
|
|
- _lights.ambient[ 2 ] = b;
|
|
|
-
|
|
|
- _lights.directional.length = directionalLength;
|
|
|
- _lights.spot.length = spotLength;
|
|
|
- _lights.rectArea.length = rectAreaLength;
|
|
|
- _lights.point.length = pointLength;
|
|
|
- _lights.hemi.length = hemiLength;
|
|
|
-
|
|
|
- // TODO (sam-g-steel) why aren't we using join
|
|
|
- _lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + _lights.shadows.length;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
// GL state setting
|
|
|
|
|
|
this.setFaceCulling = function ( cullFace, frontFaceDirection ) {
|