Projected textures - too many projections

I have a small problem when using projected textures for creating shadow imitation beneath characters. I would like to have only one projection but the texture gets projected through the object, on both sides.

And if the obj has multiple geoms or a more complex shape i could get unlimited number of projections whitch i dont want.

Can i somehow affect the distance haow far the textre gets projected or any other way to get only one projection on top of the object?

A small exmple to illustrate the problem.

from direct.directbase.DirectStart import *
from direct.actor import Actor
from pandac.PandaModules import *
from direct.task import Task
from direct.interval.IntervalGlobal import *


base.setBackgroundColor(0, 0, 0, 1)

proj = render.attachNewNode(LensNode('proj'))
#lens = OrthographicLens()
lens=PerspectiveLens()
lens.setFar(2.5)
#add two plins

#vert data
vdata = GeomVertexData('name',GeomVertexFormat.getV3(),Geom.UHDynamic)

#writers
vertex = GeomVertexWriter(vdata, 'vertex')

#verts
vertex.addData3f(1,1,0)
vertex.addData3f(1,-1,0)
vertex.addData3f(-1,-1,0)
vertex.addData3f(-1,1,0)

vertex.addData3f(2,2,-2)
vertex.addData3f(2,-2,-2)
vertex.addData3f(-2,-2,-2)
vertex.addData3f(-2,2,-2)    

#create prims
prim1 = GeomTristrips(Geom.UHStatic)
prim1.addVertex(0)
prim1.addVertex(1)
prim1.addVertex(3)
prim1.addVertex(2)
prim1.closePrimitive()

prim2 = GeomTristrips(Geom.UHStatic)
prim2.addVertex(4)
prim2.addVertex(5)
prim2.addVertex(7)
prim2.addVertex(6)
prim2.closePrimitive()


#geom
geom=Geom(vdata)
geom.addPrimitive(prim1)
geom.addPrimitive(prim2)

 
node=GeomNode('gnode')
node.addGeom(geom)

geom.doublesideInPlace()
 
nodep = render.attachNewNode(node) 


#projector
proj.node().setLens(lens)
proj.node().showFrustum()
proj.find('frustum').setColor(1, 0, 0, 1)
camModel = loader.loadModel('camera.egg')
camModel.reparentTo(proj)
proj.reparentTo(render)
proj.setPos(0,0, 5)
proj.setHpr(0, -90, 0)

tex = loader.loadTexture('maps/envir-reeds.png')
tex.setWrapU(Texture.WMBorderColor)
tex.setWrapV(Texture.WMBorderColor)
tex.setBorderColor(VBase4(1, 1, 1, 0))
ts = TextureStage('ts')
ts.setSort(1)
ts.setMode(TextureStage.MDecal)
nodep.projectTexture(ts, tex, proj)

base.disableMouse()
camera.setPos(0,-20, 10)
camera.setHpr(0, -25, 0)




inter=LerpHprInterval(nodep, 3, (0,0,360), (0,0,0))
inter.loop()
run()

Hate to say it, but that’s a limitation of projected textures. The projection continues infinitely in either direction, and will flip itself over on the other side beyond the focal point. (Which will be the centroid of the object that has the projection applied to it.)

If you implement projected textures yourself, using a shader, you can use basic shadow mapping approaches to solve this issue.

No, this is the classic limitation with projected shadows of this nature. I think you could reduce the problem if you wrote a custom shader that checked the dot product of the light vector to the vertex normal. Without a shader, you’ll have to be selective in which surfaces you apply your shadow texture to.

David

Sure, if you write a shader that does normal detection you can make it work.

But if you’re writing a shader, you might as well just use some other superior shadow algorithm, such as shadowmaps or even volume shadows. Panda3d already comes with an example program which uses shaders for shadowmapping, and in 1.7.0, it’s built straight into the engine.

I wrote some fallback code in my game to use projected texture shadows, but I had to be careful to only apply them objects where the flipping wouldn’t show up. (ie: Shadows on terrain were okay, but not OK on buildings on that terrain.)

If you just want the texture not to be shown on the backface, and really want to use the fixed-function-pipeline. There’s a chance you could still do it with some clever tricks with lights and/or texture stages.