From 90eac01be0f68ecfd5992757f83d6572a5a68745 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 12 Feb 2012 15:22:04 +0000 Subject: [PATCH] One more step towards PointLight shadows --- panda/src/display/graphicsStateGuardian.cxx | 102 +++++++++++++++----- 1 file changed, 80 insertions(+), 22 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c465a417e2..e9759b6b7b 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -2638,34 +2638,59 @@ PT(Texture) GraphicsStateGuardian:: make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { // Make sure everything is valid. nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) || + light_np.node()->is_of_type(PointLight::get_class_type()) || light_np.node()->is_of_type(Spotlight::get_class_type()), NULL); + PT(LightLensNode) light = DCAST(LightLensNode, light_np.node()); if (light == NULL || !light->_shadow_caster) { return NULL; } - + + bool is_point = light->is_of_type(PointLight::get_class_type()); + nassertr(light->_sbuffers.count(this) == 0, NULL); - + display_cat.debug() << "Constructing shadow buffer for light '" << light->get_name() << "', size=" << light->_sb_xsize << "x" << light->_sb_ysize << ", sort=" << light->_sb_sort << "\n"; + + // Setup some flags and properties FrameBufferProperties fbp; fbp.set_depth_bits(1); // We only need depth + WindowProperties props = WindowProperties::size(light->_sb_xsize, light->_sb_ysize); + int flags = GraphicsPipe::BF_refuse_window; + if (is_point) { + flags |= GraphicsPipe::BF_size_square; + } + + // Create the buffer PT(GraphicsOutput) sbuffer = get_engine()->make_output(get_pipe(), light->get_name(), - light->_sb_sort, fbp, WindowProperties::size(light->_sb_xsize, light->_sb_ysize), - GraphicsPipe::BF_refuse_window, this, DCAST(GraphicsOutput, host)); + light->_sb_sort, fbp, props, flags, this, DCAST(GraphicsOutput, host)); nassertr(sbuffer != NULL, NULL); - + // Create a texture and fill it in with some data to workaround an OpenGL error PT(Texture) tex = new Texture(light->get_name()); - tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_float, Texture::F_depth_component); + if (is_point) { + if (light->_sb_xsize != light->_sb_ysize) { + display_cat.error() + << "PointLight shadow buffers must have an equal width and height!\n"; + } + tex->setup_cube_map(light->_sb_xsize, Texture::T_float, Texture::F_depth_component); + } else { + tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_float, Texture::F_depth_component); + } tex->make_ram_image(); - sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, - GraphicsOutput::RTP_depth); - // Set the wrap mode to BORDER_COLOR - tex->set_wrap_u(Texture::WM_border_color); - tex->set_wrap_v(Texture::WM_border_color); - tex->set_border_color(LVecBase4(1, 1, 1, 1)); + sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth); + + // Set the wrap mode + if (is_point) { + tex->set_wrap_u(Texture::WM_clamp); + tex->set_wrap_v(Texture::WM_clamp); + } else { + tex->set_wrap_u(Texture::WM_border_color); + tex->set_wrap_v(Texture::WM_border_color); + tex->set_border_color(LVecBase4(1, 1, 1, 1)); + } if (get_supports_shadow_filter()) { // If we have the ARB_shadow extension, enable shadow filtering. @@ -2676,9 +2701,23 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { tex->set_minfilter(Texture::FT_linear); tex->set_magfilter(Texture::FT_linear); } - sbuffer->make_display_region(0, 1, 0, 1)->set_camera(light_np); + + // Assign display region(s) to the buffer and camera + if (is_point) { + for (int i = 0; i < 6; ++i) { + PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1); + dr->set_lens_index(i); + dr->set_cube_map_index(i); + dr->set_camera(light_np); + dr->set_clear_depth_active(true); + } + } else { + PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1); + dr->set_camera(light_np); + dr->set_clear_depth_active(true); + } light->_sbuffers[this] = sbuffer; - + return tex; } @@ -2687,47 +2726,66 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { // Access: Public, Virtual // Description: Returns the vendor of the video card driver //////////////////////////////////////////////////////////////////// -string GraphicsStateGuardian::get_driver_vendor() { return string("0"); } +string GraphicsStateGuardian:: +get_driver_vendor() { + return string("0"); +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_vendor // Access: Public, Virtual // Description: Returns GL_Renderer //////////////////////////////////////////////////////////////////// -string GraphicsStateGuardian::get_driver_renderer() { return string("0"); } +string GraphicsStateGuardian::get_driver_renderer() { + return string("0"); +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_version // Access: Public, Virtual // Description: Returns driver version //////////////////////////////////////////////////////////////////// -string GraphicsStateGuardian::get_driver_version() { return string("0"); } +string GraphicsStateGuardian:: +get_driver_version() { + return string("0"); +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_version_major // Access: Public, Virtual // Description: Returns major version of the video driver //////////////////////////////////////////////////////////////////// -int GraphicsStateGuardian::get_driver_version_major() { return -1; } +int GraphicsStateGuardian:: +get_driver_version_major() { + return -1; +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_version_minor // Access: Public, Virtual // Description: Returns the minor version of the video driver //////////////////////////////////////////////////////////////////// -int GraphicsStateGuardian::get_driver_version_minor() { return -1; } +int GraphicsStateGuardian:: +get_driver_version_minor() { + return -1; +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_shader_version_major // Access: Public, Virtual // Description: Returns the major version of the shader model //////////////////////////////////////////////////////////////////// -int GraphicsStateGuardian::get_driver_shader_version_major() { return -1; } +int GraphicsStateGuardian:: +get_driver_shader_version_major() { + return -1; +} //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_driver_shader_version_minor // Access: Public, Virtual // Description: Returns the minor version of the shader model //////////////////////////////////////////////////////////////////// -int GraphicsStateGuardian::get_driver_shader_version_minor() { return -1; } - +int GraphicsStateGuardian:: +get_driver_shader_version_minor() { + return -1; +}