提交 35836933 编写于 作者: M Mr.doob

WebGLRenderer: Moved more lights code to WebGLLights.

上级 7c83499f
......@@ -55,7 +55,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;
......@@ -156,31 +157,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
......@@ -261,8 +237,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;
......@@ -295,7 +271,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 );
......@@ -329,7 +305,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;
......@@ -1048,19 +1024,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 ) {
......@@ -1136,7 +1119,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;
......@@ -1160,11 +1145,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();
......@@ -1306,7 +1289,13 @@ function WebGLRenderer( parameters ) {
if ( object.isLight ) {
lights.push( object );
lightsArray.push( object );
if ( object.castShadow ) {
shadowsArray.push( object );
}
} else if ( object.isSprite ) {
......@@ -1474,7 +1463,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 );
......@@ -1586,25 +1575,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
}
......@@ -1652,7 +1641,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;
......@@ -2243,226 +2232,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 ) {
......
......@@ -3,10 +3,11 @@
*/
import { Color } from '../../math/Color';
import { Vector3 } from '../../math/Vector3';
import { Matrix4 } from '../../math/Matrix4';
import { Vector2 } from '../../math/Vector2';
import { Vector3 } from '../../math/Vector3';
function WebGLLights() {
function UniformsCache() {
var lights = {};
......@@ -99,5 +100,231 @@ 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
}
}
export { WebGLLights };
......@@ -103,7 +103,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 ];
......@@ -187,7 +187,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,
......
......@@ -15,15 +15,13 @@ import { Vector2 } from '../../math/Vector2';
import { Matrix4 } from '../../math/Matrix4';
import { Frustum } from '../../math/Frustum';
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 ),
......@@ -110,7 +108,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 );
......@@ -122,9 +120,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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册