| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #!/usr/bin/env python
- #
- # Bump mapping is a way of making polygonal surfaces look
- # less flat. This sample uses normal mapping for all
- # surfaces, and also parallax mapping for the column.
- #
- # This is a tutorial to show how to do normal mapping
- # in panda3d using the Shader Generator.
- from direct.showbase.ShowBase import ShowBase
- from panda3d.core import loadPrcFileData
- from panda3d.core import WindowProperties
- from panda3d.core import Filename, Shader
- from panda3d.core import AmbientLight, PointLight
- from panda3d.core import TextNode
- from panda3d.core import LPoint3, LVector3
- from direct.task.Task import Task
- from direct.actor.Actor import Actor
- from direct.gui.OnscreenText import OnscreenText
- from direct.showbase.DirectObject import DirectObject
- from direct.filter.CommonFilters import *
- import sys
- import os
- # 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=.08,
- parent=base.a2dBottomRight, align=TextNode.ARight,
- pos=(-0.1, 0.09), shadow=(0, 0, 0, 1))
- class BumpMapDemo(ShowBase):
- def __init__(self):
- # Configure the parallax mapping settings (these are just the defaults)
- loadPrcFileData("", "parallax-mapping-samples 3\n"
- "parallax-mapping-scale 0.1")
- # Initialize the ShowBase class from which we inherit, which will
- # create a window and set up everything we need for rendering into it.
- ShowBase.__init__(self)
- # Check video card capabilities.
- if not self.win.getGsg().getSupportsBasicShaders():
- addTitle("Bump Mapping: "
- "Video driver reports that Cg shaders are not supported.")
- return
- # Post the instructions
- self.title = addTitle("Panda3D: Tutorial - Bump Mapping")
- self.inst1 = addInstructions(0.06, "Press ESC to exit")
- self.inst2 = addInstructions(0.12, "Move mouse to rotate camera")
- self.inst3 = addInstructions(0.18, "Left mouse button: Move forwards")
- self.inst4 = addInstructions(0.24, "Right mouse button: Move backwards")
- self.inst5 = addInstructions(0.30, "Enter: Turn bump maps Off")
- # Load the 'abstract room' model. This is a model of an
- # empty room containing a pillar, a pyramid, and a bunch
- # of exaggeratedly bumpy textures.
- self.room = loader.loadModel("models/abstractroom")
- self.room.reparentTo(render)
- # Make the mouse invisible, turn off normal mouse controls
- self.disableMouse()
- props = WindowProperties()
- props.setCursorHidden(True)
- self.win.requestProperties(props)
- self.camLens.setFov(60)
- # Set the current viewing target
- self.focus = LVector3(55, -55, 20)
- self.heading = 180
- self.pitch = 0
- self.mousex = 0
- self.mousey = 0
- self.last = 0
- self.mousebtn = [0, 0, 0]
- # Start the camera control task:
- taskMgr.add(self.controlCamera, "camera-task")
- self.accept("escape", sys.exit, [0])
- self.accept("mouse1", self.setMouseBtn, [0, 1])
- self.accept("mouse1-up", self.setMouseBtn, [0, 0])
- self.accept("mouse2", self.setMouseBtn, [1, 1])
- self.accept("mouse2-up", self.setMouseBtn, [1, 0])
- self.accept("mouse3", self.setMouseBtn, [2, 1])
- self.accept("mouse3-up", self.setMouseBtn, [2, 0])
- self.accept("enter", self.toggleShader)
- self.accept("j", self.rotateLight, [-1])
- self.accept("k", self.rotateLight, [1])
- self.accept("arrow_left", self.rotateCam, [-1])
- self.accept("arrow_right", self.rotateCam, [1])
- # Add a light to the scene.
- self.lightpivot = render.attachNewNode("lightpivot")
- self.lightpivot.setPos(0, 0, 25)
- self.lightpivot.hprInterval(10, LPoint3(360, 0, 0)).loop()
- plight = PointLight('plight')
- plight.setColor((1, 1, 1, 1))
- plight.setAttenuation(LVector3(0.7, 0.05, 0))
- plnp = self.lightpivot.attachNewNode(plight)
- plnp.setPos(45, 0, 0)
- self.room.setLight(plnp)
- # Add an ambient light
- alight = AmbientLight('alight')
- alight.setColor((0.2, 0.2, 0.2, 1))
- alnp = render.attachNewNode(alight)
- self.room.setLight(alnp)
- # Create a sphere to denote the light
- sphere = loader.loadModel("models/icosphere")
- sphere.reparentTo(plnp)
- # Tell Panda that it should generate shaders performing per-pixel
- # lighting for the room.
- self.room.setShaderAuto()
- self.shaderenable = 1
- def setMouseBtn(self, btn, value):
- self.mousebtn[btn] = value
- def rotateLight(self, offset):
- self.lightpivot.setH(self.lightpivot.getH() + offset * 20)
- def rotateCam(self, offset):
- self.heading = self.heading - offset * 10
- def toggleShader(self):
- self.inst5.destroy()
- if (self.shaderenable):
- self.inst5 = addInstructions(0.30, "Enter: Turn bump maps On")
- self.shaderenable = 0
- self.room.setShaderOff()
- else:
- self.inst5 = addInstructions(0.30, "Enter: Turn bump maps Off")
- self.shaderenable = 1
- self.room.setShaderAuto()
- def controlCamera(self, task):
- # figure out how much the mouse has moved (in pixels)
- md = self.win.getPointer(0)
- x = md.getX()
- y = md.getY()
- if self.win.movePointer(0, 100, 100):
- self.heading = self.heading - (x - 100) * 0.2
- self.pitch = self.pitch - (y - 100) * 0.2
- if self.pitch < -45:
- self.pitch = -45
- if self.pitch > 45:
- self.pitch = 45
- self.camera.setHpr(self.heading, self.pitch, 0)
- dir = self.camera.getMat().getRow3(1)
- elapsed = task.time - self.last
- if self.last == 0:
- elapsed = 0
- if self.mousebtn[0]:
- self.focus = self.focus + dir * elapsed * 30
- if self.mousebtn[1] or self.mousebtn[2]:
- self.focus = self.focus - dir * elapsed * 30
- self.camera.setPos(self.focus - (dir * 5))
- if self.camera.getX() < -59.0:
- self.camera.setX(-59)
- if self.camera.getX() > 59.0:
- self.camera.setX(59)
- if self.camera.getY() < -59.0:
- self.camera.setY(-59)
- if self.camera.getY() > 59.0:
- self.camera.setY(59)
- if self.camera.getZ() < 5.0:
- self.camera.setZ(5)
- if self.camera.getZ() > 45.0:
- self.camera.setZ(45)
- self.focus = self.camera.getPos() + (dir * 5)
- self.last = task.time
- return Task.cont
- demo = BumpMapDemo()
- demo.run()
|