@@ -4,11 +4,15 @@ class ContactShadowRenderer extends Renderer {
44 if ( ! this . target . _renderer . hasWebGL2 ) {
55 this . target . _renderer . GL . getExtension ( 'OES_standard_derivatives' )
66 }
7+ this . fbo2 = target . createFramebuffer ( options )
8+ this . blurShader = target . createShader ( this . blurVert ( ) , this . blurFrag ( ) )
79 this . intensity = 0.5
8- this . numSamples = 15
10+ this . numShadowSamples = 15
11+ this . numBlurSamples = 20
912 this . exponent = 250
10- this . bias = 1.
13+ this . bias = 0.1
1114 this . searchRadius = 100
15+ this . blurRadius = 50
1216 }
1317
1418 prefix ( ) {
@@ -27,11 +31,25 @@ class ContactShadowRenderer extends Renderer {
2731 return this . prefix ( ) + ContactShadowRenderer . frag
2832 }
2933
34+ blurVert ( ) {
35+ return this . vert ( )
36+ }
37+
38+ blurFrag ( ) {
39+ return this . prefix ( ) + ContactShadowRenderer . blurFrag
40+ }
41+
3042 setIntensity ( intensity ) {
3143 this . intensity = intensity
3244 }
33- setSamples ( numSamples ) {
34- this . numSamples = numSamples
45+ setShadowSamples ( numSamples ) {
46+ this . numShadowSamples = numSamples
47+ }
48+ setBlurSamples ( numSamples ) {
49+ this . numBlurSamples = numSamples
50+ }
51+ setBlurRadius ( r ) {
52+ this . blurRadius = r
3553 }
3654 setExponent ( exponent ) {
3755 this . exponent = exponent
@@ -43,7 +61,7 @@ class ContactShadowRenderer extends Renderer {
4361 this . searchRadius = radius
4462 }
4563
46- getUniforms ( ) {
64+ getShadowUniforms ( ) {
4765 const projInfo = [
4866 - 2 / ( this . target . width * this . target . _renderer . uPMatrix . mat4 [ 0 ] ) ,
4967 - 2 / ( this . target . height * this . target . _renderer . uPMatrix . mat4 [ 5 ] ) ,
@@ -56,7 +74,7 @@ class ContactShadowRenderer extends Renderer {
5674 uDepth : this . fbo . depth ,
5775 uSize : [ this . target . width , this . target . height ] ,
5876 uIntensity : this . intensity ,
59- uNumSamples : this . numSamples ,
77+ uNumSamples : this . numShadowSamples ,
6078 uNear : this . target . _renderer . _curCamera . cameraNear ,
6179 uFar : this . target . _renderer . _curCamera . cameraFar ,
6280 uProjInfo : projInfo ,
@@ -65,6 +83,55 @@ class ContactShadowRenderer extends Renderer {
6583 uSearchRadius : this . searchRadius ,
6684 }
6785 }
86+
87+ getBlurUniforms ( ) {
88+ return {
89+ uImg : this . fbo . color ,
90+ uDepth : this . fbo . depth ,
91+ uShadow : this . fbo2 . color ,
92+ uSize : [ this . target . width , this . target . height ] ,
93+ uIntensity : this . intensity ,
94+ uNear : this . target . _renderer . _curCamera . cameraNear ,
95+ uFar : this . target . _renderer . _curCamera . cameraFar ,
96+ uNumSamples : this . numBlurSamples ,
97+ uBlurRadius : this . blurRadius ,
98+ }
99+ }
100+
101+ draw ( cb ) {
102+ const shadowUniforms = this . getShadowUniforms ( )
103+ const blurUniforms = this . getBlurUniforms ( )
104+
105+ this . fbo . draw ( ( ) => {
106+ this . target . push ( )
107+ cb ( )
108+ this . target . pop ( )
109+ } )
110+
111+ this . target . push ( )
112+
113+ this . fbo2 . draw ( ( ) => {
114+ this . target . push ( )
115+ this . target . clear ( )
116+ this . target . noStroke ( )
117+ this . target . rectMode ( CENTER )
118+ this . target . shader ( this . shader )
119+ for ( const key in shadowUniforms ) {
120+ this . shader . setUniform ( key , shadowUniforms [ key ] )
121+ }
122+ this . target . rect ( 0 , 0 , this . target . width , - this . target . height )
123+ this . target . pop ( )
124+ } )
125+
126+ this . target . noStroke ( )
127+ this . target . rectMode ( CENTER )
128+ this . target . shader ( this . blurShader )
129+ for ( const key in blurUniforms ) {
130+ this . blurShader . setUniform ( key , blurUniforms [ key ] )
131+ }
132+ this . target . rect ( 0 , 0 , this . target . width , - this . target . height )
133+ this . target . pop ( )
134+ }
68135}
69136
70137p5 . prototype . createContactShadowRenderer = function ( ) {
@@ -120,11 +187,14 @@ uniform float uIntensity;
120187uniform float uExponent;
121188uniform float uBias;
122189
123- const int MAX_NUM_SAMPLES = 50 ;
190+ const int MAX_NUM_SAMPLES = 100 ;
124191
125- float rand(vec2 co){
192+ float rand(vec2 co) {
126193 return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
127194}
195+ float rand(vec4 co) {
196+ return fract(rand(co.xz) + rand(co.xy) + rand(co.yw) + rand(co.zw));
197+ }
128198
129199vec3 worldFromScreen(vec2 offset) {
130200#ifdef IS_WEBGL2
@@ -189,8 +259,8 @@ void main() {
189259 float t = (float(i + 1) / float(uNumSamples));
190260
191261 // Sample a sort of random ish coordinate in a half sphere pointing up
192- float phi = t * 11. * ${ 2 * Math . PI } + 0.5* rand(gl_FragCoord.xy);
193- float theta = t * ${ Math . PI / 2 } + 0.5* rand(gl_FragCoord.xy);
262+ float phi = ${ 2 * Math . PI } * rand(vec4( gl_FragCoord.xy,t*100.,0.) );
263+ float theta = ${ Math . PI / 2 } * rand(vec4( gl_FragCoord.xy,t*100.,100.) );
194264 float radius = 1.0 - t*t;
195265 vec3 localOff = vec3(
196266 radius * cos(phi) * sin(theta),
@@ -228,10 +298,82 @@ void main() {
228298 }
229299 occlusion = 1.0 - (occlusion / float(uNumSamples));
230300 occlusion = clamp(pow(occlusion, 1.0 + uExponent), 0.0, 1.0);
301+ vec4 finalColor = vec4(occlusion, occlusion, occlusion, 1.);
302+ #ifdef IS_WEBGL2
303+ outColor = finalColor;
304+ #else
305+ gl_FragColor = finalColor;
306+ #endif
307+ }
308+ `
309+
310+ ContactShadowRenderer . blurFrag = `
311+ precision highp float;
312+ #ifdef IS_WEBGL2
313+ in highp vec2 vVertTexCoord;
314+ out highp vec4 outColor;
315+ #else
316+ varying highp vec2 vVertTexCoord;
317+ #endif
318+
319+ uniform sampler2D uImg;
320+ uniform sampler2D uDepth;
321+ uniform sampler2D uShadow;
322+ uniform vec2 uSize;
323+ uniform float uNear;
324+ uniform float uFar;
325+ uniform float uIntensity;
326+ uniform int uNumSamples;
327+ uniform float uBlurRadius;
328+
329+ #ifdef IS_WEBGL2
330+ #define texFn texture
331+ #else
332+ #define texFn texture2D
333+ #endif
334+
335+ float depthToZ(float depth) {
336+ float depthNormalized = 2.0 * depth - 1.0;
337+ return 2.0 * uNear * uFar / (uFar + uNear - depthNormalized * (uFar - uNear));
338+ }
339+
340+ const int MAX_NUM_SAMPLES = 100;
341+
342+ float rand(vec2 co) {
343+ return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
344+ }
345+ float rand(vec4 co) {
346+ return fract(rand(co.xz) + rand(co.xy) + rand(co.yw) + rand(co.zw));
347+ }
348+
349+ void main() {
350+ vec4 color = texFn(uImg, vVertTexCoord);
351+
352+ float origZ = depthToZ(texFn(uDepth, vVertTexCoord).x);
353+ float occlusion = texFn(uShadow, vVertTexCoord).x;
354+ float total = 1.;
355+
356+ for (int i = 0; i < MAX_NUM_SAMPLES; i++) {
357+ if (i >= uNumSamples) break;
358+ float t = (float(i) / float(uNumSamples - 1));
359+ float angle = (t*12.0) * ${ 2 * Math . PI } ;
360+ float radius = 1.0 - t;
361+ angle += 5.*rand(gl_FragCoord.xy);
362+
363+ vec2 offset = (vec2(cos(angle),sin(angle)) * radius * uBlurRadius)/uSize;
364+ float z = depthToZ(texFn(uDepth, vVertTexCoord + offset).x);
365+
366+ float weight = float(z >= origZ);
367+ float shadowSample = texFn(uShadow, vVertTexCoord + offset).x;
368+ occlusion += weight * shadowSample;
369+ total += weight;
370+ }
371+ occlusion /= total;
372+ vec4 mixedColor = vec4(color.rgb * mix(1., occlusion, uIntensity), color.a);
231373#ifdef IS_WEBGL2
232- outColor = vec4(color.rgb * mix(1., occlusion, uIntensity), color.a) ;
374+ outColor = mixedColor ;
233375#else
234- gl_FragColor = vec4(color.rgb * mix(1., occlusion, uIntensity), color.a) ;
376+ gl_FragColor = mixedColor ;
235377#endif
236378}
237379`
0 commit comments