Skip to content

Commit

Permalink
added new PCFPoissonShadowMap && added strength and quality to lights…
Browse files Browse the repository at this point in the history
…hadow(only works on directional light)
  • Loading branch information
liuwenjie committed Sep 22, 2020
1 parent b0e609d commit 2ba2bb2
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 1,059 deletions.
28 changes: 24 additions & 4 deletions build/three.js

Large diffs are not rendered by default.

1,037 changes: 0 additions & 1,037 deletions build/three.min.js

This file was deleted.

29 changes: 24 additions & 5 deletions build/three.module.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export var BasicShadowMap = 0;
export var PCFShadowMap = 1;
export var PCFSoftShadowMap = 2;
export var VSMShadowMap = 3;
export var PCFPoissonShadowMap = 4;
export var FrontSide = 0;
export var BackSide = 1;
export var DoubleSide = 2;
Expand Down
6 changes: 6 additions & 0 deletions src/lights/LightShadow.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ function LightShadow( camera ) {

this.bias = 0;
this.radius = 1;
this.strength = 1;
this.quality = 5;

this.mapSize = new Vector2( 512, 512 );

Expand Down Expand Up @@ -102,6 +104,8 @@ Object.assign( LightShadow.prototype, {

this.bias = source.bias;
this.radius = source.radius;
this.strength = source.strength;
this.quality = source.quality;

this.mapSize.copy( source.mapSize );

Expand All @@ -120,6 +124,8 @@ Object.assign( LightShadow.prototype, {
var object = {};

if ( this.bias !== 0 ) object.bias = this.bias;
if ( this.strength !== 1 ) object.strength = this.strength;
if ( this.quality !== 5 ) object.quality = this.quality;
if ( this.radius !== 1 ) object.radius = this.radius;
if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();

Expand Down
2 changes: 2 additions & 0 deletions src/loaders/ObjectLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,8 @@ ObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
if ( data.shadow ) {

if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
if ( data.shadow.strength !== undefined ) object.shadow.strength = data.shadow.strength;
if ( data.shadow.quality !== undefined ) object.shadow.quality = data.shadow.quality;
if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ IncidentLight directLight;
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
spotLightShadow = spotLightShadows[ i ];
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ], 1 ) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
Expand All @@ -96,7 +96,8 @@ IncidentLight directLight;
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
directionalLightShadow = directionalLightShadows[ i ];
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) )
? min((1.0 - directionalLightShadow.shadowStrength) + getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ], directionalLightShadow.shadowQuality ), 1.0) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
struct DirectionalLightShadow {
float shadowBias;
float shadowStrength;
int shadowQuality;
float shadowRadius;
vec2 shadowMapSize;
};
Expand Down
75 changes: 67 additions & 8 deletions src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,51 @@
export default /* glsl */`
#ifdef USE_SHADOWMAP
#ifdef SHADOWMAP_TYPE_PCF_POISSON
#define NUM_SAMPLES 9
#define NUM_RINGS 7
#define MAX_NUM_SAMPLES 27
#define MAX_NUM_RINGS 16
#define MAX_QUALITY 10
vec2 poissonDisk[MAX_NUM_SAMPLES];
void initPoissonSamplesQuality( const in vec2 randomSeed, const in int numRings, const in int numSamples ) {
float ANGLE_STEP = PI2 * float( numRings ) / float( numSamples );
float INV_NUM_SAMPLES = 1.0 / float( numSamples );
// jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/
float angle = rand( randomSeed ) * PI2;
float radius = INV_NUM_SAMPLES;
float radiusStep = radius;
for( int i = 0; i < MAX_NUM_SAMPLES; i ++ ) {
if ( i > numSamples ) break;
poissonDisk[i] = vec2( cos( angle ), sin( angle ) ) * pow( radius, 0.75 );
radius += radiusStep;
angle += ANGLE_STEP;
}
}
void initPoissonSamples( const in vec2 randomSeed ) {
float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );
float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );
// jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/
float angle = rand( randomSeed ) * PI2;
float radius = INV_NUM_SAMPLES;
float radiusStep = radius;
for( int i = 0; i < NUM_SAMPLES; i ++ ) {
poissonDisk[i] = vec2( cos( angle ), sin( angle ) ) * pow( radius, 0.75 );
radius += radiusStep;
angle += ANGLE_STEP;
}
}
#endif
#if NUM_DIR_LIGHT_SHADOWS > 0
uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];
Expand Down Expand Up @@ -63,7 +108,7 @@ export default /* glsl */`
}
float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, int quality ) {
float shadow = 1.0;
Expand Down Expand Up @@ -115,6 +160,20 @@ export default /* glsl */`
texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
) * ( 1.0 / 17.0 );
#elif defined( SHADOWMAP_TYPE_PCF_POISSON )
// int numRings = MAX_NUM_RINGS - (MAX_QUALITY - quality);
// int numSamples = MAX_NUM_SAMPLES - 2 * (MAX_QUALITY - quality);
initPoissonSamples( shadowCoord.xy );
float sum = 0.0;
vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
for( int i = 0; i < NUM_SAMPLES; i ++ ) {
// if ( i > numSamples ) break;
sum += texture2DCompare( shadowMap, shadowCoord.xy + poissonDisk[ i ] * texelSize.x * shadowRadius, shadowCoord.z );
sum += texture2DCompare( shadowMap, shadowCoord.xy + -poissonDisk[ i ].yx * texelSize.x * shadowRadius, shadowCoord.z );
}
shadow = sum / ( 2.0 * float( NUM_SAMPLES ) );
#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
Expand All @@ -130,22 +189,22 @@ export default /* glsl */`
texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +
texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +
texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +
mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),
mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),
f.x ) +
mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),
mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),
f.x ) +
mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),
mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),
f.y ) +
mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),
mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),
f.y ) +
mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),
mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),
f.x ),
mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),
mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),
texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),
f.x ),
f.y )
Expand Down Expand Up @@ -253,7 +312,7 @@ export default /* glsl */`
// bd3D = base direction 3D
vec3 bd3D = normalize( lightToPosition );
#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )
#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_POISSON )|| defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )
vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ float getShadowMask() {
for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
directionalLight = directionalLightShadows[ i ];
shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ], directionalLight.shadowQuality ) : 1.0;
}
#pragma unroll_loop_end
Expand All @@ -28,7 +28,7 @@ float getShadowMask() {
for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {
spotLight = spotLightShadows[ i ];
shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ], 1 ) : 1.0;
}
#pragma unroll_loop_end
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/shaders/UniformsLib.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ var UniformsLib = {

directionalLightShadows: { value: [], properties: {
shadowBias: {},
shadowStrength: {},
shadowQuality: {},
shadowRadius: {},
shadowMapSize: {}
} },
Expand Down
4 changes: 4 additions & 0 deletions src/renderers/webgl/WebGLLights.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ function ShadowUniformsCache() {
case 'DirectionalLight':
uniforms = {
shadowBias: 0,
shadowStrength: 1,
shadowQuality: 5,
shadowRadius: 1,
shadowMapSize: new Vector2()
};
Expand Down Expand Up @@ -258,6 +260,8 @@ function WebGLLights() {
var shadowUniforms = shadowCache.get( light );

shadowUniforms.shadowBias = shadow.bias;
shadowUniforms.shadowStrength = shadow.strength;
shadowUniforms.shadowQuality = shadow.quality;
shadowUniforms.shadowRadius = shadow.radius;
shadowUniforms.shadowMapSize = shadow.mapSize;

Expand Down
6 changes: 5 additions & 1 deletion src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, VSMShadowMap, 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, PCFPoissonShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';

var programIdCount = 0;

Expand Down Expand Up @@ -291,6 +291,10 @@ function generateShadowMapTypeDefine( parameters ) {

shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';

} else if ( parameters.shadowMapType === PCFPoissonShadowMap ) {

shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_POISSON';

} else if ( parameters.shadowMapType === VSMShadowMap ) {

shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
Expand Down

0 comments on commit 2ba2bb2

Please sign in to comment.