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 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): # Create the voxel grid used to store the voxels self._voxel_grid = Image.create_3d( "Voxels", self._voxel_res, self._voxel_res, self._voxel_res, Texture.T_float, Texture.F_r11_g11_b10 ) self._voxel_grid.set_clear_color(Vec4(0)) # Create the camera for voxelization self._voxel_cam = Camera("VoxelizeCam") self._voxel_cam.set_camera_mask(self._pipeline.tag_mgr.get_voxelize_mask()) self._voxel_cam_lens = OrthographicLens() self._voxel_cam_lens.set_film_size(-self._voxel_ws, self._voxel_ws) self._voxel_cam_lens.set_near_far(0.0, 2.0 * self._voxel_ws) self._voxel_cam.set_lens(self._voxel_cam_lens) self._voxel_cam_np = Globals.base.render.attach_new_node(self._voxel_cam) self._pipeline.tag_mgr.register_voxelize_camera(self._voxel_cam) # Create the voxelization target self._voxel_target = self._create_target("VoxelizeScene") self._voxel_target.set_source(source_cam=self._voxel_cam_np, source_win=Globals.base.win) self._voxel_target.set_size(self._voxel_res, self._voxel_res) self._voxel_target.set_create_overlay_quad(False) self._voxel_target.prepare_scene_render() # Create the initial state used for rendering voxels initial_state = NodePath("VXInitialState") initial_state.set_attrib(CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000) initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000) initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000) self._voxel_cam.set_initial_state(initial_state.get_state()) Globals.base.render.set_shader_input("voxelGridPosition", self._pta_grid_pos) Globals.base.render.set_shader_input("voxelGridRes", self._pta_grid_res) Globals.base.render.set_shader_input("voxelGridSize", self._pta_grid_size) Globals.base.render.set_shader_input("VoxelGridDest", self._voxel_grid.texture)
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 registerTagState(self, name, state): """ Registers a new tag state """ state.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) state.setDepthWrite(False) state.setDepthTest(False) state.setAttrib(DepthTestAttrib.make(DepthTestAttrib.MNone)) state.setShaderInput("voxelizeCam", self.voxelizeCameraNode) self.voxelizeCamera.setTagState(name, state.getState())
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 check_and_create_rendering_buffers(showbase): if not settings.render_scene_to_buffer: return if not settings.buffer_texture: print("Render to buffer not supported") return print("Render scene to buffer") buffer_multisamples = 0 if settings.render_scene_to_buffer and not settings.disable_multisampling and settings.use_multisampling and settings.multisamples > 0: buffer_multisamples = settings.multisamples manager = FilterManager(showbase.win, showbase.cam) color_buffer = Texture() if settings.use_inverse_z: render.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_greater)) depth_buffer = Texture() showbase.win.set_clear_depth(0) float_depth = True depth_bits = 24 else: depth_buffer = None float_depth = False depth_bits = 1 if settings.render_scene_to_float: if settings.floating_point_buffer: rgba_bits = (32, 32, 32, 32) float_colors = True else: print( "Floating point buffer not available, sRBG conversion will show artifacts" ) rgba_bits = (1, 1, 1, 1) float_colors = False else: rgba_bits = (1, 1, 1, 1) float_colors = False textures = {'color': color_buffer, 'depth': depth_buffer} fbprops = FrameBufferProperties() fbprops.setFloatColor(float_colors) fbprops.setRgbaBits(*rgba_bits) fbprops.setSrgbColor(settings.srgb_buffer) fbprops.setDepthBits(depth_bits) fbprops.setFloatDepth(float_depth) fbprops.setMultisamples(buffer_multisamples) final_quad = manager.render_scene_into(textures=textures, fbprops=fbprops) final_quad_shader = PostProcessShader( gamma_correction=settings.software_srgb, hdr=settings.use_hdr).create_shader() final_quad.set_shader(final_quad_shader) final_quad.set_shader_input("color_buffer", color_buffer) final_quad.set_shader_input("exposure", 2)
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 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 configure_scene(self): #Force frame update to render the last status of the splash screen base.graphicsEngine.renderFrame() self.splash.close() if self.gui is None: self.gui = Gui(self, self.time, self.observer, self.mouse, self.nav, self.autopilot) self.set_nav(self.nav) self.nav.register_events(self) self.gui.register_events(self) self.pointset = PointsSet(use_sprites=True, sprite=GaussianPointSprite(size=16, fwhm=8)) if settings.render_sprite_points: self.pointset.instance.reparentTo(self.world) self.haloset = PointsSet(use_sprites=True, sprite=ExpPointSprite(size=256, max_value=0.6), background=settings.halo_depth) if settings.render_sprite_points: self.haloset.instance.reparentTo(self.world) render.setAntialias(AntialiasAttrib.MMultisample) self.setFrameRateMeter(False) self.render.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_less_equal)) self.set_ambient(settings.global_ambient) self.equatorial_grid = Grid("Equatorial", J2000EquatorialReferenceFrame.orientation, LColor(0.28, 0.28, 0.38, 1)) self.equatorial_grid.set_shown(settings.show_equatorial_grid) self.ecliptic_grid = Grid("Ecliptic", J2000EclipticReferenceFrame.orientation, LColor(0.28, 0.28, 0.38, 1)) self.ecliptic_grid.set_shown(settings.show_ecliptic_grid) self.time.set_current_date() for controller in self.controllers: controller.init() self.universe.first_update() self.camera_controller.update(self.time.time_full, 0) self.universe.first_update_obs(self.observer) self.window_event(None) self.time_task(None) taskMgr.add(self.time_task, "time-task") self.start_universe() if self.app_config.test_start: #TODO: this is where the tests should be inserted print("Tests done.") self.userExit()
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 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 create(self): # Create the voxel grid used to generate the voxels self.voxel_temp_grid = Image.create_3d("VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_temp_grid.set_clear_color(Vec4(0)) self.voxel_temp_nrm_grid = Image.create_3d("VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "R11G11B10") self.voxel_temp_nrm_grid.set_clear_color(Vec4(0)) # Create the voxel grid which is a copy of the temporary grid, but stable self.voxel_grid = Image.create_3d("Voxels", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_grid.set_clear_color(Vec4(0)) self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear) # Create the camera for voxelization self.voxel_cam = Camera("VoxelizeCam") self.voxel_cam.set_camera_mask( self._pipeline.tag_mgr.get_voxelize_mask()) self.voxel_cam_lens = OrthographicLens() self.voxel_cam_lens.set_film_size(-2.0 * self.voxel_world_size, 2.0 * self.voxel_world_size) self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size) self.voxel_cam.set_lens(self.voxel_cam_lens) self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam) self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam) # Create the voxelization target self.voxel_target = self.create_target("VoxelizeScene") self.voxel_target.size = self.voxel_resolution self.voxel_target.prepare_render(self.voxel_cam_np) # Create the target which copies the voxel grid self.copy_target = self.create_target("CopyVoxels") self.copy_target.size = self.voxel_resolution self.copy_target.prepare_buffer() # TODO! Does not work with the new render target yet - maybe add option # to post process region for instances? self.copy_target.instance_count = self.voxel_resolution self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid) self.copy_target.set_shader_input("DestTex", self.voxel_grid) # Create the target which generates the mipmaps self.mip_targets = [] mip_size, mip = self.voxel_resolution, 0 while mip_size > 1: mip_size, mip = mip_size // 2, mip + 1 mip_target = self.create_target("GenMipmaps:" + str(mip)) mip_target.size = mip_size mip_target.prepare_buffer() mip_target.instance_count = mip_size mip_target.set_shader_input("SourceTex", self.voxel_grid) mip_target.set_shader_input("sourceMip", mip - 1) mip_target.set_shader_input("DestTex", self.voxel_grid, False, True, -1, mip, 0) self.mip_targets.append(mip_target) # Create the initial state used for rendering voxels initial_state = NodePath("VXGIInitialState") initial_state.set_attrib( CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000) initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000) initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000) self.voxel_cam.set_initial_state(initial_state.get_state()) Globals.base.render.set_shader_input("voxelGridPosition", self.pta_next_grid_pos) Globals.base.render.set_shader_input("VoxelGridDest", self.voxel_temp_grid)
def check_and_create_rendering_buffers(showbase): if settings.allow_floating_point_buffer: settings.floating_point_buffer = True if not test_floating_point_buffer((32, 0, 0, 0)): print("One component floating point buffer not supported") settings.floating_point_buffer = False if not test_floating_point_buffer((32, 32, 32, 32)): print("Three components floating point buffer not supported") settings.floating_point_buffer = False else: settings.floating_point_buffer = False if settings.floating_point_buffer: print("Using floating point buffer") if not settings.encode_float and not settings.floating_point_buffer: settings.encode_float = True if settings.use_srgb and settings.use_hardware_srgb and not showbase.win.getFbProperties( ).get_srgb_color(): print("Could not enable sRGB on main framebuffer") settings.use_hardware_srgb = False final_stage_srgb = False if settings.use_srgb and not settings.use_hardware_srgb: settings.render_scene_to_buffer = True settings.render_scene_to_float = True final_stage_srgb = True buffer_multisamples = 0 if settings.render_scene_to_buffer and settings.multisamples > 0: buffer_multisamples = settings.multisamples if settings.render_scene_to_buffer: manager = FilterManager(showbase.win, showbase.cam) color_buffer = Texture() if settings.use_inverse_z: render.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_greater)) depth_buffer = Texture() showbase.win.set_clear_depth(0) depthtex = depth_buffer floatdepth = True depthbits = 24 else: depthtex = None floatdepth = False depthbits = 1 if settings.render_scene_to_float: if settings.floating_point_buffer: rgbabits = (32, 32, 32, 32) floatcolor = True else: print( "Floating point buffer not available, sRBG conversion will show artifacts" ) rgbabits = (1, 1, 1, 1) floatcolor = False else: rgbabits = (1, 1, 1, 1) floatcolor = False srgb_buffer = settings.use_srgb and settings.use_hardware_srgb final_quad = manager.render_scene_into( colortex=color_buffer, rgbabits=rgbabits, floatcolor=floatcolor, srgb=srgb_buffer, depthtex=depthtex, depthbits=depthbits, floatdepth=floatdepth, multisamples=buffer_multisamples) final_quad_shader = PostProcessShader( gamma_correction=final_stage_srgb, hdr=settings.use_hdr).create_shader() final_quad.set_shader(final_quad_shader) final_quad.set_shader_input("color_buffer", color_buffer) final_quad.set_shader_input("exposure", 2)
def create(self): # Create the voxel grid used to generate the voxels self.voxel_temp_grid = Image.create_3d( "VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_temp_grid.set_clear_color(Vec4(0)) self.voxel_temp_nrm_grid = Image.create_3d( "VoxelsTemp", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "R11G11B10") self.voxel_temp_nrm_grid.set_clear_color(Vec4(0)) # Create the voxel grid which is a copy of the temporary grid, but stable self.voxel_grid = Image.create_3d( "Voxels", self.voxel_resolution, self.voxel_resolution, self.voxel_resolution, "RGBA8") self.voxel_grid.set_clear_color(Vec4(0)) self.voxel_grid.set_minfilter(SamplerState.FT_linear_mipmap_linear) # Create the camera for voxelization self.voxel_cam = Camera("VoxelizeCam") self.voxel_cam.set_camera_mask(self._pipeline.tag_mgr.get_voxelize_mask()) self.voxel_cam_lens = OrthographicLens() self.voxel_cam_lens.set_film_size( -2.0 * self.voxel_world_size, 2.0 * self.voxel_world_size) self.voxel_cam_lens.set_near_far(0.0, 2.0 * self.voxel_world_size) self.voxel_cam.set_lens(self.voxel_cam_lens) self.voxel_cam_np = Globals.base.render.attach_new_node(self.voxel_cam) self._pipeline.tag_mgr.register_camera("voxelize", self.voxel_cam) # Create the voxelization target self.voxel_target = self.create_target("VoxelizeScene") self.voxel_target.size = self.voxel_resolution self.voxel_target.prepare_render(self.voxel_cam_np) # Create the target which copies the voxel grid self.copy_target = self.create_target("CopyVoxels") self.copy_target.size = self.voxel_resolution self.copy_target.prepare_buffer() # TODO! Does not work with the new render target yet - maybe add option # to post process region for instances? self.copy_target.instance_count = self.voxel_resolution self.copy_target.set_shader_input("SourceTex", self.voxel_temp_grid) self.copy_target.set_shader_input("DestTex", self.voxel_grid) # Create the target which generates the mipmaps self.mip_targets = [] mip_size, mip = self.voxel_resolution, 0 while mip_size > 1: mip_size, mip = mip_size // 2, mip + 1 mip_target = self.create_target("GenMipmaps:" + str(mip)) mip_target.size = mip_size mip_target.prepare_buffer() mip_target.instance_count = mip_size mip_target.set_shader_input("SourceTex", self.voxel_grid) mip_target.set_shader_input("sourceMip", mip - 1) mip_target.set_shader_input("DestTex", self.voxel_grid, False, True, -1, mip, 0) self.mip_targets.append(mip_target) # Create the initial state used for rendering voxels initial_state = NodePath("VXGIInitialState") initial_state.set_attrib(CullFaceAttrib.make(CullFaceAttrib.M_cull_none), 100000) initial_state.set_attrib(DepthTestAttrib.make(DepthTestAttrib.M_none), 100000) initial_state.set_attrib(ColorWriteAttrib.make(ColorWriteAttrib.C_off), 100000) self.voxel_cam.set_initial_state(initial_state.get_state()) Globals.base.render.set_shader_input("voxelGridPosition", self.pta_next_grid_pos) Globals.base.render.set_shader_input("VoxelGridDest", self.voxel_temp_grid)
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)