121 lines
5 KiB
Python
121 lines
5 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
# Author: Tree Form starplant@gmail.com
|
||
|
|
||
|
from direct.showbase.ShowBase import ShowBase
|
||
|
from panda3d.core import FrameBufferProperties, TextNode, BitMask32, LPoint3
|
||
|
from panda3d.core import WindowProperties, GraphicsOutput, Texture, GraphicsPipe
|
||
|
from direct.showbase.DirectObject import DirectObject
|
||
|
from direct.gui.OnscreenText import OnscreenText
|
||
|
from sys import exit
|
||
|
|
||
|
# Function to put instructions on the screen.
|
||
|
def addInstructions(pos, msg):
|
||
|
return OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1),
|
||
|
pos=(-1.25, pos), align=TextNode.ALeft, scale=.05)
|
||
|
|
||
|
# Function to put title on the screen.
|
||
|
def addTitle(text):
|
||
|
return OnscreenText(text=text, style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
|
||
|
pos=(1.25, -0.95), align=TextNode.ARight, scale=.07)
|
||
|
|
||
|
|
||
|
class DistortionDemo(ShowBase):
|
||
|
def __init__(self):
|
||
|
# 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)
|
||
|
|
||
|
if not base.win.getGsg().getSupportsBasicShaders():
|
||
|
t = addTitle("Distortion Demo: Video driver says Cg shaders not supported.")
|
||
|
return
|
||
|
|
||
|
self.disableMouse()
|
||
|
self.setBackgroundColor(0, 0, 0)
|
||
|
|
||
|
# Show the instructions
|
||
|
self.title = addTitle("Panda3D: Tutorial - Distortion Effect")
|
||
|
self.inst1 = addInstructions(0.92, "ESC: Quit")
|
||
|
self.inst2 = addInstructions(0.86, "Space: Toggle distortion filter On/Off")
|
||
|
self.inst4 = addInstructions(0.80, "V: View the render-to-texture results")
|
||
|
|
||
|
# Load background
|
||
|
self.seascape = loader.loadModel("models/plane")
|
||
|
self.seascape.reparentTo(render)
|
||
|
self.seascape.setPosHpr(0, 145, 0, 0, 0, 0)
|
||
|
self.seascape.setScale(100)
|
||
|
self.seascape.setTexture(loader.loadTexture("models/ocean.jpg"))
|
||
|
|
||
|
# Create the distortion buffer. This buffer renders like a normal
|
||
|
# scene,
|
||
|
self.distortionBuffer = self.makeFBO("model buffer")
|
||
|
self.distortionBuffer.setSort(-3)
|
||
|
self.distortionBuffer.setClearColor((0, 0, 0, 0))
|
||
|
|
||
|
# We have to attach a camera to the distortion buffer. The distortion camera
|
||
|
# must have the same frustum as the main camera. As long as the aspect
|
||
|
# ratios match, the rest will take care of itself.
|
||
|
distortionCamera = self.makeCamera(self.distortionBuffer, scene=render,
|
||
|
lens=self.cam.node().getLens(), mask=BitMask32.bit(4))
|
||
|
|
||
|
# load the object with the distortion
|
||
|
self.distortionObject = loader.loadModel("models/boat")
|
||
|
self.distortionObject.setScale(1)
|
||
|
self.distortionObject.setPos(0, 20, -3)
|
||
|
self.distortionObject.hprInterval(10, LPoint3(360, 0, 0)).loop()
|
||
|
self.distortionObject.reparentTo(render)
|
||
|
|
||
|
# Create the shader that will determime what parts of the scene will
|
||
|
# distortion
|
||
|
distortionShader = loader.loadShader("distortion.sha")
|
||
|
self.distortionObject.setShader(distortionShader)
|
||
|
self.distortionObject.hide(BitMask32.bit(4))
|
||
|
|
||
|
# Textures
|
||
|
tex1 = loader.loadTexture("models/water.png")
|
||
|
self.distortionObject.setShaderInput("waves", tex1)
|
||
|
|
||
|
self.texDistortion = Texture()
|
||
|
self.distortionBuffer.addRenderTexture(
|
||
|
self.texDistortion, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor)
|
||
|
self.distortionObject.setShaderInput("screen", self.texDistortion)
|
||
|
|
||
|
# Panda contains a built-in viewer that lets you view the results of
|
||
|
# your render-to-texture operations. This code configures the viewer.
|
||
|
self.accept("v", self.bufferViewer.toggleEnable)
|
||
|
self.accept("V", self.bufferViewer.toggleEnable)
|
||
|
self.bufferViewer.setPosition("llcorner")
|
||
|
self.bufferViewer.setLayout("hline")
|
||
|
self.bufferViewer.setCardSize(0.652, 0)
|
||
|
|
||
|
# event handling
|
||
|
self.accept("space", self.toggleDistortion)
|
||
|
self.accept("escape", exit, [0])
|
||
|
self.distortionOn = True
|
||
|
|
||
|
def makeFBO(self, name):
|
||
|
# This routine creates an offscreen buffer. All the complicated
|
||
|
# parameters are basically demanding capabilities from the offscreen
|
||
|
# buffer - we demand that it be able to render to texture on every
|
||
|
# bitplane, that it can support aux bitplanes, that it track
|
||
|
# the size of the host window, that it can render to texture
|
||
|
# cumulatively, and so forth.
|
||
|
winprops = WindowProperties()
|
||
|
props = FrameBufferProperties()
|
||
|
props.setRgbColor(1)
|
||
|
return self.graphicsEngine.makeOutput(
|
||
|
self.pipe, "model buffer", -2, props, winprops,
|
||
|
GraphicsPipe.BFSizeTrackHost | GraphicsPipe.BFRefuseWindow,
|
||
|
self.win.getGsg(), self.win)
|
||
|
|
||
|
def toggleDistortion(self):
|
||
|
# Toggles the distortion on/off.
|
||
|
if self.distortionOn:
|
||
|
self.distortionObject.hide()
|
||
|
else:
|
||
|
self.distortionObject.show()
|
||
|
self.distortionOn = not(self.distortionOn)
|
||
|
|
||
|
demo = DistortionDemo()
|
||
|
demo.run()
|