Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/shader/projtexShadower.cxx

Go to the documentation of this file.
00001 // Filename: projtexShadower.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 #include "projtexShadower.h"
00019 #include "config_shader.h"
00020 
00021 #include <light.h>
00022 #include <spotlight.h>
00023 #include <renderBuffer.h>
00024 #include <transformTransition.h>
00025 #include <lightTransition.h>
00026 #include <textureTransition.h>
00027 #include <colorBlendTransition.h>
00028 #include <colorTransition.h>
00029 #include <depthTestTransition.h>
00030 #include <depthWriteTransition.h>
00031 #include <polygonOffsetTransition.h>
00032 #include <get_rel_pos.h>
00033 #include <dftraverser.h>
00034 #include <displayRegion.h>
00035 #include <graphicsWindow.h>
00036 #include <directRenderTraverser.h>
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 // Static variables
00040 ////////////////////////////////////////////////////////////////////
00041 TypeHandle ProjtexShadower::_type_handle;
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: ProjtexShadower::Constructor
00045 //       Access:
00046 //  Description:
00047 ////////////////////////////////////////////////////////////////////
00048 ProjtexShadower::ProjtexShadower(int size) : CasterShader()
00049 {
00050   set_size(size);
00051 
00052   Texture* texture = new Texture;
00053   texture->set_minfilter(Texture::FT_linear);
00054   texture->set_magfilter(Texture::FT_linear);
00055   texture->set_wrapu(Texture::WM_clamp);
00056   texture->set_wrapv(Texture::WM_clamp);
00057   texture->_pbuffer->set_xsize(_size);
00058   texture->_pbuffer->set_ysize(_size);
00059 
00060   _projtex_shader = new ProjtexShader(texture, ColorBlendProperty::M_multiply);
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: ProjtexShadower::set_priority
00065 //       Access: Public
00066 //  Description:
00067 ////////////////////////////////////////////////////////////////////
00068 void ProjtexShadower::
00069 set_priority(int priority)
00070 {
00071   Shader::set_priority(priority);
00072   _projtex_shader->set_priority(priority);
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: ProjtexShadower::set_multipass
00077 //       Access: Public
00078 //  Description:
00079 ////////////////////////////////////////////////////////////////////
00080 void ProjtexShadower::
00081 set_multipass(bool on)
00082 {
00083   Shader::set_multipass(on);
00084   _projtex_shader->set_multipass(on);
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: ProjtexShadower::pre_apply
00089 //       Access:
00090 //  Description:
00091 ////////////////////////////////////////////////////////////////////
00092 void ProjtexShadower::
00093 pre_apply(Node *node, const AllAttributesWrapper &init_state,
00094       const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg)
00095 {
00096   DirectRenderTraverser drt(gsg, RenderRelation::get_class_type());
00097 
00098   int num_lights = 1;
00099 
00100   if (get_num_casters() == 0) {
00101     shader_cat.error()
00102       << "ProjtexShadower::config() - no casters in caster list" << endl;
00103     return;
00104   }
00105   if (get_num_frusta() == 0) {
00106     shader_cat.error()
00107       << "ProjtexShadower::config() - no lights in frusta list" << endl;
00108     return;
00109   } else if (get_num_frusta() > 1) {
00110     shader_cat.warning()
00111       << "ProjtexShadower::config() - frusta list has more than one "
00112       << "frustum - ignore all but the first one for now..." << endl;
00113     num_lights = 1;
00114   }
00115   if (_frusta[0]->get_type() != Spotlight::get_class_type()) {
00116     shader_cat.error()
00117       << "ProjtexShadower::config() - only works for Spotlights" << endl;
00118     return;
00119   }
00120   Spotlight* light = (Spotlight *)_frusta[0];
00121 
00122   // Save the current display region from the gsg
00123   Colorf clear_color = gsg->get_color_clear_value();
00124 
00125   // Make sure the projtex shader has the same frustum
00126   _projtex_shader->remove_frustum(light);
00127   _projtex_shader->add_frustum(light);
00128 
00129   // Compute an approximation for the shadow color
00130   Colorf diffuse = light->get_color();
00131   Colorf shadow_color;
00132   for (int i = 0; i < 4; i++)
00133     shadow_color[i] = 1.0 / ((diffuse[i] + 1) * num_lights);
00134 
00135   nassertv(node != (Node *)NULL && gsg != (GraphicsStateGuardian *)NULL);
00136 
00137   // First, draw the receiving node quickly (with no rendering attributes)
00138   // from the point of view of the light
00139 
00140   // Make a display region of the proper size and clear it to prepare for
00141   // rendering the shadow map
00142   PT(DisplayRegion) disp_region =
00143         gsg->get_window()->make_scratch_display_region(_size, _size);
00144   DisplayRegionStack old_dr = gsg->push_display_region(disp_region);
00145 
00146   // Save scratch region before clearing it to be non-destructive
00147   FrameBufferStack old_fb = gsg->push_frame_buffer
00148     (gsg->get_render_buffer(RenderBuffer::T_back | RenderBuffer::T_depth),
00149      disp_region);
00150 
00151   gsg->set_color_clear_value(Colorf(1., 1., 1., 1.));
00152   gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
00153                                       RenderBuffer::T_depth), disp_region);
00154 
00155   // Copy the transition wrapper so we can modify it freely.
00156   AllTransitionsWrapper trans(net_trans);
00157 
00158   // Disable lighting, texturing, blending, dithering
00159   trans.set_transition(new LightTransition(LightTransition::all_off()));
00160   //The 100 is to set the priority of this transition high enough
00161   //(hopefully) to turn off any existing texture in the geometry
00162   TextureTransition *t = new TextureTransition(TextureTransition::off());
00163   t->set_priority(100);
00164   trans.set_transition(t);
00165   trans.set_transition(new ColorBlendTransition(ColorBlendProperty::M_none));
00166 
00167 
00168   //We need a state that we can modify to remove the camera transform
00169   //that is passed to us
00170   AllAttributesWrapper state(init_state);
00171   state.clear_attribute(TransformTransition::get_class_type());
00172 
00173   // Render the node with the new transitions from the viewpoint of the light
00174 
00175   gsg->render_subgraph(&drt, node, light, state, trans);
00176 
00177   // Now draw each of the casting objects in the shadow color using the
00178   // depth buffer from the receiving object (this will project the shadows
00179   // onto the surface properly), and use this to generate the shadow texture
00180   // map
00181 
00182   DepthTestTransition *dta =
00183     new DepthTestTransition(DepthTestProperty::M_less);
00184   trans.set_transition(dta);
00185 
00186   DepthWriteTransition *dwa = new DepthWriteTransition;
00187   trans.set_transition(dwa);
00188 
00189   ColorTransition *ca = new ColorTransition(shadow_color);
00190   trans.set_transition(ca);
00191 
00192   // Create a temporary node that is the parent of all of the caster
00193   // objects, so we can render them from the point of view of the
00194   // light.
00195 
00196   PT_Node caster_group = new Node;
00197   NamedNodeVector::iterator ci;
00198   for (ci = _casters.begin(); ci != _casters.end(); ++ci) {
00199     Node *caster = (*ci);
00200 
00201     LMatrix4f mat;
00202     get_rel_mat(caster, node, mat);
00203 
00204     RenderRelation *arc = new RenderRelation(caster_group, caster);
00205     arc->set_transition(new TransformTransition(mat));
00206   }
00207 
00208   // Parent this caster group to the node itself, since it's already
00209   // converted to the coordinate space of the node
00210   PT(RenderRelation) caster_arc = new RenderRelation(node, caster_group);
00211 
00212   // Now render the group.
00213   gsg->render_subgraph(&drt, caster_group, light, state, trans);
00214 
00215   // Remove the caster group from the scene graph.  This will also
00216   // delete the temporary group node (since the reference count is
00217   // zero), but not the caster objects themselves.
00218   remove_arc(caster_arc);
00219 
00220   // Copy the results of the render from the framebuffer into the projtex
00221   // shader's texture
00222   // _projtex_shader->get_texture()->prepare(gsg);
00223   _projtex_shader->get_texture()->copy(gsg, disp_region, gsg->get_render_buffer(RenderBuffer::T_back));
00224 
00225   // Restore the original display region and clear value
00226 
00227   gsg->set_color_clear_value(clear_color);
00228   gsg->pop_frame_buffer(old_fb);
00229   gsg->pop_display_region(old_dr);
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: ProjtexShadower::apply
00234 //       Access:
00235 //  Description:
00236 ////////////////////////////////////////////////////////////////////
00237 void ProjtexShadower::
00238 apply(Node *node, const AllAttributesWrapper &init_state,
00239       const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg) {
00240 
00241   Shader::apply(node, init_state, net_trans, gsg);
00242 
00243   // Now apply the projected shadow map
00244   _projtex_shader->apply(node, init_state, net_trans, gsg);
00245 }
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 

Generated on Fri May 2 00:44:01 2003 for Panda by doxygen1.3