PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Tue Dec 30, 2008 5:51 am

I recently was experimenting with PSSM on my terrain and was getting those cracks that occur when doing self shadowing. I read online that VSM doesn't have this issue so much, so I grabbed nullsquared's great VSM soft shadow demo and then hooked it up with the PSSM demo. This code is really unrefined, but it seems to be working so maybe it will help someone.

[edit]Sorry, I had pasted in the regular PSSM shadow caster shader instead of the VSM shadow caster shader doh! Fixed now[/edit]

Here's the PSVSM shadow caster material:

Code: Select all

vertex_program pssm_vsm_caster_vp glsl
{
    source pssm_vsm_caster_vp.glsl

    default_params
    {
        param_named_auto wvMat worldview_matrix
    }
}

fragment_program pssm_vsm_caster_fp glsl
{
    source pssm_vsm_caster_fp.glsl

    default_params
    {
        param_named_auto depthRange scene_depth_range
    }
}

material pssm_vsm_caster
{
    technique
    {
        // all this will do is write depth and depth squared to red and green
        pass
        {
            vertex_program_ref pssm_vsm_caster_vp
            {
            }

            fragment_program_ref pssm_vsm_caster_fp
            {
            }
        }
    }
}
PSVSM shadow caster vertex shader:

Code: Select all

uniform mat4 wvMat;

varying vec4 vertexDepth;

void main()
{
    vertexDepth = wvMat * gl_Vertex;
    
    // pass the vertex position, transforming it to clip space
	gl_Position = ftransform();
}
PSVSM shadow caster pixel shader:

Code: Select all

uniform vec4 depthRange;

varying vec4 vertexDepth;

void main()
{
    // derive a per-pixel depth and depth squared
    // (length of the view space position == distance from camera)
    // (this is linear space, not post-projection quadratic space)
    float d = (length(vertexDepth.xyz) - depthRange.x) * depthRange.w;
    
    gl_FragColor = vec4(d, d * d, 1, 1);
}
PSVSM shadow receiver material:

Code: Select all

vertex_program pssm_vsm_diffuse_vp glsl
{
    source pssm_vsm_vp.glsl
    default_params
    {
        param_named_auto lightPosition			light_position  0
        param_named_auto worldViewProjMatrix	worldviewproj_matrix
        param_named_auto worldMatrix            world_matrix
		param_named_auto texViewProjMatrix0     texture_viewproj_matrix 0
		param_named_auto texViewProjMatrix1     texture_viewproj_matrix 1
		param_named_auto texViewProjMatrix2     texture_viewproj_matrix 2
    }
}

fragment_program pssm_vsm_diffuse_fp glsl
{
    source pssm_vsm_fp.glsl
    
    default_params
    {
        param_named shadowMap0  int 0
        param_named shadowMap1  int 1
        param_named shadowMap2  int 2
        param_named diffuseMap0 int 3
        
        // pssm shadow info
		param_named_auto invShadowMapSize0	inverse_texture_size 0
		param_named_auto invShadowMapSize1	inverse_texture_size 1
		param_named_auto invShadowMapSize2	inverse_texture_size 2
            
        param_named_auto depthRange0 shadow_scene_depth_range 0
        param_named_auto depthRange1 shadow_scene_depth_range 1
        param_named_auto depthRange2 shadow_scene_depth_range 2
        param_named_auto lightPos0 light_position 0
    }
}

material pssm_vsm_material
{
	technique
	{
// put your ambient pass here and uncomment the scene_blend below if you want to do a separate ambient pass first
		pass
		{
		    max_lights 8
//			scene_blend add  // only needed when doing multiple passes (with ambient)
            iteration once_per_light

            ambient  0 0 0
            diffuse  1 1 1
            specular 1 1 1 128

            vertex_program_ref pssm_vsm_diffuse_vp
            {
            }

            fragment_program_ref pssm_vsm_diffuse_fp
            {
            }

			texture_unit shadow_tex0
			{
                content_type shadow
                filtering anisotropic
                max_anisotropy 16
                tex_address_mode border
                tex_border_colour 1 1 1
			}
			texture_unit shadow_tex1
			{
                content_type shadow
                filtering anisotropic
                max_anisotropy 16
                tex_address_mode border
                tex_border_colour 1 1 1
			}
			texture_unit shadow_tex2
			{
                content_type shadow
                filtering anisotropic
                max_anisotropy 16
                tex_address_mode border
                tex_border_colour 1 1 1
			}

			texture_unit diffuse_tex
			{
                texture grey.png
                tex_coord_set 0             
			}
		}
	}
}
PSVSM Shadow receiver vertex shader:

Code: Select all

uniform vec4 lightPosition;           // world space
uniform mat4 worldViewProjMatrix;
uniform mat4 worldMatrix;
uniform mat4 texViewProjMatrix0;
uniform mat4 texViewProjMatrix1;
uniform mat4 texViewProjMatrix2;

uniform mat4 worldInverseTranspose; 

varying vec4 lightPosition0;
varying vec4 lightPosition1;
varying vec4 lightPosition2;
varying vec3 vertexNormal;
varying vec4  vertexWorldPosition;
varying float shadowDistance;

void main()
{
    // get normal in world space
    vertexNormal = vec3(worldMatrix * vec4(normalize(gl_Normal.xyz), 0.0));
    
    // pass the vertex position, transforming it to clip space
	gl_Position = ftransform();

	// pass texture co-ords through unchanged
	gl_TexCoord[0] = gl_MultiTexCoord0;
    
    // shadowDistance is in clip space
	shadowDistance = gl_Position.z;
    
    // get vertex position in world space
    vertexWorldPosition = worldMatrix * gl_Vertex;
    
	// Calculate the position of vertex in light space for shadowing
	lightPosition0 = texViewProjMatrix0 * vertexWorldPosition;
	lightPosition1 = texViewProjMatrix1 * vertexWorldPosition;
	lightPosition2 = texViewProjMatrix2 * vertexWorldPosition;
}
PSVSM Shadow receiver pixel shader:

Code: Select all

uniform sampler2D shadowMap0;
uniform sampler2D shadowMap1;
uniform sampler2D shadowMap2;
uniform sampler2D diffuseMap0;

uniform vec4 invShadowMapSize0;
uniform vec4 invShadowMapSize1;
uniform vec4 invShadowMapSize2;
uniform vec4 pssmSplitPoints;
uniform vec4 depthRange0;
uniform vec4 depthRange1;
uniform vec4 depthRange2;
uniform vec4 lightPos0;

varying vec3  vertexNormal;
varying vec4  vertexWorldPosition;
varying vec4  lightPosition0;
varying vec4  lightPosition1;
varying vec4  lightPosition2;
varying float shadowDistance;

float shadowPCF(in sampler2D shadowMap, in vec4 shadowMapPos, const in vec2 offset, float depth)
{
	shadowMapPos = shadowMapPos / shadowMapPos.w;
	vec2 uv = shadowMapPos.xy;
    
   vec2 o = offset;
   vec2 c = texture2D(shadowMap, uv.xy).rg; // center
    c += texture2D(shadowMap, uv.xy - o.xy).rg; // top left
    c += texture2D(shadowMap, uv.xy + o.xy).rg; // bottom right
    c += texture2D(shadowMap, vec2(uv.x - o.x, uv.y)).rg; // left
    c += texture2D(shadowMap, vec2(uv.x + o.x, uv.y)).rg; // right
    c += texture2D(shadowMap, vec2(uv.x, uv.y + o.y)).rg; // bottom
    c += texture2D(shadowMap, vec2(uv.x, uv.y - o.y)).rg; // top
    c += texture2D(shadowMap, vec2(uv.x - o.x, uv.y + o.y)).rg; // bottom left
    c += texture2D(shadowMap, vec2(uv.x + o.x, uv.y - o.y)).rg; // top right
    c /= 9.0;
        
    vec2 moments = c;
    float litFactor = (depth <= moments.x ? 1.0 : 0.0);

    // standard variance shadow mapping code
    float E_x2 = moments.y;
    float Ex_2 = moments.x * moments.x;
    float vsmEpsilon = 0.0001;
    float variance = min(max(E_x2 - Ex_2, 0.0) + vsmEpsilon, 1.0);
    float m_d = moments.x - depth;
    float p = variance / (variance + m_d * m_d);

    return smoothstep(0.4, 1.0, max(litFactor, p));
}

void main()
{
    vec3 lightDir0 = normalize(lightPos0.xyz - (lightPos0.w * vertexWorldPosition.xyz));
    vec3 normalizedNormal   = normalize(vertexNormal);
    float diffuseAmount = max(dot(normalizedNormal, lightDir0), 0.0);
        
	// calculate shadow
	float shadowAmount = 1.0;
    vec4 shadowColor = vec4(0.0, 0.0, 0.0, 1.0);
    
	if (shadowDistance <= pssmSplitPoints.y) {
        float depth = (length(lightPos0.xyz - vertexWorldPosition.xyz) - depthRange0.x) * depthRange0.w;

		shadowAmount = shadowPCF(shadowMap0, lightPosition0, invShadowMapSize0.xy, depth);
        shadowColor = vec4(1.0, 0, 0, 1.0);
	}
	else if (shadowDistance <= pssmSplitPoints.z) {
        float depth = (length(lightPos0.xyz - vertexWorldPosition.xyz) - depthRange1.x) * depthRange1.w;

		shadowAmount = shadowPCF(shadowMap1, lightPosition1, invShadowMapSize1.xy, depth);
        shadowColor = vec4(0.0, 1.0, 0, 1.0);        
	}
	else {
        float depth = (length(lightPos0.xyz - vertexWorldPosition.xyz) - depthRange2.x) * depthRange2.w;

		shadowAmount = shadowPCF(shadowMap2, lightPosition2, invShadowMapSize2.xy, depth);
        shadowColor = vec4(0.0, 0.0, 1.0, 1.0);        
	}
    
    const float shadowAmbient = 0.9;

    // if you do your own ambient pass you'll want to remove the ambient code from here
    const vec4 ambientColor = vec4 (0.05, 0.075, 0.1, 1.0);
    vec4 diffuseColor =  texture2D(diffuseMap0, gl_TexCoord[0].st);

    gl_FragColor = ((1.0 - shadowAmbient) * diffuseColor * shadowColor) + 
                         (diffuseColor * shadowAmbient * diffuseAmount * shadowAmount * shadowColor);
}
Here's what my test images looked like with 3 1024x1024 shadow maps and just using the shadow colour to show the splits:
Image

Image

It still needs tuning because I have a large landscape and also using 1024x1024 kills my framerate as you can see in those screenshots.

BTW this is roughly what I'm doing to set up the shadows in my app:

Code: Select all

    // 3 shadow textures per light
    const int numShadowTextures = 3;

    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
    MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_ANISOTROPIC);
    
    // set shadow far distance BEFORE creating any lights (see API documentation)
    mSceneMgr->setShadowFarDistance(4096);
    mSceneMgr->setShadowTextureCountPerLightType(Ogre::Light::LT_POINT, numShadowTextures);

    mSceneMgr->setShadowTextureCount(numShadowTextures);

    // can't use anything larger than 512 if our screen/window resolution?  is less than 1024 in either dimension and 
    // we're using open gl - macbook pro screen is 1440x900 or something so it has this issue ugh.
    // might also try other pixel formats to improve the speed at the risk of quality: PF_FLOAT32_R, PF_X8R8G8B8, PF_R8G8B8
    if(mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
        if(mWindow->getWidth() >= 1024 && mWindow->getHeight() >= 1024) {
            mSceneMgr->setShadowTextureConfig(0, 1024, 1024, PF_FLOAT16_RGB);           
        }
        else {
            mSceneMgr->setShadowTextureConfig(0, 512, 512, PF_FLOAT16_RGB);
        }
    }
    else {
        mSceneMgr->setShadowTextureConfig(0, 512, 512, PF_FLOAT16_RGB);    
    }
    mSceneMgr->setShadowTextureConfig(1, 1024, 1024, PF_FLOAT16_RGB); 
    mSceneMgr->setShadowTextureConfig(2, 1024, 1024, PF_FLOAT16_RGB); 
    mSceneMgr->setShadowTextureSelfShadow(true);

    // shadow camera setup
    PSSMShadowCameraSetup* pssmSetup = new PSSMShadowCameraSetup();
    PSSMShadowCameraSetup::SplitPointList splitPointList = pssmSetup->getSplitPoints();

#ifdef MANUAL_SPLIT_POINTS
    // set the split points manually
    splitPointList[0] = 1.0;
    splitPointList[1] = 96.0;
    splitPointList[2] = 256.0;
    splitPointList[3] = 512.0;
    pssmSetup->setSplitPoints(splitPointList);
#else    
    // use the Ogre split point calculator
    pssmSetup->calculateSplitPoints(numShadowTextures, mCamera->getNearClipDistance(), mCamera->getFarClipDistance());
#endif    
    pssmSetup->setSplitPadding(5);

    // set the LISPM adjustment factor (see API documentation for these)
    pssmSetup->setOptimalAdjustFactor(0, 2.0);
    pssmSetup->setOptimalAdjustFactor(1, 1.0);
    pssmSetup->setOptimalAdjustFactor(2, 0.5);
	
    mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(pssmSetup));

    // use a vsm caster material
    mSceneMgr->setShadowTextureCasterMaterial("pssm_vsm_caster");
    mSceneMgr->setShadowCasterRenderBackFaces(false);

    // set the receiver params for any materials that need the split point information
    Vector4 splitPoints;
    splitPointList = pssmSetup->getSplitPoints();
    for (int i = 0; i < numShadowTextures; ++i)   {
        splitPoints[i] = splitPointList[i];
    }
    mat = MaterialManager::getSingleton().getByName("pssm_vsm_material");
    for(int i = 0; i < mat->getNumTechniques(); ++i) {
        mat->getTechnique(i)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
    }

   // create a light now after all that
    Light* l = mSceneMgr->createLight("Sun");
    l->setType(Light::LT_POINT);
    l->setPosition(0.0, 10000.0, 0.0);

   // add the overlay elements to show the shadow maps:
    // init overlay elements
    OverlayManager& mgr = OverlayManager::getSingleton();
    Overlay* overlay = mgr.create("DebugOverlay");
    
    for (size_t i = 0; i < numShadowTextures; ++i) {
        TexturePtr tex = mSceneMgr->getShadowTexture(i);

        // Set up a debug panel to display the shadow
        MaterialPtr debugMat = MaterialManager::getSingleton().create(
            "Ogre/DebugTexture" + StringConverter::toString(i), 
            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
        debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
        TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
        t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

        OverlayContainer* debugPanel = (OverlayContainer*)
            (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
        debugPanel->_setPosition(0.8, i*0.25);
        debugPanel->_setDimensions(0.2, 0.24);
        debugPanel->setMaterialName(debugMat->getName());
        overlay->add2D(debugPanel);
    }
Maybe I will (or someone more knowledgeable) can/should make a wiki article about this?

Happy New Year!!
Last edited by petrocket on Tue Dec 30, 2008 6:10 pm, edited 1 time in total.
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by nullsquared » Tue Dec 30, 2008 1:31 pm

Wait, it looks like there's a slight error in the caster code - you're outputting (depth, depth, depth) - but for VSM you want (depth, depth^2)
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Tue Dec 30, 2008 2:50 pm

Doh! You're right. I pasted the wrong caster shader. Will fix when I get back to my computer.
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by nullsquared » Tue Dec 30, 2008 2:57 pm

petrocket wrote:Doh! You're right. I pasted the wrong caster shader. Will fix when I get back to my computer.
Oh, so it's simply a copy-paste error? Because otherwise it looks great :D I was wondering how it just worked like that :lol:. Looks really nice, I didn't think VSM would magically fix an error just like that :mrgreen:
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Tue Dec 30, 2008 6:12 pm

OK, pasted the right shadow caster code this time :D

Now does anyone have an ESM implementation I could test with PSSM?
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Wed Dec 31, 2008 3:54 am

Oh bother, I just realized that I didn't implement the gaussian blur pass to the shadow maps to soften the shadows! argh. Well my frame rate is hovering around 30fps now so I'm going to focus on optimizing for a bit, but it shouldn't be hard to add the blur like nullsquared did in his VSM demo.
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by nullsquared » Wed Dec 31, 2008 4:37 am

Actually I didn't add a gaussian blur pre-pass on the shadow map, the 'softness' came from a brute-force 3x3 filter when sampling the shadow map.
0 x

User avatar
nikki
Old One
Posts: 2730
Joined: Sat Sep 17, 2005 10:08 am
Location: Princeton, New Jersey, USA
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by nikki » Wed Dec 31, 2008 5:48 am

Just reducing the resolution of the map should induce some filtering.
0 x

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by nullsquared » Wed Dec 31, 2008 2:46 pm

nikki wrote:Just reducing the resolution of the map should induce some filtering.
Make sure to enable bilinear filtering.
0 x

User avatar
PolyVox
OGRE Contributor
OGRE Contributor
Posts: 1316
Joined: Tue Nov 21, 2006 11:28 am
Location: Groningen, The Netherlands
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by PolyVox » Fri Jan 02, 2009 10:47 am

nullsquared wrote:Make sure to enable bilinear filtering.
It would also be very interesting to see how higher order filtering using Bezier or Catmull-Rom curves looks. The authors mention this as future work in the SAVSM article in GPU Gems 3. For anyone interested, a description of implementing higher order filtering can be found in Chapter 20 of GPU Gems 2, which is available online.
0 x

User avatar
calsmurf2904
Orc
Posts: 401
Joined: Tue Sep 16, 2008 9:39 pm
Location: Netherlands

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by calsmurf2904 » Fri Jan 02, 2009 1:28 pm

PolyVox wrote:
nullsquared wrote:Make sure to enable bilinear filtering.
It would also be very interesting to see how higher order filtering using Bezier or Catmull-Rom curves looks. The authors mention this as future work in the SAVSM article in GPU Gems 3. For anyone interested, a description of implementing higher order filtering can be found in Chapter 20 of GPU Gems 2, which is available online.
GPU Gems 3 is also availible online...but not completly yet...they are working on it.
0 x
Visit my blog at http://calsmurf2904.wordpress.com !
Got a Google Wave account? Add me as contact! (projectxgame <at> gmail <dot> com)
Image

lukeneorm
Halfling
Posts: 61
Joined: Wed Apr 01, 2009 12:03 am

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by lukeneorm » Tue Jun 02, 2009 6:31 pm

Hi,
I try to use your shader in my scene, and it works fine, but it seems I have some problems using spotlight instead of point light: the shadows don't cross the limit between the split planes. I have something like this:

Image

as you can see, the shadows break down suddently when they reach the first split plane.
I also tried to change this line:
mgr.sceneMgr->setShadowTextureCountPerLightType(Ogre::Light::LT_POINT, numShadowTextures);
into this:
mgr.sceneMgr->setShadowTextureCountPerLightType(Ogre::Light::LT_SPOTLIGHT, numShadowTextures);
but I have the same problem.
..how can I fix that? :?

Thank you!
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Tue Jun 02, 2009 7:49 pm

maybe the start/end shadow distances need adjusting. Have you played with the pssm split points?

This code:

Code: Select all

    splitPointList[0] = 1.0;
    splitPointList[1] = 96.0;
    splitPointList[2] = 256.0;
    splitPointList[3] = 512.0;
    pssmSetup->setSplitPoints(splitPointList);
or are you using this?

Code: Select all

pssmSetup->calculateSplitPoints(numShadowTextures, mCamera->getNearClipDistance(), mCamera->getFarClipDistance());
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

lukeneorm
Halfling
Posts: 61
Joined: Wed Apr 01, 2009 12:03 am

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by lukeneorm » Tue Jun 02, 2009 8:20 pm

petrocket wrote:maybe the start/end shadow distances need adjusting. Have you played with the pssm split points?

This code:

Code: Select all

    splitPointList[0] = 1.0;
    splitPointList[1] = 96.0;
    splitPointList[2] = 256.0;
    splitPointList[3] = 512.0;
    pssmSetup->setSplitPoints(splitPointList);
or are you using this?

Code: Select all

pssmSetup->calculateSplitPoints(numShadowTextures, mCamera->getNearClipDistance(), mCamera->getFarClipDistance());
If i use manual split points, the default values are too distant so the scene is all in red (the first split-plane), and the shadows seem to be ok. If I decrease the distance between the points the previous problem rise up.
If I use automatic split points, the problem remains. :?
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Tue Jun 02, 2009 8:23 pm

so have you gotten it to work with a regular point light or directional light, or have shadows never appeared in the green and blue zones?
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

lukeneorm
Halfling
Posts: 61
Joined: Wed Apr 01, 2009 12:03 am

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by lukeneorm » Mon Jul 27, 2009 11:19 am

petrocket wrote:so have you gotten it to work with a regular point light or directional light, or have shadows never appeared in the green and blue zones?
Hi, sorry for answering so late.
Using automatic split points seems to work fine: thanks to your shader, now I removed all kind of light-bleeding artifacts in my scene. THANK YOU! :D
Now I got this problem:

* Your shader is in GLSL, so it will run only in OGL mode, right? Now I want to add a technique to pssm_vsm_material that use shaders in CG language to add a compositor effect. I modify pssm_vsm_material in this way:

Code: Select all

material pssm_vsm_material
{
   technique 
   {
// put your ambient pass here and uncomment the scene_blend below if you want to do a separate ambient pass first
	  pass 
	  {
		  max_lights 8
//         scene_blend add  // only needed when doing multiple passes (with ambient)
			iteration once_per_light

			ambient  0 0 0
			diffuse  1 1 1
			specular 1 1 1 128

			vertex_program_ref pssm_vsm_diffuse_vp
			{
			}

			fragment_program_ref pssm_vsm_diffuse_fp
			{
			}

		 texture_unit shadow_tex0
		 {
				content_type shadow
				filtering anisotropic
				max_anisotropy 16
				tex_address_mode border
				tex_border_colour 1 1 1
		 }
		 texture_unit shadow_tex1
		 {
				content_type shadow
				filtering anisotropic
				max_anisotropy 16
				tex_address_mode border
				tex_border_colour 1 1 1
		 }
		 texture_unit shadow_tex2
		 {
				content_type shadow
				filtering anisotropic
				max_anisotropy 16
				tex_address_mode border
				tex_border_colour 1 1 1
		 }

		 texture_unit diffuse_tex
		 {
				texture white.jpg
				tex_coord_set 0             
		 }
	  }
   }
    // ------ THIS IS THE TECHNIQUE ADDED ------
	technique newTechnique
	{
	    scheme newScheme

	    pass
	    {
	        vertex_program_ref new_vs
	        {
	        }

	        fragment_program_ref new_ps
	        {
	        }
	    }
	}
}

..but with this simple addition, the OGRE loader seems don't recognize pssmSplitPoints parameter:

Code: Select all

OGRE EXCEPTION(2:InvalidParametersException): Parameter called pssmSplitPoints does not exist.
..where I am wrong? :\
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Mon Jul 27, 2009 1:09 pm

Because it is CG instead of OpenGL you may need to declare the pssmSplitPoints parameter in your technique now - it wouldn't hurt to do so in the OpenGL version too. Something like:

Code: Select all

param_named pssmSplitPoints float4 1.0 1.0 1.0 1.0
My guess is that CG might not allow declaring the parameter after shader compile like OpenGL is.

Also, check out the original PSSM material script & shader in the Ogre Playpen folder/project. It was written in CG if I recall.
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

lukeneorm
Halfling
Posts: 61
Joined: Wed Apr 01, 2009 12:03 am

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by lukeneorm » Thu Aug 13, 2009 3:20 pm

petrocket wrote: My guess is that CG might not allow declaring the parameter after shader compile like OpenGL is.
Also, check out the original PSSM material script & shader in the Ogre Playpen folder/project. It was written in CG if I recall.
Hi,
thank you for your hint: I'm currently working on the porting of your shader in CG using the PSSM shader in the Ogre Playpen folder as you suggest: it is almost ready, when I'll finish it I'll post the CG version in the forum. :)

A few month ago, when I tried for the first time your shader, I had a problem with the split planes. Lately, when I begin to study your shader code, I found again that problem, and that problem is also in the CG porting that I'm working on. It rises up if the light is created when the green or the red split planes (the 2 planes nearest to the observer) are displayed in the viewport.

This is the problem:
When the observer is distant from the objects of the scene so that all the objects are in the blue split plane (the farther one) and a light is created in the observer position (1a), then the shadows are ok (2a/3a/4a), as you can see in this image:

Image

But.. if the observer is near the objects of the scene so that the green and the red split planes are visible, the shadows seems to "live" in the split plane they are created. I mean: if we create a light in the observer position in (1b), the shadow of the nearest box in the scene (that is in the red split plane) will be visible only in the red split plane: we can see it if we move forward so that the red split plane cover the shadow area (2b/3b). In the same way, the spheres that are in the green split plane in 2b will cast their shadows on the walls only if we move forward so that the green split plane cover the walls.

Image

I use the same shadow setup that is in the first post of this thread.
I tried both with spot/point light - manual/automatic split points configurations, but the problem remains the same.

How can I solve that? :?
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1028
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by al2950 » Thu Aug 13, 2009 8:42 pm

I am glad to hear you are having this problem, as i have done the exactly the same thing (converting to a cg shader), and i was going mad trying to work out what i had done wrong!!

I gave up on the problem as there were more pressing things to get done, however i will come back to it next week and try what you have found out and see if i can get to the bottom of it.

Please post any other findings you get

Cheers

Angus
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Thu Aug 13, 2009 8:49 pm

My guess is that somehow when you draw a shadow depth buffer - say the depth buffer for the green zone - and there is an object that is entirely in the red zone, the shadow depth buffer for the green zone does not include the object's that are not inside it because of some kind of bounding box culling. It is as if every time a depth buffer is rendered for a shadow zone it is culling objects that are outside the zone and there might be some way to disable this.

One thing you can try to determine if this is the issue is double the size of the bounding box for one of the objects (say the cube) so that the bounding box gets included in 2 zones even though the geometry only fits inside one zone.

Of course, this is just for determining if that is the issue. If it is the issue then somehow you need to figure out how to include the objects between the light and the zone.

I haven't looked at Ogre's pssm shadow / lipsm code in a while but maybe one of the ogre guru's on this forum know how the object/scene graph culling works when generating PSSM shadow depth maps.
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

lukeneorm
Halfling
Posts: 61
Joined: Wed Apr 01, 2009 12:03 am

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by lukeneorm » Tue Aug 25, 2009 10:08 am

petrocket wrote:My guess is that somehow when you draw a shadow depth buffer - say the depth buffer for the green zone - and there is an object that is entirely in the red zone, the shadow depth buffer for the green zone does not include the object's that are not inside it because of some kind of bounding box culling. It is as if every time a depth buffer is rendered for a shadow zone it is culling objects that are outside the zone and there might be some way to disable this.
I still can't solve this problem :?
I'm trying to study how PSSM works in this thread:
http://www.ogre3d.org/forums/viewtopic.php?f=5&t=52013
maybe someone can help me to understand if I'm wrong in what I wrote? I guess it would be very useful also to the other people that are still a bit confused about PSSM.

Thank you! ;)
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1028
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by al2950 » Tue Aug 25, 2009 10:58 am

I have gone back to the pssm code from the playpen, and i am slowly going to try and turn it into VSM and see where the problem creeps in. (Its working fine now).

Unfortuantley I am going on holiday soon and so as always work is getting busy so that is taking up most of my time. BUT I WILL SOLVE THIS, when i get back!!

Angus
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1028
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by al2950 » Thu Aug 27, 2009 8:35 am

Have not had time to try this but part of the problem could well be to do with this;

http://www.ogre3d.org/forums/viewtopic.php?f=4&t=52157
0 x

User avatar
petrocket
Gremlin
Posts: 178
Joined: Tue Mar 20, 2007 3:29 am
Contact:

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by petrocket » Thu Aug 27, 2009 1:43 pm

It could have to do with this, yes. Interesting. Holiday in August? What holiday?
0 x
Ogre API & Manual | Ogre Wiki

blog | website | work

Follow me on twitter @ twitter.com/petrocket

ndoxx
Kobold
Posts: 31
Joined: Tue Mar 11, 2008 4:54 pm

Re: PSVSM (PSSM + VSM) Shadow Material + GLSL Shader

Post by ndoxx » Wed Sep 02, 2009 4:03 pm

Hi all,

I am trying to implement PSVSM with cg, but i am using directional light instead of point light.
I have problem when comparing depth stored in shadow texture with fragment depth from light in Shadow Receiver fragment program.
When i compare both value, the fragment depth from light always smaller than depth stored in shadow texture (the chebysev inequality), thus my surface is always lit.
What i want to ask is:
1. how to get right fragment depth from light in shadow receiver? I assume that i could use post projection z value, but i dont know if its right
2. how to know whether the depth value stored in my texture shadow is right? It seems right from the debug overlay.

Shadow Receiver Vertex program:

Code: Select all

// Calculate the position of vertex in light space
	tOutput.lightPosition0 = mul(pTexWVPMatrix0, pInput.position);
	tOutput.lightPosition1 = mul(pTexWVPMatrix1, pInput.position);
	tOutput.lightPosition2 = mul(pTexWVPMatrix2, pInput.position);
Shadow Receiver Fragment program:

Code: Select all

if (pInput.uv.z <= pPSSMSplitPoints.y)
	{
		tDistanceFromLight = (pInput.lightPosition0.z - pDepthRange0.x) * pDepthRange0.w;
		tOutput.color = AngelShadowContribution(pShadowMap0, pInput.lightPosition0, tDistanceFromLight, pInvShadowMapSize0.xy) * float4(1, 0, 0, 0);
	}
Many thanks,
ndoxx
0 x

Post Reply