I have modified the ShadowDemo a little to match my needs, here is what i got:
from pandac.PandaModules import *
from direct.task import Task
sc = None
class ShadowCaster:
texXSize = 1024
texYSize = 1024
def __init__(self, lightPath, objectPath, filmX, filmY):
self.lightPath = lightPath
self.objectPath = objectPath
self.groundPath = None
# Create an offscreen buffer to render the view of the avatar
# into a texture.
self.buffer = base.win.makeTextureBuffer(
'shadowBuffer', self.texXSize, self.texYSize)
# The background of this buffer--and the border of the
# texture--is pure white.
clearColor = VBase4(1, 1, 1, 1)
self.buffer.setClearColor(clearColor)
self.tex = self.buffer.getTexture()
self.tex.setBorderColor(clearColor)
self.tex.setWrapU(Texture.WMBorderColor)
self.tex.setWrapV(Texture.WMBorderColor)
# Set up a display region on this buffer, and create a camera.
dr = self.buffer.makeDisplayRegion()
self.camera = Camera('shadowCamera')
self.cameraPath = self.lightPath.attachNewNode(self.camera)
self.camera.setScene(self.objectPath)
dr.setCamera(self.cameraPath)
# Use a temporary NodePath to define the initial state for the
# camera. The initial state will render everything in a
# flat-shaded gray, as if it were a shadow.
initial = NodePath('initial')
initial.setColor(0.75, 0.75, 0.75, 1, 1)
initial.setTextureOff(2)
initial.setLightOff(2)
self.camera.setInitialState(initial.getState())
# Use an orthographic lens for this camera instead of the
# usual perspective lens. An orthographic lens is better to
# simulate sunlight, which is (almost) orthographic. We set
# the film size large enough to render a typical avatar (but
# not so large that we lose detail in the texture).
self.lens = OrthographicLens()
self.lens.setFilmSize(filmX, filmY)
self.camera.setLens(self.lens)
# Finally, we'll need a unique TextureStage to apply this
# shadow texture to the world.
self.stage = TextureStage('shadow')
# Make sure the shadowing object doesn't get its own shadow
# applied to it.
self.objectPath.setTextureOff(self.stage)
def setGround(self, groundPath):
""" Specifies the part of the world that is to be considered
the ground: this is the part onto which the rendered texture
will be applied. """
if self.groundPath:
self.groundPath.clearProjectTexture(self.stage)
self.groundPath = groundPath
self.groundPath.projectTexture(self.stage, self.tex, self.cameraPath)
def clear(self):
""" Undoes the effect of the ShadowCaster. """
if self.groundPath:
self.groundPath.clearProjectTexture(self.stage)
self.groundPath = None
if self.lightPath:
self.lightPath.detachNode()
self.lightPath = None
if self.cameraPath:
self.cameraPath.detachNode()
self.cameraPath = None
self.camera = None
self.lens = None
if self.buffer:
base.graphicsEngine.removeWindow(self.buffer)
self.tex = None
self.buffer = None
def arbitraryShadow(node, groundPath):
# Turn off the existing drop shadow, if any
if hasattr(node, "dropShadow"):
# stash it so that when the game hides and shows it, it will still be gone
node.dropShadow.stash()
# Set up a new node to hold the "light": this is an abitrary point
# somewhere above the node, looking down, as if from the sun.
objectPath = node
shadowCamera = objectPath.attachNewNode('shadowCamera')
lightPath = shadowCamera.attachNewNode('lightPath')
# We can change this position at will to change the angle of the
# sun.
lightPath.setPos(0, 0, 30)
# We need a task to keep the shadowCamera rotated in the same
# direction relative to render (otherwise, the shadow seems to
# rotate when you rotate your avatar, which is strange). We can't
# just use a compass effect, since that doesn't work on cameras.
def shadowCameraRotate(task, shadowCamera = shadowCamera):
shadowCamera.setHpr(render, 0, 0, 0)
lightPath.lookAt(shadowCamera, 0, 0, 0)
return Task.cont
taskMgr.remove('shadowCamera')
taskMgr.add(shadowCameraRotate, 'shadowCamera')
global sc
if sc != None:
sc.clear()
sc = ShadowCaster(lightPath, objectPath, 30, 30)
# Naively, just apply the shadow to everything in the world. It
# would probably be better to use a little restraint.
sc.setGround(groundPath)
return sc
My problem is that sc is overwritten each time i call arbitraryShadow(), meaning that only one model is able to cast a shadow at a time.
It may be a cheap question, but I simply can’t think of a way to change that behavior to add shadows to my other models. I have approximately 30 models that need shadowing.
I’d also like to stick with that simple kind of shadowing because something more sophisticated would simply be too much.
thanks in advance for any help supplied.