灯光uniforms传递准备工作

时间:2024-10-02 18:59:39

文章目录

        • setup
        • setupView (每次渲染scene都会执行) * viewMatrix

取自 WebGlLights.js r168

setup
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;

const 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.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 ++;

}
setupView (每次渲染scene都会执行) * viewMatrix
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 ++;

		}

	}

}