Question about multiple shadows with ShadowDemo.py

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.

don’t use sc as global. remove it’s definition on top of your script and remove :

    global sc
    if sc != None:
        sc.clear()

I’ ve tried that already.
I’ve even tried to duplicate the method arbitraryShadow and sc (arbitraryShadow0 and arbitraryShadow1 with sc0 and sc1 respectively) and used those 2 methods to test them on 2 models to see if both display a shadow.
This didn’t solve the problem, the last model with reparentTo(render) set declared to have a shadow does actually display one. The others are ignored:

shadow.arbitraryShadow(self.stange00, self.boden)
shadow.arbitraryShadow(self.stange01, self.boden)
shadow.arbitraryShadow(self.ball, self.boden)

Here only the ball gets a shadow because its the last I gave reparentTo(render).
Sorry for my english :wink: and thx for your help.

remove “taskMgr.remove(‘shadowCamera’)” too.

thx worked, but in a strange kind of way. Seemed to work fine, until i tried to add shadows to all the players. Some just got left out apparently randomly:

firstblood.de/screen.JPG

in this screen all the players “should” have shadows applied.

it’s when your hardware has reached the multitexture limit, which is 8.
read :
discourse.panda3d.org/viewtopic.php?t=1938

  1. You’re currently using 1k x 1k buffer for each player. The camera would never go down to the field, right ? So it’s a big waste. try to use larger size buffer, or keep using 1k x 1k, and cast your entire players and ball at once.
  2. use
loadPrcFileData( '', 'show-buffers 1' )

before importing DirectStart to show the buffer, so you can see if it covers the entire players.