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

panda/src/shader/planarReflector.cxx

Go to the documentation of this file.
00001 // Filename: planarReflector.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 "planarReflector.h"
00019 #include "config_shader.h"
00020 
00021 #include <pt_Node.h>
00022 #include <dftraverser.h>
00023 #include <attribTraverser.h>
00024 #include <displayRegion.h>
00025 #include <graphicsWindow.h>
00026 #include <renderBuffer.h>
00027 #include <perspectiveProjection.h>
00028 #include <look_at.h>
00029 #include <compose_matrix.h>
00030 #include <get_rel_pos.h>
00031 #include <lightTransition.h>
00032 #include <depthTestTransition.h>
00033 #include <depthWriteTransition.h>
00034 #include <depthWriteTransition.h>
00035 #include <textureTransition.h>
00036 #include <stencilTransition.h>
00037 #include <colorBlendTransition.h>
00038 #include <colorBlendAttribute.h>
00039 #include <cullFaceTransition.h>
00040 #include <transformTransition.h>
00041 #include <colorMaskTransition.h>
00042 #include <colorTransition.h>
00043 #include <clipPlaneTransition.h>
00044 #include <directRenderTraverser.h>
00045 #include <nodeAttributes.h>
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 // Static variables
00049 ////////////////////////////////////////////////////////////////////
00050 TypeHandle PlanarReflector::_type_handle;
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: PlanarReflector::Constructor
00054 //       Access:
00055 //  Description:
00056 ////////////////////////////////////////////////////////////////////
00057 PlanarReflector::PlanarReflector(void) : CasterShader()
00058 {
00059   Colorf c(0.8f, 0.8f, 0.8f, 1.0f);
00060   init(NULL, c);
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: PlanarReflector::Constructor
00065 //       Access:
00066 //  Description:
00067 ////////////////////////////////////////////////////////////////////
00068 PlanarReflector::
00069 PlanarReflector(PlaneNode* plane_node) : CasterShader()
00070 {
00071   Colorf c(0.8f, 0.8f, 0.8f, 1.0f);
00072   init(plane_node, c);
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: PlanarReflector::Constructor
00077 //       Access:
00078 //  Description:
00079 ////////////////////////////////////////////////////////////////////
00080 PlanarReflector::
00081 PlanarReflector(const Colorf& c) : CasterShader()
00082 {
00083   init(NULL, c);
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: PlanarReflector::Constructor
00088 //       Access:
00089 //  Description:
00090 ////////////////////////////////////////////////////////////////////
00091 PlanarReflector::
00092 PlanarReflector(PlaneNode* plane_node, const Colorf& c) : CasterShader()
00093 {
00094   init(plane_node, c);
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: PlanarReflector::init
00099 //       Access:
00100 //  Description:
00101 ////////////////////////////////////////////////////////////////////
00102 void PlanarReflector::init(PlaneNode *plane_node, const Colorf& c)
00103 {
00104   if (plane_node == NULL)
00105     plane_node = new PlaneNode;
00106 
00107   _save_color_buffer = true;
00108   _save_depth_buffer = true;
00109   _clip_to_plane = true;
00110 
00111   _color_buffer = NULL;
00112   _depth_buffer = NULL;
00113 
00114   _plane_node = plane_node;
00115   _color = c;
00116 }
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: PlanarReflector::pre_apply
00120 //       Access:
00121 //  Description:
00122 ////////////////////////////////////////////////////////////////////
00123 void PlanarReflector::
00124 pre_apply(Node *, const AllAttributesWrapper &,
00125           const AllTransitionsWrapper &, GraphicsStateGuardian *gsg)
00126 {
00127   int xo, yo, w, h;
00128   gsg->get_current_display_region()->get_region_pixels(xo, yo, w, h);
00129   _color_buffer = new PixelBuffer(PixelBuffer::rgb_buffer(w, h));
00130   _depth_buffer = new PixelBuffer(PixelBuffer::depth_buffer(w, h));
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: PlanarReflector::apply
00135 //       Access:
00136 //  Description:
00137 ////////////////////////////////////////////////////////////////////
00138 void PlanarReflector::
00139 apply(Node *node, const AllAttributesWrapper &init_state,
00140       const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg) {
00141   DirectRenderTraverser drt(gsg, RenderRelation::get_class_type());
00142 
00143   Shader::apply(node, init_state, net_trans, gsg);
00144 
00145   init_state.write(shader_cat->debug(false), 4);
00146 
00147   if (get_num_casters() == 0) {
00148     shader_cat.error()
00149       << "PlanarReflector::apply() - no casters in caster list" << endl;
00150     return;
00151   }
00152 
00153   //Due to possible priority problems, make an Off TextureTransition
00154   //with a high priority to ensure that textures are indeed turned of
00155   PT(TextureTransition) tex_off = new TextureTransition(TextureTransition::off());
00156   tex_off->set_priority(100);
00157 
00158   // If the node is un-textured, we need to render it once first (since
00159   // the shader transition won't have drawn it unless it is textured)
00160 
00161   if (!_multipass_on) {
00162     gsg->render_subgraph(&drt, node, init_state, net_trans);
00163   }
00164 
00165   // Save the stencil buffer clear value for below
00166   bool clear_stencil = gsg->get_stencil_clear_value();
00167   gsg->set_stencil_clear_value(false);
00168 
00169   {
00170     // Copy the transition wrapper so we can modify it freely.
00171     AllTransitionsWrapper trans(net_trans);
00172 
00173     // Save the current fully-rendered scene that is in the back buffer
00174     int buffer_mask = RenderBuffer::T_stencil;
00175     if (_save_color_buffer) {
00176       gsg->copy_pixel_buffer(_color_buffer,
00177                              gsg->get_current_display_region(),
00178                              gsg->get_render_buffer(RenderBuffer::T_back));
00179       buffer_mask |= RenderBuffer::T_back;
00180 
00181       ColorMaskTransition *cm = new ColorMaskTransition(0);
00182       trans.set_transition(cm);
00183     } else {
00184       ColorMaskTransition *cm =
00185         new ColorMaskTransition(ColorMaskProperty::M_a);
00186       trans.set_transition(cm);
00187     }
00188 
00189     if (_save_depth_buffer)
00190     {
00191       gsg->copy_pixel_buffer(_depth_buffer,
00192                              gsg->get_current_display_region(),
00193                              gsg->get_render_buffer(RenderBuffer::T_depth));
00194       //                     gsg->get_render_buffer(RenderBuffer::T_back));
00195     }
00196 
00197     // The scene has already been rendered so we need to stencil in an area
00198     // on the reflecting plane that is covered by the reflected objects.
00199 
00200     // Turn lighting off
00201     trans.set_transition(new LightTransition(LightTransition::all_off()));
00202 
00203     // Set the depth test to M_equal (? Or should this be M_none?)
00204     DepthTestTransition *dta =
00205       new DepthTestTransition(DepthTestProperty::M_equal);
00206     trans.set_transition(dta);
00207 
00208     // Turn off writes to the depth buffer
00209     DepthWriteTransition *dwa = new DepthWriteTransition;
00210     dwa->set_off();
00211     trans.set_transition(dwa);
00212 
00213     // Enable the stencil buffer
00214     StencilTransition *sa =
00215       new StencilTransition(StencilProperty::M_not_equal,
00216                             StencilProperty::A_replace);
00217     trans.set_transition(sa);
00218 
00219     // Disable texturing
00220     trans.set_transition(tex_off);
00221 
00222     // Disable blending
00223     trans.set_transition(new ColorBlendTransition(ColorBlendProperty::M_none));
00224 
00225     // Clear the stencil buffer (and color buffer if we're saving it)
00226     gsg->clear(gsg->get_render_buffer(buffer_mask));
00227 
00228     // Draw the reflecting object
00229     gsg->render_subgraph(&drt, node, init_state, trans);
00230   }
00231 
00232   {
00233     // Reflecting area on the plane has a stencil value of 1.  We can now
00234     // draw the reflected objects into this area.
00235     gsg->clear(gsg->get_render_buffer(RenderBuffer::T_depth));
00236 
00237     // Copy the transition wrapper so we can modify it freely.
00238     AllTransitionsWrapper trans(net_trans);
00239 
00240     // Adjust the stencil buffer properties
00241     StencilTransition *sa =
00242       new StencilTransition(StencilProperty::M_equal,
00243                             StencilProperty::A_keep);
00244     trans.set_transition(sa);
00245 
00246 
00247     // Draw back facing polys only
00248     CullFaceTransition *cf =
00249       new CullFaceTransition(CullFaceProperty::M_cull_counter_clockwise);
00250     trans.set_transition(cf);
00251 
00252     if (_clip_to_plane) {
00253       // Clip to the indicated plane.
00254       ClipPlaneTransition *cp = new ClipPlaneTransition;
00255       cp->set_on(_plane_node);
00256       trans.set_transition(cp);
00257     }
00258 
00259     // Reflect objects about the given plane
00260     PT_Node caster_group = new Node;
00261     NamedNodeVector::iterator c;
00262     for (c = _casters.begin(); c != _casters.end(); ++c) {
00263       Node *caster = (*c);
00264 
00265       LMatrix4f mat;
00266       get_rel_mat(caster, _plane_node, mat);
00267 
00268       RenderRelation *arc = new RenderRelation(caster_group, caster);
00269       arc->set_transition(new TransformTransition(mat));
00270     }
00271 
00272     // Parent this caster group to the node itself, since it's already
00273     // converted to the coordinate space of the node.
00274     PT(RenderRelation) caster_arc =
00275       new RenderRelation(_plane_node, caster_group);
00276 
00277     LMatrix4f plane_mat = _plane_node->get_plane().get_reflection_mat();
00278     caster_arc->set_transition(new TransformTransition(plane_mat));
00279 
00280     // Draw the reflected objects
00281     gsg->render_subgraph(&drt, _plane_node, init_state, trans);
00282 
00283     // Remove the caster group from the scene graph.  This will also
00284     // delete the temporary group node (since the reference count is
00285     // zero), but not the caster objects themselves.
00286     remove_arc(caster_arc);
00287   }
00288 
00289   {
00290     // Draw the reflecting object once more to modulate the reflected objects
00291     // by the reflectivity color
00292     AllTransitionsWrapper trans(net_trans);
00293 
00294     trans.set_transition(new StencilTransition(StencilProperty::M_none));
00295 
00296     ColorBlendTransition *cb =
00297       new ColorBlendTransition(ColorBlendProperty::M_multiply);
00298     trans.set_transition(cb);
00299 
00300     ColorTransition *c = new ColorTransition;
00301     c->set_on(_color);
00302     trans.set_transition(c);
00303 
00304     trans.set_transition(new LightTransition(LightTransition::all_off()));
00305     trans.set_transition(tex_off);
00306 
00307     gsg->render_subgraph(&drt, node, init_state, trans);
00308   }
00309 
00310   // Blend the previously rendered image with the reflected image
00311 
00312   if (_save_color_buffer) {
00313     NodeAttributes na;
00314 
00315     ColorBlendAttribute *cb =
00316       new ColorBlendAttribute;
00317     cb->set_mode(ColorBlendProperty::M_add);
00318     na.set_attribute(ColorBlendTransition::get_class_type(), cb);
00319 
00320     gsg->draw_pixel_buffer(_color_buffer, gsg->get_current_display_region(),
00321                            gsg->get_render_buffer(RenderBuffer::T_back), na);
00322   } else {
00323     // One more pass to redraw the reflecting object (additive blending)
00324     // Final color is reflecting obj color + (ref. obj. color * reflectivity)
00325     AllTransitionsWrapper trans(net_trans);
00326 
00327     StencilTransition *sa =
00328       new StencilTransition(StencilProperty::M_equal,
00329                             StencilProperty::A_keep);
00330     trans.set_transition(sa);
00331 
00332     DepthTestTransition *dta =
00333       new DepthTestTransition(DepthTestProperty::M_equal);
00334     trans.set_transition(dta);
00335 
00336     DepthWriteTransition *dwa = new DepthWriteTransition;
00337     dwa->set_off();
00338     trans.set_transition(dwa);
00339 
00340     ColorBlendTransition *cb =
00341       new ColorBlendTransition(ColorBlendProperty::M_add);
00342     trans.set_transition(cb);
00343 
00344     gsg->render_subgraph(&drt, node, init_state, trans);
00345   }
00346 
00347   if (_save_depth_buffer)
00348   {
00349     gsg->draw_pixel_buffer(_depth_buffer, gsg->get_current_display_region(),
00350                            gsg->get_render_buffer(RenderBuffer::T_depth));
00351               //           gsg->get_render_buffer(RenderBuffer::T_back));
00352   }
00353 
00354 
00355   // Restore the stencil buffer clear value
00356   gsg->set_stencil_clear_value(clear_stencil);
00357 }
00358 
00359 
00360 
00361 

Generated on Fri May 2 00:43:59 2003 for Panda by doxygen1.3