*** empty log message ***

This commit is contained in:
David Rose 2004-08-03 22:34:53 +00:00
parent 1726a5ea95
commit b639794b19

142
direct/src/showbase/ShadowDemo.py Executable file
View File

@ -0,0 +1,142 @@
"""Create a cheesy shadow effect by rendering the view of an
object (e.g. the local avatar) from a special camera as seen from
above (as if from the sun), using a solid gray foreground and a
solid white background, and then multitexturing that view onto the
world.
This is meant primarily as a demonstration of multipass and
multitexture rendering techniques. It's not a particularly great
way to do shadows.
"""
from pandac.PandaModules import *
from direct.task import Task
sc = None
class ShadowCaster:
texXSize = 256
texYSize = 256
def __init__(self, lightPath, objectPath):
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.
layer = self.buffer.getChannel(0).makeLayer()
dr = layer.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.5, 0.5, 0.5, 1, 1)
initial.setTextureOff(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(4, 6)
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 avatarShadow():
# Turn off the existing drop shadow.
base.localAvatar.dropShadow.hide()
# Set up a new node to hold the "light": this is an abitrary point
# somewhere above the avatar, looking down, as if from the sun.
objectPath = base.localAvatar
shadowCamera = objectPath.attachNewNode('shadowCamera')
lightPath = shadowCamera.attachNewNode('lightPath')
# We can change this position at will to change the angle of the
# sun.
lightPath.setPos(5, 0, 7)
# 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, 3)
return Task.cont
taskMgr.remove('shadowCamera')
taskMgr.add(shadowCameraRotate, 'shadowCamera')
global sc
if sc != None:
sc.clear()
sc = ShadowCaster(lightPath, objectPath)
# Naively, just apply the shadow to everything in the world. It
# would probably be better to use a little restraint.
sc.setGround(render)
return sc