advanced.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. if not LBuffer:
  44. self.t = addTitle(
  45. "Shadow Demo: Video driver cannot create an offscreen buffer.")
  46. return
  47. Ldepthmap = Texture()
  48. LBuffer.addRenderTexture(Ldepthmap, GraphicsOutput.RTMBindOrCopy,
  49. GraphicsOutput.RTPDepthStencil)
  50. if base.win.getGsg().getSupportsShadowFilter():
  51. Ldepthmap.setMinfilter(Texture.FTShadow)
  52. Ldepthmap.setMagfilter(Texture.FTShadow)
  53. # Adding a color texture is totally unnecessary, but it helps with
  54. # debugging.
  55. Lcolormap = Texture()
  56. LBuffer.addRenderTexture(Lcolormap, GraphicsOutput.RTMBindOrCopy,
  57. GraphicsOutput.RTPColor)
  58. self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation')
  59. self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle')
  60. self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot')
  61. self.inst_l = addInstructions(0.24, 'L : move light source far or close')
  62. self.inst_v = addInstructions(0.30, 'V: View the Depth-Texture results')
  63. self.inst_x = addInstructions(0.36, 'Left/Right Arrow : switch camera angles')
  64. self.inst_a = addInstructions(0.42, 'Something about A/Z and push bias')
  65. base.setBackgroundColor(0, 0, 0.2, 1)
  66. base.camLens.setNearFar(1.0, 10000)
  67. base.camLens.setFov(75)
  68. base.disableMouse()
  69. # Load the scene.
  70. floorTex = loader.loadTexture('maps/envir-ground.jpg')
  71. cm = CardMaker('')
  72. cm.setFrame(-2, 2, -2, 2)
  73. floor = render.attachNewNode(PandaNode("floor"))
  74. for y in range(12):
  75. for x in range(12):
  76. nn = floor.attachNewNode(cm.generate())
  77. nn.setP(-90)
  78. nn.setPos((x - 6) * 4, (y - 6) * 4, 0)
  79. floor.setTexture(floorTex)
  80. floor.flattenStrong()
  81. self.pandaAxis = render.attachNewNode('panda axis')
  82. self.pandaModel = Actor.Actor('panda-model', {'walk': 'panda-walk4'})
  83. self.pandaModel.reparentTo(self.pandaAxis)
  84. self.pandaModel.setPos(9, 0, 0)
  85. self.pandaModel.setShaderInput("scale", 0.01, 0.01, 0.01, 1.0)
  86. self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8)
  87. self.pandaWalk.loop()
  88. self.pandaMovement = self.pandaAxis.hprInterval(
  89. 20.0, LPoint3(-360, 0, 0), startHpr=LPoint3(0, 0, 0))
  90. self.pandaMovement.loop()
  91. self.teapot = loader.loadModel('teapot')
  92. self.teapot.reparentTo(render)
  93. self.teapot.setPos(0, -20, 10)
  94. self.teapot.setShaderInput("texDisable", 1, 1, 1, 1)
  95. self.teapotMovement = self.teapot.hprInterval(50, LPoint3(0, 360, 360))
  96. self.teapotMovement.loop()
  97. self.accept('escape', sys.exit)
  98. self.accept("arrow_left", self.incrementCameraPosition, [-1])
  99. self.accept("arrow_right", self.incrementCameraPosition, [1])
  100. self.accept("p", self.toggleInterval, [self.pandaMovement])
  101. self.accept("P", self.toggleInterval, [self.pandaMovement])
  102. self.accept("t", self.toggleInterval, [self.teapotMovement])
  103. self.accept("T", self.toggleInterval, [self.teapotMovement])
  104. self.accept("w", self.toggleInterval, [self.pandaWalk])
  105. self.accept("W", self.toggleInterval, [self.pandaWalk])
  106. self.accept("v", base.bufferViewer.toggleEnable)
  107. self.accept("V", base.bufferViewer.toggleEnable)
  108. self.accept("l", self.incrementLightPosition, [1])
  109. self.accept("L", self.incrementLightPosition, [1])
  110. self.accept("o", base.oobe)
  111. self.accept('a', self.adjustPushBias, [1.1])
  112. self.accept('A', self.adjustPushBias, [1.1])
  113. self.accept('z', self.adjustPushBias, [0.9])
  114. self.accept('Z', self.adjustPushBias, [0.9])
  115. self.LCam = base.makeCamera(LBuffer)
  116. self.LCam.node().setScene(render)
  117. self.LCam.node().getLens().setFov(40)
  118. self.LCam.node().getLens().setNearFar(10, 100)
  119. # default values
  120. self.pushBias = 0.04
  121. self.ambient = 0.2
  122. self.cameraSelection = 0
  123. self.lightSelection = 0
  124. # setting up shader
  125. render.setShaderInput('light', self.LCam)
  126. render.setShaderInput('Ldepthmap', Ldepthmap)
  127. render.setShaderInput('ambient', self.ambient, 0, 0, 1.0)
  128. render.setShaderInput('texDisable', 0, 0, 0, 0)
  129. render.setShaderInput('scale', 1, 1, 1, 1)
  130. # Put a shader on the Light camera.
  131. lci = NodePath(PandaNode("Light Camera Initializer"))
  132. lci.setShader(loader.loadShader('caster.sha'))
  133. self.LCam.node().setInitialState(lci.getState())
  134. # Put a shader on the Main camera.
  135. # Some video cards have special hardware for shadow maps.
  136. # If the card has that, use it. If not, use a different
  137. # shader that does not require hardware support.
  138. mci = NodePath(PandaNode("Main Camera Initializer"))
  139. if base.win.getGsg().getSupportsShadowFilter():
  140. mci.setShader(loader.loadShader('shadow.sha'))
  141. else:
  142. mci.setShader(loader.loadShader('shadow-nosupport.sha'))
  143. base.cam.node().setInitialState(mci.getState())
  144. self.incrementCameraPosition(0)
  145. self.incrementLightPosition(0)
  146. self.adjustPushBias(1.0)
  147. def toggleInterval(self, ival):
  148. if ival.isPlaying():
  149. ival.pause()
  150. else:
  151. ival.resume()
  152. def incrementCameraPosition(self, n):
  153. self.cameraSelection = (self.cameraSelection + n) % 6
  154. if (self.cameraSelection == 0):
  155. base.cam.reparentTo(render)
  156. base.cam.setPos(30, -45, 26)
  157. base.cam.lookAt(0, 0, 0)
  158. self.LCam.node().hideFrustum()
  159. if (self.cameraSelection == 1):
  160. base.cam.reparentTo(self.pandaModel)
  161. base.cam.setPos(7, -3, 9)
  162. base.cam.lookAt(0, 0, 0)
  163. self.LCam.node().hideFrustum()
  164. if (self.cameraSelection == 2):
  165. base.cam.reparentTo(self.pandaModel)
  166. base.cam.setPos(-7, -3, 9)
  167. base.cam.lookAt(0, 0, 0)
  168. self.LCam.node().hideFrustum()
  169. if (self.cameraSelection == 3):
  170. base.cam.reparentTo(render)
  171. base.cam.setPos(7, -23, 12)
  172. base.cam.lookAt(self.teapot)
  173. self.LCam.node().hideFrustum()
  174. if (self.cameraSelection == 4):
  175. base.cam.reparentTo(render)
  176. base.cam.setPos(-7, -23, 12)
  177. base.cam.lookAt(self.teapot)
  178. self.LCam.node().hideFrustum()
  179. if (self.cameraSelection == 5):
  180. base.cam.reparentTo(render)
  181. base.cam.setPos(1000, 0, 195)
  182. base.cam.lookAt(0, 0, 0)
  183. self.LCam.node().showFrustum()
  184. def incrementLightPosition(self, n):
  185. self.lightSelection = (self.lightSelection + n) % 2
  186. if (self.lightSelection == 0):
  187. self.LCam.setPos(0, -40, 25)
  188. self.LCam.lookAt(0, -10, 0)
  189. self.LCam.node().getLens().setNearFar(10, 100)
  190. if (self.lightSelection == 1):
  191. self.LCam.setPos(0, -600, 200)
  192. self.LCam.lookAt(0, -10, 0)
  193. self.LCam.node().getLens().setNearFar(10, 1000)
  194. def shaderSupported(self):
  195. return base.win.getGsg().getSupportsBasicShaders() and \
  196. base.win.getGsg().getSupportsDepthTexture() and \
  197. base.win.getGsg().getSupportsShadowFilter()
  198. def adjustPushBias(self, inc):
  199. self.pushBias *= inc
  200. self.inst_a.setText(
  201. 'A/Z: Increase/Decrease the Push-Bias [%F]' % self.pushBias)
  202. render.setShaderInput('push', self.pushBias)
  203. if __name__ == '__main__':
  204. base = ShowBase()
  205. w = World()
  206. base.run()