未验证 提交 79f6e564 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #17171 from supereggbert/vsm

Addition of variance shadow maps
......@@ -39,13 +39,15 @@
THREE.BasicShadowMap
THREE.PCFShadowMap
THREE.PCFSoftShadowMap
THREE.VSMShadowMap
</code>
<p>
These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.<br /><br />
[page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but lowest quality.<br />
[page:constant PCFShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm (default).<br />
[page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Soft Shadows (PCSS) algorithm.
[page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Soft Shadows (PCSS) algorithm.<br />
[page:constant VSMShadowMap] filters shadow maps using the Variance Shadow Map (VSM) algorithm.
</p>
<h2>Tone Mapping</h2>
......
......@@ -22,7 +22,7 @@
<p>
[page:Camera camera] - the light's view of the world.<br /><br />
Create a new [name]. This is not intended to be called directly - it is used as a base class by
Create a new [name]. This is not intended to be called directly - it is used as a base class by
other light shadows.
</p>
......@@ -46,6 +46,12 @@
in shadow. Computed internally during rendering.
</p>
<h3>[property:WebGLRenderTarget mapPass]</h3>
<p>
The distribution map generated using the internal camera; an occlusion is calculated based
on the distribution of depths. Computed internally during rendering.
</p>
<h3>[property:Vector2 mapSize]</h3>
<p>
A [Page:Vector2] defining the width and height of the shadow map.<br /><br />
......@@ -56,7 +62,6 @@
The default is *( 512, 512 )*.
</p>
<h3>[property:Matrix4 matrix]</h3>
<p>
Model to shadow camera space, to compute location and depth in shadow map. Stored
......@@ -118,8 +123,6 @@
<h2>Source</h2>
<p>
[link:https://github.com/mrdoob/three.js/blob/master/src/lights/[name].js src/lights/[name].js]
</p>
[link:https://github.com/mrdoob/three.js/blob/master/src/lights/[name].js src/lights/[name].js]
</body>
</html>
......@@ -248,7 +248,7 @@
<h3>[property:Integer shadowMap.type]</h3>
<p>Defines shadow map type (unfiltered, percentage close filtering, percentage close filtering with bilinear filtering in shader)</p>
<p>Options are THREE.BasicShadowMap, THREE.PCFShadowMap (default) and THREE.PCFSoftShadowMap. See [page:Renderer Renderer constants] for details.</p>
<p>Options are THREE.BasicShadowMap, THREE.PCFShadowMap (default), THREE.PCFSoftShadowMap and THREE.VSMShadowMap. See [page:Renderer Renderer constants] for details.</p>
<h3>[property:Boolean sortObjects]</h3>
<p>
......
......@@ -229,6 +229,7 @@ var files = {
"webgl_shaders_vector",
"webgl_shading_physical",
"webgl_shadowmap",
"webgl_shadowmap_vsm",
"webgl_shadowmap_performance",
"webgl_shadowmap_pointlight",
"webgl_shadowmap_viewer",
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - VSM Shadows example </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - VSM Shadows example by <a href="https://github.com/supereggbert">Paul Brunt</a>
</div>
<script type="module">
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
import { GUI } from './jsm/libs/dat.gui.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
var camera, scene, renderer, clock, stats;
var dirLight, spotLight;
var torusKnot, dirGroup;
init();
animate();
function init() {
initScene();
initMisc();
// Init gui
var gui = new GUI();
var config = {
'Spotlight Radius': 4,
'Directional light Radius': 4,
};
gui.add( config, 'Spotlight Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
spotLight.shadow.radius = value;
} );
gui.add( config, 'Directional light Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
dirLight.shadow.radius = value;
} );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function initScene() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 10, 30 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xCCCCCC, 50, 100 );
// Lights
scene.add( new THREE.AmbientLight( 0x444444 ) );
spotLight = new THREE.SpotLight( 0x888888 );
spotLight.name = 'Spot Light';
spotLight.angle = Math.PI / 5;
spotLight.penumbra = 0.3;
spotLight.position.set( 8, 10, 5 );
spotLight.castShadow = true;
spotLight.shadow.camera.near = 8;
spotLight.shadow.camera.far = 200;
spotLight.shadow.mapSize.width = 256;
spotLight.shadow.mapSize.height = 256;
spotLight.shadow.bias = -0.002;
spotLight.shadow.radius = 4;
scene.add( spotLight );
dirLight = new THREE.DirectionalLight( 0xFFFFFF, 1 );
dirLight.name = 'Dir. Light';
dirLight.position.set( 3, 12, 17 );
dirLight.castShadow = true;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 500;
dirLight.shadow.camera.right = 17;
dirLight.shadow.camera.left = - 17;
dirLight.shadow.camera.top = 17;
dirLight.shadow.camera.bottom = - 17;
dirLight.shadow.mapSize.width = 512;
dirLight.shadow.mapSize.height = 512;
dirLight.shadow.radius = 4;
dirLight.shadow.bias = -0.0005;
scene.add( dirLight );
dirGroup = new THREE.Group();
dirGroup.add( dirLight );
scene.add( dirGroup );
// Geometry
var geometry = new THREE.TorusKnotBufferGeometry( 25, 8, 75, 20 );
var material = new THREE.MeshPhongMaterial( {
color: 0x999999,
shininess: 0,
specular: 0x222222
} );
torusKnot = new THREE.Mesh( geometry, material );
torusKnot.scale.multiplyScalar( 1 / 18 );
torusKnot.position.y = 3;
torusKnot.castShadow = true;
torusKnot.receiveShadow = true;
scene.add( torusKnot );
var geometry = new THREE.CylinderBufferGeometry( 0.75, 0.75, 7, 32 );
var pillar1 = new THREE.Mesh( geometry, material );
pillar1.position.set( 10, 3.5, 10 );
pillar1.castShadow = true;
pillar1.receiveShadow = true;
var pillar2 = pillar1.clone();
pillar2.position.set( 10, 3.5, -10 );
var pillar3 = pillar1.clone();
pillar3.position.set( -10, 3.5, 10 );
var pillar4 = pillar1.clone();
pillar4.position.set( -10, 3.5, -10 );
scene.add( pillar1 );
scene.add( pillar2 );
scene.add( pillar3 );
scene.add( pillar4 );
var geometry = new THREE.PlaneBufferGeometry( 200, 200 );
var material = new THREE.MeshPhongMaterial( {
color: 0x999999,
shininess: 0,
specular: 0x111111
} );
var ground = new THREE.Mesh( geometry, material );
ground.rotation.x = -Math.PI/2;
ground.scale.multiplyScalar( 3 );
ground.castShadow = true;
ground.receiveShadow = true;
scene.add( ground );
}
function initMisc() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.VSMShadowMap;
renderer.setClearColor( 0xCCCCCC, 1 );
// Mouse control
var controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 2, 0 );
controls.update();
clock = new THREE.Clock();
stats = new Stats();
document.body.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function renderScene() {
renderer.render( scene, camera );
}
function render() {
var delta = clock.getDelta();
var time = clock.elapsedTime;
renderScene();
torusKnot.rotation.x += 0.25 * delta;
torusKnot.rotation.y += 2 * delta;
torusKnot.rotation.z += 1 * delta;
dirGroup.rotation.y += 0.7 * delta;
dirLight.position.z = 17 + Math.sin(time*0.001)*5;
}
</script>
</body>
</html>
......@@ -33,6 +33,7 @@ export enum ShadowMapType {}
export const BasicShadowMap: ShadowMapType;
export const PCFShadowMap: ShadowMapType;
export const PCFSoftShadowMap: ShadowMapType;
export const VSMShadowMap: ShadowMapType;
// MATERIAL CONSTANTS
......
......@@ -10,6 +10,7 @@ export var FrontFaceDirectionCCW = 1;
export var BasicShadowMap = 0;
export var PCFShadowMap = 1;
export var PCFSoftShadowMap = 2;
export var VSMShadowMap = 3;
export var FrontSide = 0;
export var BackSide = 1;
export var DoubleSide = 2;
......
......@@ -14,6 +14,7 @@ export class LightShadow {
radius: number;
mapSize: Vector2;
map: RenderTarget;
mapPass: RenderTarget;
matrix: Matrix4;
copy( source: LightShadow ): this;
......
......@@ -18,6 +18,7 @@ function LightShadow( camera ) {
this.mapSize = new Vector2( 512, 512 );
this.map = null;
this.mapPass = null;
this.matrix = new Matrix4();
this._frustum = new Frustum();
......
......@@ -122,6 +122,8 @@ import shadow_frag from './ShaderLib/shadow_frag.glsl.js';
import shadow_vert from './ShaderLib/shadow_vert.glsl.js';
import sprite_frag from './ShaderLib/sprite_frag.glsl.js';
import sprite_vert from './ShaderLib/sprite_vert.glsl.js';
import vsm_frag from './ShaderLib/vsm_frag.glsl.js';
import vsm_vert from './ShaderLib/vsm_vert.glsl.js';
export var ShaderChunk = {
alphamap_fragment: alphamap_fragment,
......@@ -247,5 +249,7 @@ export var ShaderChunk = {
shadow_frag: shadow_frag,
shadow_vert: shadow_vert,
sprite_frag: sprite_frag,
sprite_vert: sprite_vert
sprite_vert: sprite_vert,
vsm_frag: vsm_frag,
vsm_vert: vsm_vert
};
......@@ -25,6 +25,23 @@ float unpackRGBAToDepth( const in vec4 v ) {
return dot( v, UnpackFactors );
}
vec4 encodeHalfRGBA ( vec2 v ) {
vec4 encoded = vec4( 0.0 );
const vec2 offset = vec2( 1.0 / 255.0, 0.0 );
encoded.xy = vec2( v.x, fract( v.x * 255.0 ) );
encoded.xy = encoded.xy - ( encoded.yy * offset );
encoded.zw = vec2( v.y, fract( v.y * 255.0 ) );
encoded.zw = encoded.zw - ( encoded.ww * offset );
return encoded;
}
vec2 decodeHalfRGBA( vec4 v ) {
return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );
}
// NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions
float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {
......
......@@ -36,6 +36,33 @@ export default /* glsl */`
}
vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {
return decodeHalfRGBA( texture2D( shadow, uv ) );
}
float VSMShadow (sampler2D shadow, vec2 uv, float compare ){
float occlusion = 1.0;
vec2 distribution = texture2DDistribution( shadow, uv );
float hard_shadow = step( compare , distribution.x ); // Hard Shadow
if (hard_shadow != 1.0 ) {
float distance = compare - distribution.x ;
float variance = max( 0.00000, distribution.y * distribution.y );
float softness_probability = variance / (variance + distance * distance ); // Chebeyshevs inequality
softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); // 0.3 reduces light bleed
occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );
}
return occlusion;
}
float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {
const vec2 offset = vec2( 0.0, 1.0 );
......@@ -131,6 +158,10 @@ export default /* glsl */`
texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
) * ( 1.0 / 9.0 );
#elif defined( SHADOWMAP_TYPE_VSM )
shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );
#else // no percentage-closer filtering:
shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );
......@@ -229,7 +260,7 @@ export default /* glsl */`
// bd3D = base direction 3D
vec3 bd3D = normalize( lightToPosition );
#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )
vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;
......
export default /* glsl */`
uniform sampler2D shadow_pass;
uniform vec2 resolution;
uniform float radius;
#include <packing>
void main() {
float mean = 0.0;
float squared_mean = 0.0;
// This seems totally useless but it's a crazy work around for a Adreno compiler bug
float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );
for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {
#ifdef HORIZONAL_PASS
vec2 distribution = decodeHalfRGBA ( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );
mean += distribution.x;
squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;
#else
float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );
mean += depth;
squared_mean += depth * depth;
#endif
}
mean = mean * HALF_SAMPLE_RATE;
squared_mean = squared_mean * HALF_SAMPLE_RATE;
float std_dev = pow( squared_mean - mean * mean, 0.5 );
gl_FragColor = encodeHalfRGBA( vec2( mean, std_dev ) );
}
`;
export default /* glsl */`
void main() {
gl_Position = vec4( position, 1.0 );
}
`;
......@@ -5,7 +5,7 @@
import { WebGLUniforms } from './WebGLUniforms.js';
import { WebGLShader } from './WebGLShader.js';
import { ShaderChunk } from '../shaders/ShaderChunk.js';
import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';
import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';
var programIdCount = 0;
......@@ -262,6 +262,10 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
} else if ( parameters.shadowMapType === VSMShadowMap ) {
shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
}
var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
......
......@@ -3,10 +3,15 @@
* @author mrdoob / http://mrdoob.com/
*/
import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, PCFShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, LinearFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.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 { ShaderChunk } from '../shaders/ShaderChunk.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector2 } from '../../math/Vector2.js';
import { Frustum } from '../../math/Frustum.js';
......@@ -32,6 +37,39 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
var shadowMaterialVertical = new ShaderMaterial( {
defines: {
SAMPLE_RATE: 2.0 / 8.0,
HALF_SAMPLE_RATE: 1.0 / 8.0
},
uniforms: {
shadow_pass: { value: null },
resolution: { value: new Vector2() },
radius: { value: 4.0 }
},
vertexShader: ShaderChunk.vsm_vert,
fragmentShader: ShaderChunk.vsm_frag
} );
var shadowMaterialHorizonal = shadowMaterialVertical.clone();
shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
var fullScreenTri = new BufferGeometry();
fullScreenTri.addAttribute(
"position",
new BufferAttribute(
new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
3
)
);
var fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
// init
for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
......@@ -133,6 +171,19 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
}
if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
shadow.map.texture.name = light.name + ".shadowMap";
shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
shadow.camera.updateProjectionMatrix();
}
if ( shadow.map === null ) {
var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
......@@ -166,7 +217,15 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
_frustum = shadow.getFrustum();
renderObject( scene, camera, shadow.camera, light );
renderObject( scene, camera, shadow.camera, light, this.type );
}
// do blur pass for VSM
if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
VSMPass( shadow, camera );
}
......@@ -178,7 +237,31 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
};
function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar ) {
function VSMPass( shadow, camera ) {
var geometry = _objects.update( fullScreenMesh );
// vertical pass
shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
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 );
// horizonal pass
shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
_renderer.setRenderTarget( shadow.map );
_renderer.clear();
_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );
}
function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) {
var geometry = object.geometry;
......@@ -267,7 +350,15 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
result.visible = material.visible;
result.wireframe = material.wireframe;
result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
if ( type === VSMShadowMap ) {
result.side = ( material.shadowSide != null ) ? material.shadowSide : material.side;
} else {
result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
}
result.clipShadows = material.clipShadows;
result.clippingPlanes = material.clippingPlanes;
......@@ -288,7 +379,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
}
function renderObject( object, camera, shadowCamera, light ) {
function renderObject( object, camera, shadowCamera, light, type ) {
if ( object.visible === false ) return;
......@@ -296,7 +387,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
......@@ -314,7 +405,8 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
if ( groupMaterial && groupMaterial.visible ) {
var depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far );
var depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
}
......@@ -323,7 +415,8 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
} else if ( material.visible ) {
var depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far );
var depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type );
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
}
......@@ -336,7 +429,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
for ( var i = 0, l = children.length; i < l; i ++ ) {
renderObject( children[ i ], camera, shadowCamera, light );
renderObject( children[ i ], camera, shadowCamera, light, type );
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册