def drawNametag(self): self.setPriority(MarginGlobals.MP_low) if self.textNodePath is not None: self.textNodePath.removeNode() self.textNodePath = None if self.arrow is not None: self.arrow.removeNode() self.arrow = None if self.font is None: return if self.icon is not None: self.contents.attachNewNode(self.icon) if self.isClickable(): foreground, background = self.nametagColor[self.clickState] else: foreground, background = self.nametagColor[PGButton.SInactive] self.textNode.setTextColor(foreground) self.textNodePath = self.contents.attachNewNode(self.textNode, 1) self.textNodePath.setTransparency(foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) self.textNodePath.setY(self.TEXT_Y_OFFSET) self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0) self.panel.setColor(background) self.panel.setTransparency(background[3] < 1) x = (self.textNode.getLeft() + self.textNode.getRight()) / 2.0 z = (self.textNode.getBottom() + self.textNode.getTop()) / 2.0 self.panel.setPos(x, 0, z) self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING self.panel.setScale(self.panelWidth, 1, self.panelHeight) self.arrow = NametagGlobals.arrowModel.copyTo(self.contents) self.arrow.setZ(self.ARROW_OFFSET + self.textNode.getBottom()) self.arrow.setScale(self.ARROW_SCALE) self.arrow.setColor(self.nametagColor[4])
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 _prepare_early_z(self, early_z=False): """ Prepares the earlyz stage """ if early_z: self._prepass_cam = Camera(Globals.base.camNode) self._prepass_cam.set_tag_state_key("EarlyZShader") self._prepass_cam.set_name("EarlyZCamera") self._prepass_cam_node = Globals.base.camera.attach_new_node( self._prepass_cam) Globals.render.set_tag("EarlyZShader", "Default") else: self._prepass_cam = None # modify default camera initial state initial = Globals.base.camNode.get_initial_state() initial_node = NodePath("IntialState") initial_node.set_state(initial) if early_z: initial_node.set_attrib( DepthWriteAttrib.make(DepthWriteAttrib.M_off)) initial_node.set_attrib( DepthTestAttrib.make(DepthTestAttrib.M_equal)) else: initial_node.set_attrib( DepthTestAttrib.make(DepthTestAttrib.M_less_equal)) Globals.base.camNode.set_initial_state(initial_node.get_state())
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 drawNametag(self): # Set our priority in the margin system: self.setPriority(MarginGlobals.MP_low) if self.textNodePath is not None: self.textNodePath.removeNode() self.textNodePath = None if self.arrow is not None: self.arrow.removeNode() self.arrow = None if self.font is None: # We can't draw this without a font. return # Attach the icon: if self.icon is not None: self.contents.attachNewNode(self.icon) if self.isClickable(): foreground, background = self.nametagColor[self.clickState] else: foreground, background = self.nametagColor[PGButton.SInactive] # Set the color of the TextNode: self.textNode.setTextColor(foreground) # Attach the TextNode: self.textNodePath = self.contents.attachNewNode( self.textNode.generate(), 1) self.textNodePath.setTransparency(foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) self.textNodePath.setY(self.TEXT_Y_OFFSET) # Attach a panel behind the TextNode: self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0) self.panel.setColor(background) self.panel.setTransparency(background[3] < 1) # Reposition the panel: x = (self.textNode.getLeft() + self.textNode.getRight()) / 2.0 z = (self.textNode.getBottom() + self.textNode.getTop()) / 2.0 self.panel.setPos(x, 0, z) # Resize the panel: self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING self.panel.setScale(self.panelWidth, 1, self.panelHeight) #self.cTag.set_panel_size(self.panelWidth, self.panelHeight) # Add an arrow: self.arrow = NametagGlobals.arrowModel.copyTo(self.contents) self.arrow.setZ(self.ARROW_OFFSET + self.textNode.getBottom()) self.arrow.setScale(self.ARROW_SCALE) self.arrow.setColor( NametagGlobals.NametagColors[NametagGlobals.CCOtherPlayer][0][0])
def DoubleSidedNoZ(): global _DoubleSidedNoZ if not _DoubleSidedNoZ: _DoubleSidedNoZ = RenderState.make( CullFaceAttrib.make(CullFaceAttrib.MCullNone), DepthTestAttrib.make(DepthTestAttrib.MOff), DepthWriteAttrib.make(DepthWriteAttrib.MOff), CullBinAttrib.make("fixed", LEGlobals.WidgetSort)) return _DoubleSidedNoZ
def select(self): self.state3D = self.state3D.setAttrib(ColorScaleAttrib.make(Vec4(1, 0.75, 0.75, 1))) self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(Vec4(1, 0, 0, 1))) self.state2D = self.state2D.setAttrib(CullBinAttrib.make("fixed", LEGlobals.SelectedSort)) self.state2D = self.state2D.setAttrib(DepthWriteAttrib.make(False)) self.state2D = self.state2D.setAttrib(DepthTestAttrib.make(False)) self.solid.setFaceGeomState(self.geom3D, self.state3D) self.solid.setFaceGeomState(self.geom2D, self.state2D) self.show3DLines() self.isSelected = True
def drawNametag(self): # Set our priority in the margin system: self.setPriority(MarginGlobals.MP_low) if self.textNodePath is not None: self.textNodePath.removeNode() self.textNodePath = None if self.arrow is not None: self.arrow.removeNode() self.arrow = None if self.font is None: # We can't draw this without a font. return # Attach the icon: if self.icon is not None: self.contents.attachNewNode(self.icon) if self.isClickable(): foreground, background = self.nametagColor[self.clickState] else: foreground, background = self.nametagColor[PGButton.SInactive] # Set the color of the TextNode: self.textNode.setTextColor(foreground) # Attach the TextNode: self.textNodePath = self.contents.attachNewNode(self.textNode, 1) self.textNodePath.setTransparency(foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) self.textNodePath.setY(self.TEXT_Y_OFFSET) # Attach a panel behind the TextNode: self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0) self.panel.setColor(background) self.panel.setTransparency(background[3] < 1) # Reposition the panel: x = (self.textNode.getLeft()+self.textNode.getRight()) / 2.0 z = (self.textNode.getBottom()+self.textNode.getTop()) / 2.0 self.panel.setPos(x, 0, z) # Resize the panel: self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING self.panel.setScale(self.panelWidth, 1, self.panelHeight) # Add an arrow: self.arrow = NametagGlobals.arrowModel.copyTo(self.contents) self.arrow.setZ(self.ARROW_OFFSET + self.textNode.getBottom()) self.arrow.setScale(self.ARROW_SCALE) self.arrow.setColor(self.nametagColor[0][0])
def DashedLineNoZ(): global _DashedLineNoZ if not _DashedLineNoZ: shattr = getStippleShader() _DashedLineNoZ = RenderState.make( shattr, DepthTestAttrib.make(DepthTestAttrib.MOff), DepthWriteAttrib.make(DepthWriteAttrib.MOff), CullFaceAttrib.make(CullFaceAttrib.MCullNone), ) _DashedLineNoZ = _DashedLineNoZ.setAttrib(CullBinAttrib.make("fixed", LEGlobals.BoxSort)) return _DashedLineNoZ
def generate(self, text, font, textColor=(0, 0, 0, 1), balloonColor=(1, 1, 1, 1), wordWrap=10.0, button=None): root = NodePath('balloon') balloon = self.model.copyTo(root) top = balloon.find('**/top') middle = balloon.find('**/middle') bottom = balloon.find('**/bottom') if top.isEmpty() or middle.isEmpty() or bottom.isEmpty(): raise StandardError('invalid chat balloon model') balloon.setColor(balloonColor) if balloonColor[3] < 1.0: balloon.setTransparency(1) t = root.attachNewNode(TextNode('text')) t.node().setFont(font) t.node().setWordwrap(wordWrap) t.node().setText(text) t.node().setTextColor(textColor) width, height = t.node().getWidth(), t.node().getHeight() if height < self.MIN_HEIGHT: height = self.MIN_HEIGHT bubblePadding = self.BUBBLE_PADDING if width == self.MIN_WIDTH: bubblePadding /= 2 else: bubblePadding *= 0.75 t.setAttrib(DepthWriteAttrib.make(0)) t.setPos(self.TEXT_SHIFT) t.setX(t, self.TEXT_SHIFT_PROP * width) t.setZ(t, height) if button: np = button.copyTo(root) np.setPos(t, width - bubblePadding, 0, -height + bubblePadding) np.setPos(np, self.BUTTON_SHIFT) np.setScale(self.BUTTON_SCALE) t.setZ(t, bubblePadding * 2) if width < self.MIN_WIDTH: width = self.MIN_WIDTH t.setX(t, width / 2) t.node().setAlign(TextNode.ACenter) width *= 1 + self.BUBBLE_PADDING_PROP width += bubblePadding balloon.setSx(width / self.NATIVE_WIDTH) if button: height += bubblePadding * 2 middle.setSz(height) top.setZ(top, height - 1) return root
def registerEarlyZTagState(self, name, state): """ Registers a new tag state """ if not self.prepassCam: return # state.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullClockwise), 10000) state.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.COff), 10000) state.setAttrib(AlphaTestAttrib.make(AlphaTestAttrib.MNone, 1.0), 10000) state.setAttrib(DepthWriteAttrib.make(DepthWriteAttrib.MOn), 10000) state.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MLess), 10000) state.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MNone), 10000) self.prepassCam.setTagState(name, state.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 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 drawNametag(self): if self.font is None: # We can't draw this without a font. return # Attach the icon: if self.icon is not None: self.contents.attachNewNode(self.icon) if self.isClickable(): foreground, background = self.nametagColor[self.clickState] else: foreground, background = self.nametagColor[PGButton.SInactive] # Set the color of the TextNode: self.textNode.setTextColor(foreground) # Attach the TextNode: textNodePath = self.contents.attachNewNode(self.textNode.generate(), 1) textNodePath.setTransparency(foreground[3] < 1) textNodePath.setAttrib(DepthWriteAttrib.make(0)) textNodePath.setY(self.TEXT_Y_OFFSET) # Attach a panel behind the TextNode: self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0) self.panel.setColor(background) self.panel.setTransparency(background[3] < 1) # Reposition the panel: x = (self.textNode.getLeft()+self.textNode.getRight()) / 2.0 z = (self.textNode.getBottom()+self.textNode.getTop()) / 2.0 self.panel.setPos(x, 0, z) # Resize the panel: self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING self.panel.setScale(self.panelWidth, 1, self.panelHeight) self.cTag.set_panel_size(self.panelWidth, self.panelHeight) if not base.config.GetBool('want-nametags', True): self.contents.hide()
def drawNametag(self): if self.font is None: return if self.icon is not None: self.contents.attachNewNode(self.icon) if self.isClickable(): foreground, background = self.nametagColor[self.clickState] else: foreground, background = self.nametagColor[PGButton.SInactive] self.textNode.setTextColor(foreground) textNodePath = self.contents.attachNewNode(self.textNode, 1) textNodePath.setTransparency(foreground[3] < 1) textNodePath.setAttrib(DepthWriteAttrib.make(0)) textNodePath.setY(-0.1) self.panel = NametagGlobals.cardModel.copyTo(self.contents, 0) self.panel.setColor(background) self.panel.setTransparency(background[3] < 1) x = (self.textNode.getLeft() + self.textNode.getRight()) / 2.0 z = (self.textNode.getBottom() + self.textNode.getTop()) / 2.0 self.panel.setPos(x, 0, z) self.panelWidth = self.textNode.getWidth() + self.PANEL_X_PADDING self.panelHeight = self.textNode.getHeight() + self.PANEL_Z_PADDING self.panel.setScale(self.panelWidth, 1, self.panelHeight)
def __init__(self, model, modelWidth, modelHeight, textNode, foreground=VBase4(0, 0, 0, 1), background=VBase4(1, 1, 1, 1), reversed=False, button=None): NodePath.__init__(self, 'chatBalloon') self.model = model self.modelWidth = modelWidth self.modelHeight = modelHeight self.textNode = textNode self.foreground = foreground self.background = background self.button = button self.textNode.setTextColor(self.foreground) self.balloon = self.model.copyTo(self) self.balloon.setColor(self.background) self.balloon.setTransparency(self.background[3] < 1) self.textNodePath = self.attachNewNode(self.textNode) self.textNodePath.setTransparency(self.foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) middle = self.balloon.find('**/middle') top = self.balloon.find('**/top') self.textWidth = self.textNode.getWidth() if self.textWidth < self.TEXT_MIN_WIDTH: self.textWidth = self.TEXT_MIN_WIDTH paddedWidth = self.textWidth + self.BALLOON_X_PADDING * 2 self.balloon.setSx(paddedWidth / modelWidth) self.textHeight = textNode.getHeight() if self.textHeight < self.TEXT_MIN_HEIGHT: self.textHeight = self.TEXT_MIN_HEIGHT paddedHeight = self.textHeight + self.BALLOON_Z_PADDING * 2 middle.setSz(paddedHeight - 1.5) top.setZ(middle, 1) if reversed: self.balloon.setSx(-self.balloon.getSx()) self.balloon.setTwoSided(True) self.width = paddedWidth self.height = paddedHeight self.center = self.balloon.getBounds().getCenter() self.textNodePath.setPos(self.center) self.textNodePath.setY(self.TEXT_Y_OFFSET) self.textNodePath.setX(self.textNodePath, -(self.textWidth / 2)) if self.textWidth == self.TEXT_MIN_WIDTH: centerX = (self.TEXT_MIN_WIDTH - self.textNode.getWidth()) / 2.0 self.textNodePath.setX(self.textNodePath, centerX) self.textNodePath.setZ(top, -self.BALLOON_Z_PADDING + self.TEXT_Z_OFFSET) if self.textHeight == self.TEXT_MIN_HEIGHT: centerZ = (ChatBalloon.TEXT_MIN_HEIGHT - self.textNode.getHeight()) / 2.0 self.textNodePath.setZ(self.textNodePath, -centerZ) self.textNodePath.setX(self.textNodePath, self.TEXT_X_OFFSET) if self.button is not None: self.buttonNodePath = button.copyTo(self) self.buttonNodePath.setPos(self.textNodePath, self.textWidth, 0, -self.textHeight) self.buttonNodePath.setPos(self.buttonNodePath, ChatBalloon.BUTTON_SHIFT) self.buttonNodePath.setScale(ChatBalloon.BUTTON_SCALE) else: self.buttonNodePath = None self.setAntialias(AntialiasAttrib.MMultisample) return
def __init__(self, model, modelWidth, modelHeight, textNode, foreground=VBase4(0, 0, 0, 1), background=VBase4(1, 1, 1, 1), reversed=False, button=None, is2d=False): NodePath.__init__(self, 'chatBalloon') # We don't want chat bubbles to glow from the bloom filter, it looks terrible. #CIGlobals.applyNoGlow(self) #self.setLightOff(1) self.hide(CIGlobals.ShadowCameraBitmask | CIGlobals.ReflectionCameraBitmask) # Disable bloom on the chat bubbles so you can actually read the text self.setAttrib(BloomAttrib.make(False)) #self.setColorScale(0.8, 0.8, 0.8, 1.0, 1) self.model = model self.modelWidth = modelWidth self.modelHeight = modelHeight self.textNode = textNode self.foreground = foreground self.background = background self.button = button self.is2d = is2d # Set the TextNode color: self.textNode.setTextColor(self.foreground) # Create a balloon: self.balloon = self.model.copyTo(self) self.balloon.setColor(self.background) self.balloon.setTransparency(self.background[3] < 1) # self.balloon.setLightOff(1) # if is2d: # Don't use the black outline on 2d chat balloons (old toontown). #self.balloon.setTextureOff(1) #self.balloon.setShaderOff(1) #else: #self.balloon.setShaderAuto(2) # Attach the TextNode: self.textNodePath = self.attachNewNode(self.textNode.generate()) self.textNodePath.setTransparency(self.foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) # Resize the balloon as necessary: middle = self.balloon.find('**/middle') top = self.balloon.find('**/top') self.textWidth = self.textNode.getWidth() if self.textWidth < self.TEXT_MIN_WIDTH: self.textWidth = self.TEXT_MIN_WIDTH paddedWidth = self.textWidth + (self.BALLOON_X_PADDING * 2) self.balloon.setSx(paddedWidth / modelWidth) self.textHeight = textNode.getHeight() if self.textHeight < self.TEXT_MIN_HEIGHT: self.textHeight = self.TEXT_MIN_HEIGHT paddedHeight = self.textHeight + (self.BALLOON_Z_PADDING * 2) middle.setSz(paddedHeight - 1.5) # Compensate for the top, as well. top.setZ(middle, 1) if reversed: self.balloon.setSx(-self.balloon.getSx()) self.balloon.setTwoSided( True) # Render the backface of the balloon. self.width = paddedWidth self.height = paddedHeight # Position the TextNode: self.center = self.balloon.getBounds().getCenter() self.textNodePath.setPos(self.center) self.textNodePath.setY(self.TEXT_Y_OFFSET) self.textNodePath.setX(self.textNodePath, -(self.textWidth / 2)) if self.textWidth == self.TEXT_MIN_WIDTH: centerX = (self.TEXT_MIN_WIDTH - self.textNode.getWidth()) / 2.0 self.textNodePath.setX(self.textNodePath, centerX) self.textNodePath.setZ(top, -self.BALLOON_Z_PADDING + self.TEXT_Z_OFFSET) if self.textHeight == self.TEXT_MIN_HEIGHT: centerZ = (ChatBalloon.TEXT_MIN_HEIGHT - self.textNode.getHeight()) / 2.0 self.textNodePath.setZ(self.textNodePath, -centerZ) self.textNodePath.setX(self.textNodePath, self.TEXT_X_OFFSET) # Add a button if one is given: if self.button is not None: self.buttonNodePath = button.copyTo(self) self.buttonNodePath.setPos(self.textNodePath, self.textWidth, 0, -self.textHeight) self.buttonNodePath.setPos(self.buttonNodePath, ChatBalloon.BUTTON_SHIFT) self.buttonNodePath.setScale(ChatBalloon.BUTTON_SCALE) else: self.buttonNodePath = None self.balloon.clearModelNodes() self.balloon.flattenStrong()
def apply(self, nodePath): if self.is_unset(): return attrib = DepthWriteAttrib.make(self.is_on()) nodePath.setAttrib(attrib)
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 __init__(self): DebugObject.__init__(self, "LightManager") self._initArrays() # create arrays to store lights & shadow sources self.lights = [] self.shadowSources = [] self.allLightsArray = ShaderStructArray(Light, 30) self.cullBounds = None self.shadowScene = render ## SHADOW ATLAS ## # todo: move to separate class # When you change this, change also SHADOW_MAP_ATLAS_SIZE in configuration.include, # and reduce the default shadow map resolution of point lights self.shadowAtlasSize = 512 self.maxShadowMaps = 24 # When you change it , change also SHAODOW_GEOMETRY_MAX_VERTICES and # SHADOW_MAX_UPDATES_PER_FRAME in configuration.include! self.maxShadowUpdatesPerFrame = 2 self.tileSize = 128 self.tileCount = self.shadowAtlasSize / self.tileSize self.tiles = [] self.updateShadowsArray = ShaderStructArray( ShadowSource, self.maxShadowUpdatesPerFrame) self.allShadowsArray = ShaderStructArray(ShadowSource, self.maxShadowMaps) # self.shadowAtlasTex = Texture("ShadowAtlas") # self.shadowAtlasTex.setup2dTexture( # self.shadowAtlasSize, self.shadowAtlasSize, Texture.TFloat, Texture.FRg16) # self.shadowAtlasTex.setMinfilter(Texture.FTLinear) # self.shadowAtlasTex.setMagfilter(Texture.FTLinear) self.debug("Init shadow atlas with tileSize =", self.tileSize, ", tileCount =", self.tileCount) for i in xrange(self.tileCount): self.tiles.append([None for j in xrange(self.tileCount)]) # create shadow compute buffer self.shadowComputeCamera = Camera("ShadowComputeCamera") self.shadowComputeCameraNode = self.shadowScene.attachNewNode( self.shadowComputeCamera) self.shadowComputeCamera.getLens().setFov(90, 90) self.shadowComputeCamera.getLens().setNearFar(10.0, 100000.0) self.shadowComputeCameraNode.setPos(0, 0, 150) self.shadowComputeCameraNode.lookAt(0, 0, 0) self.shadowComputeTarget = RenderTarget("ShadowCompute") self.shadowComputeTarget.setSize(self.shadowAtlasSize, self.shadowAtlasSize) # self.shadowComputeTarget.setLayers(self.maxShadowUpdatesPerFrame) self.shadowComputeTarget.addRenderTexture(RenderTargetType.Depth) self.shadowComputeTarget.setDepthBits(32) self.shadowComputeTarget.setSource(self.shadowComputeCameraNode, base.win) self.shadowComputeTarget.prepareSceneRender() self.shadowComputeTarget.getInternalRegion().setSort(3) self.shadowComputeTarget.getRegion().setSort(3) self.shadowComputeTarget.getInternalRegion().setNumRegions( self.maxShadowUpdatesPerFrame + 1) self.shadowComputeTarget.getInternalRegion().setDimensions( 0, (0, 1, 0, 1)) self.shadowComputeTarget.setClearDepth(False) self.depthClearer = [] for i in xrange(self.maxShadowUpdatesPerFrame): buff = self.shadowComputeTarget.getInternalBuffer() dr = buff.makeDisplayRegion() dr.setSort(2) dr.setClearDepthActive(True) dr.setClearDepth(1.0) dr.setClearColorActive(False) dr.setDimensions(0, 0, 0, 0) self.depthClearer.append(dr) self.queuedShadowUpdates = [] # Assign copy shader self._setCopyShader() # self.shadowComputeTarget.setShaderInput("atlas", self.shadowComputeTarget.getColorTexture()) # self.shadowComputeTarget.setShaderInput( # "renderResult", self.shadowComputeTarget.getDepthTexture()) # self.shadowComputeTarget.setActive(False) # Create shadow caster shader self.shadowCasterShader = BetterShader.load( "Shader/DefaultShadowCaster.vertex", "Shader/DefaultShadowCaster.fragment", "Shader/DefaultShadowCaster.geometry") self.shadowComputeCamera.setTagStateKey("ShadowPass") initialState = NodePath("ShadowCasterState") initialState.setShader(self.shadowCasterShader, 30) self.shadowComputeCamera.setInitialState( RenderState.make(ColorWriteAttrib.make(ColorWriteAttrib.C_off), DepthWriteAttrib.make(DepthWriteAttrib.M_on), 100)) self.shadowComputeCamera.setTagState("True", initialState.getState()) self.shadowScene.setTag("ShadowPass", "True") self._createDebugTexts() self.updateShadowsArray.bindTo(self.shadowScene, "updateSources") self.updateShadowsArray.bindTo(self.shadowComputeTarget, "updateSources") self.numShadowUpdatesPTA = PTAInt.emptyArray(1) # Set initial inputs for target in [self.shadowComputeTarget, self.shadowScene]: target.setShaderInput("numUpdates", self.numShadowUpdatesPTA) self.lightingComputator = None self.lightCuller = None
def __init__(self, pipeline): """ Creates a new LightManager. It expects a RenderPipeline as parameter. """ DebugObject.__init__(self, "LightManager") self._initArrays() self.pipeline = pipeline self.settings = pipeline.getSettings() # Create arrays to store lights & shadow sources self.lights = [] self.shadowSources = [] self.queuedShadowUpdates = [] self.allLightsArray = ShaderStructArray(Light, self.maxTotalLights) self.cullBounds = None self.shadowScene = Globals.render # Create atlas self.shadowAtlas = ShadowAtlas() self.shadowAtlas.setSize(self.settings.shadowAtlasSize) self.shadowAtlas.create() self.maxShadowMaps = 24 self.maxShadowUpdatesPerFrame = self.settings.maxShadowUpdatesPerFrame self.numShadowUpdatesPTA = PTAInt.emptyArray(1) self.updateShadowsArray = ShaderStructArray( ShadowSource, self.maxShadowUpdatesPerFrame) self.allShadowsArray = ShaderStructArray( ShadowSource, self.maxShadowMaps) # Create shadow compute buffer self._createShadowComputationBuffer() # Create the initial shadow state self.shadowComputeCamera.setTagStateKey("ShadowPassShader") self.shadowComputeCamera.setInitialState(RenderState.make( ColorWriteAttrib.make(ColorWriteAttrib.C_off), DepthWriteAttrib.make(DepthWriteAttrib.M_on), # CullFaceAttrib.make(CullFaceAttrib.MCullNone), 100)) self._createTagStates() self.shadowScene.setTag("ShadowPassShader", "Default") # Create debug overlay self._createDebugTexts() # Disable buffer on start self.shadowComputeTarget.setActive(False) # Bind arrays self.updateShadowsArray.bindTo(self.shadowScene, "updateSources") self.updateShadowsArray.bindTo( self.shadowComputeTarget, "updateSources") # Set initial inputs for target in [self.shadowComputeTarget, self.shadowScene]: target.setShaderInput("numUpdates", self.numShadowUpdatesPTA) self.lightingComputator = None self.lightCuller = None
def __init__(self, model, modelWidth, modelHeight, textNode, foreground=VBase4(0, 0, 0, 1), background=VBase4(1, 1, 1, 1), reversed=False, button=None): NodePath.__init__(self, 'chatBalloon') self.model = model self.modelWidth = modelWidth self.modelHeight = modelHeight self.textNode = textNode self.foreground = foreground self.background = background self.button = button # Set the TextNode color: self.textNode.setTextColor(self.foreground) # Create a balloon: self.balloon = self.model.copyTo(self) self.balloon.setColor(self.background) self.balloon.setTransparency(self.background[3] < 1) # Attach the TextNode: self.textNodePath = self.attachNewNode(self.textNode) self.textNodePath.setTransparency(self.foreground[3] < 1) self.textNodePath.setAttrib(DepthWriteAttrib.make(0)) # Resize the balloon as necessary: middle = self.balloon.find('**/middle') top = self.balloon.find('**/top') self.textWidth = self.textNode.getWidth() if self.textWidth < self.TEXT_MIN_WIDTH: self.textWidth = self.TEXT_MIN_WIDTH paddedWidth = self.textWidth + (self.BALLOON_X_PADDING * 2) self.balloon.setSx(paddedWidth / modelWidth) self.textHeight = textNode.getHeight() if self.textHeight < self.TEXT_MIN_HEIGHT: self.textHeight = self.TEXT_MIN_HEIGHT paddedHeight = self.textHeight + (self.BALLOON_Z_PADDING * 2) middle.setSz(paddedHeight - 1.5) # Compensate for the top, as well. top.setZ(middle, 1) if reversed: self.balloon.setSx(-self.balloon.getSx()) self.balloon.setTwoSided( True) # Render the backface of the balloon. self.width = paddedWidth self.height = paddedHeight # Position the TextNode: self.center = self.balloon.getBounds().getCenter() self.textNodePath.setPos(self.center) self.textNodePath.setY(self.TEXT_Y_OFFSET) self.textNodePath.setX(self.textNodePath, -(self.textWidth / 2)) if self.textWidth == self.TEXT_MIN_WIDTH: centerX = (self.TEXT_MIN_WIDTH - self.textNode.getWidth()) / 2.0 self.textNodePath.setX(self.textNodePath, centerX) self.textNodePath.setZ(top, -self.BALLOON_Z_PADDING + self.TEXT_Z_OFFSET) if self.textHeight == self.TEXT_MIN_HEIGHT: centerZ = (ChatBalloon.TEXT_MIN_HEIGHT - self.textNode.getHeight()) / 2.0 self.textNodePath.setZ(self.textNodePath, -centerZ) self.textNodePath.setX(self.textNodePath, self.TEXT_X_OFFSET) # Add a button if one is given: if self.button is not None: self.buttonNodePath = button.copyTo(self) self.buttonNodePath.setPos(self.textNodePath, self.textWidth, 0, -self.textHeight) self.buttonNodePath.setPos(self.buttonNodePath, ChatBalloon.BUTTON_SHIFT) self.buttonNodePath.setScale(ChatBalloon.BUTTON_SCALE) else: self.buttonNodePath = None # Finally, enable anti-aliasing: self.setAntialias(AntialiasAttrib.MMultisample)