#Trouble implementing PCSS

14 messages · Page 1 of 1 (latest)

long tusk
#

Hello, I'm trying to impl PCSS into my OpenGL project, following these 2 PDFs, https://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf
https://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf.

Howerver, my result is quite ugly and I have some question about implement pcss with CSM.

my code is as follow :

// blocker search
    float avgBlockerDepth = 0;
    float numBlockers = 0;
    //currentDepth = projCoord.z
    float receiver = currentDepth - normalBias - _depthBias;
    float nearPlane = _nearPlane;

    //_lightWidthUv was calculated on cpu => lightSize / frustumWidth.
    float lightWidthUv = _lightWidthUv;
    FindBlocker( avgBlockerDepth, numBlockers, projCoords.xy, lightWidthUv, receiver, nearPlane, layer);
    if( numBlockers < 1 )
        return 0.0f;

    float penumbraRatio = lightWidthUv * (receiver - avgBlockerDepth) / avgBlockerDepth;
    float filterRadius = penumbraRatio * nearPlane / receiver;

    float shadow = 0.0;
    shadow = PCF_Filter(projCoords.xy, receiver, filterRadius, layer);

    return shadow;

and this is the FindBlocker function

void FindBlocker(out float avgBlockerDepth, out float numBlockers, vec2 uv, float lightWidthUV, float zReceiver, float nearPlane, int layer)
{
    float searchWidth = lightWidthUV * (zReceiver - nearPlane) / zReceiver;
    float blockerSum = 0;
    numBlockers = 0;
    vec2 texelSize = 1.0 /  vec2(textureSize(_shadowMap, 0));
    for( int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; ++i )
    {
        vec2 offset = POISSON16[i] * searchWidth;
        float shadowMapDepth = texture(_shadowMap, vec3(uv + offset * texelSize, layer)).r;
        if ( shadowMapDepth < zReceiver ) {
            blockerSum += shadowMapDepth;
            numBlockers++;
        }
    }
    avgBlockerDepth = blockerSum / numBlockers;
}

#

So here’s some question:

  1. How to reduce the artifact showing up when I increase the search radius for blocker search, adding some bias?
  2. How to improve the overall quaity of the pcss shadow? I’ve seen someone rotate the sampling uv and maybe a better PCF?
  3. For the blocker’s searchRadius :
searchWidth = lightSize/   * (zReceiver - nearPlane) / zReceiver;```
My current understanding is that the **lightFrustumWidth **should be each cascade’s frusutum width, does the **nearPlane **variable should be depend on cascade also? 
Right now I’m directly assign the **lightSize **variable via debug menu, whats the appropriate value?
molten garden
#

I use Possion disk sampling in PCF to get rid of those "blocky artifacts"

long tusk
#

oh yeah I forgot to mention both my block search and pcf use poisson disk sampling, with sampling number set to 16.

molten garden
#

Oh, I didn't read tour code carefully 😅

small kayak
#

try rotating your sample coordinates per pixel. it looks like all pixels share the same set of sample coordinates which usually gives these repetitive looking blocky patterns

#

also I don't know how you compute the actual sample coordinates, if you copied them from somewhere it might be worth checking their actual distribution. Whenever I e.g. copy random stuff from shadertoy for testing, often it turns out to be quite low quality

#

I have a python / matplotlib script for that on my work pc now

long tusk
#

hmm I see, I'll try rotate the sampling uv first, I copied the poisson disk sampling coords from nvidia's pdf. But yeah always verify the distribution is a good point. thanks!

small kayak
#

your question about the blocker searches radius and the nearPlane... for perspective projections / spot lights that is part of the computation because as you get further away from the light source, the light source is essentially smaller from the point of view of the receiving surface and you need to adjust the initial filter radius for it, or you could also say that the world space area a pixel of the shadow camera covers scales with the distance to the light source. and if you compute the light source size as seen from a certain pixel the nearPlane will be in there in the computation somehow.

but for directional light cascades it shouldn't matter, it should be fine to have the initial blocker search radius match the light source size and only adjust it for the differences in uv coordinates / world space size of each pixel in the cascade.

#

(it's the light source size since the penumbra can never get larger than that anyways, so no blockers are relevant outside that radius)

long tusk
#

ah I see, thanks for the detailed explanation frOK.

long tusk
#

After randomly rotate the sampling uv and fixed the depth & normal bias for csm. the result improve alot.
Thanks guys! I'll keep experiment different ways to denoising and improve the pcf