PSSM Shadows

Here is another demonstration of PSSM using the Roaming Ralph demo. Parallel Split Shadow Maps is an algorithm of dividing the view frustum into several chunks to improve shadow mapping texture usuage efficiency and reducing the blockiness of shadows for large world views without using a HUGE shadow texture.

Fabion posted some code snippets of a PSSM framework a while ago, but the version that is still floating around is missing all of the critical chunks for positioning the three shadow cams.

I wrote everything from scratch and semi-optimized the shadow view frustum against the camera view frustum. Further optimizing can be performed by bounding the shadow frustum against the world objects, but I haven’t done this yet.

You can get this files from

starchroniclesgame.com/RalphShadows.zip

The red,green,blue world coloring denotes the different shadow frustums.

I hope you want some feedback. I can’t run your application:

DirectStart: Starting the game.
Known pipe types:
  glxGraphicsPipe
(all display modules loaded.)
:gobj(error): /home/flavio/Scrivania/RalphShadows/zshadow.c: Invalid type for a k-parameter (uniform in unknown k_smapkernal)
:gobj(error): /home/flavio/Scrivania/RalphShadows/zshadow.c: Invalid type for a k-parameter (uniform in unknown k_DebugLabelIntensity)
:gobj(error): Shader encountered an error.
Traceback (most recent call last):
  File "Tut-Roaming-Ralph.py", line 360, in <module>
    npRoot.setShaderInput('KeyLightDir', objShadManager.GetLightDirAsVB4() )
TypeError: Arguments must match one of:
setShaderInput(non-const NodePath this, const ShaderInput inp)
setShaderInput(non-const NodePath this, non-const InternalName id)
setShaderInput(non-const NodePath this, string id)
setShaderInput(non-const NodePath this, non-const InternalName id, const Vec4 v)
setShaderInput(non-const NodePath this, non-const InternalName id, const NodePath np)
setShaderInput(non-const NodePath this, non-const InternalName id, non-const Texture tex)
setShaderInput(non-const NodePath this, string id, const Vec4 v)
setShaderInput(non-const NodePath this, string id, const NodePath np)
setShaderInput(non-const NodePath this, string id, non-const Texture tex)
setShaderInput(non-const NodePath this, non-const InternalName id, float n1)
setShaderInput(non-const NodePath this, string id, float n1)
setShaderInput(non-const NodePath this, non-const InternalName id, const Vec4 v, int priority)
setShaderInput(non-const NodePath this, non-const InternalName id, const NodePath np, int priority)
setShaderInput(non-const NodePath this, non-const InternalName id, non-const Texture tex, int priority)
setShaderInput(non-const NodePath this, string id, const Vec4 v, int priority)
setShaderInput(non-const NodePath this, string id, const NodePath np, int priority)
setShaderInput(non-const NodePath this, string id, non-const Texture tex, int priority)
setShaderInput(non-const NodePath this, non-const InternalName id, float n1, float n2)
setShaderInput(non-const NodePath this, string id, float n1, float n2)
setShaderInput(non-const NodePath this, non-const InternalName id, float n1, float n2, float n3)
setShaderInput(non-const NodePath this, string id, float n1, float n2, float n3)
setShaderInput(non-const NodePath this, non-const InternalName id, float n1, float n2, float n3, float n4)
setShaderInput(non-const NodePath this, string id, float n1, float n2, float n3, float n4)
setShaderInput(non-const NodePath this, non-const InternalName id, float n1, float n2, float n3, float n4, int priority)
setShaderInput(non-const NodePath this, string id, float n1, float n2, float n3, float n4, int priority)

PS The code of the image in your post doesn’t work.

Try upgrading to 1.7.2.

Hm… I’m running 1.7.0/1.7.1 and it seems to work fine.

Can you try changing in ShadowManager.py the VBase4 return in GetLightDirAsVB4 to a Vec4 and see if that helps? Looking at your error dump, your version of python wants to take a Vec4 for shaderInput, while my only lists VBase4 as an option (but is willing to take a Vec4.) So I’ve been using VBase4 for all of my shaderinputs.

What’s the proper syntax for getting the Img thing to work? You can go to the Image shack link directly.

Ehr, I’ve a problem now (I’m sorry zhao, this is offtopic). I was sure I had 1.7.2, however I reinstalled it:

flavio@flavio-desktop:~/Scrivania/RalphShadows$ LANG=C sudo apt-get remove panda3d
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Note, selecting panda3d1.7 instead of panda3d
The following packages were automatically installed and are no longer required:
  nvidia-cg-toolkit libcvaux4 fftw2 libmpich1.0gf python-pmw libosmesa6 libcv4 libhighgui4 python-profiler
Use 'apt-get autoremove' to remove them.
The following packages will be REMOVED:
  panda3d1.7
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 0B of additional disk space will be used.
Do you want to continue [Y/n]? 
(Reading database ... 403326 files and directories currently installed.)
Removing panda3d1.7 ...
running ldconfig
Processing triggers for shared-mime-info ...
Unknown media type in type 'all/all'

Unknown media type in type 'all/allfiles'

Unknown media type in type 'uri/mms'

Unknown media type in type 'uri/mmst'

Unknown media type in type 'uri/mmsu'

Unknown media type in type 'uri/pnm'

Unknown media type in type 'uri/rtspt'

Unknown media type in type 'uri/rtspu'

Unknown media type in type 'fonts/package'

Unknown media type in type 'interface/x-winamp-skin'

Processing triggers for desktop-file-utils ...
Processing triggers for python-gmenu ...
Rebuilding /usr/share/applications/desktop.C.cache...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
Processing triggers for python-support ...
flavio@flavio-desktop:~/Scrivania/RalphShadows$ LANG=C sudo apt-get install panda3d
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Note, selecting panda3d1.7 instead of panda3d
The following NEW packages will be installed:
  panda3d1.7
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0B/58.8MB of archives.
After this operation, 0B of additional disk space will be used.
WARNING: The following packages cannot be authenticated!
  panda3d1.7
Install these packages without verification [y/N]? Y
Selecting previously deselected package panda3d1.7.
(Reading database ... 398659 files and directories currently installed.)
Unpacking panda3d1.7 (from .../panda3d1.7_1.7.2-1~lucid2_amd64.deb) ...
Processing triggers for desktop-file-utils ...
Processing triggers for python-gmenu ...
Rebuilding /usr/share/applications/desktop.C.cache...
Processing triggers for shared-mime-info ...
Unknown media type in type 'all/all'

Unknown media type in type 'all/allfiles'

Unknown media type in type 'uri/mms'

Unknown media type in type 'uri/mmst'

Unknown media type in type 'uri/mmsu'

Unknown media type in type 'uri/pnm'

Unknown media type in type 'uri/rtspt'

Unknown media type in type 'uri/rtspu'

Unknown media type in type 'fonts/package'

Unknown media type in type 'interface/x-winamp-skin'

Processing triggers for python-support ...
Setting up panda3d1.7 (1.7.2-1~lucid2) ...
running ldconfig

Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

Now, the odd part:

flavio@flavio-desktop:~/Scrivania/RalphShadows$ python Tut-Roaming-Ralph.py 
Traceback (most recent call last):
  File "Tut-Roaming-Ralph.py", line 11, in <module>
    import direct.directbase.DirectStart
ImportError: No module named direct.directbase.DirectStart

And (maybe?) this is strange, too:

flavio@flavio-desktop:~/Scrivania/RalphShadows$ apt-cache show panda3d | grep Version
Version: 1.7.0b-1~lucid2
Config-Version: 1.7.0b-1~lucid2
flavio@flavio-desktop:~/Scrivania/RalphShadows$ apt-cache show panda3d1.7 | grep Version
Version: 1.7.2-1~lucid2

When I can reinstall Panda, yes!

In your case, it should be:

[URL=http://img6.imageshack.us/i/bugafoo.png/][IMG]http://img6.imageshack.us/img6/2249/bugafoo.th.png[/IMG][/URL]

Ok. I just downloaded 1.7.2 and found that uniform float is no longer a valid shaderinput. So made the appropriate changes and everything should work now.

Although, with 1.7.2, there is some wierd texturing issues with the ‘invisible walls’ that I never realized existed in Roaming Ralph.

http://img862.imageshack.us/i/picss.jpg/

The walls aren’t invisible. In the demo they are textured black, and the window everything is drawn in is told to draw a black background, so the walls appear invisible.

If you have tried this shadow demo, do your ralph walls also flicker between textures?

I don’t have this problem with the 1.7.0 branch, but the 1.7.2 branch is causing the walls to swapping textures randomly…

1.7.0 and 1.7.2 are both on the same branch (1.7). No functionality has been removed on the 1.7 branch.

Perhaps you were using a buildbot build before, one which mistakenly identified itself as being Panda3D 1.7.1 or 1.7.0, while it was actually from the 1.8 branch?

That’s possible – I pulled mine directly from CVS a while ago.

Would you happen to be on a mac? If so I suspect this is caused by the textures not loading into the default texture stage. In recent panda builds (between 1.7.0 and 1.7.2 it changed), some egg files seem to no longer use the default texture stage on mac when some attributes are set on the texture, which when used with shaders expecting the default texture, causes them to get random textures on the GPU which swap randomly, which is clearly what I saw when running this sample on my mac, and is exactly the same as occurred with my own project.

No, I’m not using a Mac. I actually getting the problem on both my desktop and my laptop. Different models seem to trigger the two computers in different ways, but they all seemingly boil down to loading an egg file with multiple geoms and texture sets. On my laptop, loading the panda and a teapot will cause the teapot to flicker even under the fixed pipeline.

I get that texture flickering on Windows too.

Excellent job, Zhao!

Just a few things:

:arrow_right: I get this flickering effect too (Linux).

:arrow_right: On the EagleView function there is a typo on the else part:

Original:

else:
    base.cam.node().setActive(0)
    camEagle.node().setActive(1)

Modified:

else:
    base.cam.node().setActive(1)
    camEagle.node().setActive(0)

:arrow_right: Another thing is that the lighting creation is totally useless, as we’re not using it at any time on the shader, so you can comment it of (all shader calculations use “tdir”):

# Create some lighting
ambientLight = AmbientLight("ambientLight")
ambientLight.setColor(Vec4(.3, .3, .3, 1))
directionalLight = DirectionalLight("directionalLight")
directionalLight.setDirection(Vec3(-5, -5, -5))
directionalLight.setColor(Vec4(.8, .8, 1, 1))
directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
render.setLight(render.attachNewNode(ambientLight))
render.setLight(render.attachNewNode(directionalLight))

:arrow_right: Now, a question: I wanted to show the depth buffers on screen, but they appear all blank. I guess that happens because i’m not sending them the returned shader values. How would i do that? (If you didn’t undertand my question, i’d like to show the buffer for all cameras just as when you press “v” on the Tut-Shadow-Mapping-Advanced.py included on the shadows demo of panda3d)
What i’m currently using:
First i create this buffer (because i don’t know how to access the current ones):

    def createBuffer(self):
        # creating the offscreen buffer.
    
        winprops = WindowProperties.size(1024,1024)
        props = FrameBufferProperties()
        props.setRgbColor(1)
        props.setAlphaBits(1)
        props.setDepthBits(1)
        self.LBuffer = base.graphicsEngine.makeOutput(
                 base.pipe, "offscreen buffer", -2,
                 props, winprops,
                 GraphicsPipe.BFRefuseWindow,
                 base.win.getGsg(), base.win)
    
        if (self.LBuffer == None):
           self.t=addTitle("Shadow Problem: Video driver cannot create an offscreen buffer.")
           return

        Lcolormap = Texture()
        self.LBuffer.addRenderTexture(Lcolormap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor)

        Ldepthmap = Texture()
        self.LBuffer.addRenderTexture(Ldepthmap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPDepthStencil)
        if (base.win.getGsg().getSupportsShadowFilter()):
            Ldepthmap.setMinfilter(Texture.FTShadow)
            Ldepthmap.setMagfilter(Texture.FTShadow) 


        return self.LBuffer

Then i create a camera with that buffer on the GUI part and set it to look at my character:

camHere = w.createBuffer()
global camEagle2 = base.makeCamera(camHere , sort = 4, camName = 'Eagle Buffer' )
camEagle2.lookAt(w.character)
camEagle2.node().setActive(1)
camEagle2.setPos( 0, 0, 100)

Then, when i allow buffer view on screen with:

self.accept("v", base.bufferViewer.toggleEnable)

I receive exactly what the eagle camera views, as expected. But i have no idea of what to do now to make it receive the depthbuffer from the shader. On pandas’ examples, when i comment off:

self.LCam.node().setInitialState(lci.getState())

I loose the buffer view, so i guess i need to use it somehow on code, but i didn’t really understand what this does.

In fact, what i really wanted is a way to store all 3 depthBuffer results from the shader in a texture that will then be displayed on screen and used on later calculations.

So, does anyone have an idea of how to do that?

Thanks, and sorry for the long text :unamused:.

It’s been a while since I’ve played with this, and my memory is very hazy, but I think the depth texture isn’t being displayed correctly because of the shadow texture filtering. eg., comment out these two lines or replace them with the linear filtering.

  Ldepthmap.setMinfilter(Texture.FTShadow)
  Ldepthmap.setMagfilter(Texture.FTShadow)

Thanks for the reply, Zhao.
I’ve done that, and, as expected, nothing happened. The problem is that i’m not passing the shader depth texture, so it will never guess what to show, and will continue showing blank (if i comment off both the lines you said and the Lcolormap texture). If i keep the Lcolormap, it will show the eagle camera.