def regesterGeomRequirements(self, LOD, collection): n = NodePath('tmp') if self.barkTexture is not None: n.setTexture(self.barkTexture) n.setShaderInput('diffTex', self.barkTexture) format = GeomVertexFormat.getV3n3t2() else: format = GeomVertexFormat.getV3n3() n.setColor(.4, .3, .3, 1) #n.setShader(customLoader.makeShader(n)) trunkRequirements = meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState()) n = NodePath('tmp') if self.leafTexture is not None: #n.setTag("alpha","") n.setShaderInput("alpha", 0, 0, 0) # marker we need cutout alpha n.setTexture(self.leafTexture) n.setShaderInput('diffTex', self.leafTexture) format = GeomVertexFormat.getV3n3t2() else: format = GeomVertexFormat.getV3n3c4() #n.setShader(customLoader.makeShader(n,debugCodePrefix="tree",debugGraphPrefix="tree")) leafRequirements = meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState()) self.trunkDataIndex[LOD] = collection.add(trunkRequirements) self.leafDataIndex[LOD] = collection.add(leafRequirements)
def apply(self): winprops = WindowProperties.size(2048, 2048) 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 ldepthmap = Texture() lbuffer.addRenderTexture(ldepthmap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPDepthStencil) ldepthmap.setMinfilter(Texture.FTShadow) ldepthmap.setMagfilter(Texture.FTShadow) base.camLens.setNearFar(1.0, 10000) base.camLens.setFov(75) self.lcam = base.makeCamera(lbuffer) self.lcam.node().setScene(render) self.lcam.node().getLens().setFov(45) self.lcam.node().getLens().setNearFar(1, 100) render.setShaderInput('light', self.lcam) render.setShaderInput('depthmap', ldepthmap) render.setShaderInput('ambient', .15, .15, .15, 1.0) lci = NodePath(PandaNode('light camera initializer')) with open('yyagl/assets/shaders/caster.vert') as f: vert = f.read() with open('yyagl/assets/shaders/caster.frag') as f: frag = f.read() lci.setShader(Shader.make(Shader.SLGLSL, vert, frag)) self.lcam.node().setInitialState(lci.getState()) mci = NodePath(PandaNode('main camera initializer')) with open('yyagl/assets/shaders/main.vert') as f: vert = f.read() with open('yyagl/assets/shaders/main.frag') as f: frag = f.read() frag = frag.replace('<LIGHTS>', str(len(self.lights))) # use PTALVecBaseX instead # setShaderInput('vec3argname', PTALVecBase3(((0, 0, 0), (1, 1, 1)))) render.setShader(Shader.make(Shader.SLGLSL, vert, frag)) render.setShaderInput('num_lights', len(self.lights)) map(lambda lgt: self.set_lgt_args(*lgt), enumerate(self.lights)) mci.setShader(Shader.make(Shader.SLGLSL, vert, frag)) base.cam.node().setInitialState(mci.getState()) self.lcam.setPos(15, 30, 45) self.lcam.lookAt(0, 15, 0) self.lcam.node().getLens().setNearFar(1, 100)
def setEffect(self, obj, effect, properties = None, sort=0): """ Applies the effect to an object with the given properties """ effect = self.effectLoader.loadEffect(effect, properties) if effect.getSetting("transparent"): pass if effect.getSetting("dynamic"): self.registerDynamicObject(obj) if not effect.getSetting("castShadows"): obj.hide(self.getShadowPassBitmask()) if not effect.getSetting("castGI"): obj.hide(self.getVoxelizePassBitmask()) obj.setShader(effect.getShader("Default"), sort) # Create shadow caster state if effect.getSetting("castShadows"): initialState = NodePath("EffectInitialState"+str(effect.getEffectID())) initialState.setShader(effect.getShader("Shadows"), sort + 20) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) stateName = "NodeEffect" + str(effect.getEffectID()) self.lightManager.shadowPass.registerTagState(stateName, initialState.getState()) obj.setTag("ShadowPassShader", stateName)
def create(self): winprops = WindowProperties.size(self.size, self.size) props = FrameBufferProperties() props.setRgbColor(0) props.setAlphaBits(0) props.setDepthBits(1) self.buffer = base.graphicsEngine.makeOutput( base.pipe, "shadowsBuffer", -2, props, winprops, GraphicsPipe.BFRefuseWindow, base.win.getGsg(), base.win) if not self.buffer: print("Video driver cannot create an offscreen buffer.") return self.depthmap = Texture() self.buffer.addRenderTexture(self.depthmap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPDepthStencil) self.depthmap.setMinfilter(Texture.FTShadow) self.depthmap.setMagfilter(Texture.FTShadow) self.depthmap.setBorderColor(LColor(1, 1, 1, 1)) self.depthmap.setWrapU(Texture.WMBorderColor) self.depthmap.setWrapV(Texture.WMBorderColor) self.cam = base.makeCamera(self.buffer, lens=OrthographicLens()) self.cam.reparent_to(render) self.node = self.cam.node() lci = NodePath(PandaNode("Light Camera Initializer")) lci.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.M_none), 1000) lci.set_attrib( CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise), 1000) self.node.setInitialState(lci.getState()) self.node.setScene(render) if settings.debug_shadow_frustum: self.node.showFrustum()
def __init__(self,manager,xml): self.surface = getWaterSurface(manager) self.surface.reparentTo(render) self.surface.hide(BitMask32.bit(1)) # Invisible to reflection camera (speedup) self.surface.hide(BitMask32.bit(2)) # Invisible to volumetric lighting camera (speedup) self.surface.hide(BitMask32.bit(3)) # Invisible to shadow cameras (speedup) self.surface.setShader(loader.loadShader(manager.get('paths').getConfig().find('shaders').get('path')+'/water.cg')) self.surface.setShaderInput('time', 0.0, 0.0, 0.0, 0.0) ntex = loader.loadTexture(manager.get('paths').getConfig().find('textures').get('path')+'/water-normal.png') ntex.setMinfilter(Texture.FTLinearMipmapLinear) self.surface.setShaderInput('normal', ntex) self.surface.setShaderInput('camera', base.cam) self.surface.setTransparency(TransparencyAttrib.MDual, 10) self.surface.setTwoSided(True) self.surface.setShaderInput('waveInfo', Vec4(0.4, 0.4, 0.4, 0)) self.surface.setShaderInput('param2', Vec4(-0.015,0.005, 0.05, 0.05)) self.surface.setShaderInput('param3', Vec4(0.7, 0.3, 0, 0)) self.surface.setShaderInput('param4', Vec4(2.0, 0.5, 0.5, 0.0)) #self.surface.setShaderInput('speed', Vec4(-.8, -.4, -.9, .3)) self.surface.setShaderInput('speed', Vec4(0.2, -1.2, -0.2, -0.7)) self.surface.setShaderInput('deepcolor', Vec4(0.0,0.3,0.5,1.0)) self.surface.setShaderInput('shallowcolor', Vec4(0.0,1.0,1.0,1.0)) self.surface.setShaderInput('reflectioncolor', Vec4(0.95,1.0,1.0,1.0)) self.surface.hide() self.wbuffer = base.win.makeTextureBuffer('water', 512, 512) self.wbuffer.setClearColorActive(True) self.wbuffer.setClearColor(base.win.getClearColor()) self.wcamera = base.makeCamera(self.wbuffer) if manager.get('sky') != None and manager.get('sky').model != None: self.sky = manager.get('sky').model.copyTo(self.wcamera) self.sky.setTwoSided(True) self.sky.setSz(self.sky, -1) self.sky.setClipPlaneOff(1) self.sky.show() self.sky.hide(BitMask32.bit(0)) # Hide for normal camera self.sky.hide(BitMask32.bit(2)) # Hide for volumetric lighting camera self.sky.hide(BitMask32.bit(3)) # Hide for shadow camera(s), if any else: self.sky = None self.wcamera.reparentTo(render) self.wcamera.node().setLens(base.camLens) self.wcamera.node().setCameraMask(BitMask32.bit(1)) self.surface.hide(BitMask32.bit(1)) wtexture = self.wbuffer.getTexture() wtexture.setWrapU(Texture.WMClamp) wtexture.setWrapV(Texture.WMClamp) wtexture.setMinfilter(Texture.FTLinearMipmapLinear) self.surface.setShaderInput('reflection', wtexture) self.wplane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)) self.wplanenp = render.attachNewNode(PlaneNode('water', self.wplane)) tmpnp = NodePath('StateInitializer') tmpnp.setClipPlane(self.wplanenp) tmpnp.setAttrib(CullFaceAttrib.makeReverse()) self.wcamera.node().setInitialState(tmpnp.getState()) #self.fog = Fog('UnderwaterFog') #self.fog.setColor(0.0,0.3,0.5) self.fogEnabled = False
def prepareOffscreenBuffer(self): """ Creates an offscreen buffer for this target """ self.debug("Preparing offscreen buffer") # Init buffer object self._createBuffer() # Prepare fullscreen quad self._quad = self._makeFullscreenQuad() # Prepare fullscreen camera bufferCam = self._makeFullscreenCam() initialState = NodePath("is") if not self._writeColor: initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 1000) initialState.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MNone), 1000) bufferCam.setInitialState(initialState.getState()) bufferCamNode = self._quad.attachNewNode(bufferCam) bufferRegion = self._buffer.getInternalBuffer().getDisplayRegion(0) bufferRegion.setCamera(bufferCamNode) bufferRegion.setActive(1) self._setSizeShaderInput()
def prepareOffscreenBuffer(self): """ Creates an offscreen buffer for this target """ self.debug("Preparing offscreen buffer") # Init buffer object self._createBuffer() # Prepare fullscreen quad self._node = NodePath("RTRoot") self._quad = self._makeFullscreenQuad() self._quad.reparentTo(self._node) # Prepare fullscreen camera bufferCam = self._makeFullscreenCam() initialState = NodePath("is") if not self._writeColor: initialState.setAttrib( ColorWriteAttrib.make(ColorWriteAttrib.COff), 1000) initialState.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MNone), 1000) bufferCam.setInitialState(initialState.getState()) self._camera = self._node.attachNewNode(bufferCam) bufferRegion = self._internalBuffer.getDisplayRegion(0) bufferRegion.setCamera(self._camera) bufferRegion.setActive(1) self._setSizeShaderInput() self._active = True self._registerBuffer()
def makeRenderState(material=None, diffuseTexture=None, normalTexture=None, glowTexture=None): n = NodePath("n") if not material: material = makeMaterial((0, 0, 0, 1), (1, 1, 1, 1), (0.01, 0.01, 0.01, 1), 1, (1, 1, 1, 1)) n.setMaterial(material) if diffuseTexture: tsDiffuse = TextureStage('diffuse') tsDiffuse.setMode(TextureStage.MModulate) n.setTexture(tsDiffuse, diffuseTexture) if glowTexture: tsGlow = TextureStage('glow') tsGlow.setMode(TextureStage.MGlow) n.setTexture(tsGlow, glowTexture) if normalTexture: tsNormal = TextureStage('normal') tsNormal.setMode(TextureStage.MNormal) n.setTexture(tsNormal, normalTexture) # weird bugs :| #n.setTransparency(True) #n.setColorOff() return n.getState()
def handle_window(self, window): # Regenerate frame buffer self.base.graphicsEngine.removeWindow(self.frame_buffer) self.frame_buffer = self.base.win.makeTextureBuffer( "Color Picker Buffer", window.size.x, window.size.y, to_ram=True) self.frame_buffer.setSort(-100) self.frame_buffer.setClearColor((0, 0, 0, 1)) # Set up color picking camera self.color_cam.removeNode() self.color_cam = self.base.makeCamera(self.frame_buffer) color_cam_options = NodePath("color_cam_options") color_cam_options.setShader(self.color_picker_shader) self.color_cam.node().setInitialState(color_cam_options.getState()) self.color_cam.node().setTagStateKey("shader type") skinned_render_state = NodePath("") skinned_render_state.set_shader(self.skinned_shader) self.color_cam.node().setTagState("skinned", skinned_render_state.get_state()) gizmo_render_state = NodePath("") gizmo_render_state.set_shader(self.gizmo_shader) self.color_cam.node().setTagState("gizmo", gizmo_render_state.get_state())
def makeRenderState(material = None, diffuseTexture=None, normalTexture=None, glowTexture=None): n = NodePath("n") if not material: material = makeMaterial((0,0,0,1), (1,1,1,1), (0.01,0.01,0.01,1), 1, (1,1,1,1)) n.setMaterial(material) if diffuseTexture: tsDiffuse = TextureStage('diffuse') tsDiffuse.setMode(TextureStage.MModulate) n.setTexture(tsDiffuse, diffuseTexture) if glowTexture: tsGlow = TextureStage('glow') tsGlow.setMode(TextureStage.MGlow) n.setTexture(tsGlow, glowTexture) if normalTexture: tsNormal = TextureStage('normal') tsNormal.setMode(TextureStage.MNormal) n.setTexture(tsNormal, normalTexture) # weird bugs :| #n.setTransparency(True) #n.setColorOff() return n.getState()
class ShadowCreator: def __init__(self): self.shadowBuffer = base.win.makeTextureBuffer('Shadow Buffer', 2048, 2048) self.shadowBuffer.setClearColorActive(True) self.shadowBuffer.setClearColor((0, 0, 0, 1)) self.shadowCamera = base.makeCamera(self.shadowBuffer) self.shadowCamera.reparentTo(render) self.lens = base.camLens self.lens.setAspectRatio(1 / 1) self.shadowCamera.node().setLens(self.lens) self.shadowCamera.node().setCameraMask(BitMask32.bit(1)) self.initial = NodePath('initial') self.initial.setColor(0.75, 0.75, 0.75, 1, 1) self.initial.setTextureOff(2) self.initial.setMaterialOff(2) self.initial.setLightOff(2) self.shadowCamera.node().setInitialState(self.initial.getState()) self.shadowCamera.setPos(-10, 0, 20) self.shadowCamera.lookAt(0, 0, 0) self.filters = CommonFilters(self.shadowBuffer, self.shadowCamera) self.filters.setBlurSharpen(0.1) self.shadowTexture = self.shadowBuffer.getTexture() self.imageObject = OnscreenImage(image=self.shadowTexture, pos=(-0.75, 0, 0.75), scale=0.2)
def __init__(self,manager,xml): self.updateTask = None self.sun = base.cam.attachNewNode('sun') loader.loadModel(manager.get('paths').getConfig().find('misc').get('path')+'/sphere').reparentTo(self.sun) self.sun.setScale(0.1) self.sun.setTwoSided(True) self.sun.setColorScale(10.0, 10.0, 10.0, 1.0, 10001) self.sun.setLightOff(1) self.sun.setShaderOff(1) self.sun.setFogOff(1) self.sun.setCompass() self.sun.setBin('background', 10) self.sun.setDepthWrite(False) self.sun.setDepthTest(False) # Workaround an annoyance in Panda. No idea why it's needed. self.sun.node().setBounds(OmniBoundingVolume()) isa = xml.find('isa') inst = xml.find('instance') if isa != None or inst != None: if inst != None: orig = Vec3(float(inst.get('x', '0')), float(inst.get('y', '0')), float(inst.get('z', '0'))) else: level = manager.get(isa.get('source')) orig = Vec3(level.getByIsA(isa.get('name'))[0].getPos(render)) orig.normalize() self.sun.setPos(orig) godrays = xml.find('godrays') if godrays != None: self.vlbuffer = base.win.makeTextureBuffer('volumetric-lighting', base.win.getXSize()/2, base.win.getYSize()/2) self.vlbuffer.setClearColor(Vec4(0, 0, 0, 1)) cam = base.makeCamera(self.vlbuffer) cam.node().setLens(base.camLens) cam.reparentTo(base.cam) initstatenode = NodePath('InitialState') initstatenode.setColorScale(0, 0, 0, 1, 10000) initstatenode.setShaderOff(10000) initstatenode.setLightOff(10000) initstatenode.setMaterialOff(10000) initstatenode.setTransparency(TransparencyAttrib.MBinary, 10000) cam.node().setCameraMask(BitMask32.bit(2)) cam.node().setInitialState(initstatenode.getState()) self.vltexture = self.vlbuffer.getTexture() self.vltexture.setWrapU(Texture.WMClamp) self.vltexture.setWrapV(Texture.WMClamp) card = CardMaker('VolumetricLightingCard') card.setFrameFullscreenQuad() self.finalQuad = render2d.attachNewNode(card.generate()) self.finalQuad.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OIncomingColor, ColorBlendAttrib.OFbufferColor)) self.finalQuad.setShader(Shader.load(posixpath.join(manager.get('paths').getConfig().find('shaders').get('path'), 'filter-vlight.cg'))) self.finalQuad.setShaderInput('src', self.vltexture) self.finalQuad.setShaderInput('vlparams', 32, 0.9/32.0, 0.97, 0.5) # Note - first 32 is now hardcoded into shader for cards that don't support variable sized loops. self.finalQuad.setShaderInput('casterpos', 0.5, 0.5, 0, 0) # Last parameter to vlcolor is the exposure vlcolor = Vec4(float(godrays.get('r', '1')), float(godrays.get('g', '1')), float(godrays.get('b', '1')), 0.04) self.finalQuad.setShaderInput('vlcolor', vlcolor) else: self.finalQuad = None
def setCartoonShader(self, switchtoon=False): """ set cartoon shader, the following program is a reference https://github.com/panda3d/panda3d/blob/master/samples/cartoon-shader/advanced.py :return: author: weiwei date: 20180601 """ this_dir, this_filename = os.path.split(__file__) if switchtoon: lightinggen = Filename.fromOsSpecific( os.path.join(this_dir, "shaders", "lightingGen.sha")) tempnode = NodePath("temp") tempnode.setShader(loader.loadShader(lightinggen)) self.cam.node().setInitialState(tempnode.getState()) # self.render.setShaderInput("light", self.cam) self.render.setShaderInput("light", self.__ptlightnode0) # normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(Vec4(0.5, 0.5, 0.5, 1)) normalsCamera = self.makeCamera(normalsBuffer, lens=self.cam.node().getLens(), scene=self.render) normalsCamera.reparentTo(self.cam) normalgen = Filename.fromOsSpecific( os.path.join(this_dir, "shaders", "normalGen.sha")) tempnode = NodePath("temp") tempnode.setShader(loader.loadShader(normalgen)) normalsCamera.node().setInitialState(tempnode.getState()) drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(render2d) self.drawnScene = drawnScene self.separation = 0.0007 self.cutoff = 0.05 normalgen = Filename.fromOsSpecific( os.path.join(this_dir, "shaders", "inkGen.sha")) drawnScene.setShader(loader.loadShader(normalgen)) drawnScene.setShaderInput("separation", Vec4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("cutoff", Vec4(self.cutoff))
def prepareSceneRender(self): self.debug("Preparing scene render for", self._name) # Init buffer object self._createBuffer() # Prepare fullscreen quad self._quad = self._makeFullscreenQuad() # Prepare initial state cs = NodePath("InitialStateDummy") cs.setState(self._sourceCam.node().getInitialState()) if self.hasTarget(RenderTargetType.Aux0): cs.setAttrib(AuxBitplaneAttrib.make(self._auxBits), 20) cs.setAttrib(StencilAttrib.makeOff(), 20) if not self._enableTransparency: cs.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MNone), 20) self._sourceCam.node().setInitialState(cs.getState()) # Set new camera bufferCam = self._makeFullscreenCam() bufferCamNode = self._quad.attachNewNode(bufferCam) self._region.setCamera(bufferCamNode) self._region.setSort(5) # Set clears bufferRegion = self._buffer.getInternalBuffer().getDisplayRegion(0) self._correctClears() bufferRegion.setClearStencilActive(False) # self._sourceWindow.setClearStencilActive(False) # Set aux clears targetCheck = [ (RenderTargetType.Aux0, GraphicsOutput.RTPAuxRgba0), (RenderTargetType.Aux1, GraphicsOutput.RTPAuxRgba1), (RenderTargetType.Aux2, GraphicsOutput.RTPAuxRgba2), (RenderTargetType.Aux3, GraphicsOutput.RTPAuxRgba3), ] for target, targetBindPos in targetCheck: if self.hasTarget(target): bufferRegion.setClearActive(targetBindPos, 1) bufferRegion.setClearValue(targetBindPos, Vec4(0.5, 0.5, 1.0, 0.0)) self._region.disableClears() bufferRegion.setCamera(self._sourceCam) bufferRegion.setActive(1) # bufferRegion.setClearDepthActive(False) bufferRegion.setSort(20) self._setSizeShaderInput()
def __init__(self, name = 'glow', amount = 0, red = 100, green = 100, blue = 100): print "Glow enabled!" ## Glow by Adam Bell ([email protected]) ## with some original code from Kwasi Mensah ([email protected]) ## for PandaCamp (code.google.com/p/pandacamp/) #The shader is important (but yet a variable). ## The next part I'll replace with a single file as soon ## as I can work with variables in the *.SHA files. redd = red / 100 greend = green / 100 blued = blue / 100 if amount == 0: print "glowShader set to it's default value of 1." amount = 1 ## Custom number for a positive non-integer or above 4. if amount > 0: ### NOTE: the line below is an RGB render.setShaderInput('amnt',amount * redd,amount * greend,amount * blued,amount) print "glowShader set as " + str(amount) + "!" if amount < 0: raise TypeError('Only positive numbers work for the glowShader!') # except that only the glowing materials should show up nonblack. base.disableMouse() glowBuffer=base.win.makeTextureBuffer("Glow scene", 512, 512) glowBuffer.setSort(-3) glowBuffer.setClearColor(Vec4(0,0,0,1)) glowCamera=base.makeCamera(glowBuffer, lens=base.cam.node().getLens()) # Tell the glow camera to use the glow shader tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader('/c/panda/pandacamp/src/shaders/glowShader.sha')) ## Was 'Shader.load' glowCamera.node().setInitialState(tempnode.getState()) # X and Y shaders to make the earlier "glowShader.sha" work (or effective). blurXBuffer=makeFilterBuffer(glowBuffer, "Blur X", -2, "/c/panda/pandacamp/src/shaders/XBlurShader.sha") blurYBuffer=makeFilterBuffer(blurXBuffer, "Blur Y", -1, "/c/panda/pandacamp/src/shaders/YBlurShader.sha") self.finalcard = blurYBuffer.getTextureCard() self.finalcard.reparentTo(render2d) self.finalcard.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd)) # Panda contains a built-in viewer that lets you view the results of # your render-to-texture operations. This code configures the viewer. base.bufferViewer.setPosition("llcorner") base.bufferViewer.setLayout("hline") base.bufferViewer.setCardSize(0.652,0)
def __init__(self): base.disableMouse() base.cam.node().getLens().setNear(10.0) base.cam.node().getLens().setFar(9999999) camera.setPos(0, -50, 0) # Check video card capabilities. if (base.win.getGsg().getSupportsBasicShaders() == 0): addTitle("Toon Shader: Video driver reports that shaders are not supported.") return # Enable a 'light ramp' - this discretizes the lighting, # which is half of what makes a model look like a cartoon. # Light ramps only work if shader generation is enabled, # so we call 'setShaderAuto'. tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4)) tempnode.setShaderAuto() base.cam.node().setInitialState(tempnode.getState()) # Use class 'CommonFilters' to enable a cartoon inking filter. # This can fail if the video card is not powerful enough, if so, # display an error and exit. self.separation = 1 # Pixels self.filters = CommonFilters(base.win, base.cam) filterok = self.filters.setCartoonInk(separation=self.separation) if (filterok == False): addTitle("Toon Shader: Video card not powerful enough to do image postprocessing") return # Create a non-attenuating point light and an ambient light. plightnode = PointLight("point light") plightnode.setAttenuation(Vec3(1,0,0)) plight = render.attachNewNode(plightnode) plight.setPos(30,-50,0) alightnode = AmbientLight("ambient light") alightnode.setColor(Vec4(0.8,0.8,0.8,1)) alight = render.attachNewNode(alightnode) render.setLight(alight) render.setLight(plight) # Panda contains a built-in viewer that lets you view the # results of all render-to-texture operations. This lets you # see what class CommonFilters is doing behind the scenes. self.accept("v", base.bufferViewer.toggleEnable) self.accept("V", base.bufferViewer.toggleEnable) base.bufferViewer.setPosition("llcorner") self.accept("s", self.filters.manager.resizeBuffers) # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0])
def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None): if textures: colortex = textures.get('color', None) depthtex = textures.get('depth', None) auxtex = textures.get('aux', None) auxtex0 = textures.get('aux0', auxtex) auxtex1 = textures.get('aux1', None) else: auxtex0 = auxtex auxtex1 = None if colortex == None: colortex = Texture('filter-base-color') colortex.setWrapU(Texture.WMClamp) colortex.setWrapV(Texture.WMClamp) texgroup = (depthtex, colortex, auxtex0, auxtex1) winx, winy = self.getScaledSize(1, 1, 1) buffer = self.createBuffer('filter-base', winx, winy, texgroup) if buffer == None: return cm = CardMaker('filter-base-quad') cm.setFrameFullscreenQuad() quad = NodePath(cm.generate()) quad.setDepthTest(0) quad.setDepthWrite(0) quad.setTexture(colortex) quad.setColor(1, 0.5, 0.5, 1) cs = NodePath('dummy') cs.setState(self.camstate) if auxbits: cs.setAttrib(AuxBitplaneAttrib.make(auxbits)) self.camera.node().setInitialState(cs.getState()) quadcamnode = Camera('filter-quad-cam') lens = OrthographicLens() lens.setFilmSize(2, 2) lens.setFilmOffset(0, 0) lens.setNearFar(-1000, 1000) quadcamnode.setLens(lens) quadcam = quad.attachNewNode(quadcamnode) self.region.setCamera(quadcam) self.setStackedClears(buffer, self.rclears, self.wclears) if auxtex0: buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1) buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, (0.5, 0.5, 1.0, 0.0)) if auxtex1: buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1) self.region.disableClears() if self.isFullscreen(): self.win.disableClears() dr = buffer.makeDisplayRegion() dr.disableClears() dr.setCamera(self.camera) dr.setActive(1) self.buffers.append(buffer) self.sizes.append((1, 1, 1)) return quad
def setShaders(self): casterShader = Shader.load(Shader.SLGLSL, "Shader/DefaultShaders/ShadowCasting/vertex.glsl", "Shader/DefaultShaders/ShadowCasting/fragment.glsl") initialState = NodePath("ShadowCasterState") initialState.setShader(casterShader, 100) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) for camera in self.shadowCameras: camera.node().setTagState("Default", initialState.getState()) casterShaderTransparent = Shader.load(Shader.SLGLSL, "Shader/DefaultShaders/TransparentShadowCasting/vertex.glsl", "Shader/DefaultShaders/TransparentShadowCasting/fragment.glsl") initialState = NodePath("ShadowCasterStateTransparent") initialState.setShader(casterShaderTransparent, 100) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) for camera in self.shadowCameras: camera.node().setTagState("Transparent", initialState.getState()) return [casterShader, casterShaderTransparent]
def _createTagStates(self): # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster/vertex.glsl", "Shader/DefaultShadowCaster/fragment.glsl", "Shader/DefaultShadowCaster/geometry.glsl") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) self.shadowComputeCamera.setTagState( "Default", initialState.getState())
def regesterGeomRequirements(self,LOD,collection): n=NodePath('tmp') if self.barkTexture is not None: n.setTexture(self.barkTexture) n.setShaderInput('diffTex',self.barkTexture) format=GeomVertexFormat.getV3n3t2() else: format=GeomVertexFormat.getV3n3() n.setColor(.4,.3,.3,1) #n.setShader(customLoader.makeShader(n)) trunkRequirements=meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState() ) n=NodePath('tmp') if self.leafTexture is not None: #n.setTag("alpha","") n.setShaderInput("alpha",0,0,0) # marker we need cutout alpha n.setTexture(self.leafTexture) n.setShaderInput('diffTex',self.leafTexture) format=GeomVertexFormat.getV3n3t2() else: format=GeomVertexFormat.getV3n3c4() #n.setShader(customLoader.makeShader(n,debugCodePrefix="tree",debugGraphPrefix="tree")) leafRequirements=meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState() ) self.trunkDataIndex[LOD]=collection.add(trunkRequirements) self.leafDataIndex[LOD]=collection.add(leafRequirements)
def _createTagStates(self): # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster/vertex.glsl", "Shader/DefaultShadowCaster/fragment.glsl", "Shader/DefaultShadowCaster/geometry.glsl") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) # initialState.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) self.shadowComputeCamera.setTagState( "Default", initialState.getState())
def create(self): earlyZ = self.pipeline.settings.enableEarlyZ if earlyZ: self.prepassCam = Camera(Globals.base.camNode) self.prepassCam.setTagStateKey("EarlyZShader") self.prepassCam.setName("EarlyZCamera") self.prepassCamNode = Globals.base.camera.attachNewNode( self.prepassCam) Globals.render.setTag("EarlyZShader", "Default") else: self.prepassCam = None # modify default camera initial state initial = Globals.base.camNode.getInitialState() initialNode = NodePath("IntiialState") initialNode.setState(initial) if earlyZ: initialNode.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MOff)) initialNode.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MEqual)) pass else: initialNode.setAttrib( DepthTestAttrib.make(DepthTestAttrib.MLessEqual)) # initialNode.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 10000) # initialNode.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullClockwise), 10000) Globals.base.camNode.setInitialState(initialNode.getState()) self.target = RenderTarget("DeferredScenePass") self.target.addColorAndDepth() self.target.addAuxTextures(3) self.target.setAuxBits(16) self.target.setDepthBits(32) self.target.setCreateOverlayQuad(False) if earlyZ: self.target.prepareSceneRender(earlyZ=True, earlyZCam=self.prepassCamNode) else: self.target.prepareSceneRender() self.target.setClearColor(True, color=Vec4(1, 1, 0, 1)) if earlyZ: self.target.setClearDepth(False) else: self.target.setClearDepth(True)
def make_buffer(self, name: str, shader_path: str, clear_color=0.0): buffer = self.panda3d.win.makeTextureBuffer(name, 0, 0) color = LVecBase4(clear_color) buffer.setClearColor(color) camera_lens = self.panda3d.cam.node().getLens() camera = self.panda3d.makeCamera(buffer, lens=camera_lens) camera.node().setScene(self.panda3d.render) temp_node = NodePath(PandaNode("node " + name)) shader = self.panda3d.loader.loadShader(shader_path) temp_node.setShader(shader) temp_node.setShaderInput("showborders", LVecBase4(1)) temp_node.setShaderInput("colorborders", LVecBase4(0, 0, 0, 1)) camera.node().setInitialState(temp_node.getState()) return buffer, camera
def create(self): earlyZ = self.pipeline.settings.enableEarlyZ if earlyZ: self.prepassCam = Camera(Globals.base.camNode) self.prepassCam.setTagStateKey("EarlyZShader") self.prepassCam.setName("EarlyZCamera") self.prepassCamNode = Globals.base.camera.attachNewNode(self.prepassCam) Globals.render.setTag("EarlyZShader", "Default") else: self.prepassCam = None # modify default camera initial state initial = Globals.base.camNode.getInitialState() initialNode = NodePath("IntiialState") initialNode.setState(initial) if earlyZ: initialNode.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MOff)) initialNode.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MEqual)) pass else: initialNode.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MLessEqual)) # initialNode.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 10000) # initialNode.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullClockwise), 10000) Globals.base.camNode.setInitialState(initialNode.getState()) self.target = RenderTarget("DeferredScenePass") self.target.addColorAndDepth() self.target.addAuxTextures(3) self.target.setAuxBits(16) self.target.setDepthBits(32) self.target.setCreateOverlayQuad(False) if earlyZ: self.target.prepareSceneRender(earlyZ=True, earlyZCam=self.prepassCamNode) else: self.target.prepareSceneRender() self.target.setClearColor(True, color=Vec4(1, 1, 0, 1)) if earlyZ: self.target.setClearDepth(False) else: self.target.setClearDepth(True)
def _createVoxelizeState(self): """ Creates the tag state and loades the voxelizer shader """ self.voxelizeShader = BetterShader.load("Shader/GI/Voxelize.vertex", "Shader/GI/Voxelize.fragment" # "Shader/GI/Voxelize.geometry" ) initialState = NodePath("VoxelizerState") initialState.setShader(self.voxelizeShader, 50) initialState.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) initialState.setDepthWrite(False) initialState.setDepthTest(False) initialState.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MNone)) initialState.setShaderInput("dv_dest_tex", self.voxelGenTex) self.voxelizeCamera.setTagState("Default", initialState.getState())
def toggle_cartoon(self): ''' Use Cartoon ink filter ''' self.cartoon = not self.cartoon if self.cartoon: tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.4, 0.6)) tempnode.setShaderAuto() base.cam.node().setInitialState(tempnode.getState()) self.separation = 1.3 # Pixels self.filters = CommonFilters(base.win, base.cam) self.filters.setCartoonInk(separation=self.separation) # Currently using MAuto antialias, uncomment to use different #render.setAntialias(AntialiasAttrib.MBetter) #self.filters.finalQuad.setAntialias(AntialiasAttrib.MBetter) else: self.filters.cleanup() base.cam.node().setInitialState(self.alight.getState())
def compose_filters(self, win, cam, seperation=.6): """ function to handle the composing, which makes for the basic look and feel of the game also handles any filters which are attached to the cam :return: """ # set up the lightramp effect tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeSingleThreshold( 0.5, 0.4)) # warning can be ignored.. tempnode.setShaderAuto() cam.node().setInitialState(tempnode.getState()) self.separation = seperation # Pixels self.filters = CommonFilters(win, cam) filterok = self.filters.setCartoonInk(separation=self.separation) if (filterok == False): return
def setShaders(self): """ Creates the tag state and loades the voxelizer shader """ voxelizeShader = Shader.load(Shader.SLGLSL, "Shader/GI/Voxelize.vertex", "Shader/GI/Voxelize.fragment") # Create tag state initialState = NodePath("VoxelizerState") initialState.setShader(voxelizeShader, 500) initialState.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) initialState.setDepthWrite(False) initialState.setDepthTest(False) initialState.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MNone)) initialState.setShaderInput("giVoxelGenerationTex", self.voxelGenTex) # Apply tag state self.voxelizeCamera.setTagState("Default", initialState.getState()) return [voxelizeShader]
def regesterGeomRequirements(self,LOD,collection): n=NodePath('tmp') if self.leafTexture is not None: n.setTexture(self.leafTexture) n.setShaderInput('diffTex',self.leafTexture) format=GeomVertexFormat.getV3n3t2() else: n.setColor(.1,.3,.1,1) format=GeomVertexFormat.getV3n3() #n.setShader(customLoader.makeShader(n,debugCodePrefix="fern",debugGraphPrefix="fern")) leafRequirements=meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState(), ) self.leafDataIndex[LOD]=collection.add(leafRequirements)
def regesterGeomRequirements(self, LOD, collection): n = NodePath('tmp') if self.leafTexture is not None: n.setTexture(self.leafTexture) n.setShaderInput('diffTex', self.leafTexture) format = GeomVertexFormat.getV3n3t2() else: n.setColor(.1, .3, .1, 1) format = GeomVertexFormat.getV3n3() #n.setShader(customLoader.makeShader(n,debugCodePrefix="fern",debugGraphPrefix="fern")) leafRequirements = meshManager.GeomRequirements( geomVertexFormat=format, renderState=n.getState(), ) self.leafDataIndex[LOD] = collection.add(leafRequirements)
class ShadowCreator: def __init__(self): #Create a buffer for storing the shadow texture, #the higher the buffer size the better quality the shadow. self.shadowBuffer = base.win.makeTextureBuffer("Shadow Buffer", 2048, 2048) self.shadowBuffer.setClearColorActive(True) self.shadowBuffer.setClearColor((0, 0, 0, 1)) self.shadowCamera = base.makeCamera(self.shadowBuffer) self.shadowCamera.reparentTo(render) self.lens = base.camLens self.lens.setAspectRatio(1 / 1) self.shadowCamera.node().setLens(self.lens) self.shadowCamera.node().setCameraMask(BitMask32.bit(1)) #Make everything rendered by the shadow camera grey: self.initial = NodePath('initial') self.initial.setColor(.75, .75, .75, 1, 1) self.initial.setTextureOff(2) self.initial.setMaterialOff(2) self.initial.setLightOff(2) self.shadowCamera.node().setInitialState(self.initial.getState()) #The cameras pos effects the shadows dirrection: self.shadowCamera.setPos(-10, 0, 20) self.shadowCamera.lookAt(0, 0, 0) #Make the shadows soft by bluring the screen: self.filters = CommonFilters(self.shadowBuffer, self.shadowCamera) self.filters.setBlurSharpen(.1) self.shadowTexture = self.shadowBuffer.getTexture() #Draw the shadowTexture on sceen: self.imageObject = OnscreenImage(image=self.shadowTexture, pos=(-.75, 0, .75), scale=.2)
def setShaders(self): if not base.win.getGsg().getSupportsBasicShaders(): print( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeHdr0()) self.filters = CommonFilters(base.win, base.cam) # GLOW self.filters.setBloom(blend=(0.3, 0.4, 0.3, 0.0), mintrigger=0.6, maxtrigger=1.0, desat=0.6, intensity=1.0, size="medium") tempnode.setShaderAuto() base.cam.node().setInitialState(tempnode.getState())
def setEffect(self, obj, effect, properties = None, sort=0): """ Applies the effect to an object with the given properties """ effect = self.effectLoader.loadEffect(effect, properties) if effect.getSetting("transparent"): if not self.settings.useTransparency: self.error("Cannot assign transparent material when transparency is disabled") return False if effect.getSetting("dynamic"): self.registerDynamicObject(obj) if not effect.getSetting("castShadows"): obj.hide(self.getShadowPassBitmask()) if not effect.getSetting("castGI"): obj.hide(self.getVoxelizePassBitmask()) if not effect.getSetting("mainPass"): obj.hide(self.getMainPassBitmask()) effect.assignNode(obj, "Default", sort) # Create shadow caster state if effect.getSetting("castShadows"): initialState = NodePath("EffectInitialState"+str(effect.getEffectID())) initialState.setShader(effect.getShader("Shadows"), sort + 20) initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) # Fix for the shadowed terrain. Initial state doesn't seem to work with instancing # initialState.setInstanceCount(500) stateName = "NodeEffect" + str(effect.getEffectID()) self.lightManager.shadowPass.registerTagState(stateName, initialState.getState()) obj.setTag("ShadowPassShader", stateName)
def setup_glow_shader(self): glow_shader = self.base.loader.loadShader("shader/glowShader.cg") glow_buffer = self.base.win.makeTextureBuffer("Glow scene", 512, 512) glow_buffer.setSort(-3) glow_buffer.setClearColor(Vec4(0, 0, 0, 1)) self.glowcam = self.base.makeCamera( glow_buffer, lens=self.base.cam.node().getLens()) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(glow_shader) self.glowcam.node().setInitialState(tempnode.getState()) self.glowcam.reparentTo(self.base.camera) blurXBuffer = self.makeFilterBuffer(glow_buffer, "Blur X", -2, "shader/XBlurShader.cg") blurYBuffer = self.makeFilterBuffer(blurXBuffer, "Blur Y", -1, "shader/YBlurShader.cg") self.finalcard = blurYBuffer.getTextureCard() self.finalcard.reparentTo(self.base.render2d) self.finalcard.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd)) self.base.accept("v", self.base.bufferViewer.toggleEnable) self.base.accept("V", self.base.bufferViewer.toggleEnable) self.base.bufferViewer.setPosition("llcorner") self.base.bufferViewer.setLayout("hline") self.base.bufferViewer.setCardSize(0.652, 0)
def __init__(self, mainWin=base.win, mainCam=base.cam, scene=render): self.lastMousePos = Vec2(-2, -2) self.lastId = 0 self.pressedNode = None self.mDownId = 0 self.idStack = range(1, 256) self.idTable = {} self.aspectRatio = 1 self.checkCursorTask = Task(self.checkCursor, 'checkCursorTask') self.enabled = True self.mouseListeners = [] self.mainCam = mainCam mainCam.node().setCameraMask(BitMask32(1)) tempnode = NodePath(PandaNode('temp node')) tempnode.setShaderAuto() tempnode.setShaderInput('hi_id', Vec4(0, 0, 0, 0), 2) mainCam.node().setInitialState(tempnode.getState()) # Set up a node with the silhouetteGen shader. We'll apply this node's # state to custom cameras below. tempnode.setShader(loader.loadShader('silhouetteGen.sha'), 100) tempnode.setShaderInput('hi_id', Vec4(0, 0, 0, 0), 0) tempnode.setAntialias(AntialiasAttrib.MNone, 100) tempnode.setBin('inactive', 0, 1) initialState = tempnode.getState() tempnode.setBin('opaque', 0, 1) selnodeState = tempnode.getState() # We'll be using this a few times, so make an easy name for it. mainLens = mainCam.node().getLens() # Set up a buffer to which we draw a silhouette of any geometry that # we want to outline. We draw the outline by applying a Sobel edge # detection shader to the contents of this buffer. silhouetteBuffer = mainWin.makeTextureBuffer('silhouetteBuffer', 0, 0) silhouetteBuffer.setClearColor(Vec4(0, 0, 0, 1)) self.silhouetteBuffer = silhouetteBuffer silhouetteCamera = base.makeCamera(silhouetteBuffer, lens=mainLens) silhouetteCamera.node().setScene(scene) silhouetteCamera.node().setInitialState(initialState) silhouetteCamera.node().setTagState('sel', selnodeState) silhouetteCamera.node().setTagStateKey('sel') silhouetteCamera.node().setCameraMask(BitMask32(8)) tempnode.setShader(loader.loadShader('mousePicker.sha'), 100) selnodeState = tempnode.getState() tempnode.setBin('inactive', 0, 1) initialState = tempnode.getState() # Set up a 1-by-1 buffer to which we'll just render the pixel under # the mouse. selectBuffer = mainWin.makeTextureBuffer('selectBuffer', 1, 1) selectBuffer.setClearColor(Vec4(0, 0, 0, 1)) self.selectBuffer = selectBuffer selectLens = PerspectiveLens() selectLens.setNearFar(mainLens.getNear(), mainLens.getFar()) selectLens.setFocalLength(mainLens.getFocalLength()) selectCamera = base.makeCamera(selectBuffer, lens=selectLens) selectCamera.node().setScene(scene) selectCamera.node().setInitialState(initialState) selectCamera.node().setTagState('sel', selnodeState) selectCamera.node().setTagStateKey('sel') selectCamera.node().setCameraMask(BitMask32(16)) self.selectLens = selectLens self.selectTex = selectBuffer.getTexture() self.selectTex.makeRamImage() self.gsg = mainWin.getGsg() # Set up a texture card to render the silhouette texture with the # Sobel shader, which will draw the edges of the silhouettes. silhouetteCard = silhouetteBuffer.getTextureCard() silhouetteCard.setTransparency(1) inkGen = loader.loadShader('sobel.sha') silhouetteCard.setShader(inkGen) silhouetteCard.setShaderInput('separation', 0.001, 0) silhouetteCard.reparentTo(render2d) self.silhouetteCard = silhouetteCard self.accept(mainWin.getWindowEvent(), self.windowEventHandler) self.accept('mouse1', self.mouseDownHandler, ['l']) self.accept('mouse1-up', self.mouseUpHandler, ['l']) self.accept('mouse3', self.mouseDownHandler, ['r']) self.accept('mouse3-up', self.mouseUpHandler, ['r']) self.buttonWatcher = ButtonWatcher([ KeyboardButton.shift(), KeyboardButton.control(), MouseButton.one(), MouseButton.three(), ]) CameraController.getInstance().addEventHandler(EVT_CAMERA_MODE, self._cameraModeHandler) self.enable(False)
node.addGeom(geom) return node cbm = CullBinManager.getGlobalPtr() cbm.addBin('handles', CullBinEnums.BTFrontToBack, 35) cbm.setBinActive('handles', True) tempnode = NodePath(PandaNode('temp node')) tempnode.setShaderAuto() tempnode.setShaderInput('hi_id', Vec4(0, 0, 0, 0), 2) tempnode.setBin('inactive', 0, 50) tempnode.setAntialias(AntialiasAttrib.MNone, 10) newCamera = base.makeCamera(base.win, lens=base.cam.node().getLens()) newCamera.node().setInitialState(tempnode.getState()) newCamera.node().getDisplayRegion(0).setSort(1) newCamera.node().getDisplayRegion(0).setClearDepthActive(1) newCamera.node().setCameraMask(BitMask32(4)) newCamera.node().setScene(render) class RotationHandle(PandaNode, MouseEventListener): geomNode = makeRotationGeomNode() def __init__(self, parent, color, hpr, dim): PandaNode.__init__(self, dim+'rotHandle') self.path = NodePath(self) self.parent = parent self.dim = dim
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) self.disableMouse() self.cam.node().getLens().setNear(10.0) self.cam.node().getLens().setFar(200.0) camera.setPos(0, -50, 0) # Check video card capabilities. if not self.win.getGsg().getSupportsBasicShaders(): addTitle( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return # Enable a 'light ramp' - this discretizes the lighting, # which is half of what makes a model look like a cartoon. # Light ramps only work if shader generation is enabled, # so we call 'setShaderAuto'. tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4)) tempnode.setShaderAuto() self.cam.node().setInitialState(tempnode.getState()) # Use class 'CommonFilters' to enable a cartoon inking filter. # This can fail if the video card is not powerful enough, if so, # display an error and exit. self.separation = 1 # Pixels self.filters = CommonFilters(self.win, self.cam) filterok = self.filters.setCartoonInk(separation=self.separation) if (filterok == False): addTitle( "Toon Shader: Video card not powerful enough to do image postprocessing" ) return # Show instructions in the corner of the window. self.title = addTitle( "Panda3D: Tutorial - Toon Shading with Normals-Based Inking") self.inst1 = addInstructions(0.06, "ESC: Quit") self.inst2 = addInstructions( 0.12, "Up/Down: Increase/Decrease Line Thickness") self.inst3 = addInstructions(0.18, "V: View the render-to-texture results") # Load a dragon model and animate it. self.character = Actor() self.character.loadModel('models/nik-dragon') self.character.reparentTo(render) self.character.loadAnims({'win': 'models/nik-dragon'}) self.character.loop('win') self.character.hprInterval(15, (360, 0, 0)).loop() # Create a non-attenuating point light and an ambient light. plightnode = PointLight("point light") plightnode.setAttenuation((1, 0, 0)) plight = render.attachNewNode(plightnode) plight.setPos(30, -50, 0) alightnode = AmbientLight("ambient light") alightnode.setColor((0.8, 0.8, 0.8, 1)) alight = render.attachNewNode(alightnode) render.setLight(alight) render.setLight(plight) # Panda contains a built-in viewer that lets you view the # results of all render-to-texture operations. This lets you # see what class CommonFilters is doing behind the scenes. self.accept("v", self.bufferViewer.toggleEnable) self.accept("V", self.bufferViewer.toggleEnable) self.bufferViewer.setPosition("llcorner") self.accept("s", self.filters.manager.resizeBuffers) # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.increaseSeparation) self.accept("arrow_down", self.decreaseSeparation)
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) self.setBackgroundColor((0, 0, 0, 0)) # Preliminary capabilities check. if not self.win.getGsg().getSupportsBasicShaders(): self.t = addTitle("Firefly Demo: Video driver reports that Cg " "shaders are not supported.") return if not self.win.getGsg().getSupportsDepthTexture(): self.t = addTitle("Firefly Demo: Video driver reports that depth " "textures are not supported.") return # This algorithm uses two offscreen buffers, one of which has # an auxiliary bitplane, and the offscreen buffers share a single # depth buffer. This is a heck of a complicated buffer setup. self.modelbuffer = self.makeFBO("model buffer", 1) self.lightbuffer = self.makeFBO("light buffer", 0) # Creation of a high-powered buffer can fail, if the graphics card # doesn't support the necessary OpenGL extensions. if self.modelbuffer is None or self.lightbuffer is None: self.t = addTitle("Toon Shader: Video driver does not support " "multiple render targets") return # Create four render textures: depth, normal, albedo, and final. # attach them to the various bitplanes of the offscreen buffers. self.texDepth = Texture() self.texDepth.setFormat(Texture.FDepthStencil) self.texAlbedo = Texture() self.texNormal = Texture() self.texFinal = Texture() self.modelbuffer.addRenderTexture(self.texDepth, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPDepthStencil) self.modelbuffer.addRenderTexture(self.texAlbedo, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor) self.modelbuffer.addRenderTexture(self.texNormal, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPAuxRgba0) self.lightbuffer.addRenderTexture(self.texFinal, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor) # Set the near and far clipping planes. self.cam.node().getLens().setNear(50.0) self.cam.node().getLens().setFar(500.0) lens = self.cam.node().getLens() # This algorithm uses three cameras: one to render the models into the # model buffer, one to render the lights into the light buffer, and # one to render "plain" stuff (non-deferred shaded) stuff into the # light buffer. Each camera has a bitmask to identify it. self.modelMask = 1 self.lightMask = 2 self.plainMask = 4 self.modelcam = self.makeCamera(self.modelbuffer, lens=lens, scene=render, mask=self.modelMask) self.lightcam = self.makeCamera(self.lightbuffer, lens=lens, scene=render, mask=self.lightMask) self.plaincam = self.makeCamera(self.lightbuffer, lens=lens, scene=render, mask=self.plainMask) # Panda's main camera is not used. self.cam.node().setActive(0) # Take explicit control over the order in which the three # buffers are rendered. self.modelbuffer.setSort(1) self.lightbuffer.setSort(2) self.win.setSort(3) # Within the light buffer, control the order of the two cams. self.lightcam.node().getDisplayRegion(0).setSort(1) self.plaincam.node().getDisplayRegion(0).setSort(2) # By default, panda usually clears the screen before every # camera and before every window. Tell it not to do that. # Then, tell it specifically when to clear and what to clear. self.modelcam.node().getDisplayRegion(0).disableClears() self.lightcam.node().getDisplayRegion(0).disableClears() self.plaincam.node().getDisplayRegion(0).disableClears() self.cam.node().getDisplayRegion(0).disableClears() self.cam2d.node().getDisplayRegion(0).disableClears() self.modelbuffer.disableClears() self.win.disableClears() self.modelbuffer.setClearColorActive(1) self.modelbuffer.setClearDepthActive(1) self.lightbuffer.setClearColorActive(1) self.lightbuffer.setClearColor((0, 0, 0, 1)) # Miscellaneous stuff. self.disableMouse() self.camera.setPos(-9.112, -211.077, 46.951) self.camera.setHpr(0, -7.5, 2.4) random.seed() # Calculate the projection parameters for the final shader. # The math here is too complex to explain in an inline comment, # I've put in a full explanation into the HTML intro. proj = self.cam.node().getLens().getProjectionMat() proj_x = 0.5 * proj.getCell(3, 2) / proj.getCell(0, 0) proj_y = 0.5 * proj.getCell(3, 2) proj_z = 0.5 * proj.getCell(3, 2) / proj.getCell(2, 1) proj_w = -0.5 - 0.5 * proj.getCell(1, 2) # Configure the render state of the model camera. tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib( AlphaTestAttrib.make(RenderAttrib.MGreaterEqual, 0.5)) tempnode.setShader(loader.loadShader("model.sha")) tempnode.setAttrib(DepthTestAttrib.make(RenderAttrib.MLessEqual)) self.modelcam.node().setInitialState(tempnode.getState()) # Configure the render state of the light camera. tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader("light.sha")) tempnode.setShaderInput("texnormal", self.texNormal) tempnode.setShaderInput("texalbedo", self.texAlbedo) tempnode.setShaderInput("texdepth", self.texDepth) tempnode.setShaderInput("proj", (proj_x, proj_y, proj_z, proj_w)) tempnode.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOne)) tempnode.setAttrib( CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise)) # The next line causes problems on Linux. # tempnode.setAttrib(DepthTestAttrib.make(RenderAttrib.MGreaterEqual)) tempnode.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MOff)) self.lightcam.node().setInitialState(tempnode.getState()) # Configure the render state of the plain camera. rs = RenderState.makeEmpty() self.plaincam.node().setInitialState(rs) # Clear any render attribs on the root node. This is necessary # because by default, panda assigns some attribs to the root # node. These default attribs will override the # carefully-configured render attribs that we just attached # to the cameras. The simplest solution is to just clear # them all out. render.setState(RenderState.makeEmpty()) # My artist created a model in which some of the polygons # don't have textures. This confuses the shader I wrote. # This little hack guarantees that everything has a texture. white = loader.loadTexture("models/white.jpg") render.setTexture(white, 0) # Create two subroots, to help speed cull traversal. self.lightroot = NodePath(PandaNode("lightroot")) self.lightroot.reparentTo(render) self.modelroot = NodePath(PandaNode("modelroot")) self.modelroot.reparentTo(render) self.lightroot.hide(BitMask32(self.modelMask)) self.modelroot.hide(BitMask32(self.lightMask)) self.modelroot.hide(BitMask32(self.plainMask)) # Load the model of a forest. Make it visible to the model camera. # This is a big model, so we load it asynchronously while showing a # load text. We do this by passing in a callback function. self.loading = addTitle("Loading models...") self.forest = NodePath(PandaNode("Forest Root")) self.forest.reparentTo(render) self.forest.hide(BitMask32(self.lightMask | self.plainMask)) loader.loadModel([ "models/background", "models/foliage01", "models/foliage02", "models/foliage03", "models/foliage04", "models/foliage05", "models/foliage06", "models/foliage07", "models/foliage08", "models/foliage09"], callback=self.finishLoading) # Cause the final results to be rendered into the main window on a # card. self.card = self.lightbuffer.getTextureCard() self.card.setTexture(self.texFinal) self.card.reparentTo(render2d) # Panda contains a built-in viewer that lets you view the results of # your render-to-texture operations. This code configures the viewer. self.bufferViewer.setPosition("llcorner") self.bufferViewer.setCardSize(0, 0.40) self.bufferViewer.setLayout("vline") self.toggleCards() self.toggleCards() # Firefly parameters self.fireflies = [] self.sequences = [] self.scaleseqs = [] self.glowspheres = [] self.fireflysize = 1.0 self.spheremodel = loader.loadModel("misc/sphere") # Create the firefly model, a fuzzy dot dotSize = 1.0 cm = CardMaker("firefly") cm.setFrame(-dotSize, dotSize, -dotSize, dotSize) self.firefly = NodePath(cm.generate()) self.firefly.setTexture(loader.loadTexture("models/firefly.png")) self.firefly.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.M_add, ColorBlendAttrib.O_incoming_alpha, ColorBlendAttrib.O_one)) # these allow you to change parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.incFireflyCount, [1.1111111]) self.accept("arrow_down", self.decFireflyCount, [0.9000000]) self.accept("arrow_right", self.setFireflySize, [1.1111111]) self.accept("arrow_left", self.setFireflySize, [0.9000000]) self.accept("v", self.toggleCards) self.accept("V", self.toggleCards)
def create(self): # Create the atlas target self.target = RenderTarget("ShadowAtlas") self.target.setSize(self.size) self.target.addDepthTexture() self.target.setDepthBits(32) self.target.setColorWrite(False) self.target.setCreateOverlayQuad(False) # self.target.setActive(False) self.target.setSource( NodePath(Camera("tmp")), Globals.base.win) self.target.prepareSceneRender() self.target.setClearDepth(False) # Set the appropriate filter modes dTex = self.target.getDepthTexture() dTex.setWrapU(SamplerState.WMClamp) dTex.setWrapV(SamplerState.WMClamp) # Remove the default postprocess quad # self.target.getQuad().node().removeAllChildren() # self.target.getInternalRegion().setSort(-200) self.target.getInternalRegion().disableClears() self.target.getInternalBuffer().disableClears() # self.target.getInternalBuffer().setSort(-300) # Create default initial state initialState = NodePath("InitialState") initialState.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff)) # Create a camera for each update self.shadowCameras = [] for i in xrange(self.maxRegions): shadowCam = Camera("ShadowComputeCamera") shadowCam.setTagStateKey("ShadowPassShader") shadowCam.setInitialState(initialState.getState()) shadowCam.setCameraMask(BitMask32.bit(3)) shadowCamNode = self.shadowScene.attachNewNode(shadowCam) self.shadowCameras.append(shadowCamNode) # Create regions self.renderRegions = [] buff = self.target.getInternalBuffer() for i in xrange(self.maxRegions): dr = buff.makeDisplayRegion() dr.setSort(1000) dr.setClearDepthActive(True) dr.setClearDepth(1.0) # dr.setClearColorActive(False) # dr.setClearColor(Vec4(1,1,1,1)) dr.setCamera(self.shadowCameras[i]) dr.setActive(False) self.renderRegions.append(dr) self.pcfSampleState = SamplerState() self.pcfSampleState.setMinfilter(SamplerState.FTShadow) self.pcfSampleState.setMagfilter(SamplerState.FTShadow) self.pcfSampleState.setWrapU(SamplerState.WMClamp) self.pcfSampleState.setWrapV(SamplerState.WMClamp)
def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None): """ Causes the scene to be rendered into the supplied textures instead of into the original window. Puts a fullscreen quad into the original window to show the render-to-texture results. Returns the quad. Normally, the caller would then apply a shader to the quad. To elaborate on how this all works: * An offscreen buffer is created. It is set up to mimic the original display region - it is the same size, uses the same clear colors, and contains a DisplayRegion that uses the original camera. * A fullscreen quad and an orthographic camera to render that quad are both created. The original camera is removed from the original window, and in its place, the orthographic quad-camera is installed. * The fullscreen quad is textured with the data from the offscreen buffer. A shader is applied that tints the results pink. * Automatic shader generation NOT enabled. If you have a filter that depends on a render target from the auto-shader, you either need to set an auto-shader attrib on the main camera or scene, or, you need to provide these outputs in your own shader. * All clears are disabled on the original display region. If the display region fills the whole window, then clears are disabled on the original window as well. It is assumed that rendering the full-screen quad eliminates the need to do clears. Hence, the original window which used to contain the actual scene, now contains a pink-tinted quad with a texture of the scene. It is assumed that the user will replace the shader on the quad with a more interesting filter. """ if (textures): colortex = textures.get("color", None) depthtex = textures.get("depth", None) auxtex = textures.get("aux", None) auxtex0 = textures.get("aux0", auxtex) auxtex1 = textures.get("aux1", None) else: auxtex0 = auxtex auxtex1 = None if (colortex == None): colortex = Texture("filter-base-color") colortex.setWrapU(Texture.WMClamp) colortex.setWrapV(Texture.WMClamp) texgroup = (depthtex, colortex, auxtex0, auxtex1) # Choose the size of the offscreen buffer. (winx, winy) = self.getScaledSize(1,1,1) buffer = self.createBuffer("filter-base", winx, winy, texgroup) if (buffer == None): return None cm = CardMaker("filter-base-quad") cm.setFrameFullscreenQuad() quad = NodePath(cm.generate()) quad.setDepthTest(0) quad.setDepthWrite(0) quad.setTexture(colortex) quad.setColor(1, 0.5, 0.5, 1) cs = NodePath("dummy") cs.setState(self.camstate) # Do we really need to turn on the Shader Generator? #cs.setShaderAuto() if (auxbits): cs.setAttrib(AuxBitplaneAttrib.make(auxbits)) self.camera.node().setInitialState(cs.getState()) quadcamnode = Camera("filter-quad-cam") lens = OrthographicLens() lens.setFilmSize(2, 2) lens.setFilmOffset(0, 0) lens.setNearFar(-1000, 1000) quadcamnode.setLens(lens) quadcam = quad.attachNewNode(quadcamnode) self.region.setCamera(quadcam) self.setStackedClears(buffer, self.rclears, self.wclears) if (auxtex0): buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1) buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, (0.5, 0.5, 1.0, 0.0)) if (auxtex1): buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1) self.region.disableClears() if (self.isFullscreen()): self.win.disableClears() dr = buffer.makeDisplayRegion() dr.disableClears() dr.setCamera(self.camera) dr.setActive(1) self.buffers.append(buffer) self.sizes.append((1, 1, 1)) return quad
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) self.disableMouse() camera.setPos(0, -50, 0) # Check video card capabilities. if not self.win.getGsg().getSupportsBasicShaders(): addTitle("Toon Shader: Video driver reports that Cg shaders are not supported.") return # Show instructions in the corner of the window. self.title = addTitle( "Panda3D: Tutorial - Toon Shading with Normals-Based Inking") self.inst1 = addInstructions(0.06, "ESC: Quit") self.inst2 = addInstructions(0.12, "Up/Down: Increase/Decrease Line Thickness") self.inst3 = addInstructions(0.18, "Left/Right: Decrease/Increase Line Darkness") self.inst4 = addInstructions(0.24, "V: View the render-to-texture results") # This shader's job is to render the model with discrete lighting # levels. The lighting calculations built into the shader assume # a single nonattenuating point light. tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader("lightingGen.sha")) self.cam.node().setInitialState(tempnode.getState()) # This is the object that represents the single "light", as far # the shader is concerned. It's not a real Panda3D LightNode, but # the shader doesn't care about that. light = render.attachNewNode("light") light.setPos(30, -50, 0) # this call puts the light's nodepath into the render state. # this enables the shader to access this light by name. render.setShaderInput("light", light) # The "normals buffer" will contain a picture of the model colorized # so that the color of the model is a representation of the model's # normal at that point. normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) self.normalsBuffer = normalsBuffer normalsCamera = self.makeCamera( normalsBuffer, lens=self.cam.node().getLens()) normalsCamera.node().setScene(render) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader("normalGen.sha")) normalsCamera.node().setInitialState(tempnode.getState()) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(render2d) self.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. self.separation = 0.001 self.cutoff = 0.3 inkGen = loader.loadShader("inkGen.sha") drawnScene.setShader(inkGen) drawnScene.setShaderInput("separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) # 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") # Load a dragon model and start its animation. self.character = Actor() self.character.loadModel('models/nik-dragon') self.character.reparentTo(render) self.character.loop('win') self.character.hprInterval(15, (360, 0, 0)).loop() # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.increaseSeparation) self.accept("arrow_down", self.decreaseSeparation) self.accept("arrow_left", self.increaseCutoff) self.accept("arrow_right", self.decreaseCutoff)
class FPSCamera(DirectObject): MaxP = 90.0 MinP = -90.0 PitchUpdateEpsilon = 0.1 ViewModelFOV = 70.0 BobCycleMin = 1.0 BobCycleMax = 0.45 Bob = 0.002 BobUp = 0.5 PunchDamping = 9.0 PunchSpring = 65.0 PrintAnimLengths = False def __init__(self): DirectObject.__init__(self) self.mouseEnabled = False self.lastCamRoot2Quat = Quat(Quat.identQuat()) self.punchAngleVel = Vec3(0) self.punchAngle = Vec3(0) self.lastFacing = Vec3(0) self.lastMousePos = Point2(0) self.currMousePos = Point2(0) self.bobTime = 0 self.lastBobTime = 0 self.lastVMPos = Point3(0) self.camRoot = NodePath("camRoot") self.camRoot2 = self.camRoot.attachNewNode("camRoot2") self.lastPitch = 0 self.lastEyeHeight = 0.0 # Updates to the transform of camRoot self.vmRender = NodePath( BSPRender('vmRender', BSPLoader.getGlobalPtr())) self.vmRender.setShaderAuto() self.vmRoot = self.vmRender.attachNewNode('vmRoot') self.vmRoot2 = self.vmRoot.attachNewNode(ModelRoot('vmRoot2')) self.viewModel = Actor( "phase_14/models/char/v_toon_arms.bam", { "zero": "phase_14/models/char/v_toon_arms.egg", # Squirt gun viewmodel animations "sg_draw": "phase_14/models/char/v_toon_arms-draw.egg", "sg_idle": "phase_14/models/char/v_toon_arms-idle.egg", "sg_inspect": "phase_14/models/char/v_toon_arms-inspect.egg", "sg_shoot_begin": "phase_14/models/char/v_toon_arms-shoot_begin.egg", "sg_shoot_loop": "phase_14/models/char/v_toon_arms-shoot_loop.egg", "sg_shoot_end": "phase_14/models/char/v_toon_arms-shoot_end.egg", "pie_draw": "phase_14/models/char/v_toon_arms-pie_draw.egg", "pie_idle": "phase_14/models/char/v_toon_arms-pie_idle.egg", "button_draw": "phase_14/models/char/v_toon_arms-button_draw.egg", "button_idle": "phase_14/models/char/v_toon_arms-button_idle.egg", "button_press": "phase_14/models/char/v_toon_arms-button_press.egg", "gumball_draw": "phase_14/models/char/v_toon_arms-gumball_draw.egg", "gumball_idle": "phase_14/models/char/v_toon_arms-gumball_idle.egg", "gumball_fire": "phase_14/models/char/v_toon_arms-gumball_fire.egg", "hose_draw": "phase_14/models/char/v_toon_arms-hose_draw.egg", "hose_idle": "phase_14/models/char/v_toon_arms-hose_idle.egg", "hose_shoot_begin": "phase_14/models/char/v_toon_arms-hose_shoot_begin.egg", "hose_shoot_loop": "phase_14/models/char/v_toon_arms-hose_shoot_loop.egg", "hose_shoot_end": "phase_14/models/char/v_toon_arms-hose_shoot_end.egg", "tnt_draw": "phase_14/models/char/v_toon_arms-tnt_draw.egg", "tnt_idle": "phase_14/models/char/v_toon_arms-tnt_idle.egg", "tnt_throw": "phase_14/models/char/v_toon_arms-tnt_throw.egg", "slap_idle": "phase_14/models/char/v_toon_arms-slap_idle.egg", "slap_hit": "phase_14/models/char/v_toon_arms-slap_hit.egg", "sound": "phase_14/models/char/v_toon_arms-sound.egg" }) self.viewModel.setBlend( frameBlend=base.config.GetBool("interpolate-frames", False)) self.viewModel.reparentTo(self.vmRoot2) self.viewModel.find("**/hands").setTwoSided(True) self.viewModel.hide() self.defaultViewModel = self.viewModel self.idealFov = self.ViewModelFOV precacheActor(self.viewModel) #self.viewModel.clearMaterial() #self.viewModel.setMaterial(CIGlobals.getCharacterMaterial(specular = (0, 0, 0, 1)), 1) self.viewportLens = PerspectiveLens() self.viewportLens.setMinFov(self.ViewModelFOV / (4. / 3.)) self.viewportLens.setNear(0.3) # Updates to the transform of base.camera self.viewportCam = base.makeCamera(base.win, clearDepth=True, camName='fpsViewport', mask=CIGlobals.ViewModelCamMask, lens=self.viewportLens) # Pretend to be the main camera so the viewmodel gets ambient probes updated self.viewportCam.node().setTag("__mainpass__", "1") self.viewportCam.reparentTo(self.vmRoot) self.vmGag = None self.vmAnimTrack = None self.dmgFade = OnscreenImage(image="phase_14/maps/damage_effect.png", parent=render2d) self.dmgFade.setBin('gui-popup', 100) self.dmgFade.setTransparency(1) self.dmgFade.setColorScale(1, 1, 1, 0) self.dmgFadeIval = None #self.accept('v', self.vmRender.ls) #base.bspLoader.addDynamicNode(self.vmRoot) if self.PrintAnimLengths: print "v_toon_arms animation lengths:" for anim in self.viewModel.getAnimNames(): print "\t{0}\t:\t{1}".format(anim, self.viewModel.getDuration(anim)) taskMgr.add(self.__vpDebugTask, "vpdebutask", sort=-100) def setViewModelFOV(self, fov): self.idealFov = fov def restoreViewModelFOV(self): self.idealFov = self.ViewModelFOV def swapViewModel(self, newViewModel, fov=70.0): if newViewModel.isEmpty(): return isHidden = False if not self.viewModel.isEmpty(): self.viewModel.reparentTo(hidden) isHidden = self.viewModel.isHidden() self.viewModel = newViewModel self.viewModel.reparentTo(self.vmRoot2) if isHidden: self.viewModel.hide() else: self.viewModel.show() self.setViewModelFOV(fov) def restoreViewModel(self): isHidden = False if not self.viewModel.isEmpty(): self.viewModel.reparentTo(hidden) isHidden = self.viewModel.isHidden() self.viewModel = self.defaultViewModel self.viewModel.reparentTo(self.vmRoot2) if isHidden: self.viewModel.hide() else: self.viewModel.show() self.restoreViewModelFOV() def addViewPunch(self, punch): self.punchAngleVel += punch * 20 def resetViewPunch(self, tolerance=0.0): if tolerance != 0.0: tolerance *= tolerance check = self.punchAngleVel.lengthSquared( ) + self.punchAngle.lengthSquared() if check > tolerance: return self.punchAngle = Vec3(0) self.punchAngleVel = Vec3(0) def decayPunchAngle(self): if self.punchAngle.lengthSquared( ) > 0.001 or self.punchAngleVel.lengthSquared() > 0.001: dt = globalClock.getDt() self.punchAngle += self.punchAngleVel * dt damping = 1 - (self.PunchDamping * dt) if damping < 0: damping = 0 self.punchAngleVel *= damping # Torsional spring springForceMag = self.PunchSpring * dt springForceMag = CIGlobals.clamp(springForceMag, 0.0, 2.0) self.punchAngleVel -= self.punchAngle * springForceMag # Don't wrap around self.punchAngle.set(CIGlobals.clamp(self.punchAngle[0], -179, 179), CIGlobals.clamp(self.punchAngle[1], -89, 89), CIGlobals.clamp(self.punchAngle[2], -89, 89)) else: self.punchAngle = Vec3(0) self.punchAngleVel = Vec3(0) def hideViewModel(self): self.viewModel.hide(BitMask32.allOn()) def showViewModel(self): if not base.localAvatar.isFirstPerson(): return self.viewModel.showThrough(CIGlobals.ViewModelCamMask) def __vpDebugTask(self, task): if self.vmRender.getState() != render.getState(): # pretend like the view model is part of the main scene self.vmRender.setState(render.getState()) self.viewportLens.setAspectRatio(base.getAspectRatio()) self.viewportLens.setMinFov(self.idealFov / (4. / 3.)) self.vmRoot.setTransform(render, self.camRoot.getTransform(render)) self.viewportCam.setTransform(render, base.camera.getTransform(render)) # Since the viewmodel is not underneath BSPRender, it's not going to be automatically # influenced by the ambient probes. We need to do this explicitly. #base.bspLoader.updateDynamicNode(self.vmRoot) #self.viewportDebug.setImage(self.viewportCam.node().getDisplayRegion(0).getScreenshot()) return task.cont def handleSuitAttack(self, attack): print "FPSCamera handleSuitAttack:", attack def doDamageFade(self, r, g, b, severity=1.0): if self.dmgFadeIval: self.dmgFadeIval.finish() self.dmgFadeIval = None severity = min(1.0, severity) self.dmgFadeIval = Sequence( LerpColorScaleInterval(self.dmgFade, 0.25, (r, g, b, severity), (r, g, b, 0), blendType='easeOut'), Wait(1.0), LerpColorScaleInterval(self.dmgFade, 2.0, (r, g, b, 0), (r, g, b, severity), blendType='easeInOut')) self.dmgFadeIval.start() def setVMAnimTrack(self, track, loop=False): self.clearVMAnimTrack() self.vmAnimTrack = track if loop: self.vmAnimTrack.loop() else: self.vmAnimTrack.start() def clearVMAnimTrack(self): if self.vmAnimTrack: self.vmAnimTrack.pause() self.vmAnimTrack = None def setVMGag(self, gag, pos=(0, 0, 0), hpr=(0, 0, 0), scale=(1, 1, 1), hand=0, animate=True): self.clearVMGag() handNode = NodePath() if hand == ATTACK_HOLD_RIGHT: handNode = self.getViewModelRightHand() elif hand == ATTACK_HOLD_LEFT: handNode = self.getViewModelLeftHand() if isinstance(gag, Actor) and animate: self.vmGag = Actor(other=gag) self.vmGag.reparentTo(handNode) self.vmGag.loop('chan') else: self.vmGag = gag.copyTo(handNode) self.vmGag.setPos(pos) self.vmGag.setHpr(hpr) self.vmGag.setScale(scale) def clearVMGag(self): if self.vmGag: if isinstance(self.vmGag, Actor): self.vmGag.cleanup() self.vmGag.removeNode() self.vmGag = None def setup(self): try: # Match the arm color with the torso color of local avatar self.viewModel.find("**/arms").setColorScale( base.localAvatar.getTorsoColor(), 1) # Same with glove cover self.viewModel.find("**/hands").setColorScale( base.localAvatar.getGloveColor(), 1) except: pass self.attachCamera() def attachCamera(self, reset=True): if reset: self.camRoot.reparentTo(base.localAvatar) if base.localAvatar.isFirstPerson(): self.camRoot.setPos(base.localAvatar.getEyePoint()) else: self.camRoot.setPos(0, 0, max(base.localAvatar.getHeight(), 3.0)) self.camRoot.setHpr(0, 0, 0) self.camRoot2.setPosHpr(0, 0, 0, 0, 0, 0) base.camera.reparentTo(self.camRoot2) if base.localAvatar.isFirstPerson(): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) elif base.localAvatar.isThirdPerson(): pos, lookAt = self.getThirdPersonBattleCam() base.localAvatar.smartCamera.setIdealCameraPos(pos) base.localAvatar.smartCamera.setLookAtPoint(lookAt) def getThirdPersonBattleCam(self): camHeight = max(base.localAvatar.getHeight(), 3.0) heightScaleFactor = camHeight * 0.3333333333 return ((1, -5 * heightScaleFactor, 0), (1, 10, 0)) def getViewModelLeftHand(self): return self.viewModel.find("**/def_left_hold") def getViewModelRightHand(self): return self.viewModel.find("**/def_right_hold") def getViewModel(self): return self.viewModel def acceptEngageKeys(self): self.acceptOnce("escape", self.__handleEscapeKey) def ignoreEngageKeys(self): self.ignore("escape") def enableMouseMovement(self): props = WindowProperties() props.setMouseMode(WindowProperties.MConfined) props.setCursorHidden(True) base.win.requestProperties(props) self.attachCamera(False) if base.localAvatar.isFirstPerson(): base.localAvatar.getGeomNode().hide() base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2) base.taskMgr.add(self.__updateTask, "mouseUpdateFPSCamera", sort=-40) self.acceptEngageKeys() self.mouseEnabled = True base.localAvatar.enableGagKeys() def disableMouseMovement(self, allowEnable=False, showAvatar=True): props = WindowProperties() props.setMouseMode(WindowProperties.MAbsolute) props.setCursorHidden(False) base.win.requestProperties(props) base.taskMgr.remove("mouseUpdateFPSCamera") base.localAvatar.disableGagKeys() if allowEnable: self.acceptEngageKeys() else: self.ignoreEngageKeys() if showAvatar or base.localAvatar.isThirdPerson(): base.localAvatar.getGeomNode().show() else: base.localAvatar.getGeomNode().hide() self.mouseEnabled = False def __handleEscapeKey(self): if self.mouseEnabled: self.disableMouseMovement(True) else: self.enableMouseMovement() #def doCameraJolt(self, amplitude, horizRange = [-1, 1], vertRange = [1]): #h = random.choice(horizRange) * amplitude #p = random.choice(vertRange) * amplitude #nquat = Quat(Quat.identQuat()) #nquat.setHpr((h, p, 0)) #self.lastCamRoot2Quat = self.lastCamRoot2Quat + nquat #Effects.createPBounce(self.camRoot2, 3, self.camRoot2.getHpr(), 1, amplitude).start() #Effects.createHBounce(self.camRoot2, 3, self.camRoot2.getHpr(), 1, amplitude).start() def handleJumpHardLand(self): down = Parallel( LerpPosInterval(base.cam, 0.1, (-0.1, 0, -0.2), (0, 0, 0), blendType='easeOut'), LerpHprInterval(base.cam, 0.1, (0, 0, -2.5), (0, 0, 0), blendType='easeOut')) up = Parallel( LerpPosInterval(base.cam, 0.7, (0, 0, 0), (-0.1, 0, -0.2), blendType='easeInOut'), LerpHprInterval(base.cam, 0.7, (0, 0, 0), (0, 0, -2.5), blendType='easeInOut')) Sequence(down, up).start() def __updateTask(self, task): # TODO -- This function does a lot of math, I measured it to take .5 ms on my laptop # That's a lot of time for something miniscule like sway and bob. dt = globalClock.getDt() time = globalClock.getFrameTime() if base.localAvatar.isFirstPerson(): eyePoint = base.localAvatar.getEyePoint() if base.localAvatar.walkControls.crouching: eyePoint[2] = eyePoint[2] / 2.0 eyePoint[2] = CIGlobals.lerpWithRatio(eyePoint[2], self.lastEyeHeight, 0.4) self.lastEyeHeight = eyePoint[2] camRootAngles = Vec3(0) # Mouse look around mw = base.mouseWatcherNode if mw.hasMouse(): md = base.win.getPointer(0) center = Point2(base.win.getXSize() / 2, base.win.getYSize() / 2) xDist = md.getX() - center.getX() yDist = md.getY() - center.getY() sens = self.__getMouseSensitivity() angular = -(xDist * sens) / dt base.localAvatar.walkControls.controller.setAngularMovement( angular) camRootAngles.setY(self.lastPitch - yDist * sens) if camRootAngles.getY() > FPSCamera.MaxP: camRootAngles.setY(FPSCamera.MaxP) yDist = 0 elif camRootAngles.getY() < FPSCamera.MinP: yDist = 0 camRootAngles.setY(FPSCamera.MinP) base.win.movePointer(0, int(center.getX()), int(center.getY())) if base.localAvatar.isFirstPerson(): # Camera / viewmodel bobbing vmBob = Point3(0) vmAngles = Vec3(0) vmRaise = Point3(0) camBob = Point3(0) maxSpeed = base.localAvatar.walkControls.BattleRunSpeed * 16.0 speed = base.localAvatar.walkControls.speeds.length() * 16.0 speed = max(-maxSpeed, min(maxSpeed, speed)) bobOffset = CIGlobals.remapVal(speed, 0, maxSpeed, 0.0, 1.0) self.bobTime += (time - self.lastBobTime) * bobOffset self.lastBobTime = time # Calculate the vertical bob cycle = self.bobTime - int( self.bobTime / self.BobCycleMax) * self.BobCycleMax cycle /= self.BobCycleMax if cycle < self.BobUp: cycle = math.pi * cycle / self.BobUp else: cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 - self.BobUp) verticalBob = speed * 0.005 verticalBob = verticalBob * 0.3 + verticalBob * 0.7 * math.sin( cycle) verticalBob = max(-7.0, min(4.0, verticalBob)) verticalBob /= 16.0 # Calculate the lateral bob cycle = self.bobTime - int( self.bobTime / self.BobCycleMax * 2) * self.BobCycleMax * 2 cycle /= self.BobCycleMax * 2 if cycle < self.BobUp: cycle = math.pi * cycle / self.BobUp else: cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 - self.BobUp) lateralBob = speed * 0.005 lateralBob = lateralBob * 0.3 + lateralBob * 0.7 * math.sin(cycle) lateralBob = max(-7.0, min(4.0, lateralBob)) lateralBob /= 16.0 # Apply bob, but scaled down a bit vmBob.set(lateralBob * 0.8, 0, verticalBob * 0.1) # Z bob a bit more vmBob[2] += verticalBob * 0.1 # Bob the angles vmAngles[2] += verticalBob * 0.5 vmAngles[1] -= verticalBob * 0.4 vmAngles[0] -= lateralBob * 0.3 # ================================================================ # Viewmodel lag/sway angles = self.camRoot.getHpr(render) quat = Quat() quat.setHpr(angles) invQuat = Quat() invQuat.invertFrom(quat) maxVMLag = 1.5 lagforward = quat.getForward() if dt != 0.0: lagdifference = lagforward - self.lastFacing lagspeed = 5.0 lagdiff = lagdifference.length() if (lagdiff > maxVMLag) and (maxVMLag > 0.0): lagscale = lagdiff / maxVMLag lagspeed *= lagscale self.lastFacing = CIGlobals.extrude(self.lastFacing, lagspeed * dt, lagdifference) self.lastFacing.normalize() lfLocal = invQuat.xform(lagdifference) vmBob = CIGlobals.extrude(vmBob, 5.0 / 16.0, lfLocal * -1.0) pitch = angles[1] if pitch > 180: pitch -= 360 elif pitch < -180: pitch += 360 vmBob = CIGlobals.extrude(vmBob, pitch * (0.035 / 16), Vec3.forward()) vmBob = CIGlobals.extrude(vmBob, pitch * (0.03 / 16), Vec3.right()) vmBob = CIGlobals.extrude(vmBob, pitch * (0.02 / 16), Vec3.up()) # ================================================================ vmRaise.set( 0, 0, 0 ) #(0, abs(camRootAngles.getY()) * -0.002, camRootAngles.getY() * 0.002) camBob.set(0, 0, 0) # Apply bob, raise, and sway to the viewmodel. self.viewModel.setPos(vmBob + vmRaise + self.lastVMPos) self.vmRoot2.setHpr(vmAngles) self.camRoot.setPos(eyePoint + camBob) newPitch = camRootAngles.getY() if abs(newPitch - self.lastPitch) > self.PitchUpdateEpsilon: # Broadcast where our head is looking head = base.localAvatar.getPart("head") if head and not head.isEmpty(): # Constrain the head pitch a little bit so it doesn't look like their head snapped headPitch = max(-47, newPitch) headPitch = min(75, headPitch) base.localAvatar.b_setLookPitch(headPitch) self.lastPitch = newPitch if base.localAvatar.isFirstPerson(): # Apply punch angle self.decayPunchAngle() camRootAngles += self.punchAngle self.camRoot.setHpr(camRootAngles) return task.cont def __getMouseSensitivity(self): return CIGlobals.getSettingsMgr().getSetting('fpmgms').getValue() def cleanup(self): taskMgr.remove("vpdebutask") self.disableMouseMovement(False, False) self.clearVMAnimTrack() self.clearVMGag() if self.viewModel: self.viewModel.cleanup() self.viewModel.removeNode() self.viewModel = None if self.vmRender: self.vmRender.removeNode() self.vmRender = None self.vmRoot = None self.vmRoot2 = None self.viewportLens = None if self.viewportCam: self.viewportCam.removeNode() self.viewportCam = None if self.camRoot: self.camRoot.removeNode() self.camRoot = None self.camRoot2 = None self.lastEyeHeight = None self.lastPitch = None self.bobTime = None self.lastBobTime = None self.mouseEnabled = None self.lastCamRoot2Quat = None self.punchAngleVel = None self.punchAngle = None self.lastFacing = None self.lastMousePos = None self.currMousePos = None self.lastVMPos = None self.defaultViewModel = None self.idealFov = None self.vmGag = None self.vmAnimTrack = None self.dmgFade = None self.dmgFadeIval = None self.ignoreAll()
def add_shadders(self: ShowBase): normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 0.5)) self.normalsBuffer = normalsBuffer normalsCamera = self.makeCamera(normalsBuffer, lens=self.cam.node().getLens()) normalsCamera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node")) normalGen = self.loader.loadShader("app/view/shaders/normalGen.sha") tempnode.setShader(normalGen) tempnode.setShaderInput("showborders", LVecBase4(1)) normalsCamera.node().setInitialState(tempnode.getState()) depth_buffer = self.win.makeTextureBuffer("depthBuffer", 0, 0) depth_buffer.setClearColor(LVecBase4(0, 0, 0, 0)) self.depth_buffer = depth_buffer depth_camera = self.makeCamera(depth_buffer, lens=self.cam.node().getLens()) depth_camera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node depth")) depth_gen = self.loader.loadShader("app/view/shaders/depthGen.sha") tempnode.setShader(depth_gen) depth_camera.node().setInitialState(tempnode.getState()) colors_buffer = self.win.makeTextureBuffer("colorsBuffer", 0, 0) colors_buffer.setClearColor(LVecBase4(0, 0, 0, 0)) self.colors_buffer = colors_buffer colorsCamera = self.makeCamera(colors_buffer, lens=self.cam.node().getLens()) colorsCamera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node colors")) colorGen = self.loader.loadShader("app/view/shaders/colorGen.sha") tempnode.setShader(colorGen) tempnode.setShaderInput("showborders", LVecBase4(1)) tempnode.setShaderInput("colorborders", LVecBase4(0, 0, 0, 1)) colorsCamera.node().setInitialState(tempnode.getState()) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() colorBorderTex = colors_buffer.getTextureCard() depthTex = depth_buffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 1) drawnScene.reparentTo(render2d) self.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. self.separation = 0.0005 self.separation = 1 self.cutoff = 0.3 inkGen = loader.loadShader("app/view/shaders/inkGen.sha") stage_border = TextureStage("border") stage_border.setSort(1) drawnScene.setTexture(stage_border, colorBorderTex.getTexture()) stage_depth = TextureStage("depth") stage_depth.setSort(2) drawnScene.setTexture(stage_depth, depthTex.getTexture()) drawnScene.setShader(inkGen) drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("screen", 1280, 720) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) print("SHADER DEBUG") print(drawnScene.findAllTextureStages())
def generateWater(self, style): print "Generate Water:", self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax '''Generates water style 0: blue card style 1: reflective card style 2: reflective card with shaders ''' self.waterHeight = 22.0 if self.water: self.water.removeNode() if style is 0: cm = CardMaker("water") #cm.setFrame(-1, 1, -1, 1) cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax) cm.setColor(0, 0, 1, 0.9) self.water = render.attachNewNode(cm.generate()) if self.waterYMax > self.waterXMax: size = self.waterYMax else: size = self.waterXMax self.water.lookAt(0, 0, -1) self.water.setZ(self.waterHeight) messenger.send('makePickable', [self.water]) elif style is 1: # From Prosoft's super awesome terrain demo cm = CardMaker("water") #cm.setFrame(-1, 1, -1, 1) cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax) self.water = render.attachNewNode(cm.generate()) if self.waterYMax > self.waterXMax: size = self.waterYMax else: size = self.waterXMax #self.water.setScale(size) self.water.lookAt(0, 0, -1) self.water.setZ(self.waterHeight) self.water.setShaderOff(1) self.water.setLightOff(1) self.water.setAlphaScale(0.5) self.water.setTransparency(TransparencyAttrib.MAlpha) wbuffer = base.win.makeTextureBuffer("water", 512, 512) wbuffer.setClearColorActive(True) wbuffer.setClearColor(base.win.getClearColor()) self.wcamera = base.makeCamera(wbuffer) self.wcamera.reparentTo(render) self.wcamera.node().setLens(base.camLens) self.wcamera.node().setCameraMask(BitMask32.bit(1)) self.water.hide(BitMask32.bit(1)) wtexture = wbuffer.getTexture() wtexture.setWrapU(Texture.WMClamp) wtexture.setWrapV(Texture.WMClamp) wtexture.setMinfilter(Texture.FTLinearMipmapLinear) self.wplane = Plane(Vec3(0, 0, 1), Point3(0, 0, self.water.getZ())) wplanenp = render.attachNewNode(PlaneNode("water", self.wplane)) tmpnp = NodePath("StateInitializer") tmpnp.setClipPlane(wplanenp) tmpnp.setAttrib(CullFaceAttrib.makeReverse()) self.wcamera.node().setInitialState(tmpnp.getState()) self.water.projectTexture(TextureStage("reflection"), wtexture, self.wcamera) messenger.send('makePickable', [self.water]) elif style is 2: # From Clcheung just as super awesome demomaster self.water_level = Vec4(0.0, 0.0, self.waterHeight, 1.0) self.water = water.WaterNode(self.waterXMin, self.waterYMin, self.waterXMax, self.waterYMax, self.water_level.getZ()) self.water.setStandardControl() self.water.changeParams(None) wl=self.water_level wl.setZ(wl.getZ()-0.05) #root.setShaderInput('waterlevel', self.water_level) render.setShaderInput('time', 0) messenger.send('makePickable', [self.water.waterNP])
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) base.disableMouse() base.setBackgroundColor(0, 0, 0) camera.setPos(0, -50, 0) # Check video card capabilities. if not base.win.getGsg().getSupportsBasicShaders(): addTitle( "Glow Filter: Video driver reports that Cg shaders are not supported.") return # Post the instructions self.title = addTitle("Panda3D: Tutorial - Glow Filter") self.inst1 = addInstructions(0.06, "ESC: Quit") self.inst2 = addInstructions(0.12, "Space: Toggle Glow Filter On/Off") self.inst3 = addInstructions(0.18, "Enter: Toggle Running/Spinning") self.inst4 = addInstructions(0.24, "V: View the render-to-texture results") # Create the shader that will determime what parts of the scene will # glow glowShader = loader.loadShader("shaders/glowShader.sha") # load our model self.tron = Actor() self.tron.loadModel("models/tron") self.tron.loadAnims({"running": "models/tron_anim"}) self.tron.reparentTo(render) self.interval = self.tron.hprInterval(60, LPoint3(360, 0, 0)) self.interval.loop() self.isRunning = False # put some lighting on the tron model dlight = DirectionalLight('dlight') alight = AmbientLight('alight') dlnp = render.attachNewNode(dlight) alnp = render.attachNewNode(alight) dlight.setColor(LVector4(1.0, 0.7, 0.2, 1)) alight.setColor(LVector4(0.2, 0.2, 0.2, 1)) dlnp.setHpr(0, -60, 0) render.setLight(dlnp) render.setLight(alnp) # create the glow buffer. This buffer renders like a normal scene, # except that only the glowing materials should show up nonblack. glowBuffer = base.win.makeTextureBuffer("Glow scene", 512, 512) glowBuffer.setSort(-3) glowBuffer.setClearColor(LVector4(0, 0, 0, 1)) # We have to attach a camera to the glow buffer. The glow camera # must have the same frustum as the main camera. As long as the aspect # ratios match, the rest will take care of itself. glowCamera = base.makeCamera( glowBuffer, lens=base.cam.node().getLens()) # Tell the glow camera to use the glow shader tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(glowShader) glowCamera.node().setInitialState(tempnode.getState()) # set up the pipeline: from glow scene to blur x to blur y to main # window. blurXBuffer = makeFilterBuffer( glowBuffer, "Blur X", -2, "shaders/XBlurShader.sha") blurYBuffer = makeFilterBuffer( blurXBuffer, "Blur Y", -1, "shaders/YBlurShader.sha") self.finalcard = blurYBuffer.getTextureCard() self.finalcard.reparentTo(render2d) # This attribute is used to add the results of the post-processing # effects to the existing framebuffer image, rather than replace it. # This is mainly useful for glow effects like ours. self.finalcard.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd)) # 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", base.bufferViewer.toggleEnable) self.accept("V", base.bufferViewer.toggleEnable) base.bufferViewer.setPosition("llcorner") base.bufferViewer.setLayout("hline") base.bufferViewer.setCardSize(0.652, 0) # event handling self.accept("space", self.toggleGlow) self.accept("enter", self.toggleDisplay) self.accept("escape", sys.exit, [0]) self.glowOn = True
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) self.disableMouse() self.cam.node().getLens().setNear(10.0) self.cam.node().getLens().setFar(200.0) camera.setPos(0, -50, 0) # Check video card capabilities. if not self.win.getGsg().getSupportsBasicShaders(): addTitle("Toon Shader: Video driver reports that Cg shaders are not supported.") return # Enable a 'light ramp' - this discretizes the lighting, # which is half of what makes a model look like a cartoon. # Light ramps only work if shader generation is enabled, # so we call 'setShaderAuto'. tempnode = NodePath(PandaNode("temp node")) tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4)) tempnode.setShaderAuto() self.cam.node().setInitialState(tempnode.getState()) # Use class 'CommonFilters' to enable a cartoon inking filter. # This can fail if the video card is not powerful enough, if so, # display an error and exit. self.separation = 1 # Pixels self.filters = CommonFilters(self.win, self.cam) filterok = self.filters.setCartoonInk(separation=self.separation) if (filterok == False): addTitle( "Toon Shader: Video card not powerful enough to do image postprocessing") return # Show instructions in the corner of the window. self.title = addTitle( "Panda3D: Tutorial - Toon Shading with Normals-Based Inking") self.inst1 = addInstructions(0.06, "ESC: Quit") self.inst2 = addInstructions(0.12, "Up/Down: Increase/Decrease Line Thickness") self.inst3 = addInstructions(0.18, "V: View the render-to-texture results") # Load a dragon model and animate it. self.character = Actor() self.character.loadModel('models/nik-dragon') self.character.reparentTo(render) self.character.loadAnims({'win': 'models/nik-dragon'}) self.character.loop('win') self.character.hprInterval(15, (360, 0, 0)).loop() # Create a non-attenuating point light and an ambient light. plightnode = PointLight("point light") plightnode.setAttenuation((1, 0, 0)) plight = render.attachNewNode(plightnode) plight.setPos(30, -50, 0) alightnode = AmbientLight("ambient light") alightnode.setColor((0.8, 0.8, 0.8, 1)) alight = render.attachNewNode(alightnode) render.setLight(alight) render.setLight(plight) # Panda contains a built-in viewer that lets you view the # results of all render-to-texture operations. This lets you # see what class CommonFilters is doing behind the scenes. self.accept("v", self.bufferViewer.toggleEnable) self.accept("V", self.bufferViewer.toggleEnable) self.bufferViewer.setPosition("llcorner") self.accept("s", self.filters.manager.resizeBuffers) # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.increaseSeparation) self.accept("arrow_down", self.decreaseSeparation)
def generateWater(self, style): print "Generate Water:", self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax '''Generates water style 0: blue card style 1: reflective card style 2: reflective card with shaders ''' self.waterHeight = 22.0 if self.water: self.water.removeNode() if style is 0: cm = CardMaker("water") #cm.setFrame(-1, 1, -1, 1) cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax) cm.setColor(0, 0, 1, 0.9) self.water = render.attachNewNode(cm.generate()) if self.waterYMax > self.waterXMax: size = self.waterYMax else: size = self.waterXMax self.water.lookAt(0, 0, -1) self.water.setZ(self.waterHeight) messenger.send('makePickable', [self.water]) elif style is 1: # From Prosoft's super awesome terrain demo cm = CardMaker("water") #cm.setFrame(-1, 1, -1, 1) cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax) self.water = render.attachNewNode(cm.generate()) if self.waterYMax > self.waterXMax: size = self.waterYMax else: size = self.waterXMax #self.water.setScale(size) self.water.lookAt(0, 0, -1) self.water.setZ(self.waterHeight) self.water.setShaderOff(1) self.water.setLightOff(1) self.water.setAlphaScale(0.5) self.water.setTransparency(TransparencyAttrib.MAlpha) wbuffer = base.win.makeTextureBuffer("water", 512, 512) wbuffer.setClearColorActive(True) wbuffer.setClearColor(base.win.getClearColor()) self.wcamera = base.makeCamera(wbuffer) self.wcamera.reparentTo(render) self.wcamera.node().setLens(base.camLens) self.wcamera.node().setCameraMask(BitMask32.bit(1)) self.water.hide(BitMask32.bit(1)) wtexture = wbuffer.getTexture() wtexture.setWrapU(Texture.WMClamp) wtexture.setWrapV(Texture.WMClamp) wtexture.setMinfilter(Texture.FTLinearMipmapLinear) self.wplane = Plane(Vec3(0, 0, 1), Point3(0, 0, self.water.getZ())) wplanenp = render.attachNewNode(PlaneNode("water", self.wplane)) tmpnp = NodePath("StateInitializer") tmpnp.setClipPlane(wplanenp) tmpnp.setAttrib(CullFaceAttrib.makeReverse()) self.wcamera.node().setInitialState(tmpnp.getState()) self.water.projectTexture(TextureStage("reflection"), wtexture, self.wcamera) messenger.send('makePickable', [self.water]) elif style is 2: # From Clcheung just as super awesome demomaster self.water_level = Vec4(0.0, 0.0, self.waterHeight, 1.0) self.water = water.WaterNode(self.waterXMin, self.waterYMin, self.waterXMax, self.waterYMax, self.water_level.getZ()) self.water.setStandardControl() self.water.changeParams(None) wl = self.water_level wl.setZ(wl.getZ() - 0.05) #root.setShaderInput('waterlevel', self.water_level) render.setShaderInput('time', 0) messenger.send('makePickable', [self.water.waterNP])
def prepareSceneRender(self): """ Renders the scene of the source camera to the buffer. See the documentation of this class for further information """ self.debug("Preparing scene render") # Init buffer object self._createBuffer() # Prepare fullscreen quad self._quad = self._makeFullscreenQuad() # Prepare initial state cs = NodePath("InitialStateDummy") cs.setState(self._sourceCam.node().getInitialState()) if self.hasTarget(RenderTargetType.Aux0): cs.setAttrib(AuxBitplaneAttrib.make(self._auxBits), 20) cs.setAttrib(StencilAttrib.makeOff(), 20) if not self._enableTransparency: cs.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MNone), 100) if not self._writeColor: cs.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 100) self._sourceCam.node().setInitialState(cs.getState()) # Set new camera bufferCam = self._makeFullscreenCam() bufferCamNode = self._quad.attachNewNode(bufferCam) self._region.setCamera(bufferCamNode) self._region.setSort(5) # Set clears bufferRegion = self._buffer.getInternalBuffer().getDisplayRegion(0) self._correctClears() bufferRegion.setClearStencilActive(False) # self._sourceWindow.setClearStencilActive(False) # Set aux clears targetCheck = [ (RenderTargetType.Aux0, GraphicsOutput.RTPAuxRgba0), (RenderTargetType.Aux1, GraphicsOutput.RTPAuxRgba1), (RenderTargetType.Aux2, GraphicsOutput.RTPAuxRgba2), (RenderTargetType.Aux3, GraphicsOutput.RTPAuxRgba3), ] for target, targetBindPos in targetCheck: if self.hasTarget(target): bufferRegion.setClearActive(targetBindPos, 1) bufferRegion.setClearValue( targetBindPos, Vec4(0.5, 0.5, 1.0, 0.0)) self._region.disableClears() bufferRegion.setCamera(self._sourceCam) bufferRegion.setActive(1) # bufferRegion.setClearDepthActive(False) bufferRegion.setSort(20) self._setSizeShaderInput()
def __init__(self): # Player Model setup self.player = Actor("Player", {"Run":"Player-Run", "Sidestep":"Player-Sidestep", "Idle":"Player-Idle"}) self.player.setBlend(frameBlend = True) self.player.setPos(0, 0, 0) self.player.pose("Idle", 0) self.player.reparentTo(render) self.player.hide() self.footstep = base.audio3d.loadSfx('footstep.ogg') self.footstep.setLoop(True) base.audio3d.attachSoundToObject(self.footstep, self.player) # Create a brush to paint on the texture splat = PNMImage("../data/Splat.png") self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1) CamMask = BitMask32.bit(0) AvBufMask = BitMask32.bit(1) self.avbuf = None if base.win: self.avbufTex = Texture('avbuf') self.avbuf = base.win.makeTextureBuffer('avbuf', 256, 256, self.avbufTex, True) cam = Camera('avbuf') cam.setLens(base.camNode.getLens()) self.avbufCam = base.cam.attachNewNode(cam) dr = self.avbuf.makeDisplayRegion() dr.setCamera(self.avbufCam) self.avbuf.setActive(False) self.avbuf.setClearColor((1, 0, 0, 1)) cam.setCameraMask(AvBufMask) base.camNode.setCameraMask(CamMask) # avbuf renders everything it sees with the gradient texture. tex = loader.loadTexture('gradient.png') np = NodePath('np') np.setTexture(tex, 100) np.setColor((1, 1, 1, 1), 100) np.setColorScaleOff(100) np.setTransparency(TransparencyAttrib.MNone, 100) np.setLightOff(100) cam.setInitialState(np.getState()) #render.hide(AvBufMask) # Setup a texture stage to paint on the player self.paintTs = TextureStage('paintTs') self.paintTs.setMode(TextureStage.MDecal) self.paintTs.setSort(10) self.paintTs.setPriority(10) self.tex = Texture('paint_av_%s'%id(self)) # Setup a PNMImage that will hold the paintable texture of the player self.imageSizeX = 64 self.imageSizeY = 64 self.p = PNMImage(self.imageSizeX, self.imageSizeY, 4) self.p.fill(1) self.p.alphaFill(0) self.tex.load(self.p) self.tex.setWrapU(self.tex.WMClamp) self.tex.setWrapV(self.tex.WMClamp) # Apply the paintable texture to the avatar self.player.setTexture(self.paintTs, self.tex) # team self.playerTeam = "" # A lable that will display the players team self.lblTeam = DirectLabel( scale = 1, pos = (0, 0, 3), frameColor = (0, 0, 0, 0), text = "TEAM", text_align = TextNode.ACenter, text_fg = (0,0,0,1)) self.lblTeam.reparentTo(self.player) self.lblTeam.setBillboardPointEye() # basic player values self.maxHits = 3 self.currentHits = 0 self.isOut = False self.TorsorControl = self.player.controlJoint(None,"modelRoot","Torsor") # setup the collision detection # wall and object collision self.playerSphere = CollisionSphere(0, 0, 1, 1) self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision%d"%id(self))) self.playerCollision.node().addSolid(self.playerSphere) base.pusher.addCollider(self.playerCollision, self.player) base.cTrav.addCollider(self.playerCollision, base.pusher) # foot (walk) collision self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision%d"%id(self))) self.playerFootRay.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1)) self.playerFootRay.node().setIntoCollideMask(0) self.lifter = CollisionHandlerFloor() self.lifter.addCollider(self.playerFootRay, self.player) base.cTrav.addCollider(self.playerFootRay, self.lifter) # Player weapon setup self.gunAttach = self.player.exposeJoint(None, "modelRoot", "WeaponSlot_R") self.color = LPoint3f(1, 1, 1) self.gun = Gun(id(self)) self.gun.reparentTo(self.gunAttach) self.gun.hide() self.gun.setColor(self.color) self.hud = None # Player controls setup self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} # screen sizes self.winXhalf = base.win.getXSize() / 2 self.winYhalf = base.win.getYSize() / 2 self.mouseSpeedX = 0.1 self.mouseSpeedY = 0.1 # AI controllable variables self.AIP = 0.0 self.AIH = 0.0 self.movespeed = 5.0 self.userControlled = False self.accept("Bulet-hit-playerCollision%d" % id(self), self.hit) self.accept("window-event", self.recalcAspectRatio)
def prepareSceneRender(self, earlyZ=False, earlyZCam=None): """ Renders the scene of the source camera to the buffer. See the documentation of this class for further information """ self.debug("Preparing scene render") # Init buffer object self._createBuffer() # Prepare initial state cs = NodePath("InitialStateDummy") cs.setState(self._sourceCam.node().getInitialState()) if self.hasTarget(RenderTargetType.Aux0): cs.setAttrib(AuxBitplaneAttrib.make(self._auxBits), 20) cs.setAttrib(StencilAttrib.makeOff(), 20) if not self._enableTransparency: cs.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MNone), 100) if not self._writeColor: cs.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 100) self._sourceCam.node().setInitialState(cs.getState()) if earlyZ: self._earlyZRegion = self._internalBuffer.makeDisplayRegion() self._earlyZRegion.setSort(-10) self._earlyZRegion.setCamera(earlyZCam) self._node = NodePath("RTRoot") # Prepare fullscreen quad if self._createOverlayQuad: self._quad = self._makeFullscreenQuad() self._quad.reparentTo(self._node) bufferCam = self._makeFullscreenCam() self._camera = self._node.attachNewNode(bufferCam) self._region.setCamera(self._camera) self._region.setSort(5) # Set clears bufferRegion = self._internalBuffer.getDisplayRegion(0) self._correctClears() bufferRegion.setClearStencilActive(False) # self._sourceWindow.setClearStencilActive(False) # Set aux clears targetCheck = [ (RenderTargetType.Aux0, GraphicsOutput.RTPAuxRgba0), (RenderTargetType.Aux1, GraphicsOutput.RTPAuxRgba1), (RenderTargetType.Aux2, GraphicsOutput.RTPAuxRgba2), (RenderTargetType.Aux3, GraphicsOutput.RTPAuxRgba3), ] for target, targetBindPos in targetCheck: if self.hasTarget(target): bufferRegion.setClearActive(targetBindPos, 1) bufferRegion.setClearValue(targetBindPos, Vec4(0.5, 0.5, 1.0, 0.0)) self._region.disableClears() bufferRegion.setCamera(self._sourceCam) bufferRegion.setActive(1) bufferRegion.setClearDepthActive(False) bufferRegion.setSort(20) if earlyZ: self._earlyZRegion.disableClears() self._earlyZRegion.setClearDepthActive(True) self._earlyZRegion.setActive(1) self._setSizeShaderInput() self._active = True self._registerBuffer()
def shadow(self): # Preliminary capabilities check. if (base.win.getGsg().getSupportsBasicShaders()==0): self.t=addTitle("It appears that shaders are not supported. They willn't work, sorry.") return if (base.win.getGsg().getSupportsDepthTexture()==0): self.t=addTitle("It appears that depth textures are not supported. They willn't work, sorry.") 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) if (LBuffer == None): self.t=addTitle("The 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) base.disableMouse() # Load the scene. 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.flattenStrong() self.LCam=base.makeCamera(LBuffer) # default values 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) render.setShaderInput('push',1,1,1,0) # Put a shader on the Light camera. lci = NodePath(PandaNode("Light Camera Initializer")) lci.setShader(Shader.load('/c/panda/pandacamp/src/shaders/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("Initiating Shadows")) if (base.win.getGsg().getSupportsShadowFilter()): mci.setShader(Shader.load('/c/panda/pandacamp/src/shaders/shadow.sha')) else: mci.setShader(Shader.load('/c/panda/pandacamp/src/shaders/shadow-nosupport.sha')) base.cam.node().setInitialState(mci.getState())
def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None, fbprops=None): """ Causes the scene to be rendered into the supplied textures instead of into the original window. Puts a fullscreen quad into the original window to show the render-to-texture results. Returns the quad. Normally, the caller would then apply a shader to the quad. To elaborate on how this all works: * An offscreen buffer is created. It is set up to mimic the original display region - it is the same size, uses the same clear colors, and contains a DisplayRegion that uses the original camera. * A fullscreen quad and an orthographic camera to render that quad are both created. The original camera is removed from the original window, and in its place, the orthographic quad-camera is installed. * The fullscreen quad is textured with the data from the offscreen buffer. A shader is applied that tints the results pink. * Automatic shader generation NOT enabled. If you have a filter that depends on a render target from the auto-shader, you either need to set an auto-shader attrib on the main camera or scene, or, you need to provide these outputs in your own shader. * All clears are disabled on the original display region. If the display region fills the whole window, then clears are disabled on the original window as well. It is assumed that rendering the full-screen quad eliminates the need to do clears. Hence, the original window which used to contain the actual scene, now contains a pink-tinted quad with a texture of the scene. It is assumed that the user will replace the shader on the quad with a more interesting filter. """ if (textures): colortex = textures.get("color", None) depthtex = textures.get("depth", None) auxtex = textures.get("aux", None) auxtex0 = textures.get("aux0", auxtex) auxtex1 = textures.get("aux1", None) else: auxtex0 = auxtex auxtex1 = None if (colortex == None): colortex = Texture("filter-base-color") colortex.setWrapU(Texture.WMClamp) colortex.setWrapV(Texture.WMClamp) texgroup = (depthtex, colortex, auxtex0, auxtex1) # Choose the size of the offscreen buffer. (winx, winy) = self.getScaledSize(1, 1, 1) if fbprops is not None: buffer = self.createBuffer("filter-base", winx, winy, texgroup, fbprops=fbprops) else: buffer = self.createBuffer("filter-base", winx, winy, texgroup) if (buffer == None): return None cm = CardMaker("filter-base-quad") cm.setFrameFullscreenQuad() quad = NodePath(cm.generate()) quad.setDepthTest(0) quad.setDepthWrite(0) quad.setTexture(colortex) quad.setColor(1, 0.5, 0.5, 1) cs = NodePath("dummy") cs.setState(self.camstate) # Do we really need to turn on the Shader Generator? #cs.setShaderAuto() if (auxbits): cs.setAttrib(AuxBitplaneAttrib.make(auxbits)) self.camera.node().setInitialState(cs.getState()) quadcamnode = Camera("filter-quad-cam") lens = OrthographicLens() lens.setFilmSize(2, 2) lens.setFilmOffset(0, 0) lens.setNearFar(-1000, 1000) quadcamnode.setLens(lens) quadcam = quad.attachNewNode(quadcamnode) self.region.setCamera(quadcam) self.setStackedClears(buffer, self.rclears, self.wclears) if (auxtex0): buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1) buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, (0.5, 0.5, 1.0, 0.0)) if (auxtex1): buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1) self.region.disableClears() if (self.isFullscreen()): self.win.disableClears() dr = buffer.makeDisplayRegion() dr.disableClears() dr.setCamera(self.camera) dr.setActive(1) self.buffers.append(buffer) self.sizes.append((1, 1, 1)) return quad
def __init__(self, sort=-1): """Set a sort value or the two extra display regions created by the CartoonPainter. """ self._enabled = True self._camera_spot_light = False self._paintings = {} self._stepf_min = self.DEFAULT_STEPFUNC_MIN self._stepf_max = self.DEFAULT_STEPFUNC_MAX self._stepf_steps = self.DEFAULT_STEPFUNC_STEPS self._separation = self.DEFAULT_SEPARATION self._cutoff = self.DEFAULT_CUTOFF # Check if the video card supports shaders. If it doesn't then the # CartoonPainter will be disabled. self._shaders_supported = base.win.getGsg().getSupportsBasicShaders() if not self._shaders_supported: self._enabled = False sys.stderr.write("CartoonPainter disabled. Video driver " + "reports that shaders are not supported.") return # Create two new scenes, one 3d and the other 2d. The 3d scene will # have attached all those nodepaths we want to cartoon paint. The # 2d scene will have a card where the black outlines of the cartoon # inking are drawn. self.toon_render = NodePath('toon_render') self.inking_render2d = NodePath('inking_render2d') self.inking_render2d.setDepthTest(False) self.inking_render2d.setDepthWrite(False) # Make a new display region where to render objects in cartoon shading. # toon_render will have a light node used by the shader as input. self._toon_dr = base.win.makeDisplayRegion() self._toon_dr.setSort(sort-1) self._toon_camera = self.toon_render.attachNewNode(Camera('toon_camera')) self._toon_camera.node().setLens(base.cam.node().getLens()) self._toon_dr.setCamera(self._toon_camera) self._light = self.toon_render.attachNewNode('light') self._light.setPos(*self.DEFAULT_LIGHT_POS) self.toon_render.setShaderInput('light', self._light) self.toon_render.setShaderInput('min', Vec4(self._stepf_min)) self.toon_render.setShaderInput('max', Vec4(self._stepf_max)) self.toon_render.setShaderInput('steps', Vec4(self._stepf_steps)) _tmp = NodePath('_tmp') _tmp.setShader(loader.loadShader(self.CARTOON_SHADING_SHADER)) self._toon_camera.node().setTagStateKey(self.CARTOON_SHADING_TAG) self._toon_camera.node().setTagState('True', _tmp.getState()) # Make a 'normals buffer' used later by the cartoon inker to get the # black outlines around all the objects of toon_render. The normals # buffer will contain a picture of the model colorized so that the # color of the model is a representation of the model's normal at that # point. self._normals_buf = base.win.makeTextureBuffer('normals_buf', 0, 0) self._normals_buf.setClearColor(Vec4(0.5, 0.5, 0.5, 1)) self._normals_camera = base.makeCamera(self._normals_buf, camName='normals_camera', lens=base.cam.node().getLens()) self._normals_camera.reparentTo(self.toon_render) _tmp = NodePath('_tmp') _tmp.setShader(loader.loadShader(self.CARTOON_NORMALS_SHADER)) self._normals_camera.node().setInitialState(_tmp.getState()) # Make a new display region for a 2d scene where we are going to draw # a texture card with the black outlines of every objects in # toon_render. self._inking_dr = base.win.makeDisplayRegion() self._inking_dr.setSort(sort) self._inking_camera = self.inking_render2d.attachNewNode(Camera('inking_camera')) self._inking_camera.node().setLens(base.cam2d.node().getLens()) self._inking_dr.setCamera(self._inking_camera) # Extract a texture card from the normal buffer and process it using # the cartoon inker. The final result will be a transparent texture # containing the black outlines for every objects in toon_render. self._ink_outlines = self._normals_buf.getTextureCard() self._ink_outlines.setTransparency(1) self._ink_outlines.setColor(1, 1, 1, 0) self._ink_outlines.reparentTo(self.inking_render2d) self._ink_outlines.setShader(loader.loadShader(self.CARTOON_INKING_SHADER)) self._ink_outlines.setShaderInput("separation", Vec4(self._separation, 0, self._separation, 0)) self._ink_outlines.setShaderInput("cutoff", Vec4(self._cutoff)) # Start a task to update the internal cameras and every nodepath in # toon_render. taskMgr.add(self._update, '%s.update' % self.__class__.__name__)