| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #!/usr/bin/env python
- from panda3d.core import *
- import sys
- import os
- from direct.showbase.ShowBase import ShowBase
- from direct.interval.IntervalGlobal import *
- from direct.gui.DirectGui import OnscreenText
- from direct.showbase.DirectObject import DirectObject
- from direct.actor import Actor
- from random import *
- # Function to put instructions on the screen.
- def addInstructions(pos, msg):
- return OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), scale=.05,
- shadow=(0, 0, 0, 1), parent=base.a2dTopLeft,
- pos=(0.08, -pos - 0.04), align=TextNode.ALeft)
- # Function to put title on the screen.
- def addTitle(text):
- return OnscreenText(text=text, style=1, fg=(1, 1, 1, 1), scale=.07,
- parent=base.a2dBottomRight, align=TextNode.ARight,
- pos=(-0.1, 0.09), shadow=(0, 0, 0, 1))
- class World(DirectObject):
- def __init__(self):
- # Preliminary capabilities check.
- if not base.win.getGsg().getSupportsBasicShaders():
- self.t = addTitle(
- "Shadow Demo: Video driver reports that shaders are not supported.")
- return
- if not base.win.getGsg().getSupportsDepthTexture():
- self.t = addTitle(
- "Shadow Demo: Video driver reports that depth textures are not supported.")
- return
- # creating the offscreen buffer.
- winprops = WindowProperties(size=(512, 512))
- props = FrameBufferProperties()
- props.setRgbColor(1)
- props.setAlphaBits(1)
- props.setDepthBits(1)
- LBuffer = base.graphicsEngine.makeOutput(
- base.pipe, "offscreen buffer", -2,
- props, winprops,
- GraphicsPipe.BFRefuseWindow,
- base.win.getGsg(), base.win)
- self.buffer = LBuffer
- if not LBuffer:
- self.t = addTitle(
- "Shadow Demo: Video driver cannot create an offscreen buffer.")
- return
- Ldepthmap = Texture()
- LBuffer.addRenderTexture(Ldepthmap, GraphicsOutput.RTMBindOrCopy,
- GraphicsOutput.RTPDepthStencil)
- if base.win.getGsg().getSupportsShadowFilter():
- Ldepthmap.setMinfilter(Texture.FTShadow)
- Ldepthmap.setMagfilter(Texture.FTShadow)
- # Adding a color texture is totally unnecessary, but it helps with
- # debugging.
- Lcolormap = Texture()
- LBuffer.addRenderTexture(Lcolormap, GraphicsOutput.RTMBindOrCopy,
- GraphicsOutput.RTPColor)
- self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation')
- self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle')
- self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot')
- self.inst_l = addInstructions(0.24, 'L : move light source far or close')
- self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results')
- self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map')
- self.inst_x = addInstructions(0.42, 'Left/Right Arrow : switch camera angles')
- self.inst_a = addInstructions(0.48, 'Something about A/Z and push bias')
- base.setBackgroundColor(0, 0, 0.2, 1)
- base.camLens.setNearFar(1.0, 10000)
- base.camLens.setFov(75)
- base.disableMouse()
- # Load the scene.
- floorTex = loader.loadTexture('maps/envir-ground.jpg')
- cm = CardMaker('')
- cm.setFrame(-2, 2, -2, 2)
- floor = render.attachNewNode(PandaNode("floor"))
- for y in range(12):
- for x in range(12):
- nn = floor.attachNewNode(cm.generate())
- nn.setP(-90)
- nn.setPos((x - 6) * 4, (y - 6) * 4, 0)
- floor.setTexture(floorTex)
- floor.flattenStrong()
- self.pandaAxis = render.attachNewNode('panda axis')
- self.pandaModel = Actor.Actor('panda-model', {'walk': 'panda-walk4'})
- self.pandaModel.reparentTo(self.pandaAxis)
- self.pandaModel.setPos(9, 0, 0)
- self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0))
- self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8)
- self.pandaWalk.loop()
- self.pandaMovement = self.pandaAxis.hprInterval(
- 20.0, LPoint3(-360, 0, 0), startHpr=LPoint3(0, 0, 0))
- self.pandaMovement.loop()
- self.teapot = loader.loadModel('teapot')
- self.teapot.reparentTo(render)
- self.teapot.setPos(0, -20, 10)
- self.teapot.setShaderInput("texDisable", (1, 1, 1, 1))
- self.teapotMovement = self.teapot.hprInterval(50, LPoint3(0, 360, 360))
- self.teapotMovement.loop()
- self.accept('escape', sys.exit)
- self.accept("arrow_left", self.incrementCameraPosition, [-1])
- self.accept("arrow_right", self.incrementCameraPosition, [1])
- self.accept("p", self.toggleInterval, [self.pandaMovement])
- self.accept("t", self.toggleInterval, [self.teapotMovement])
- self.accept("w", self.toggleInterval, [self.pandaWalk])
- self.accept("v", base.bufferViewer.toggleEnable)
- self.accept("u", self.toggleUpdateShadowMap)
- self.accept("l", self.incrementLightPosition, [1])
- self.accept("o", base.oobe)
- self.accept('a', self.adjustPushBias, [1.1])
- self.accept('z', self.adjustPushBias, [0.9])
- self.LCam = base.makeCamera(LBuffer)
- self.LCam.node().setScene(render)
- self.LCam.node().getLens().setFov(40)
- self.LCam.node().getLens().setNearFar(10, 100)
- # default values
- self.pushBias = 0.04
- self.ambient = 0.2
- self.cameraSelection = 0
- self.lightSelection = 0
- # setting up shader
- render.setShaderInput('light', self.LCam)
- render.setShaderInput('Ldepthmap', Ldepthmap)
- render.setShaderInput('ambient', (self.ambient, 0, 0, 1.0))
- render.setShaderInput('texDisable', (0, 0, 0, 0))
- render.setShaderInput('scale', (1, 1, 1, 1))
- # Put a shader on the Light camera.
- lci = NodePath(PandaNode("Light Camera Initializer"))
- lci.setShader(loader.loadShader('caster.sha'))
- self.LCam.node().setInitialState(lci.getState())
- # Put a shader on the Main camera.
- # Some video cards have special hardware for shadow maps.
- # If the card has that, use it. If not, use a different
- # shader that does not require hardware support.
- mci = NodePath(PandaNode("Main Camera Initializer"))
- if base.win.getGsg().getSupportsShadowFilter():
- mci.setShader(loader.loadShader('shadow.sha'))
- else:
- mci.setShader(loader.loadShader('shadow-nosupport.sha'))
- base.cam.node().setInitialState(mci.getState())
- self.incrementCameraPosition(0)
- self.incrementLightPosition(0)
- self.adjustPushBias(1.0)
- def toggleInterval(self, ival):
- if ival.isPlaying():
- ival.pause()
- else:
- ival.resume()
- def toggleUpdateShadowMap(self):
- self.buffer.active = not self.buffer.active
- def incrementCameraPosition(self, n):
- self.cameraSelection = (self.cameraSelection + n) % 6
- if (self.cameraSelection == 0):
- base.cam.reparentTo(render)
- base.cam.setPos(30, -45, 26)
- base.cam.lookAt(0, 0, 0)
- self.LCam.node().hideFrustum()
- if (self.cameraSelection == 1):
- base.cam.reparentTo(self.pandaModel)
- base.cam.setPos(7, -3, 9)
- base.cam.lookAt(0, 0, 0)
- self.LCam.node().hideFrustum()
- if (self.cameraSelection == 2):
- base.cam.reparentTo(self.pandaModel)
- base.cam.setPos(-7, -3, 9)
- base.cam.lookAt(0, 0, 0)
- self.LCam.node().hideFrustum()
- if (self.cameraSelection == 3):
- base.cam.reparentTo(render)
- base.cam.setPos(7, -23, 12)
- base.cam.lookAt(self.teapot)
- self.LCam.node().hideFrustum()
- if (self.cameraSelection == 4):
- base.cam.reparentTo(render)
- base.cam.setPos(-7, -23, 12)
- base.cam.lookAt(self.teapot)
- self.LCam.node().hideFrustum()
- if (self.cameraSelection == 5):
- base.cam.reparentTo(render)
- base.cam.setPos(1000, 0, 195)
- base.cam.lookAt(0, 0, 0)
- self.LCam.node().showFrustum()
- def incrementLightPosition(self, n):
- self.lightSelection = (self.lightSelection + n) % 2
- if (self.lightSelection == 0):
- self.LCam.setPos(0, -40, 25)
- self.LCam.lookAt(0, -10, 0)
- self.LCam.node().getLens().setNearFar(10, 100)
- if (self.lightSelection == 1):
- self.LCam.setPos(0, -600, 200)
- self.LCam.lookAt(0, -10, 0)
- self.LCam.node().getLens().setNearFar(10, 1000)
- def shaderSupported(self):
- return base.win.getGsg().getSupportsBasicShaders() and \
- base.win.getGsg().getSupportsDepthTexture() and \
- base.win.getGsg().getSupportsShadowFilter()
- def adjustPushBias(self, inc):
- self.pushBias *= inc
- self.inst_a.setText(
- 'A/Z: Increase/Decrease the Push-Bias [%F]' % self.pushBias)
- render.setShaderInput('push', self.pushBias)
- if __name__ == '__main__':
- base = ShowBase()
- w = World()
- base.run()
|