未验证 提交 ea1a3426 编写于 作者: G Garrett Johnson 提交者: GitHub

VSM Shadows: Add support for setting the number of blur samples (#22272)

* remove unneeded dir light add call

* Add support for blur iterations to VSM shadows

* Add samples options to vsm example

* Add folders

* Docs update

* Support blurSamples === 1.0

* fix early out

* improve example arguments
上级 8256277d
......@@ -42,7 +42,12 @@
<h3>[property:Float bias]</h3>
<p>
Shadow map bias, how much to add or subtract from the normalized depth when deciding whether a surface is in shadow.<br />
The default is 0. Very tiny adjustments here (in the order of 0.0001) may help reduce artefacts in shadows
The default is 0. Very tiny adjustments here (in the order of 0.0001) may help reduce artifacts in shadows
</p>
<h3>[property:Integer blurSamples]</h3>
<p>
The amount of samples to use when blurring a VSM shadow map.
</p>
<h3>[property:WebGLRenderTarget map]</h3>
......
......@@ -43,6 +43,11 @@
默认值为0.此处非常小的调整(大约0.0001)可能有助于减少阴影中的伪影
</p>
<h3>[property:Integer blurSamples]</h3>
<p>
The amount of samples to use when blurring a VSM shadow map.
</p>
<h3>[property:WebGLRenderTarget map]</h3>
<p>
使用内置摄像头生成的深度图;超出像素深度的位置在阴影中。在渲染期间内部计算。
......
......@@ -36,22 +36,40 @@
const gui = new GUI();
const config = {
'Spotlight Radius': 4,
'Directional light Radius': 4,
spotlightRadius: 4,
spotlightSamples: 8,
dirlightRadius: 4,
dirlightSamples: 8
};
gui.add( config, 'Spotlight Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
const spotlightFolder = gui.addFolder( 'Spotlight' );
spotlightFolder.add( config, 'spotlightRadius' ).name( 'radius' ).min( 0 ).max( 25 ).onChange( function ( value ) {
spotLight.shadow.radius = value;
} );
gui.add( config, 'Directional light Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
spotlightFolder.add( config, 'spotlightSamples', 1, 25, 1 ).name( 'samples' ).onChange( function ( value ) {
spotLight.shadow.blurSamples = value;
} );
spotlightFolder.open();
const dirlightFolder = gui.addFolder( 'Directional Light' );
dirlightFolder.add( config, 'dirlightRadius' ).name( 'radius' ).min( 0 ).max( 25 ).onChange( function ( value ) {
dirLight.shadow.radius = value;
} );
dirlightFolder.add( config, 'dirlightSamples', 1, 25, 1 ).name( 'samples' ).onChange( function ( value ) {
dirLight.shadow.blurSamples = value;
} );
dirlightFolder.open();
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize );
......@@ -98,7 +116,6 @@
dirLight.shadow.mapSize.height = 512;
dirLight.shadow.radius = 4;
dirLight.shadow.bias = - 0.0005;
scene.add( dirLight );
dirGroup = new THREE.Group();
dirGroup.add( dirLight );
......
......@@ -17,6 +17,7 @@ class LightShadow {
this.bias = 0;
this.normalBias = 0;
this.radius = 1;
this.blurSamples = 8;
this.mapSize = new Vector2( 512, 512 );
......
......@@ -2,6 +2,7 @@ export default /* glsl */`
uniform sampler2D shadow_pass;
uniform vec2 resolution;
uniform float radius;
uniform float samples;
#include <packing>
......@@ -11,19 +12,23 @@ void main() {
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 ) );
// float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );
for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {
float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );
float uvStart = samples <= 1.0 ? 0.0 : - 1.0;
for ( float i = 0.0; i < samples; i ++ ) {
float uvOffset = uvStart + i * uvStride;
#ifdef HORIZONTAL_PASS
vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );
vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 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 ) );
float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );
mean += depth;
squared_mean += depth * depth;
......@@ -31,8 +36,8 @@ void main() {
}
mean = mean * HALF_SAMPLE_RATE;
squared_mean = squared_mean * HALF_SAMPLE_RATE;
mean = mean / samples;
squared_mean = squared_mean / samples;
float std_dev = sqrt( squared_mean - mean * mean );
......
......@@ -33,15 +33,11 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) {
const 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 }
radius: { value: 4.0 },
samples: { value: 8.0 }
},
vertexShader: vsm_vert,
......@@ -213,6 +209,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) {
shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
shadowMaterialVertical.uniforms.radius.value = shadow.radius;
shadowMaterialVertical.uniforms.samples.value = shadow.blurSamples;
_renderer.setRenderTarget( shadow.mapPass );
_renderer.clear();
_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
......@@ -222,6 +219,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) {
shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
shadowMaterialHorizontal.uniforms.samples.value = shadow.blurSamples;
_renderer.setRenderTarget( shadow.map );
_renderer.clear();
_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册