advanced.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python
  2. from panda3d.core import *
  3. import sys
  4. import os
  5. from direct.showbase.ShowBase import ShowBase
  6. from direct.interval.IntervalGlobal import *
  7. from direct.gui.DirectGui import OnscreenText
  8. from direct.showbase.DirectObject import DirectObject
  9. from direct.actor import Actor
  10. from random import *
  11. # Function to put instructions on the screen.
  12. def addInstructions(pos, msg):
  13. return OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), scale=.05,
  14. shadow=(0, 0, 0, 1), parent=base.a2dTopLeft,
  15. pos=(0.08, -pos - 0.04), align=TextNode.ALeft)
  16. # Function to put title on the screen.
  17. def addTitle(text):
  18. return OnscreenText(text=text, style=1, fg=(1, 1, 1, 1), scale=.07,
  19. parent=base.a2dBottomRight, align=TextNode.ARight,
  20. pos=(-0.1, 0.09), shadow=(0, 0, 0, 1))
  21. class World(DirectObject):
  22. def __init__(self):
  23. # Preliminary capabilities check.
  24. if not base.win.getGsg().getSupportsBasicShaders():
  25. self.t = addTitle(
  26. "Shadow Demo: Video driver reports that shaders are not supported.")
  27. return
  28. if not base.win.getGsg().getSupportsDepthTexture():
  29. self.t = addTitle(
  30. "Shadow Demo: Video driver reports that depth textures are not supported.")
  31. return
  32. # creating the offscreen buffer.
  33. winprops = WindowProperties(size=(512, 512))
  34. props = FrameBufferProperties()
  35. props.setRgbColor(1)
  36. props.setAlphaBits(1)
  37. props.setDepthBits(1)
  38. LBuffer = base.graphicsEngine.makeOutput(
  39. base.pipe, "offscreen buffer", -2,
  40. props, winprops,
  41. GraphicsPipe.BFRefuseWindow,
  42. base.win.getGsg(), base.win)
  43. self.buffer = LBuffer
  44. if not LBuffer:
  45. self.t = addTitle(
  46. "Shadow Demo: Video driver cannot create an offscreen buffer.")
  47. return
  48. Ldepthmap = Texture()
  49. LBuffer.addRenderTexture(Ldepthmap, GraphicsOutput.RTMBindOrCopy,
  50. GraphicsOutput.RTPDepthStencil)
  51. if base.win.getGsg().getSupportsShadowFilter():
  52. Ldepthmap.setMinfilter(Texture.FTShadow)
  53. Ldepthmap.setMagfilter(Texture.FTShadow)
  54. # Adding a color texture is totally unnecessary, but it helps with
  55. # debugging.
  56. Lcolormap = Texture()
  57. LBuffer.addRenderTexture(Lcolormap, GraphicsOutput.RTMBindOrCopy,
  58. GraphicsOutput.RTPColor)
  59. self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation')
  60. self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle')
  61. self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot')
  62. self.inst_l = addInstructions(0.24, 'L : move light source far or close')
  63. self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results')
  64. self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map')
  65. self.inst_x = addInstructions(0.42, 'Left/Right Arrow : switch camera angles')
  66. self.inst_a = addInstructions(0.48, 'Something about A/Z and push bias')
  67. base.setBackgroundColor(0, 0, 0.2, 1)
  68. base.camLens.setNearFar(1.0, 10000)
  69. base.camLens.setFov(75)
  70. base.disableMouse()
  71. # Load the scene.
  72. floorTex = loader.loadTexture('maps/envir-ground.jpg')
  73. cm = CardMaker('')
  74. cm.setFrame(-2, 2, -2, 2)
  75. floor = render.attachNewNode(PandaNode("floor"))
  76. for y in range(12):
  77. for x in range(12):
  78. nn = floor.attachNewNode(cm.generate())
  79. nn.setP(-90)
  80. nn.setPos((x - 6) * 4, (y - 6) * 4, 0)
  81. floor.setTexture(floorTex)
  82. floor.flattenStrong()
  83. self.pandaAxis = render.attachNewNode('panda axis')
  84. self.pandaModel = Actor.Actor('panda-model', {'walk': 'panda-walk4'})
  85. self.pandaModel.reparentTo(self.pandaAxis)
  86. self.pandaModel.setPos(9, 0, 0)
  87. self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0))
  88. self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8)
  89. self.pandaWalk.loop()
  90. self.pandaMovement = self.pandaAxis.hprInterval(
  91. 20.0, LPoint3(-360, 0, 0), startHpr=LPoint3(0, 0, 0))
  92. self.pandaMovement.loop()
  93. self.teapot = loader.loadModel('teapot')
  94. self.teapot.reparentTo(render)
  95. self.teapot.setPos(0, -20, 10)
  96. self.teapot.setShaderInput("texDisable", (1, 1, 1, 1))
  97. self.teapotMovement = self.teapot.hprInterval(50, LPoint3(0, 360, 360))
  98. self.teapotMovement.loop()
  99. self.accept('escape', sys.exit)
  100. self.accept("arrow_left", self.incrementCameraPosition, [-1])
  101. self.accept("arrow_right", self.incrementCameraPosition, [1])
  102. self.accept("p", self.toggleInterval, [self.pandaMovement])
  103. self.accept("t", self.toggleInterval, [self.teapotMovement])
  104. self.accept("w", self.toggleInterval, [self.pandaWalk])
  105. self.accept("v", base.bufferViewer.toggleEnable)
  106. self.accept("u", self.toggleUpdateShadowMap)
  107. self.accept("l", self.incrementLightPosition, [1])
  108. self.accept("o", base.oobe)
  109. self.accept('a', self.adjustPushBias, [1.1])
  110. self.accept('z', self.adjustPushBias, [0.9])
  111. self.LCam = base.makeCamera(LBuffer)
  112. self.LCam.node().setScene(render)
  113. self.LCam.node().getLens().setFov(40)
  114. self.LCam.node().getLens().setNearFar(10, 100)
  115. # default values
  116. self.pushBias = 0.04
  117. self.ambient = 0.2
  118. self.cameraSelection = 0
  119. self.lightSelection = 0
  120. # setting up shader
  121. render.setShaderInput('light', self.LCam)
  122. render.setShaderInput('Ldepthmap', Ldepthmap)
  123. render.setShaderInput('ambient', (self.ambient, 0, 0, 1.0))
  124. render.setShaderInput('texDisable', (0, 0, 0, 0))
  125. render.setShaderInput('scale', (1, 1, 1, 1))
  126. # Put a shader on the Light camera.
  127. lci = NodePath(PandaNode("Light Camera Initializer"))
  128. lci.setShader(loader.loadShader('caster.sha'))
  129. self.LCam.node().setInitialState(lci.getState())
  130. # Put a shader on the Main camera.
  131. # Some video cards have special hardware for shadow maps.
  132. # If the card has that, use it. If not, use a different
  133. # shader that does not require hardware support.
  134. mci = NodePath(PandaNode("Main Camera Initializer"))
  135. if base.win.getGsg().getSupportsShadowFilter():
  136. mci.setShader(loader.loadShader('shadow.sha'))
  137. else:
  138. mci.setShader(loader.loadShader('shadow-nosupport.sha'))
  139. base.cam.node().setInitialState(mci.getState())
  140. self.incrementCameraPosition(0)
  141. self.incrementLightPosition(0)
  142. self.adjustPushBias(1.0)
  143. def toggleInterval(self, ival):
  144. if ival.isPlaying():
  145. ival.pause()
  146. else:
  147. ival.resume()
  148. def toggleUpdateShadowMap(self):
  149. self.buffer.active = not self.buffer.active
  150. def incrementCameraPosition(self, n):
  151. self.cameraSelection = (self.cameraSelection + n) % 6
  152. if (self.cameraSelection == 0):
  153. base.cam.reparentTo(render)
  154. base.cam.setPos(30, -45, 26)
  155. base.cam.lookAt(0, 0, 0)
  156. self.LCam.node().hideFrustum()
  157. if (self.cameraSelection == 1):
  158. base.cam.reparentTo(self.pandaModel)
  159. base.cam.setPos(7, -3, 9)
  160. base.cam.lookAt(0, 0, 0)
  161. self.LCam.node().hideFrustum()
  162. if (self.cameraSelection == 2):
  163. base.cam.reparentTo(self.pandaModel)
  164. base.cam.setPos(-7, -3, 9)
  165. base.cam.lookAt(0, 0, 0)
  166. self.LCam.node().hideFrustum()
  167. if (self.cameraSelection == 3):
  168. base.cam.reparentTo(render)
  169. base.cam.setPos(7, -23, 12)
  170. base.cam.lookAt(self.teapot)
  171. self.LCam.node().hideFrustum()
  172. if (self.cameraSelection == 4):
  173. base.cam.reparentTo(render)
  174. base.cam.setPos(-7, -23, 12)
  175. base.cam.lookAt(self.teapot)
  176. self.LCam.node().hideFrustum()
  177. if (self.cameraSelection == 5):
  178. base.cam.reparentTo(render)
  179. base.cam.setPos(1000, 0, 195)
  180. base.cam.lookAt(0, 0, 0)
  181. self.LCam.node().showFrustum()
  182. def incrementLightPosition(self, n):
  183. self.lightSelection = (self.lightSelection + n) % 2
  184. if (self.lightSelection == 0):
  185. self.LCam.setPos(0, -40, 25)
  186. self.LCam.lookAt(0, -10, 0)
  187. self.LCam.node().getLens().setNearFar(10, 100)
  188. if (self.lightSelection == 1):
  189. self.LCam.setPos(0, -600, 200)
  190. self.LCam.lookAt(0, -10, 0)
  191. self.LCam.node().getLens().setNearFar(10, 1000)
  192. def shaderSupported(self):
  193. return base.win.getGsg().getSupportsBasicShaders() and \
  194. base.win.getGsg().getSupportsDepthTexture() and \
  195. base.win.getGsg().getSupportsShadowFilter()
  196. def adjustPushBias(self, inc):
  197. self.pushBias *= inc
  198. self.inst_a.setText(
  199. 'A/Z: Increase/Decrease the Push-Bias [%F]' % self.pushBias)
  200. render.setShaderInput('push', self.pushBias)
  201. if __name__ == '__main__':
  202. base = ShowBase()
  203. w = World()
  204. base.run()