00001 // Filename: graphicsStateGuardian.cxx 00002 // Created by: drose (02Feb99) 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 00019 00020 #include "graphicsStateGuardian.h" 00021 #include "config_display.h" 00022 #include "textureContext.h" 00023 #include "renderBuffer.h" 00024 #include "colorAttrib.h" 00025 #include "colorScaleAttrib.h" 00026 #include "lightAttrib.h" 00027 #include "textureAttrib.h" 00028 #include "renderState.h" 00029 #include "depthWriteAttrib.h" 00030 #include "colorWriteAttrib.h" 00031 #include "textureAttrib.h" 00032 #include "lightAttrib.h" 00033 #include "clipPlaneAttrib.h" 00034 #include "light.h" 00035 #include "planeNode.h" 00036 #include "ambientLight.h" 00037 00038 #include "clockObject.h" 00039 #include "pStatTimer.h" 00040 00041 #include <algorithm> 00042 00043 #ifndef CPPPARSER 00044 PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage"); 00045 PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active"); 00046 PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms"); 00047 PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active"); 00048 PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes"); 00049 PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active"); 00050 PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory"); 00051 PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use"); 00052 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager"); 00053 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident"); 00054 PStatCollector GraphicsStateGuardian::_vertices_pcollector("Vertices"); 00055 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips"); 00056 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans"); 00057 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles"); 00058 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector("Vertices:Other"); 00059 PStatCollector GraphicsStateGuardian::_state_changes_pcollector("State changes"); 00060 PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes:Transforms"); 00061 PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures"); 00062 PStatCollector GraphicsStateGuardian::_nodes_pcollector("Nodes"); 00063 PStatCollector GraphicsStateGuardian::_geom_nodes_pcollector("Nodes:GeomNodes"); 00064 PStatCollector GraphicsStateGuardian::_frustum_cull_volumes_pcollector("Cull volumes"); 00065 PStatCollector GraphicsStateGuardian::_frustum_cull_transforms_pcollector("Cull volumes:Transforms"); 00066 00067 PStatCollector GraphicsStateGuardian::_set_state_pcollector("Draw:Set state"); 00068 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive"); 00069 PStatCollector GraphicsStateGuardian::_transform_states_pcollector("TransformStates"); 00070 PStatCollector GraphicsStateGuardian::_transform_states_unused_pcollector("TransformStates:Unused"); 00071 PStatCollector GraphicsStateGuardian::_render_states_pcollector("RenderStates"); 00072 PStatCollector GraphicsStateGuardian::_render_states_unused_pcollector("RenderStates:Unused"); 00073 00074 #endif 00075 00076 TypeHandle GraphicsStateGuardian::_type_handle; 00077 00078 //////////////////////////////////////////////////////////////////// 00079 // Function: GraphicsStateGuardian::Constructor 00080 // Access: Public 00081 // Description: 00082 //////////////////////////////////////////////////////////////////// 00083 GraphicsStateGuardian:: 00084 GraphicsStateGuardian(const FrameBufferProperties &properties) { 00085 _properties = properties; 00086 _coordinate_system = default_coordinate_system; 00087 _current_display_region = (DisplayRegion*)0L; 00088 _current_lens = (Lens *)NULL; 00089 _needs_reset = true; 00090 _closing_gsg = false; 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: GraphicsStateGuardian::Destructor 00095 // Access: Public, Virtual 00096 // Description: 00097 //////////////////////////////////////////////////////////////////// 00098 GraphicsStateGuardian:: 00099 ~GraphicsStateGuardian() { 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: GraphicsStateGuardian::reset 00104 // Access: Public, Virtual 00105 // Description: Resets all internal state as if the gsg were newly 00106 // created. 00107 //////////////////////////////////////////////////////////////////// 00108 void GraphicsStateGuardian:: 00109 reset() { 00110 _needs_reset = false; 00111 00112 _display_region_stack_level = 0; 00113 _frame_buffer_stack_level = 0; 00114 _lens_stack_level = 0; 00115 00116 _state = RenderState::make_empty(); 00117 _transform = TransformState::make_identity(); 00118 00119 _buffer_mask = 0; 00120 _color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); 00121 _depth_clear_value = 1.0f; 00122 _stencil_clear_value = 0.0f; 00123 _accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); 00124 _clear_buffer_type = RenderBuffer::T_back | RenderBuffer::T_depth; 00125 _normals_enabled = false; 00126 00127 //Color and alpha transform variables 00128 _color_transform_enabled = 0; 00129 _current_color_offset.set(0.0f, 0.0f, 0.0f, 0.0f); 00130 _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); 00131 00132 _color_write_mode = ColorWriteAttrib::M_on; 00133 _color_blend_mode = ColorBlendAttrib::M_none; 00134 _transparency_mode = TransparencyAttrib::M_none; 00135 00136 _has_scene_graph_color = false; 00137 _scene_graph_color_stale = false; 00138 _vertex_colors_enabled = true; 00139 _lighting_enabled = false; 00140 _lighting_enabled_this_frame = false; 00141 00142 _clip_planes_enabled = false; 00143 _clip_planes_enabled_this_frame = false; 00144 } 00145 00146 //////////////////////////////////////////////////////////////////// 00147 // Function: GraphicsStateGuardian::get_render_buffer 00148 // Access: Public 00149 // Description: Returns a RenderBuffer object suitable for operating 00150 // on the requested set of buffers. buffer_type is the 00151 // union of all the desired RenderBuffer::Type values. 00152 //////////////////////////////////////////////////////////////////// 00153 RenderBuffer GraphicsStateGuardian:: 00154 get_render_buffer(int buffer_type) { 00155 return RenderBuffer(this, buffer_type & _buffer_mask); 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: GraphicsStateGuardian::release_all_textures 00160 // Access: Public 00161 // Description: Frees the resources for all textures associated with 00162 // this GSG. 00163 //////////////////////////////////////////////////////////////////// 00164 void GraphicsStateGuardian:: 00165 release_all_textures() { 00166 // We must get a copy of the _prepared_textures list first, because 00167 // each call to release_texture() will remove that texture from the 00168 // list, and we don't want to traverse a list while we're modifying 00169 // it! 00170 00171 Textures temp = _prepared_textures; 00172 for (Textures::const_iterator ti = temp.begin(); 00173 ti != temp.end(); 00174 ++ti) { 00175 release_texture(*ti); 00176 } 00177 00178 // Now that we've released all of the textures, the 00179 // _prepared_textures list should have completely emptied itself. 00180 nassertv(_prepared_textures.empty()); 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: GraphicsStateGuardian::release_all_geoms 00185 // Access: Public 00186 // Description: Frees the resources for all Geoms and GeomNodes 00187 // associated with this GSG. Warning! This may make 00188 // the Geoms unrenderable, if the Panda-level 00189 // information has been deleted. 00190 //////////////////////////////////////////////////////////////////// 00191 void GraphicsStateGuardian:: 00192 release_all_geoms() { 00193 // As above, for both Geoms and GeomNodes. 00194 00195 Geoms temp_geoms = _prepared_geoms; 00196 for (Geoms::const_iterator gi = temp_geoms.begin(); 00197 gi != temp_geoms.end(); 00198 ++gi) { 00199 release_geom(*gi); 00200 } 00201 00202 GeomNodes temp_geom_nodes = _prepared_geom_nodes; 00203 for (GeomNodes::const_iterator gni = temp_geom_nodes.begin(); 00204 gni != temp_geom_nodes.end(); 00205 ++gni) { 00206 release_geom_node(*gni); 00207 } 00208 00209 nassertv(_prepared_geoms.empty()); 00210 nassertv(_prepared_geom_nodes.empty()); 00211 } 00212 00213 //////////////////////////////////////////////////////////////////// 00214 // Function: GraphicsStateGuardian::prepare_texture 00215 // Access: Public, Virtual 00216 // Description: Prepares the indicated texture for retained-mode 00217 // rendering. In the future, this texture may be 00218 // applied simply by calling apply_texture() with the 00219 // value returned by this function. 00220 //////////////////////////////////////////////////////////////////// 00221 TextureContext *GraphicsStateGuardian:: 00222 prepare_texture(Texture *) { 00223 return (TextureContext *)NULL; 00224 } 00225 00226 //////////////////////////////////////////////////////////////////// 00227 // Function: GraphicsStateGuardian::apply_texture 00228 // Access: Public, Virtual 00229 // Description: Applies the texture previously indicated via a call 00230 // to prepare_texture() to the graphics state, so that 00231 // geometry rendered in the future will be rendered with 00232 // the given texture. 00233 //////////////////////////////////////////////////////////////////// 00234 void GraphicsStateGuardian:: 00235 apply_texture(TextureContext *) { 00236 } 00237 00238 //////////////////////////////////////////////////////////////////// 00239 // Function: GraphicsStateGuardian::release_texture 00240 // Access: Public, Virtual 00241 // Description: Frees the resources previously allocated via a call 00242 // to prepare_texture(), including deleting the 00243 // TextureContext itself, if necessary. 00244 //////////////////////////////////////////////////////////////////// 00245 void GraphicsStateGuardian:: 00246 release_texture(TextureContext *) { 00247 } 00248 00249 //////////////////////////////////////////////////////////////////// 00250 // Function: GraphicsStateGuardian::prepare_geom_node 00251 // Access: Public, Virtual 00252 // Description: Prepares the indicated GeomNode for retained-mode 00253 // rendering. If this function returns non-NULL, the 00254 // value returned will be passed back to a future call 00255 // to draw_geom_node(), which is expected to draw the 00256 // contents of the node. 00257 //////////////////////////////////////////////////////////////////// 00258 GeomNodeContext *GraphicsStateGuardian:: 00259 prepare_geom_node(GeomNode *) { 00260 return (GeomNodeContext *)NULL; 00261 } 00262 00263 //////////////////////////////////////////////////////////////////// 00264 // Function: GraphicsStateGuardian::draw_geom_node 00265 // Access: Public, Virtual 00266 // Description: Draws a GeomNode previously indicated by a call to 00267 // prepare_geom_node(). 00268 //////////////////////////////////////////////////////////////////// 00269 void GraphicsStateGuardian:: 00270 draw_geom_node(GeomNode *node, const RenderState *state, 00271 GeomNodeContext *) { 00272 #if 0 // temporarily disabled until ported to new scene graph 00273 int num_geoms = node->get_num_geoms(); 00274 for (int i = 0; i < num_geoms; i++) { 00275 node->get_geom(i)->draw(this); 00276 } 00277 #endif // temporarily disabled until ported to new scene graph 00278 } 00279 00280 //////////////////////////////////////////////////////////////////// 00281 // Function: GraphicsStateGuardian::release_geom_node 00282 // Access: Public, Virtual 00283 // Description: Frees the resources previously allocated via a call 00284 // to prepare_geom_node(), including deleting the 00285 // GeomNodeContext itself, if necessary. 00286 //////////////////////////////////////////////////////////////////// 00287 void GraphicsStateGuardian:: 00288 release_geom_node(GeomNodeContext *) { 00289 } 00290 00291 //////////////////////////////////////////////////////////////////// 00292 // Function: GraphicsStateGuardian::prepare_geom 00293 // Access: Public, Virtual 00294 // Description: Prepares the indicated Geom for retained-mode 00295 // rendering. The value returned by this function will 00296 // be passed back into future calls to draw_tristrip(), 00297 // etc., along with the Geom pointer. 00298 //////////////////////////////////////////////////////////////////// 00299 GeomContext *GraphicsStateGuardian:: 00300 prepare_geom(Geom *) { 00301 return (GeomContext *)NULL; 00302 } 00303 00304 //////////////////////////////////////////////////////////////////// 00305 // Function: GraphicsStateGuardian::release_geom 00306 // Access: Public, Virtual 00307 // Description: Frees the resources previously allocated via a call 00308 // to prepare_geom(), including deleting the GeomContext 00309 // itself, if necessary. 00310 //////////////////////////////////////////////////////////////////// 00311 void GraphicsStateGuardian:: 00312 release_geom(GeomContext *) { 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: GraphicsStateGuardian::set_state_and_transform 00317 // Access: Public, Virtual 00318 // Description: Simultaneously resets the render state and the 00319 // transform state. 00320 //////////////////////////////////////////////////////////////////// 00321 void GraphicsStateGuardian:: 00322 set_state_and_transform(const RenderState *state, 00323 const TransformState *transform) { 00324 set_state(state); 00325 set_transform(transform); 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: GraphicsStateGuardian::set_color_clear_value 00330 // Access: Public 00331 // Description: Sets the color that the next do_clear() command will set 00332 // the color buffer to 00333 //////////////////////////////////////////////////////////////////// 00334 void GraphicsStateGuardian:: 00335 set_color_clear_value(const Colorf& value) { 00336 _color_clear_value = value; 00337 } 00338 00339 //////////////////////////////////////////////////////////////////// 00340 // Function: GraphicsStateGuardian::set_depth_clear_value 00341 // Access: Public 00342 // Description: Sets the depth that the next do_clear() command will set 00343 // the depth buffer to 00344 //////////////////////////////////////////////////////////////////// 00345 void GraphicsStateGuardian:: 00346 set_depth_clear_value(const float value) { 00347 _depth_clear_value = value; 00348 } 00349 00350 //////////////////////////////////////////////////////////////////// 00351 // Function: GraphicsStateGuardian::clear 00352 // Access: Public 00353 // Description: Clears the framebuffer within the current 00354 // DisplayRegion, according to the flags indicated by 00355 // the given ClearableRegion object. 00356 //////////////////////////////////////////////////////////////////// 00357 void GraphicsStateGuardian:: 00358 clear(ClearableRegion *clearable) { 00359 int clear_buffer_type = 0; 00360 if (clearable->get_clear_color_active()) { 00361 clear_buffer_type |= RenderBuffer::T_back; 00362 set_color_clear_value(clearable->get_clear_color()); 00363 } 00364 if (clearable->get_clear_depth_active()) { 00365 clear_buffer_type |= RenderBuffer::T_depth; 00366 set_depth_clear_value(clearable->get_clear_depth()); 00367 } 00368 00369 if (clear_buffer_type != 0) { 00370 prepare_display_region(); 00371 do_clear(get_render_buffer(clear_buffer_type)); 00372 } 00373 } 00374 00375 //////////////////////////////////////////////////////////////////// 00376 // Function: GraphicsStateGuardian::prepare_lens 00377 // Access: Public, Virtual 00378 // Description: Makes the current lens (whichever lens was most 00379 // recently specified with push_lens()) active, so that 00380 // it will transform future rendered geometry. Normally 00381 // this is only called from the draw process, and 00382 // usually it is called immediately after a call to 00383 // push_lens(). 00384 // 00385 // The return value is true if the lens is acceptable, 00386 // false if it is not. 00387 //////////////////////////////////////////////////////////////////// 00388 bool GraphicsStateGuardian:: 00389 prepare_lens() { 00390 return false; 00391 } 00392 00393 //////////////////////////////////////////////////////////////////// 00394 // Function: GraphicsStateGuardian::begin_frame 00395 // Access: Public, Virtual 00396 // Description: Called before each frame is rendered, to allow the 00397 // GSG a chance to do any internal cleanup before 00398 // beginning the frame. 00399 // 00400 // The return value is true if successful (in which case 00401 // the frame will be drawn and end_frame() will be 00402 // called later), or false if unsuccessful (in which 00403 // case nothing will be drawn and end_frame() will not 00404 // be called). 00405 //////////////////////////////////////////////////////////////////// 00406 bool GraphicsStateGuardian:: 00407 begin_frame() { 00408 // Undo any lighting we had enabled last frame, to force the lights 00409 // to be reissued, in case their parameters or positions have 00410 // changed between frames. 00411 if (_lighting_enabled_this_frame) { 00412 for (int i = 0; i < (int)_light_info.size(); i++) { 00413 if (_light_info[i]._enabled) { 00414 enable_light(i, false); 00415 _light_info[i]._enabled = false; 00416 } 00417 _light_info[i]._light = (Light *)NULL; 00418 } 00419 00420 // Also force the lighting state to unlit, so that issue_light() 00421 // will be guaranteed to be called next frame even if we have the 00422 // same set of light pointers we had this frame. 00423 modify_state(get_unlit_state()); 00424 00425 _lighting_enabled_this_frame = false; 00426 } 00427 00428 // Ditto for the clipping planes. 00429 if (_clip_planes_enabled_this_frame) { 00430 for (int i = 0; i < (int)_clip_plane_info.size(); i++) { 00431 if (_clip_plane_info[i]._enabled) { 00432 enable_clip_plane(i, false); 00433 _clip_plane_info[i]._enabled = false; 00434 } 00435 _clip_plane_info[i]._plane = (PlaneNode *)NULL; 00436 } 00437 00438 modify_state(get_unclipped_state()); 00439 00440 _clip_planes_enabled_this_frame = false; 00441 } 00442 00443 #ifdef DO_PSTATS 00444 // For Pstats to track our current texture memory usage, we have to 00445 // reset the set of current textures each frame. 00446 init_frame_pstats(); 00447 00448 // But since we don't get sent a new issue_texture() unless our 00449 // texture state has changed, we have to be sure to clear the 00450 // current texture state now. A bit unfortunate, but probably not 00451 // measurably expensive. 00452 modify_state(get_untextured_state()); 00453 #endif 00454 return true; 00455 } 00456 00457 //////////////////////////////////////////////////////////////////// 00458 // Function: GraphicsStateGuardian::begin_scene 00459 // Access: Public, Virtual 00460 // Description: Called between begin_frame() and end_frame() to mark 00461 // the beginning of drawing commands for a "scene" 00462 // (usually a particular DisplayRegion) within a frame. 00463 // All 3-D drawing commands, except the clear operation, 00464 // must be enclosed within begin_scene() .. end_scene(). 00465 // 00466 // The return value is true if successful (in which case 00467 // the scene will be drawn and end_scene() will be 00468 // called later), or false if unsuccessful (in which 00469 // case nothing will be drawn and end_scene() will not 00470 // be called). 00471 //////////////////////////////////////////////////////////////////// 00472 bool GraphicsStateGuardian:: 00473 begin_scene() { 00474 return true; 00475 } 00476 00477 //////////////////////////////////////////////////////////////////// 00478 // Function: GraphicsStateGuardian::end_scene 00479 // Access: Public, Virtual 00480 // Description: Called between begin_frame() and end_frame() to mark 00481 // the end of drawing commands for a "scene" (usually a 00482 // particular DisplayRegion) within a frame. All 3-D 00483 // drawing commands, except the clear operation, must be 00484 // enclosed within begin_scene() .. end_scene(). 00485 //////////////////////////////////////////////////////////////////// 00486 void GraphicsStateGuardian:: 00487 end_scene() { 00488 } 00489 00490 //////////////////////////////////////////////////////////////////// 00491 // Function: GraphicsStateGuardian::end_frame 00492 // Access: Public, Virtual 00493 // Description: Called after each frame is rendered, to allow the 00494 // GSG a chance to do any internal cleanup after 00495 // rendering the frame, and before the window flips. 00496 //////////////////////////////////////////////////////////////////// 00497 void GraphicsStateGuardian:: 00498 end_frame() { 00499 } 00500 00501 //////////////////////////////////////////////////////////////////// 00502 // Function: GraphicsStateGuardian::wants_normals 00503 // Access: Public, Virtual 00504 // Description: 00505 //////////////////////////////////////////////////////////////////// 00506 bool GraphicsStateGuardian:: 00507 wants_normals() const { 00508 return _normals_enabled; 00509 } 00510 00511 //////////////////////////////////////////////////////////////////// 00512 // Function: GraphicsStateGuardian::wants_texcoords 00513 // Access: Public, Virtual 00514 // Description: 00515 //////////////////////////////////////////////////////////////////// 00516 bool GraphicsStateGuardian:: 00517 wants_texcoords() const { 00518 return false; 00519 } 00520 00521 //////////////////////////////////////////////////////////////////// 00522 // Function: GraphicsStateGuardian::wants_colors 00523 // Access: Public, Virtual 00524 // Description: Returns true if the GSG should issue geometry color 00525 // commands, false otherwise. 00526 //////////////////////////////////////////////////////////////////// 00527 bool GraphicsStateGuardian:: 00528 wants_colors() const { 00529 return _vertex_colors_enabled; 00530 } 00531 00532 //////////////////////////////////////////////////////////////////// 00533 // Function: GraphicsStateGuardian::depth_offset_decals 00534 // Access: Public, Virtual 00535 // Description: Returns true if this GSG can implement decals using a 00536 // DepthOffsetAttrib, or false if that is unreliable 00537 // and the three-step rendering process should be used 00538 // instead. 00539 //////////////////////////////////////////////////////////////////// 00540 bool GraphicsStateGuardian:: 00541 depth_offset_decals() { 00542 return false; 00543 } 00544 00545 //////////////////////////////////////////////////////////////////// 00546 // Function: GraphicsStateGuardian::begin_decal_base_first 00547 // Access: Public, Virtual 00548 // Description: Called during draw to begin a three-step rendering 00549 // phase to draw decals. The first step, 00550 // begin_decal_base_first(), is called prior to drawing the 00551 // base geometry. It should set up whatever internal 00552 // state is appropriate, as well as returning a 00553 // RenderState object that should be applied to the base 00554 // geometry for rendering. 00555 //////////////////////////////////////////////////////////////////// 00556 CPT(RenderState) GraphicsStateGuardian:: 00557 begin_decal_base_first() { 00558 // Turn off writing the depth buffer to render the base geometry. 00559 static CPT(RenderState) decal_base_first; 00560 if (decal_base_first == (const RenderState *)NULL) { 00561 decal_base_first = RenderState::make 00562 (DepthWriteAttrib::make(DepthWriteAttrib::M_off), 00563 RenderState::get_max_priority()); 00564 } 00565 return decal_base_first; 00566 } 00567 00568 //////////////////////////////////////////////////////////////////// 00569 // Function: GraphicsStateGuardian::begin_decal_nested 00570 // Access: Public, Virtual 00571 // Description: Called during draw to begin a three-step rendering 00572 // phase to draw decals. The second step, 00573 // begin_decal_nested(), is called after drawing the 00574 // base geometry and prior to drawing any of the nested 00575 // decal geometry that is to be applied to the base 00576 // geometry. 00577 //////////////////////////////////////////////////////////////////// 00578 CPT(RenderState) GraphicsStateGuardian:: 00579 begin_decal_nested() { 00580 // We should keep the depth buffer off during this operation, so 00581 // that decals on decals will render properly. 00582 static CPT(RenderState) decal_nested; 00583 if (decal_nested == (const RenderState *)NULL) { 00584 decal_nested = RenderState::make 00585 (DepthWriteAttrib::make(DepthWriteAttrib::M_off), 00586 RenderState::get_max_priority()); 00587 } 00588 return decal_nested; 00589 } 00590 00591 //////////////////////////////////////////////////////////////////// 00592 // Function: GraphicsStateGuardian::begin_decal_base_second 00593 // Access: Public, Virtual 00594 // Description: Called during draw to begin a three-step rendering 00595 // phase to draw decals. The third step, 00596 // begin_decal_base_second(), is called after drawing the 00597 // base geometry and the nested decal geometry, and 00598 // prior to drawing the base geometry one more time (if 00599 // needed). 00600 // 00601 // It should return a RenderState object appropriate for 00602 // rendering the base geometry the second time, or NULL 00603 // if it is not necessary to re-render the base 00604 // geometry. 00605 //////////////////////////////////////////////////////////////////// 00606 CPT(RenderState) GraphicsStateGuardian:: 00607 begin_decal_base_second() { 00608 // Now let the depth buffer go back on, but turn off writing the 00609 // color buffer to render the base geometry after the second pass. 00610 // Also, turn off texturing since there's no need for it now. 00611 static CPT(RenderState) decal_base_second; 00612 if (decal_base_second == (const RenderState *)NULL) { 00613 decal_base_second = RenderState::make 00614 (ColorWriteAttrib::make(ColorWriteAttrib::M_off), 00615 // On reflection, we need to leave texturing on so the alpha 00616 // test mechanism can work (if it is enabled, e.g. we are 00617 // rendering an object with M_dual transparency). 00618 // TextureAttrib::make_off(), 00619 RenderState::get_max_priority()); 00620 } 00621 return decal_base_second; 00622 } 00623 00624 //////////////////////////////////////////////////////////////////// 00625 // Function: GraphicsStateGuardian::finish_decal 00626 // Access: Public, Virtual 00627 // Description: Called during draw to clean up after decals are 00628 // finished. 00629 //////////////////////////////////////////////////////////////////// 00630 void GraphicsStateGuardian:: 00631 finish_decal() { 00632 // No need to do anything special here. 00633 } 00634 00635 //////////////////////////////////////////////////////////////////// 00636 // Function: GraphicsStateGuardian::get_internal_coordinate_system 00637 // Access: Public, Virtual 00638 // Description: Should be overridden by derived classes to return the 00639 // coordinate system used internally by the GSG, if any 00640 // one particular coordinate system is used. The 00641 // default, CS_default, indicates that the GSG can use 00642 // any coordinate system. 00643 // 00644 // If this returns other than CS_default, the 00645 // GraphicsEngine will automatically convert all 00646 // transforms into the indicated coordinate system. 00647 //////////////////////////////////////////////////////////////////// 00648 CoordinateSystem GraphicsStateGuardian:: 00649 get_internal_coordinate_system() const { 00650 return CS_default; 00651 } 00652 00653 //////////////////////////////////////////////////////////////////// 00654 // Function: GraphicsStateGuardian::issue_transform 00655 // Access: Public, Virtual 00656 // Description: Sends the indicated transform matrix to the graphics 00657 // API to be applied to future vertices. 00658 //////////////////////////////////////////////////////////////////// 00659 void GraphicsStateGuardian:: 00660 issue_transform(const TransformState *) { 00661 } 00662 00663 //////////////////////////////////////////////////////////////////// 00664 // Function: GraphicsStateGuardian::issue_color_scale 00665 // Access: Public, Virtual 00666 // Description: 00667 //////////////////////////////////////////////////////////////////// 00668 void GraphicsStateGuardian:: 00669 issue_color_scale(const ColorScaleAttrib *attrib) { 00670 _current_color_scale = attrib->get_scale(); 00671 00672 if (_current_color_scale == LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) { 00673 _color_transform_enabled &= ~CT_scale; 00674 } else { 00675 _color_transform_enabled |= CT_scale; 00676 } 00677 00678 _scene_graph_color_stale = _has_scene_graph_color; 00679 } 00680 00681 //////////////////////////////////////////////////////////////////// 00682 // Function: GraphicsStateGuardian::issue_color 00683 // Access: Public, Virtual 00684 // Description: This method is defined in the base class because it 00685 // is likely that this functionality will be used for 00686 // all (or at least most) kinds of 00687 // GraphicsStateGuardians--it's not specific to any one 00688 // rendering backend. 00689 // 00690 // The ColorAttribute just changes the interpretation of 00691 // the color on the vertices, and fiddles with 00692 // _vertex_colors_enabled, etc. 00693 //////////////////////////////////////////////////////////////////// 00694 void GraphicsStateGuardian:: 00695 issue_color(const ColorAttrib *attrib) { 00696 switch (attrib->get_color_type()) { 00697 case ColorAttrib::T_flat: 00698 // Color attribute flat: it specifies a scene graph color that 00699 // overrides the vertex color. 00700 _scene_graph_color = attrib->get_color(); 00701 _has_scene_graph_color = true; 00702 _vertex_colors_enabled = false; 00703 _scene_graph_color_stale = true; 00704 break; 00705 00706 case ColorAttrib::T_off: 00707 // Color attribute off: it specifies that no scene graph color is 00708 // in effect, and vertex color is not important either. 00709 _has_scene_graph_color = false; 00710 _scene_graph_color_stale = false; 00711 _vertex_colors_enabled = false; 00712 break; 00713 00714 case ColorAttrib::T_vertex: 00715 // Color attribute vertex: it specifies that vertex color should 00716 // be revealed. 00717 _has_scene_graph_color = false; 00718 _scene_graph_color_stale = false; 00719 _vertex_colors_enabled = true; 00720 break; 00721 } 00722 } 00723 00724 //////////////////////////////////////////////////////////////////// 00725 // Function: GraphicsStateGuardian::issue_light 00726 // Access: Public, Virtual 00727 // Description: The default implementation of issue_light() assumes 00728 // we have a limited number of hardware lights 00729 // available. This function assigns each light to a 00730 // different hardware light id, trying to keep each 00731 // light associated with the same id where possible, but 00732 // reusing id's when necessary. When it is no longer 00733 // possible to reuse existing id's (e.g. all id's are in 00734 // use), slot_new_light() is called to prepare the next 00735 // sequential light id. 00736 // 00737 // It will call apply_light() each time a light is 00738 // assigned to a particular id for the first time in a 00739 // given frame, and it will subsequently call 00740 // enable_light() to enable or disable each light as the 00741 // frame is rendered, as well as enable_lighting() to 00742 // enable or disable overall lighting. 00743 // 00744 // If this model of hardware lights with id's does not 00745 // apply to a particular graphics engine, it should 00746 // override this function to do something more 00747 // appropriate instead. 00748 //////////////////////////////////////////////////////////////////// 00749 void GraphicsStateGuardian:: 00750 issue_light(const LightAttrib *attrib) { 00751 // Initialize the current ambient light total and newly enabled 00752 // light list 00753 Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f); 00754 int i; 00755 int max_lights = (int)_light_info.size(); 00756 for (i = 0; i < max_lights; i++) { 00757 _light_info[i]._next_enabled = false; 00758 } 00759 00760 bool any_bound = false; 00761 00762 int num_enabled = 0; 00763 int num_lights = attrib->get_num_lights(); 00764 if (attrib->get_operation() == LightAttrib::O_remove) { 00765 num_lights = 0; 00766 } 00767 for (int li = 0; li < num_lights; li++) { 00768 Light *light = attrib->get_light(li); 00769 nassertv(light != (Light *)NULL); 00770 00771 num_enabled++; 00772 00773 // Lighting should be enabled before we apply any lights. 00774 enable_lighting(true); 00775 _lighting_enabled = true; 00776 _lighting_enabled_this_frame = true; 00777 00778 if (light->get_type() == AmbientLight::get_class_type()) { 00779 // Ambient lights don't require specific light ids; simply add 00780 // in the ambient contribution to the current total 00781 cur_ambient_light += light->get_color(); 00782 00783 } else { 00784 // Check to see if this light has already been bound to an id 00785 int cur_light_id = -1; 00786 for (i = 0; i < max_lights; i++) { 00787 if (_light_info[i]._light == light) { 00788 // Light has already been bound to an id, we only need to 00789 // enable the light, not reapply it. 00790 cur_light_id = -2; 00791 enable_light(i, true); 00792 _light_info[i]._enabled = true; 00793 _light_info[i]._next_enabled = true; 00794 break; 00795 } 00796 } 00797 00798 // See if there are any unbound light ids 00799 if (cur_light_id == -1) { 00800 for (i = 0; i < max_lights; i++) { 00801 if (_light_info[i]._light == (Light *)NULL) { 00802 _light_info[i]._light = light; 00803 cur_light_id = i; 00804 break; 00805 } 00806 } 00807 } 00808 00809 // If there were no unbound light ids, see if we can replace 00810 // a currently unused but previously bound id 00811 if (cur_light_id == -1) { 00812 for (i = 0; i < max_lights; i++) { 00813 if (!attrib->has_light(_light_info[i]._light)) { 00814 _light_info[i]._light = light; 00815 cur_light_id = i; 00816 break; 00817 } 00818 } 00819 } 00820 00821 // If we *still* don't have a light id, slot a new one. 00822 if (cur_light_id == -1) { 00823 if (slot_new_light(max_lights)) { 00824 cur_light_id = max_lights; 00825 _light_info.push_back(LightInfo()); 00826 max_lights++; 00827 nassertv(max_lights == (int)_light_info.size()); 00828 } 00829 } 00830 00831 if (cur_light_id >= 0) { 00832 enable_light(cur_light_id, true); 00833 _light_info[cur_light_id]._enabled = true; 00834 _light_info[cur_light_id]._next_enabled = true; 00835 00836 if (!any_bound) { 00837 begin_bind_lights(); 00838 any_bound = true; 00839 } 00840 00841 // This is the first time this frame that this light has been 00842 // bound to this particular id. 00843 light->bind(this, cur_light_id); 00844 00845 } else if (cur_light_id == -1) { 00846 gsg_cat.warning() 00847 << "Failed to bind " << *light << " to id.\n"; 00848 } 00849 } 00850 } 00851 00852 // Disable all unused lights 00853 for (i = 0; i < max_lights; i++) { 00854 if (!_light_info[i]._next_enabled) { 00855 enable_light(i, false); 00856 _light_info[i]._enabled = false; 00857 } 00858 } 00859 00860 // If no lights were enabled, disable lighting 00861 if (num_enabled == 0) { 00862 enable_lighting(false); 00863 _lighting_enabled = false; 00864 } else { 00865 set_ambient_light(cur_ambient_light); 00866 } 00867 00868 if (any_bound) { 00869 end_bind_lights(); 00870 } 00871 } 00872 00873 //////////////////////////////////////////////////////////////////// 00874 // Function: GraphicsStateGuardian::issue_color_write 00875 // Access: Public, Virtual 00876 // Description: 00877 //////////////////////////////////////////////////////////////////// 00878 void GraphicsStateGuardian:: 00879 issue_color_write(const ColorWriteAttrib *attrib) { 00880 _color_write_mode = attrib->get_mode(); 00881 set_blend_mode(_color_write_mode, _color_blend_mode, _transparency_mode); 00882 } 00883 00884 //////////////////////////////////////////////////////////////////// 00885 // Function: GraphicsStateGuardian::issue_transparency 00886 // Access: Public, Virtual 00887 // Description: 00888 //////////////////////////////////////////////////////////////////// 00889 void GraphicsStateGuardian:: 00890 issue_transparency(const TransparencyAttrib *attrib) { 00891 _transparency_mode = attrib->get_mode(); 00892 set_blend_mode(_color_write_mode, _color_blend_mode, _transparency_mode); 00893 } 00894 00895 //////////////////////////////////////////////////////////////////// 00896 // Function: GraphicsStateGuardian::issue_color_blend 00897 // Access: Public, Virtual 00898 // Description: 00899 //////////////////////////////////////////////////////////////////// 00900 void GraphicsStateGuardian:: 00901 issue_color_blend(const ColorBlendAttrib *attrib) { 00902 _color_blend_mode = attrib->get_mode(); 00903 set_blend_mode(_color_write_mode, _color_blend_mode, _transparency_mode); 00904 } 00905 00906 //////////////////////////////////////////////////////////////////// 00907 // Function: GraphicsStateGuardian::issue_clip_plane 00908 // Access: Public, Virtual 00909 // Description: This is fundametically similar to issue_light(), with 00910 // calls to slot_new_clip_plane(), apply_clip_plane(), 00911 // and enable_clip_planes(), as appropriate. 00912 //////////////////////////////////////////////////////////////////// 00913 void GraphicsStateGuardian:: 00914 issue_clip_plane(const ClipPlaneAttrib *attrib) { 00915 int i; 00916 int max_planes = (int)_clip_plane_info.size(); 00917 for (i = 0; i < max_planes; i++) { 00918 _clip_plane_info[i]._next_enabled = false; 00919 } 00920 00921 bool any_bound = false; 00922 00923 int num_enabled = 0; 00924 int num_planes = attrib->get_num_planes(); 00925 if (attrib->get_operation() == ClipPlaneAttrib::O_remove) { 00926 num_planes = 0; 00927 } 00928 for (int li = 0; li < num_planes; li++) { 00929 PlaneNode *plane = attrib->get_plane(li); 00930 nassertv(plane != (PlaneNode *)NULL); 00931 00932 num_enabled++; 00933 00934 // Planeing should be enabled before we apply any planes. 00935 enable_clip_planes(true); 00936 _clip_planes_enabled = true; 00937 _clip_planes_enabled_this_frame = true; 00938 00939 // Check to see if this plane has already been bound to an id 00940 int cur_plane_id = -1; 00941 for (i = 0; i < max_planes; i++) { 00942 if (_clip_plane_info[i]._plane == plane) { 00943 // Plane has already been bound to an id, we only need to 00944 // enable the plane, not reapply it. 00945 cur_plane_id = -2; 00946 enable_clip_plane(i, true); 00947 _clip_plane_info[i]._enabled = true; 00948 _clip_plane_info[i]._next_enabled = true; 00949 break; 00950 } 00951 } 00952 00953 // See if there are any unbound plane ids 00954 if (cur_plane_id == -1) { 00955 for (i = 0; i < max_planes; i++) { 00956 if (_clip_plane_info[i]._plane == (PlaneNode *)NULL) { 00957 _clip_plane_info[i]._plane = plane; 00958 cur_plane_id = i; 00959 break; 00960 } 00961 } 00962 } 00963 00964 // If there were no unbound plane ids, see if we can replace 00965 // a currently unused but previously bound id 00966 if (cur_plane_id == -1) { 00967 for (i = 0; i < max_planes; i++) { 00968 if (!attrib->has_plane(_clip_plane_info[i]._plane)) { 00969 _clip_plane_info[i]._plane = plane; 00970 cur_plane_id = i; 00971 break; 00972 } 00973 } 00974 } 00975 00976 // If we *still* don't have a plane id, slot a new one. 00977 if (cur_plane_id == -1) { 00978 if (slot_new_clip_plane(max_planes)) { 00979 cur_plane_id = max_planes; 00980 _clip_plane_info.push_back(ClipPlaneInfo()); 00981 max_planes++; 00982 nassertv(max_planes == (int)_clip_plane_info.size()); 00983 } 00984 } 00985 00986 if (cur_plane_id >= 0) { 00987 enable_clip_plane(cur_plane_id, true); 00988 _clip_plane_info[cur_plane_id]._enabled = true; 00989 _clip_plane_info[cur_plane_id]._next_enabled = true; 00990 00991 if (!any_bound) { 00992 begin_bind_clip_planes(); 00993 any_bound = true; 00994 } 00995 00996 // This is the first time this frame that this plane has been 00997 // bound to this particular id. 00998 bind_clip_plane(plane, cur_plane_id); 00999 01000 } else if (cur_plane_id == -1) { 01001 gsg_cat.warning() 01002 << "Failed to bind " << *plane << " to id.\n"; 01003 } 01004 } 01005 01006 // Disable all unused planes 01007 for (i = 0; i < max_planes; i++) { 01008 if (!_clip_plane_info[i]._next_enabled) { 01009 enable_clip_plane(i, false); 01010 _clip_plane_info[i]._enabled = false; 01011 } 01012 } 01013 01014 // If no planes were enabled, disable clip planes in general. 01015 if (num_enabled == 0) { 01016 enable_clip_planes(false); 01017 _clip_planes_enabled = false; 01018 } 01019 01020 if (any_bound) { 01021 end_bind_clip_planes(); 01022 } 01023 } 01024 01025 //////////////////////////////////////////////////////////////////// 01026 // Function: GraphicsStateGuardian::bind_light 01027 // Access: Public, Virtual 01028 // Description: Called the first time a particular light has been 01029 // bound to a given id within a frame, this should set 01030 // up the associated hardware light with the light's 01031 // properties. 01032 //////////////////////////////////////////////////////////////////// 01033 void GraphicsStateGuardian:: 01034 bind_light(PointLight *light, int light_id) { 01035 } 01036 01037 //////////////////////////////////////////////////////////////////// 01038 // Function: GraphicsStateGuardian::bind_light 01039 // Access: Public, Virtual 01040 // Description: Called the first time a particular light has been 01041 // bound to a given id within a frame, this should set 01042 // up the associated hardware light with the light's 01043 // properties. 01044 //////////////////////////////////////////////////////////////////// 01045 void GraphicsStateGuardian:: 01046 bind_light(DirectionalLight *light, int light_id) { 01047 } 01048 01049 //////////////////////////////////////////////////////////////////// 01050 // Function: GraphicsStateGuardian::bind_light 01051 // Access: Public, Virtual 01052 // Description: Called the first time a particular light has been 01053 // bound to a given id within a frame, this should set 01054 // up the associated hardware light with the light's 01055 // properties. 01056 //////////////////////////////////////////////////////////////////// 01057 void GraphicsStateGuardian:: 01058 bind_light(Spotlight *light, int light_id) { 01059 } 01060 01061 //////////////////////////////////////////////////////////////////// 01062 // Function: GraphicsStateGuardian::slot_new_light 01063 // Access: Protected, Virtual 01064 // Description: This will be called by the base class before a 01065 // particular light id will be used for the first time. 01066 // It is intended to allow the derived class to reserve 01067 // any additional resources, if required, for the new 01068 // light; and also to indicate whether the hardware 01069 // supports this many simultaneous lights. 01070 // 01071 // The return value should be true if the additional 01072 // light is supported, or false if it is not. 01073 //////////////////////////////////////////////////////////////////// 01074 bool GraphicsStateGuardian:: 01075 slot_new_light(int light_id) { 01076 return true; 01077 } 01078 01079 //////////////////////////////////////////////////////////////////// 01080 // Function: GraphicsStateGuardian::enable_lighting 01081 // Access: Protected, Virtual 01082 // Description: Intended to be overridden by a derived class to 01083 // enable or disable the use of lighting overall. This 01084 // is called by issue_light() according to whether any 01085 // lights are in use or not. 01086 //////////////////////////////////////////////////////////////////// 01087 void GraphicsStateGuardian:: 01088 enable_lighting(bool enable) { 01089 } 01090 01091 //////////////////////////////////////////////////////////////////// 01092 // Function: GraphicsStateGuardian::set_ambient_light 01093 // Access: Protected, Virtual 01094 // Description: Intended to be overridden by a derived class to 01095 // indicate the color of the ambient light that should 01096 // be in effect. This is called by issue_light() after 01097 // all other lights have been enabled or disabled. 01098 //////////////////////////////////////////////////////////////////// 01099 void GraphicsStateGuardian:: 01100 set_ambient_light(const Colorf &color) { 01101 } 01102 01103 //////////////////////////////////////////////////////////////////// 01104 // Function: GraphicsStateGuardian::enable_light 01105 // Access: Protected, Virtual 01106 // Description: Intended to be overridden by a derived class to 01107 // enable the indicated light id. A specific Light will 01108 // already have been bound to this id via bind_light(). 01109 //////////////////////////////////////////////////////////////////// 01110 void GraphicsStateGuardian:: 01111 enable_light(int light_id, bool enable) { 01112 } 01113 01114 //////////////////////////////////////////////////////////////////// 01115 // Function: GraphicsStateGuardian::begin_bind_lights 01116 // Access: Protected, Virtual 01117 // Description: Called immediately before bind_light() is called, 01118 // this is intended to provide the derived class a hook 01119 // in which to set up some state (like transform) that 01120 // might apply to several lights. 01121 // 01122 // The sequence is: begin_bind_lights() will be called, 01123 // then one or more bind_light() calls, then 01124 // end_bind_lights(). 01125 //////////////////////////////////////////////////////////////////// 01126 void GraphicsStateGuardian:: 01127 begin_bind_lights() { 01128 } 01129 01130 //////////////////////////////////////////////////////////////////// 01131 // Function: GraphicsStateGuardian::end_bind_lights 01132 // Access: Protected, Virtual 01133 // Description: Called after before bind_light() has been called one 01134 // or more times (but before any geometry is issued or 01135 // additional state is changed), this is intended to 01136 // clean up any temporary changes to the state that may 01137 // have been made by begin_bind_lights(). 01138 //////////////////////////////////////////////////////////////////// 01139 void GraphicsStateGuardian:: 01140 end_bind_lights() { 01141 } 01142 01143 //////////////////////////////////////////////////////////////////// 01144 // Function: GraphicsStateGuardian::slot_new_clip_plane 01145 // Access: Protected, Virtual 01146 // Description: This will be called by the base class before a 01147 // particular clip plane id will be used for the first 01148 // time. It is intended to allow the derived class to 01149 // reserve any additional resources, if required, for 01150 // the new clip plane; and also to indicate whether the 01151 // hardware supports this many simultaneous clipping 01152 // planes. 01153 // 01154 // The return value should be true if the additional 01155 // plane is supported, or false if it is not. 01156 //////////////////////////////////////////////////////////////////// 01157 bool GraphicsStateGuardian:: 01158 slot_new_clip_plane(int plane_id) { 01159 return true; 01160 } 01161 01162 //////////////////////////////////////////////////////////////////// 01163 // Function: GraphicsStateGuardian::enable_clip_planes 01164 // Access: Protected, Virtual 01165 // Description: Intended to be overridden by a derived class to 01166 // enable or disable the use of clipping planes overall. 01167 // This is called by issue_clip_plane() according to 01168 // whether any planes are in use or not. 01169 //////////////////////////////////////////////////////////////////// 01170 void GraphicsStateGuardian:: 01171 enable_clip_planes(bool enable) { 01172 } 01173 01174 //////////////////////////////////////////////////////////////////// 01175 // Function: GraphicsStateGuardian::enable_clip_plane 01176 // Access: Protected, Virtual 01177 // Description: Intended to be overridden by a derived class to 01178 // enable the indicated plane id. A specific PlaneNode 01179 // will already have been bound to this id via 01180 // bind_clip_plane(). 01181 //////////////////////////////////////////////////////////////////// 01182 void GraphicsStateGuardian:: 01183 enable_clip_plane(int plane_id, bool enable) { 01184 } 01185 01186 //////////////////////////////////////////////////////////////////// 01187 // Function: GraphicsStateGuardian::begin_bind_clip_planes 01188 // Access: Protected, Virtual 01189 // Description: Called immediately before bind_clip_plane() is called, 01190 // this is intended to provide the derived class a hook 01191 // in which to set up some state (like transform) that 01192 // might apply to several planes. 01193 // 01194 // The sequence is: begin_bind_clip_planes() will be 01195 // called, then one or more bind_clip_plane() calls, 01196 // then end_bind_clip_planes(). 01197 //////////////////////////////////////////////////////////////////// 01198 void GraphicsStateGuardian:: 01199 begin_bind_clip_planes() { 01200 } 01201 01202 //////////////////////////////////////////////////////////////////// 01203 // Function: GraphicsStateGuardian::bind_clip_plane 01204 // Access: Public, Virtual 01205 // Description: Called the first time a particular clipping plane has been 01206 // bound to a given id within a frame, this should set 01207 // up the associated hardware (or API) clipping plane 01208 // with the plane's properties. 01209 //////////////////////////////////////////////////////////////////// 01210 void GraphicsStateGuardian:: 01211 bind_clip_plane(PlaneNode *plane, int plane_id) { 01212 } 01213 01214 //////////////////////////////////////////////////////////////////// 01215 // Function: GraphicsStateGuardian::end_bind_clip_planes 01216 // Access: Protected, Virtual 01217 // Description: Called after before bind_clip_plane() has been called one 01218 // or more times (but before any geometry is issued or 01219 // additional state is changed), this is intended to 01220 // clean up any temporary changes to the state that may 01221 // have been made by begin_bind_clip_planes(). 01222 //////////////////////////////////////////////////////////////////// 01223 void GraphicsStateGuardian:: 01224 end_bind_clip_planes() { 01225 } 01226 01227 //////////////////////////////////////////////////////////////////// 01228 // Function: GraphicsStateGuardian::set_blend_mode 01229 // Access: Protected, Virtual 01230 // Description: Called after any of these three blending states have 01231 // changed; this function is responsible for setting the 01232 // appropriate color blending mode based on the given 01233 // properties. 01234 //////////////////////////////////////////////////////////////////// 01235 void GraphicsStateGuardian:: 01236 set_blend_mode(ColorWriteAttrib::Mode, ColorBlendAttrib::Mode, 01237 TransparencyAttrib::Mode) { 01238 } 01239 01240 //////////////////////////////////////////////////////////////////// 01241 // Function: GraphicsStateGuardian::mark_prepared_texture 01242 // Access: Protected 01243 // Description: This is intended to be called from within 01244 // prepare_texture(). It adds the indicated 01245 // TextureContext pointer to the _prepared_textures set, 01246 // and returns true if it was successfully added 01247 // (i.e. it was not already in the set). 01248 //////////////////////////////////////////////////////////////////// 01249 bool GraphicsStateGuardian:: 01250 mark_prepared_texture(TextureContext *tc) { 01251 bool prepared = _prepared_textures.insert(tc).second; 01252 #ifdef DO_PSTATS 01253 if (prepared) { 01254 _total_texusage_pcollector.add_level(tc->estimate_texture_memory()); 01255 } 01256 #endif 01257 return prepared; 01258 } 01259 01260 //////////////////////////////////////////////////////////////////// 01261 // Function: GraphicsStateGuardian::unmark_prepared_texture 01262 // Access: Protected 01263 // Description: This is intended to be called from within 01264 // release_texture(). It removes the indicated 01265 // TextureContext pointer from the _prepared_textures 01266 // set, and returns true if it was successfully removed 01267 // (i.e. it had been in the set). 01268 //////////////////////////////////////////////////////////////////// 01269 bool GraphicsStateGuardian:: 01270 unmark_prepared_texture(TextureContext *tc) { 01271 bool removed = (_prepared_textures.erase(tc) != 0); 01272 #ifdef DO_PSTATS 01273 if (removed) { 01274 _total_texusage_pcollector.sub_level(tc->estimate_texture_memory()); 01275 } 01276 #endif 01277 return removed; 01278 } 01279 01280 //////////////////////////////////////////////////////////////////// 01281 // Function: GraphicsStateGuardian::mark_prepared_geom 01282 // Access: Protected 01283 // Description: This is intended to be called from within 01284 // prepare_geom(). It adds the indicated GeomContext 01285 // pointer to the _prepared_geoms set, and returns true 01286 // if it was successfully added (i.e. it was not already 01287 // in the set). 01288 //////////////////////////////////////////////////////////////////// 01289 bool GraphicsStateGuardian:: 01290 mark_prepared_geom(GeomContext *gc) { 01291 bool prepared = _prepared_geoms.insert(gc).second; 01292 #ifdef DO_PSTATS 01293 if (prepared) { 01294 _total_geom_pcollector.add_level(1); 01295 } 01296 #endif 01297 return prepared; 01298 } 01299 01300 //////////////////////////////////////////////////////////////////// 01301 // Function: GraphicsStateGuardian::unmark_prepared_geom 01302 // Access: Protected 01303 // Description: This is intended to be called from within 01304 // release_geom(). It removes the indicated GeomContext 01305 // pointer from the _prepared_geoms set, and returns 01306 // true if it was successfully removed (i.e. it had been 01307 // in the set). 01308 //////////////////////////////////////////////////////////////////// 01309 bool GraphicsStateGuardian:: 01310 unmark_prepared_geom(GeomContext *gc) { 01311 bool removed = (_prepared_geoms.erase(gc) != 0); 01312 #ifdef DO_PSTATS 01313 if (removed) { 01314 _total_geom_pcollector.sub_level(1); 01315 } 01316 #endif 01317 return removed; 01318 } 01319 01320 //////////////////////////////////////////////////////////////////// 01321 // Function: GraphicsStateGuardian::mark_prepared_geom_node 01322 // Access: Protected 01323 // Description: This is intended to be called from within 01324 // prepare_geom_node(). It adds the indicated 01325 // GeomNodeContext pointer to the _prepared_geom_nodes 01326 // set, and returns true if it was successfully added 01327 // (i.e. it was not already in the set). 01328 //////////////////////////////////////////////////////////////////// 01329 bool GraphicsStateGuardian:: 01330 mark_prepared_geom_node(GeomNodeContext *gnc) { 01331 bool prepared = _prepared_geom_nodes.insert(gnc).second; 01332 #ifdef DO_PSTATS 01333 if (prepared) { 01334 _total_geom_node_pcollector.add_level(1); 01335 } 01336 #endif 01337 return prepared; 01338 } 01339 01340 //////////////////////////////////////////////////////////////////// 01341 // Function: GraphicsStateGuardian::unmark_prepared_geom_node 01342 // Access: Protected 01343 // Description: This is intended to be called from within 01344 // release_geom_node(). It removes the indicated 01345 // GeomNodeContext pointer from the _prepared_geom_nodes 01346 // set, and returns true if it was successfully removed 01347 // (i.e. it had been in the set). 01348 //////////////////////////////////////////////////////////////////// 01349 bool GraphicsStateGuardian:: 01350 unmark_prepared_geom_node(GeomNodeContext *gnc) { 01351 bool removed = (_prepared_geom_nodes.erase(gnc) != 0); 01352 #ifdef DO_PSTATS 01353 if (removed) { 01354 _total_geom_node_pcollector.sub_level(1); 01355 } 01356 #endif 01357 return removed; 01358 } 01359 01360 //////////////////////////////////////////////////////////////////// 01361 // Function: GraphicsStateGuardian::free_pointers 01362 // Access: Protected, Virtual 01363 // Description: Frees some memory that was explicitly allocated 01364 // within the glgsg. 01365 //////////////////////////////////////////////////////////////////// 01366 void GraphicsStateGuardian:: 01367 free_pointers() { 01368 } 01369 01370 //////////////////////////////////////////////////////////////////// 01371 // Function: GraphicsStateGuardian::close_gsg 01372 // Access: Protected, Virtual 01373 // Description: This is called by the associated GraphicsWindow when 01374 // close_window() is called. It should null out the 01375 // _win pointer and possibly free any open resources 01376 // associated with the GSG. 01377 //////////////////////////////////////////////////////////////////// 01378 void GraphicsStateGuardian:: 01379 close_gsg() { 01380 _closing_gsg = true; 01381 free_pointers(); 01382 release_all_textures(); 01383 release_all_geoms(); 01384 } 01385 01386 #ifdef DO_PSTATS 01387 01388 //////////////////////////////////////////////////////////////////// 01389 // Function: GraphicsStateGuardian::init_frame_pstats 01390 // Access: Protected 01391 // Description: Initializes the relevant PStats data at the beginning 01392 // of the frame. 01393 //////////////////////////////////////////////////////////////////// 01394 void GraphicsStateGuardian:: 01395 init_frame_pstats() { 01396 if (PStatClient::is_connected()) { 01397 _current_textures.clear(); 01398 _current_geoms.clear(); 01399 _current_geom_nodes.clear(); 01400 _active_texusage_pcollector.clear_level(); 01401 _active_geom_pcollector.clear_level(); 01402 _active_geom_node_pcollector.clear_level(); 01403 01404 // Also clear out our other counters while we're here. 01405 _vertices_tristrip_pcollector.clear_level(); 01406 _vertices_trifan_pcollector.clear_level(); 01407 _vertices_tri_pcollector.clear_level(); 01408 _vertices_other_pcollector.clear_level(); 01409 01410 _state_changes_pcollector.clear_level(); 01411 _transform_state_pcollector.clear_level(); 01412 _texture_state_pcollector.clear_level(); 01413 01414 _nodes_pcollector.clear_level(); 01415 _geom_nodes_pcollector.clear_level(); 01416 01417 // Not to mention the view-frustum-cull counters. 01418 _frustum_cull_volumes_pcollector.clear_level(); 01419 _frustum_cull_transforms_pcollector.clear_level(); 01420 01421 _transform_states_pcollector.set_level(TransformState::get_num_states()); 01422 _render_states_pcollector.set_level(RenderState::get_num_states()); 01423 if (pstats_unused_states) { 01424 _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states()); 01425 _render_states_unused_pcollector.set_level(RenderState::get_num_unused_states()); 01426 } 01427 } 01428 } 01429 01430 //////////////////////////////////////////////////////////////////// 01431 // Function: GraphicsStateGuardian::add_to_texture_record 01432 // Access: Protected 01433 // Description: Records that the indicated texture has been applied 01434 // this frame, and thus must be present in current 01435 // texture memory. This function is only used to update 01436 // the PStats current_texmem collector; it gets compiled 01437 // out if we aren't using PStats. 01438 //////////////////////////////////////////////////////////////////// 01439 void GraphicsStateGuardian:: 01440 add_to_texture_record(TextureContext *tc) { 01441 if (PStatClient::is_connected()) { 01442 if (_current_textures.insert(tc).second) { 01443 _active_texusage_pcollector.add_level(tc->estimate_texture_memory()); 01444 } 01445 } 01446 } 01447 01448 //////////////////////////////////////////////////////////////////// 01449 // Function: GraphicsStateGuardian::add_to_geom_record 01450 // Access: Protected 01451 // Description: Records that the indicated Geom has been drawn this 01452 // frame. This function is only used to update the 01453 // PStats current_texmem collector; it gets compiled out 01454 // if we aren't using PStats. 01455 //////////////////////////////////////////////////////////////////// 01456 void GraphicsStateGuardian:: 01457 add_to_geom_record(GeomContext *gc) { 01458 if (PStatClient::is_connected()) { 01459 if (gc != (GeomContext *)NULL && _current_geoms.insert(gc).second) { 01460 _active_geom_pcollector.add_level(1); 01461 } 01462 } 01463 } 01464 01465 //////////////////////////////////////////////////////////////////// 01466 // Function: GraphicsStateGuardian::add_to_geom_node_record 01467 // Access: Protected 01468 // Description: Records that the indicated GeomNode has been drawn 01469 // this frame. This function is only used to update the 01470 // PStats current_texmem collector; it gets compiled out 01471 // if we aren't using PStats. 01472 //////////////////////////////////////////////////////////////////// 01473 void GraphicsStateGuardian:: 01474 add_to_geom_node_record(GeomNodeContext *gnc) { 01475 if (PStatClient::is_connected()) { 01476 if (gnc != (GeomNodeContext *)NULL && 01477 _current_geom_nodes.insert(gnc).second) { 01478 _active_geom_node_pcollector.add_level(1); 01479 } 01480 } 01481 } 01482 01483 //////////////////////////////////////////////////////////////////// 01484 // Function: GraphicsStateGuardian::record_state_change 01485 // Access: Protected 01486 // Description: Indicates a state change request for a property of 01487 // the given type. 01488 //////////////////////////////////////////////////////////////////// 01489 void GraphicsStateGuardian:: 01490 record_state_change(TypeHandle type) { 01491 _state_changes_pcollector.add_level(1); 01492 01493 // We can't use the get_class_type() methods since we don't have 01494 // those header files available yet. 01495 string name = type.get_name(); 01496 if (name == "TransformTransition") { 01497 _transform_state_pcollector.add_level(1); 01498 } else if (name == "TextureTransition") { 01499 _texture_state_pcollector.add_level(1); 01500 } 01501 } 01502 #endif // DO_PSTATS 01503 01504 //////////////////////////////////////////////////////////////////// 01505 // Function: GraphicsStateGuardian::get_unlit_state 01506 // Access: Protected, Static 01507 // Description: 01508 //////////////////////////////////////////////////////////////////// 01509 CPT(RenderState) GraphicsStateGuardian:: 01510 get_unlit_state() { 01511 static CPT(RenderState) state = NULL; 01512 if (state == (const RenderState *)NULL) { 01513 state = RenderState::make(LightAttrib::make_all_off()); 01514 } 01515 return state; 01516 } 01517 01518 //////////////////////////////////////////////////////////////////// 01519 // Function: GraphicsStateGuardian::get_unclipped_state 01520 // Access: Protected, Static 01521 // Description: 01522 //////////////////////////////////////////////////////////////////// 01523 CPT(RenderState) GraphicsStateGuardian:: 01524 get_unclipped_state() { 01525 static CPT(RenderState) state = NULL; 01526 if (state == (const RenderState *)NULL) { 01527 state = RenderState::make(ClipPlaneAttrib::make_all_off()); 01528 } 01529 return state; 01530 } 01531 01532 //////////////////////////////////////////////////////////////////// 01533 // Function: GraphicsStateGuardian::get_untextured_state 01534 // Access: Protected, Static 01535 // Description: 01536 //////////////////////////////////////////////////////////////////// 01537 CPT(RenderState) GraphicsStateGuardian:: 01538 get_untextured_state() { 01539 static CPT(RenderState) state = NULL; 01540 if (state == (const RenderState *)NULL) { 01541 state = RenderState::make(TextureAttrib::make_off()); 01542 } 01543 return state; 01544 } 01545 01546 void GraphicsStateGuardian:: 01547 traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) { 01548 for (Textures::const_iterator ti = _prepared_textures.begin(); ti != _prepared_textures.end(); 01549 ++ti) { 01550 bool bResult=(*pertex_callbackfn)(*ti,callback_arg); 01551 if(!bResult) 01552 return; 01553 } 01554 }