Panda3D
|
00001 // Filename: graphicsStateGuardian.cxx 00002 // Created by: drose (02Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "graphicsStateGuardian.h" 00016 #include "graphicsEngine.h" 00017 #include "config_display.h" 00018 #include "textureContext.h" 00019 #include "vertexBufferContext.h" 00020 #include "indexBufferContext.h" 00021 #include "renderBuffer.h" 00022 #include "light.h" 00023 #include "planeNode.h" 00024 #include "ambientLight.h" 00025 #include "throw_event.h" 00026 #include "clockObject.h" 00027 #include "pStatTimer.h" 00028 #include "geomTristrips.h" 00029 #include "geomTrifans.h" 00030 #include "geomLinestrips.h" 00031 #include "colorWriteAttrib.h" 00032 #include "shader.h" 00033 #include "pnotify.h" 00034 #include "drawableRegion.h" 00035 #include "displayRegion.h" 00036 #include "graphicsOutput.h" 00037 #include "texturePool.h" 00038 #include "geomMunger.h" 00039 #include "ambientLight.h" 00040 #include "directionalLight.h" 00041 #include "pointLight.h" 00042 #include "spotlight.h" 00043 #include "textureReloadRequest.h" 00044 #include "shaderAttrib.h" 00045 #include "materialAttrib.h" 00046 #include "depthWriteAttrib.h" 00047 #include "lightAttrib.h" 00048 #include "texGenAttrib.h" 00049 #include "shaderGenerator.h" 00050 #include "lightLensNode.h" 00051 #include "colorAttrib.h" 00052 #include "colorScaleAttrib.h" 00053 00054 #include <algorithm> 00055 #include <limits.h> 00056 00057 #ifdef HAVE_PYTHON 00058 #include "py_panda.h" 00059 #ifndef CPPPARSER 00060 IMPORT_THIS struct Dtool_PyTypedObject Dtool_Texture; 00061 #endif 00062 #endif // HAVE_PYTHON 00063 00064 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex"); 00065 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index"); 00066 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer"); 00067 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer"); 00068 PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer"); 00069 PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer"); 00070 PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture"); 00071 PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred"); 00072 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager"); 00073 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident"); 00074 PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches"); 00075 PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector("Primitive batches:Triangle strips"); 00076 PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector("Primitive batches:Triangle fans"); 00077 PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector("Primitive batches:Triangles"); 00078 PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector("Primitive batches:Other"); 00079 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips"); 00080 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans"); 00081 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles"); 00082 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector("Vertices:Other"); 00083 PStatCollector GraphicsStateGuardian::_state_pcollector("State changes"); 00084 PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes:Transforms"); 00085 PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures"); 00086 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive:Draw"); 00087 PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector("Draw:Set State"); 00088 PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear"); 00089 PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush"); 00090 00091 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion"); 00092 00093 00094 PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform"); 00095 PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test"); 00096 PStatCollector GraphicsStateGuardian::_draw_set_state_antialias_pcollector("Draw:Set State:Antialias"); 00097 PStatCollector GraphicsStateGuardian::_draw_set_state_clip_plane_pcollector("Draw:Set State:Clip plane"); 00098 PStatCollector GraphicsStateGuardian::_draw_set_state_color_pcollector("Draw:Set State:Color"); 00099 PStatCollector GraphicsStateGuardian::_draw_set_state_cull_face_pcollector("Draw:Set State:Cull face"); 00100 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_offset_pcollector("Draw:Set State:Depth offset"); 00101 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_test_pcollector("Draw:Set State:Depth test"); 00102 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_write_pcollector("Draw:Set State:Depth write"); 00103 PStatCollector GraphicsStateGuardian::_draw_set_state_render_mode_pcollector("Draw:Set State:Render mode"); 00104 PStatCollector GraphicsStateGuardian::_draw_set_state_rescale_normal_pcollector("Draw:Set State:Rescale normal"); 00105 PStatCollector GraphicsStateGuardian::_draw_set_state_shade_model_pcollector("Draw:Set State:Shade model"); 00106 PStatCollector GraphicsStateGuardian::_draw_set_state_blending_pcollector("Draw:Set State:Blending"); 00107 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_pcollector("Draw:Set State:Shader"); 00108 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_parameters_pcollector("Draw:Set State:Shader Parameters"); 00109 PStatCollector GraphicsStateGuardian::_draw_set_state_texture_pcollector("Draw:Set State:Texture"); 00110 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_matrix_pcollector("Draw:Set State:Tex matrix"); 00111 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_gen_pcollector("Draw:Set State:Tex gen"); 00112 PStatCollector GraphicsStateGuardian::_draw_set_state_material_pcollector("Draw:Set State:Material"); 00113 PStatCollector GraphicsStateGuardian::_draw_set_state_light_pcollector("Draw:Set State:Light"); 00114 PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector("Draw:Set State:Stencil"); 00115 PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector("Draw:Set State:Fog"); 00116 PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector("Draw:Set State:Scissor"); 00117 00118 00119 PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL; 00120 00121 TypeHandle GraphicsStateGuardian::_type_handle; 00122 00123 //////////////////////////////////////////////////////////////////// 00124 // Function: GraphicsStateGuardian::Constructor 00125 // Access: Public 00126 // Description: 00127 //////////////////////////////////////////////////////////////////// 00128 GraphicsStateGuardian:: 00129 GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, 00130 GraphicsEngine *engine, GraphicsPipe *pipe) : 00131 _internal_coordinate_system(internal_coordinate_system), 00132 _pipe(pipe), 00133 _engine(engine) 00134 { 00135 _coordinate_system = CS_invalid; 00136 _internal_transform = TransformState::make_identity(); 00137 00138 set_coordinate_system(get_default_coordinate_system()); 00139 00140 _data_reader = (GeomVertexDataPipelineReader *)NULL; 00141 _current_display_region = (DisplayRegion*)NULL; 00142 _current_stereo_channel = Lens::SC_mono; 00143 _current_lens = (Lens *)NULL; 00144 _projection_mat = TransformState::make_identity(); 00145 _projection_mat_inv = TransformState::make_identity(); 00146 00147 _needs_reset = true; 00148 _is_valid = false; 00149 _current_properties = NULL; 00150 _closing_gsg = false; 00151 _active = true; 00152 _prepared_objects = new PreparedGraphicsObjects; 00153 _stereo_buffer_mask = ~0; 00154 _incomplete_render = allow_incomplete_render; 00155 _loader = Loader::get_global_ptr(); 00156 00157 _is_hardware = false; 00158 _prefers_triangle_strips = false; 00159 _max_vertices_per_array = INT_MAX; 00160 _max_vertices_per_primitive = INT_MAX; 00161 00162 // Initially, we set this to 1 (the default--no multitexturing 00163 // supported). A derived GSG may set this differently if it 00164 // supports multitexturing. 00165 _max_texture_stages = 1; 00166 00167 // Also initially, we assume there are no limits on texture sizes, 00168 // and that 3-d and cube-map textures are not supported. 00169 _max_texture_dimension = -1; 00170 _max_3d_texture_dimension = 0; 00171 _max_cube_map_dimension = 0; 00172 00173 // Assume we don't support these fairly advanced texture combiner 00174 // modes. 00175 _supports_texture_combine = false; 00176 _supports_texture_saved_result = false; 00177 _supports_texture_dot3 = false; 00178 00179 _supports_3d_texture = false; 00180 _supports_cube_map = false; 00181 _supports_tex_non_pow2 = false; 00182 _supports_compressed_texture = false; 00183 _compressed_texture_formats.clear(); 00184 _compressed_texture_formats.set_bit(Texture::CM_off); 00185 00186 // Assume no limits on number of lights or clip planes. 00187 _max_lights = -1; 00188 _max_clip_planes = -1; 00189 00190 // Assume no vertex blending capability. 00191 _max_vertex_transforms = 0; 00192 _max_vertex_transform_indices = 0; 00193 00194 _supports_occlusion_query = false; 00195 00196 // Initially, we set this to false; a GSG that knows it has this 00197 // property should set it to true. 00198 _copy_texture_inverted = false; 00199 00200 // Similarly with these capabilities flags. 00201 _supports_multisample = false; 00202 _supports_generate_mipmap = false; 00203 _supports_render_texture = false; 00204 _supports_depth_texture = false; 00205 _supports_depth_stencil = false; 00206 _supports_shadow_filter = false; 00207 _supports_basic_shaders = false; 00208 _supports_glsl = false; 00209 00210 _supports_stencil = false; 00211 _supports_stencil_wrap = false; 00212 _supports_two_sided_stencil = false; 00213 _supports_geometry_instancing = false; 00214 00215 _maximum_simultaneous_render_targets = 1; 00216 00217 _supported_geom_rendering = 0; 00218 00219 // If this is true, then we can apply a color and/or color scale by 00220 // twiddling the material and/or ambient light (which could mean 00221 // enabling lighting even without a LightAttrib). 00222 _color_scale_via_lighting = color_scale_via_lighting; 00223 00224 // Similarly for applying a texture to achieve uniform alpha 00225 // scaling. 00226 _alpha_scale_via_texture = alpha_scale_via_texture; 00227 00228 // Few GSG's can do this, since it requires touching each vertex as 00229 // it is rendered. 00230 _runtime_color_scale = false; 00231 00232 _stencil_render_states = 0; 00233 00234 // The default is no shader support. 00235 _auto_detect_shader_model = SM_00; 00236 _shader_model = SM_00; 00237 00238 _gamma = 1.0f; 00239 _texture_quality_override = Texture::QL_default; 00240 00241 _shader_generator = NULL; 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: GraphicsStateGuardian::Destructor 00246 // Access: Public, Virtual 00247 // Description: 00248 //////////////////////////////////////////////////////////////////// 00249 GraphicsStateGuardian:: 00250 ~GraphicsStateGuardian() { 00251 remove_gsg(this); 00252 00253 if (_stencil_render_states) { 00254 delete _stencil_render_states; 00255 _stencil_render_states = 0; 00256 } 00257 00258 if (_shader_generator) { 00259 delete _shader_generator; 00260 _shader_generator = 0; 00261 } 00262 00263 GeomMunger::unregister_mungers_for_gsg(this); 00264 } 00265 00266 //////////////////////////////////////////////////////////////////// 00267 // Function: GraphicsStateGuardian::get_engine 00268 // Access: Published 00269 // Description: Returns the graphics engine that created this GSG. 00270 // Since there is normally only one GraphicsEngine 00271 // object in an application, this is usually the same as 00272 // the global GraphicsEngine. 00273 //////////////////////////////////////////////////////////////////// 00274 GraphicsEngine *GraphicsStateGuardian:: 00275 get_engine() const { 00276 nassertr(_engine != (GraphicsEngine *)NULL, GraphicsEngine::get_global_ptr()); 00277 return _engine; 00278 } 00279 00280 //////////////////////////////////////////////////////////////////// 00281 // Function: GraphicsStateGuardian::get_supports_multisample 00282 // Access: Published, Virtual 00283 // Description: Returns true if this particular GSG supports using 00284 // the multisample bits to provide antialiasing, and 00285 // also supports M_multisample and M_multisample_mask 00286 // transparency modes. If this is not true for a 00287 // particular GSG, Panda will map the M_multisample 00288 // modes to M_binary. 00289 // 00290 // This method is declared virtual solely so that it can 00291 // be queried from cullResult.cxx. 00292 //////////////////////////////////////////////////////////////////// 00293 bool GraphicsStateGuardian:: 00294 get_supports_multisample() const { 00295 return _supports_multisample; 00296 } 00297 00298 //////////////////////////////////////////////////////////////////// 00299 // Function: GraphicsStateGuardian::get_supported_geom_rendering 00300 // Access: Published, Virtual 00301 // Description: Returns the union of Geom::GeomRendering values that 00302 // this particular GSG can support directly. If a Geom 00303 // needs to be rendered that requires some additional 00304 // properties, the StandardMunger and/or the 00305 // CullableObject will convert it as needed. 00306 // 00307 // This method is declared virtual solely so that it can 00308 // be queried from cullableObject.cxx. 00309 //////////////////////////////////////////////////////////////////// 00310 int GraphicsStateGuardian:: 00311 get_supported_geom_rendering() const { 00312 return _supported_geom_rendering; 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: GraphicsStateGuardian::get_supports_cg_profile 00317 // Access: Published, Virtual 00318 // Description: Returns true if this particular GSG supports the 00319 // specified Cg Shader Profile. 00320 //////////////////////////////////////////////////////////////////// 00321 bool GraphicsStateGuardian:: 00322 get_supports_cg_profile(const string &name) const { 00323 return false; 00324 } 00325 00326 //////////////////////////////////////////////////////////////////// 00327 // Function: GraphicsStateGuardian::set_coordinate_system 00328 // Access: Published 00329 // Description: Changes the coordinate system in effect on this 00330 // particular gsg. This is also called the "external" 00331 // coordinate system, since it is the coordinate system 00332 // used by the scene graph, external to to GSG. 00333 // 00334 // Normally, this will be the default coordinate system, 00335 // but it might be set differently at runtime. 00336 //////////////////////////////////////////////////////////////////// 00337 void GraphicsStateGuardian:: 00338 set_coordinate_system(CoordinateSystem cs) { 00339 _coordinate_system = cs; 00340 00341 // Changing the external coordinate system changes the cs_transform. 00342 if (_internal_coordinate_system == CS_default || 00343 _internal_coordinate_system == _coordinate_system) { 00344 _cs_transform = TransformState::make_identity(); 00345 _inv_cs_transform = TransformState::make_identity(); 00346 00347 } else { 00348 _cs_transform = 00349 TransformState::make_mat 00350 (LMatrix4f::convert_mat(_coordinate_system, 00351 _internal_coordinate_system)); 00352 _inv_cs_transform = 00353 TransformState::make_mat 00354 (LMatrix4f::convert_mat(_internal_coordinate_system, 00355 _coordinate_system)); 00356 } 00357 } 00358 00359 //////////////////////////////////////////////////////////////////// 00360 // Function: GraphicsStateGuardian::get_internal_coordinate_system 00361 // Access: Published, Virtual 00362 // Description: Returns the coordinate system used internally by the 00363 // GSG. This may be the same as the external coordinate 00364 // system reported by get_coordinate_system(), or it may 00365 // be something different. 00366 // 00367 // In any case, vertices that have been transformed 00368 // before being handed to the GSG (that is, vertices 00369 // with a contents value of C_clip_point) will be 00370 // expected to be in this coordinate system. 00371 //////////////////////////////////////////////////////////////////// 00372 CoordinateSystem GraphicsStateGuardian:: 00373 get_internal_coordinate_system() const { 00374 return _internal_coordinate_system; 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: GraphicsStateGuardian::get_prepared_objects 00379 // Access: Public, Virtual 00380 // Description: Returns the set of texture and geom objects that have 00381 // been prepared with this GSG (and possibly other GSG's 00382 // that share objects). 00383 //////////////////////////////////////////////////////////////////// 00384 PreparedGraphicsObjects *GraphicsStateGuardian:: 00385 get_prepared_objects() { 00386 return _prepared_objects; 00387 } 00388 00389 //////////////////////////////////////////////////////////////////// 00390 // Function: GraphicsStateGuardian::set_gamma 00391 // Access: Published, Virtual 00392 // Description: Set gamma. Returns true on success. 00393 //////////////////////////////////////////////////////////////////// 00394 bool GraphicsStateGuardian:: 00395 set_gamma(float gamma) { 00396 _gamma = gamma; 00397 00398 return false; 00399 } 00400 00401 //////////////////////////////////////////////////////////////////// 00402 // Function: GraphicsStateGuardian::get_gamma 00403 // Access: Published 00404 // Description: Get the current gamma setting. 00405 //////////////////////////////////////////////////////////////////// 00406 float GraphicsStateGuardian:: 00407 get_gamma(float gamma) { 00408 return _gamma; 00409 } 00410 00411 //////////////////////////////////////////////////////////////////// 00412 // Function: GraphicsStateGuardian::restore_gamma 00413 // Access: Published, Virtual 00414 // Description: Restore original gamma setting. 00415 //////////////////////////////////////////////////////////////////// 00416 void GraphicsStateGuardian:: 00417 restore_gamma() { 00418 } 00419 00420 #ifdef HAVE_PYTHON 00421 //////////////////////////////////////////////////////////////////// 00422 // Function: GraphicsStateGuardian::get_prepared_textures 00423 // Access: Published 00424 // Description: Returns a Python list of all of the 00425 // currently-prepared textures within the GSG. 00426 //////////////////////////////////////////////////////////////////// 00427 PyObject *GraphicsStateGuardian:: 00428 get_prepared_textures() const { 00429 ReMutexHolder holder(_prepared_objects->_lock); 00430 size_t num_textures = _prepared_objects->_prepared_textures.size(); 00431 PyObject *list = PyList_New(num_textures); 00432 00433 size_t i = 0; 00434 PreparedGraphicsObjects::Textures::const_iterator ti; 00435 for (ti = _prepared_objects->_prepared_textures.begin(); 00436 ti != _prepared_objects->_prepared_textures.end(); 00437 ++ti) { 00438 PT(Texture) tex = (*ti)->get_texture(); 00439 00440 PyObject *element = 00441 DTool_CreatePyInstanceTyped(tex, Dtool_Texture, 00442 true, false, tex->get_type_index()); 00443 tex->ref(); 00444 00445 nassertr(i < num_textures, NULL); 00446 PyList_SetItem(list, i, element); 00447 ++i; 00448 } 00449 nassertr(i == num_textures, NULL); 00450 00451 return list; 00452 } 00453 #endif // HAVE_PYTHON 00454 00455 //////////////////////////////////////////////////////////////////// 00456 // Function: GraphicsStateGuardian::traverse_prepared_textures 00457 // Access: Public 00458 // Description: Calls the indicated function on all 00459 // currently-prepared textures, or until the callback 00460 // function returns false. 00461 //////////////////////////////////////////////////////////////////// 00462 void GraphicsStateGuardian:: 00463 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func, 00464 void *callback_arg) { 00465 ReMutexHolder holder(_prepared_objects->_lock); 00466 PreparedGraphicsObjects::Textures::const_iterator ti; 00467 for (ti = _prepared_objects->_prepared_textures.begin(); 00468 ti != _prepared_objects->_prepared_textures.end(); 00469 ++ti) { 00470 bool result = (*func)(*ti,callback_arg); 00471 if (!result) { 00472 return; 00473 } 00474 } 00475 } 00476 00477 #ifndef NDEBUG 00478 //////////////////////////////////////////////////////////////////// 00479 // Function: GraphicsStateGuardian::set_flash_texture 00480 // Access: Published 00481 // Description: Sets the "flash texture". This is a debug feature; 00482 // when enabled, the specified texture will begin 00483 // flashing in the scene, helping you to find it 00484 // visually. 00485 // 00486 // The texture also flashes with a color code: blue for 00487 // mipmap level 0, yellow for mipmap level 1, and red 00488 // for mipmap level 2 or higher (even for textures that 00489 // don't have mipmaps). This gives you an idea of the 00490 // choice of the texture size. If it is blue, the 00491 // texture is being drawn the proper size or magnified; 00492 // if it is yellow, it is being minified a little bit; 00493 // and if it red, it is being minified considerably. If 00494 // you see a red texture when you are right in front of 00495 // it, you should consider reducing the size of the 00496 // texture to avoid wasting texture memory. 00497 // 00498 // Not all rendering backends support the flash_texture 00499 // feature. Presently, it is only supported by OpenGL. 00500 //////////////////////////////////////////////////////////////////// 00501 void GraphicsStateGuardian:: 00502 set_flash_texture(Texture *tex) { 00503 _flash_texture = tex; 00504 } 00505 #endif // NDEBUG 00506 00507 #ifndef NDEBUG 00508 //////////////////////////////////////////////////////////////////// 00509 // Function: GraphicsStateGuardian::clear_flash_texture 00510 // Access: Published 00511 // Description: Resets the "flash texture", so that no textures will 00512 // flash. See set_flash_texture(). 00513 //////////////////////////////////////////////////////////////////// 00514 void GraphicsStateGuardian:: 00515 clear_flash_texture() { 00516 _flash_texture = NULL; 00517 } 00518 #endif // NDEBUG 00519 00520 #ifndef NDEBUG 00521 //////////////////////////////////////////////////////////////////// 00522 // Function: GraphicsStateGuardian::get_flash_texture 00523 // Access: Published 00524 // Description: Returns the current "flash texture", if any, or NULL 00525 // if none. See set_flash_texture(). 00526 //////////////////////////////////////////////////////////////////// 00527 Texture *GraphicsStateGuardian:: 00528 get_flash_texture() const { 00529 return _flash_texture; 00530 } 00531 #endif // NDEBUG 00532 00533 //////////////////////////////////////////////////////////////////// 00534 // Function: GraphicsStateGuardian::set_scene 00535 // Access: Published 00536 // Description: Sets the SceneSetup object that indicates the initial 00537 // camera position, etc. This must be called before 00538 // traversal begins. Returns true if the scene is 00539 // acceptable, false if something's wrong. This should 00540 // be called in the draw thread only. 00541 //////////////////////////////////////////////////////////////////// 00542 bool GraphicsStateGuardian:: 00543 set_scene(SceneSetup *scene_setup) { 00544 _scene_setup = scene_setup; 00545 _current_lens = scene_setup->get_lens(); 00546 if (_current_lens == (Lens *)NULL) { 00547 return false; 00548 } 00549 00550 _projection_mat = calc_projection_mat(_current_lens); 00551 if (_projection_mat == 0) { 00552 return false; 00553 } 00554 _projection_mat_inv = _projection_mat->get_inverse(); 00555 return prepare_lens(); 00556 } 00557 00558 //////////////////////////////////////////////////////////////////// 00559 // Function: GraphicsStateGuardian::get_scene 00560 // Access: Published, Virtual 00561 // Description: Returns the current SceneSetup object. 00562 //////////////////////////////////////////////////////////////////// 00563 SceneSetup *GraphicsStateGuardian:: 00564 get_scene() const { 00565 return _scene_setup; 00566 } 00567 00568 //////////////////////////////////////////////////////////////////// 00569 // Function: GraphicsStateGuardian::prepare_texture 00570 // Access: Public, Virtual 00571 // Description: Creates whatever structures the GSG requires to 00572 // represent the texture internally, and returns a 00573 // newly-allocated TextureContext object with this data. 00574 // It is the responsibility of the calling function to 00575 // later call release_texture() with this same pointer 00576 // (which will also delete the pointer). 00577 // 00578 // This function should not be called directly to 00579 // prepare a texture. Instead, call Texture::prepare(). 00580 //////////////////////////////////////////////////////////////////// 00581 TextureContext *GraphicsStateGuardian:: 00582 prepare_texture(Texture *) { 00583 return (TextureContext *)NULL; 00584 } 00585 00586 //////////////////////////////////////////////////////////////////// 00587 // Function: GraphicsStateGuardian::update_texture 00588 // Access: Public, Virtual 00589 // Description: Ensures that the current Texture data is refreshed 00590 // onto the GSG. This means updating the texture 00591 // properties and/or re-uploading the texture image, if 00592 // necessary. This should only be called within the 00593 // draw thread. 00594 // 00595 // If force is true, this function will not return until 00596 // the texture has been fully uploaded. If force is 00597 // false, the function may choose to upload a simple 00598 // version of the texture instead, if the texture is not 00599 // fully resident (and if get_incomplete_render() is 00600 // true). 00601 //////////////////////////////////////////////////////////////////// 00602 bool GraphicsStateGuardian:: 00603 update_texture(TextureContext *, bool) { 00604 return true; 00605 } 00606 00607 //////////////////////////////////////////////////////////////////// 00608 // Function: GraphicsStateGuardian::release_texture 00609 // Access: Public, Virtual 00610 // Description: Frees the resources previously allocated via a call 00611 // to prepare_texture(), including deleting the 00612 // TextureContext itself, if it is non-NULL. 00613 //////////////////////////////////////////////////////////////////// 00614 void GraphicsStateGuardian:: 00615 release_texture(TextureContext *) { 00616 } 00617 00618 //////////////////////////////////////////////////////////////////// 00619 // Function: GraphicsStateGuardian::extract_texture_data 00620 // Access: Public, Virtual 00621 // Description: This method should only be called by the 00622 // GraphicsEngine. Do not call it directly; call 00623 // GraphicsEngine::extract_texture_data() instead. 00624 // 00625 // This method will be called in the draw thread to 00626 // download the texture memory's image into its 00627 // ram_image value. It returns true on success, false 00628 // otherwise. 00629 //////////////////////////////////////////////////////////////////// 00630 bool GraphicsStateGuardian:: 00631 extract_texture_data(Texture *) { 00632 return false; 00633 } 00634 00635 //////////////////////////////////////////////////////////////////// 00636 // Function: GraphicsStateGuardian::prepare_geom 00637 // Access: Public, Virtual 00638 // Description: Prepares the indicated Geom for retained-mode 00639 // rendering, by creating whatever structures are 00640 // necessary in the GSG (for instance, vertex buffers). 00641 // Returns the newly-allocated GeomContext that can be 00642 // used to render the geom. 00643 //////////////////////////////////////////////////////////////////// 00644 GeomContext *GraphicsStateGuardian:: 00645 prepare_geom(Geom *) { 00646 return (GeomContext *)NULL; 00647 } 00648 00649 //////////////////////////////////////////////////////////////////// 00650 // Function: GraphicsStateGuardian::release_geom 00651 // Access: Public, Virtual 00652 // Description: Frees the resources previously allocated via a call 00653 // to prepare_geom(), including deleting the GeomContext 00654 // itself, if it is non-NULL. 00655 // 00656 // This function should not be called directly to 00657 // prepare a Geom. Instead, call Geom::prepare(). 00658 //////////////////////////////////////////////////////////////////// 00659 void GraphicsStateGuardian:: 00660 release_geom(GeomContext *) { 00661 } 00662 00663 //////////////////////////////////////////////////////////////////// 00664 // Function: GraphicsStateGuardian::prepare_shader 00665 // Access: Public, Virtual 00666 // Description: Compile a vertex/fragment shader body. 00667 //////////////////////////////////////////////////////////////////// 00668 ShaderContext *GraphicsStateGuardian:: 00669 prepare_shader(Shader *shader) { 00670 return (ShaderContext *)NULL; 00671 } 00672 00673 //////////////////////////////////////////////////////////////////// 00674 // Function: GraphicsStateGuardian::release_shader 00675 // Access: Public, Virtual 00676 // Description: Releases the resources allocated by prepare_shader 00677 //////////////////////////////////////////////////////////////////// 00678 void GraphicsStateGuardian:: 00679 release_shader(ShaderContext *sc) { 00680 } 00681 00682 //////////////////////////////////////////////////////////////////// 00683 // Function: GraphicsStateGuardian::prepare_vertex_buffer 00684 // Access: Public, Virtual 00685 // Description: Prepares the indicated buffer for retained-mode 00686 // rendering. 00687 //////////////////////////////////////////////////////////////////// 00688 VertexBufferContext *GraphicsStateGuardian:: 00689 prepare_vertex_buffer(GeomVertexArrayData *) { 00690 return (VertexBufferContext *)NULL; 00691 } 00692 00693 //////////////////////////////////////////////////////////////////// 00694 // Function: GraphicsStateGuardian::release_vertex_buffer 00695 // Access: Public, Virtual 00696 // Description: Frees the resources previously allocated via a call 00697 // to prepare_data(), including deleting the 00698 // VertexBufferContext itself, if necessary. 00699 //////////////////////////////////////////////////////////////////// 00700 void GraphicsStateGuardian:: 00701 release_vertex_buffer(VertexBufferContext *) { 00702 } 00703 00704 //////////////////////////////////////////////////////////////////// 00705 // Function: GraphicsStateGuardian::prepare_index_buffer 00706 // Access: Public, Virtual 00707 // Description: Prepares the indicated buffer for retained-mode 00708 // rendering. 00709 //////////////////////////////////////////////////////////////////// 00710 IndexBufferContext *GraphicsStateGuardian:: 00711 prepare_index_buffer(GeomPrimitive *) { 00712 return (IndexBufferContext *)NULL; 00713 } 00714 00715 //////////////////////////////////////////////////////////////////// 00716 // Function: GraphicsStateGuardian::release_index_buffer 00717 // Access: Public, Virtual 00718 // Description: Frees the resources previously allocated via a call 00719 // to prepare_data(), including deleting the 00720 // IndexBufferContext itself, if necessary. 00721 //////////////////////////////////////////////////////////////////// 00722 void GraphicsStateGuardian:: 00723 release_index_buffer(IndexBufferContext *) { 00724 } 00725 00726 //////////////////////////////////////////////////////////////////// 00727 // Function: GraphicsStateGuardian::get_supports_occlusion_query 00728 // Access: Public, Virtual 00729 // Description: Returns true if this GSG supports an occlusion query. 00730 // If this is true, then begin_occlusion_query() and 00731 // end_occlusion_query() may be called to bracket a 00732 // sequence of draw_triangles() (or whatever) calls to 00733 // measure pixels that pass the depth test. 00734 //////////////////////////////////////////////////////////////////// 00735 bool GraphicsStateGuardian:: 00736 get_supports_occlusion_query() const { 00737 return _supports_occlusion_query; 00738 } 00739 00740 //////////////////////////////////////////////////////////////////// 00741 // Function: GraphicsStateGuardian::begin_occlusion_query 00742 // Access: Public, Virtual 00743 // Description: Begins a new occlusion query. After this call, you 00744 // may call begin_draw_primitives() and 00745 // draw_triangles()/draw_whatever() repeatedly. 00746 // Eventually, you should call end_occlusion_query() 00747 // before the end of the frame; that will return a new 00748 // OcclusionQueryContext object that will tell you how 00749 // many pixels represented by the bracketed geometry 00750 // passed the depth test. 00751 // 00752 // It is not valid to call begin_occlusion_query() 00753 // between another begin_occlusion_query() 00754 // .. end_occlusion_query() sequence. 00755 //////////////////////////////////////////////////////////////////// 00756 void GraphicsStateGuardian:: 00757 begin_occlusion_query() { 00758 nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL); 00759 } 00760 00761 //////////////////////////////////////////////////////////////////// 00762 // Function: GraphicsStateGuardian::end_occlusion_query 00763 // Access: Public, Virtual 00764 // Description: Ends a previous call to begin_occlusion_query(). 00765 // This call returns the OcclusionQueryContext object 00766 // that will (eventually) report the number of pixels 00767 // that passed the depth test between the call to 00768 // begin_occlusion_query() and end_occlusion_query(). 00769 //////////////////////////////////////////////////////////////////// 00770 PT(OcclusionQueryContext) GraphicsStateGuardian:: 00771 end_occlusion_query() { 00772 nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL); 00773 PT(OcclusionQueryContext) result = _current_occlusion_query; 00774 _current_occlusion_query = NULL; 00775 return result; 00776 } 00777 00778 //////////////////////////////////////////////////////////////////// 00779 // Function: GraphicsStateGuardian::get_geom_munger 00780 // Access: Public, Virtual 00781 // Description: Looks up or creates a GeomMunger object to munge 00782 // vertices appropriate to this GSG for the indicated 00783 // state. 00784 //////////////////////////////////////////////////////////////////// 00785 PT(GeomMunger) GraphicsStateGuardian:: 00786 get_geom_munger(const RenderState *state, Thread *current_thread) { 00787 // We can cast the RenderState to a non-const object because we are 00788 // only updating a cache within the RenderState, not really changing 00789 // any of its properties. 00790 RenderState *nc_state = ((RenderState *)state); 00791 00792 // Before we even look up the map, see if the _last_mi value points 00793 // to this GSG. This is likely because we tend to visit the same 00794 // state multiple times during a frame. Also, this might well be 00795 // the only GSG in the world anyway. 00796 if (!nc_state->_mungers.empty()) { 00797 RenderState::Mungers::const_iterator mi = nc_state->_last_mi; 00798 if (!(*mi).first.was_deleted() && (*mi).first == this) { 00799 if ((*mi).second->is_registered()) { 00800 return (*mi).second; 00801 } 00802 } 00803 } 00804 00805 // Nope, we have to look it up in the map. 00806 RenderState::Mungers::iterator mi = nc_state->_mungers.find(this); 00807 if (mi != nc_state->_mungers.end() && !(*mi).first.was_deleted()) { 00808 if ((*mi).second->is_registered()) { 00809 nc_state->_last_mi = mi; 00810 return (*mi).second; 00811 } 00812 // This GeomMunger is no longer registered. Remove it from the 00813 // map. 00814 nc_state->_mungers.erase(mi); 00815 } 00816 00817 // Nothing in the map; create a new entry. 00818 PT(GeomMunger) munger = make_geom_munger(nc_state, current_thread); 00819 nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger); 00820 00821 mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first; 00822 nc_state->_last_mi = mi; 00823 00824 return munger; 00825 } 00826 00827 //////////////////////////////////////////////////////////////////// 00828 // Function: GraphicsStateGuardian::make_geom_munger 00829 // Access: Public, Virtual 00830 // Description: Creates a new GeomMunger object to munge vertices 00831 // appropriate to this GSG for the indicated state. 00832 //////////////////////////////////////////////////////////////////// 00833 PT(GeomMunger) GraphicsStateGuardian:: 00834 make_geom_munger(const RenderState *state, Thread *current_thread) { 00835 // The default implementation returns no munger at all, but 00836 // presumably, every kind of GSG needs some special munging action, 00837 // so real GSG's will override this to return something more 00838 // useful. 00839 return NULL; 00840 } 00841 00842 //////////////////////////////////////////////////////////////////// 00843 // Function: GraphicsStateGuardian::compute_distance_to 00844 // Access: Public, Virtual 00845 // Description: This function may only be called during a render 00846 // traversal; it will compute the distance to the 00847 // indicated point, assumed to be in eye coordinates, 00848 // from the camera plane. 00849 //////////////////////////////////////////////////////////////////// 00850 float GraphicsStateGuardian:: 00851 compute_distance_to(const LPoint3f &point) const { 00852 switch (_coordinate_system) { 00853 case CS_zup_right: 00854 return point[1]; 00855 00856 case CS_yup_right: 00857 return -point[2]; 00858 00859 case CS_zup_left: 00860 return -point[1]; 00861 00862 case CS_yup_left: 00863 return point[2]; 00864 00865 default: 00866 gsg_cat.error() 00867 << "Invalid coordinate system in compute_distance_to: " 00868 << (int)_coordinate_system << "\n"; 00869 return 0.0f; 00870 } 00871 } 00872 00873 //////////////////////////////////////////////////////////////////// 00874 // Function: GraphicsStateGuardian::fetch_specified_value 00875 // Access: Public 00876 // Description: The gsg contains a large number of useful matrices: 00877 // 00878 // * the world transform, 00879 // * the modelview matrix, 00880 // * the cs_transform, 00881 // * etc, etc. 00882 // 00883 // A shader can request any of these values, and 00884 // furthermore, it can request that various compositions, 00885 // inverses, and transposes be performed. The 00886 // ShaderMatSpec is a data structure indicating what 00887 // datum is desired and what conversions to perform. 00888 // This routine, fetch_specified_value, is responsible for 00889 // doing the actual retrieval and conversions. 00890 // 00891 // Some values, like the following, aren't matrices: 00892 // 00893 // * window size 00894 // * texture coordinates of card center 00895 // 00896 // This routine can fetch these values as well, by 00897 // shoehorning them into a matrix. In this way, we avoid 00898 // the need for a separate routine to fetch these values. 00899 // 00900 // The "altered" bits indicate what parts of the 00901 // state_and_transform have changed since the last 00902 // time this particular ShaderMatSpec was evaluated. 00903 // This may allow data to be cached and not reevaluated. 00904 // 00905 //////////////////////////////////////////////////////////////////// 00906 const LMatrix4f *GraphicsStateGuardian:: 00907 fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) { 00908 LVecBase3f v; 00909 00910 if (altered & spec._dep[0]) { 00911 const LMatrix4f *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0]); 00912 if (t != &spec._cache[0]) { 00913 spec._cache[0] = *t; 00914 } 00915 } 00916 if (altered & spec._dep[1]) { 00917 const LMatrix4f *t = fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1]); 00918 if (t != &spec._cache[1]) { 00919 spec._cache[1] = *t; 00920 } 00921 } 00922 00923 switch(spec._func) { 00924 case Shader::SMF_compose: 00925 spec._value.multiply(spec._cache[0], spec._cache[1]); 00926 return &spec._value; 00927 case Shader::SMF_transform_dlight: 00928 spec._value = spec._cache[0]; 00929 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2)); 00930 v.normalize(); 00931 spec._value.set_row(2, v); 00932 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3)); 00933 v.normalize(); 00934 spec._value.set_row(3, v); 00935 return &spec._value; 00936 case Shader::SMF_transform_plight: 00937 spec._value = spec._cache[0]; 00938 spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2))); 00939 return &spec._value; 00940 case Shader::SMF_transform_slight: 00941 spec._value = spec._cache[0]; 00942 spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2))); 00943 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3)); 00944 v.normalize(); 00945 spec._value.set_row(3, v); 00946 return &spec._value; 00947 case Shader::SMF_first: 00948 return &spec._cache[0]; 00949 default: 00950 // should never get here 00951 spec._value = LMatrix4f::ident_mat(); 00952 return &spec._value; 00953 } 00954 } 00955 00956 //////////////////////////////////////////////////////////////////// 00957 // Function: GraphicsStateGuardian::fetch_specified_part 00958 // Access: Public 00959 // Description: See fetch_specified_value 00960 //////////////////////////////////////////////////////////////////// 00961 const LMatrix4f *GraphicsStateGuardian:: 00962 fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f &t) { 00963 switch(part) { 00964 case Shader::SMO_identity: { 00965 return &LMatrix4f::ident_mat(); 00966 } 00967 case Shader::SMO_window_size: { 00968 t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(), 00969 _current_display_region->get_pixel_height(), 00970 0.0); 00971 return &t; 00972 } 00973 case Shader::SMO_pixel_size: { 00974 t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(), 00975 _current_display_region->get_pixel_height(), 00976 0.0); 00977 return &t; 00978 } 00979 case Shader::SMO_texpad_x: { 00980 Texture *tex = _target_shader->get_shader_input_texture(name); 00981 nassertr(tex != 0, &LMatrix4f::zeros_mat()); 00982 int sx = tex->get_x_size() - tex->get_pad_x_size(); 00983 int sy = tex->get_y_size() - tex->get_pad_y_size(); 00984 int sz = tex->get_z_size() - tex->get_pad_z_size(); 00985 double cx = (sx * 0.5) / tex->get_x_size(); 00986 double cy = (sy * 0.5) / tex->get_y_size(); 00987 double cz = (sz * 0.5) / tex->get_z_size(); 00988 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0); 00989 return &t; 00990 } 00991 case Shader::SMO_texpix_x: { 00992 Texture *tex = _target_shader->get_shader_input_texture(name); 00993 nassertr(tex != 0, &LMatrix4f::zeros_mat()); 00994 double px = 1.0 / tex->get_x_size(); 00995 double py = 1.0 / tex->get_y_size(); 00996 double pz = 1.0 / tex->get_z_size(); 00997 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0); 00998 return &t; 00999 } 01000 case Shader::SMO_attr_material: { 01001 const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot())); 01002 // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS 01003 if (target_material->is_off()) { 01004 t = LMatrix4f(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0); 01005 return &t; 01006 } 01007 Material *m = target_material->get_material(); 01008 LVecBase4f const &amb = m->get_ambient(); 01009 LVecBase4f const &dif = m->get_diffuse(); 01010 LVecBase4f const &emm = m->get_emission(); 01011 LVecBase4f spc = m->get_specular(); 01012 spc[3] = m->get_shininess(); 01013 t = LMatrix4f(amb[0],amb[1],amb[2],amb[3], 01014 dif[0],dif[1],dif[2],dif[3], 01015 emm[0],emm[1],emm[2],emm[3], 01016 spc[0],spc[1],spc[2],spc[3]); 01017 return &t; 01018 } 01019 case Shader::SMO_attr_color: { 01020 const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot())); 01021 if (target_color->get_color_type() != ColorAttrib::T_flat) { 01022 return &LMatrix4f::ones_mat(); 01023 } 01024 LVecBase4f c = target_color->get_color(); 01025 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]); 01026 return &t; 01027 } 01028 case Shader::SMO_attr_colorscale: { 01029 const ColorScaleAttrib *target_color = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot())); 01030 if (target_color->is_identity()) { 01031 return &LMatrix4f::ones_mat(); 01032 } 01033 LVecBase4f cs = target_color->get_scale(); 01034 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]); 01035 return &t; 01036 } 01037 case Shader::SMO_alight_x: { 01038 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01039 nassertr(!np.is_empty(), &LMatrix4f::zeros_mat()); 01040 AmbientLight *lt; 01041 DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat()); 01042 Colorf const &c = lt->get_color(); 01043 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]); 01044 return &t; 01045 } 01046 case Shader::SMO_satten_x: { 01047 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01048 nassertr(!np.is_empty(), &LMatrix4f::ones_mat()); 01049 Spotlight *lt; 01050 DCAST_INTO_R(lt, np.node(), &LMatrix4f::ones_mat()); 01051 LVecBase3f const &a = lt->get_attenuation(); 01052 float x = lt->get_exponent(); 01053 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x); 01054 return &t; 01055 } 01056 case Shader::SMO_dlight_x: { 01057 // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE 01058 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01059 nassertr(!np.is_empty(), &LMatrix4f::zeros_mat()); 01060 DirectionalLight *lt; 01061 DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat()); 01062 Colorf const &c = lt->get_color(); 01063 Colorf const &s = lt->get_specular_color(); 01064 t = np.get_net_transform()->get_mat() * 01065 get_scene()->get_world_transform()->get_mat(); 01066 LVecBase3f d = -(t.xform_vec(lt->get_direction())); 01067 d.normalize(); 01068 LVecBase3f h = d + LVecBase3f(0,-1,0); 01069 h.normalize(); 01070 t = LMatrix4f(c[0],c[1],c[2],c[3],s[0],s[1],s[2],c[3],d[0],d[1],d[2],0,h[0],h[1],h[2],0); 01071 return &t; 01072 } 01073 case Shader::SMO_plight_x: { 01074 // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION 01075 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01076 nassertr(!np.is_empty(), &LMatrix4f::ones_mat()); 01077 PointLight *lt; 01078 DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat()); 01079 Colorf const &c = lt->get_color(); 01080 Colorf const &s = lt->get_specular_color(); 01081 t = np.get_net_transform()->get_mat() * 01082 get_scene()->get_world_transform()->get_mat(); 01083 LVecBase3f p = (t.xform_point(lt->get_point())); 01084 LVecBase3f a = lt->get_attenuation(); 01085 t = LMatrix4f(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,a[0],a[1],a[2],0); 01086 return &t; 01087 } 01088 case Shader::SMO_slight_x: { 01089 // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION 01090 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01091 nassertr(!np.is_empty(), &LMatrix4f::zeros_mat()); 01092 Spotlight *lt; 01093 DCAST_INTO_R(lt, np.node(), &LMatrix4f::zeros_mat()); 01094 Lens *lens = lt->get_lens(); 01095 nassertr(lens != (Lens *)NULL, &LMatrix4f::zeros_mat()); 01096 Colorf const &c = lt->get_color(); 01097 Colorf const &s = lt->get_specular_color(); 01098 float cutoff = cos(deg_2_rad(lens->get_hfov() * 0.5f)); 01099 t = np.get_net_transform()->get_mat() * 01100 get_scene()->get_world_transform()->get_mat(); 01101 LVecBase3f p = t.xform_point(lens->get_nodal_point()); 01102 LVecBase3f d = -(t.xform_vec(lens->get_view_vector())); 01103 t = LMatrix4f(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff); 01104 return &t; 01105 } 01106 case Shader::SMO_texmat_x: { 01107 const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); 01108 const TextureAttrib *ta = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot())); 01109 int stagenr = atoi(name->get_name().c_str()); 01110 if (stagenr >= ta->get_num_on_stages()) { 01111 return &LMatrix4f::ident_mat(); 01112 } 01113 return &tma->get_mat(ta->get_on_stage(stagenr)); 01114 } 01115 case Shader::SMO_plane_x: { 01116 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01117 nassertr(!np.is_empty(), &LMatrix4f::zeros_mat()); 01118 nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4f::zeros_mat()); 01119 Planef p = DCAST(PlaneNode, np.node())->get_plane(); 01120 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]); 01121 return &t; 01122 } 01123 case Shader::SMO_clipplane_x: { 01124 const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); 01125 int planenr = atoi(name->get_name().c_str()); 01126 if (planenr >= cpa->get_num_on_planes()) { 01127 return &LMatrix4f::zeros_mat(); 01128 } 01129 const NodePath &np = cpa->get_on_plane(planenr); 01130 nassertr(!np.is_empty(), &LMatrix4f::zeros_mat()); 01131 nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4f::zeros_mat()); 01132 Planef p (DCAST(PlaneNode, np.node())->get_plane()); 01133 p.xform(np.get_net_transform()->get_mat()); // World-space 01134 t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]); 01135 return &t; 01136 } 01137 case Shader::SMO_mat_constant_x: { 01138 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01139 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01140 return &(np.node()->get_transform()->get_mat()); 01141 } 01142 case Shader::SMO_vec_constant_x: { 01143 const LVector4f &input = _target_shader->get_shader_input_vector(name); 01144 const float *data = input.get_data(); 01145 t = LMatrix4f(data[0],data[1],data[2],data[3], 01146 data[0],data[1],data[2],data[3], 01147 data[0],data[1],data[2],data[3], 01148 data[0],data[1],data[2],data[3]); 01149 return &t; 01150 } 01151 case Shader::SMO_world_to_view: { 01152 return &(get_scene()->get_world_transform()->get_mat()); 01153 break; 01154 } 01155 case Shader::SMO_view_to_world: { 01156 return &(get_scene()->get_camera_transform()->get_mat()); 01157 } 01158 case Shader::SMO_model_to_view: { 01159 return &(get_external_transform()->get_mat()); 01160 } 01161 case Shader::SMO_view_to_model: { 01162 // DANGER: SLOW AND NOT CACHEABLE! 01163 t.invert_from(get_external_transform()->get_mat()); 01164 return &t; 01165 } 01166 case Shader::SMO_apiview_to_view: { 01167 return &(_inv_cs_transform->get_mat()); 01168 } 01169 case Shader::SMO_view_to_apiview: { 01170 return &(_cs_transform->get_mat()); 01171 } 01172 case Shader::SMO_clip_to_view: { 01173 if (_current_lens->get_coordinate_system() == _coordinate_system) { 01174 return &(_current_lens->get_projection_mat_inv(_current_stereo_channel)); 01175 } else { 01176 t = _current_lens->get_projection_mat_inv(_current_stereo_channel) * 01177 LMatrix4f::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system); 01178 return &t; 01179 } 01180 } 01181 case Shader::SMO_view_to_clip: { 01182 if (_current_lens->get_coordinate_system() == _coordinate_system) { 01183 return &(_current_lens->get_projection_mat(_current_stereo_channel)); 01184 } else { 01185 t = LMatrix4f::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) * 01186 _current_lens->get_projection_mat(_current_stereo_channel); 01187 return &t; 01188 } 01189 } 01190 case Shader::SMO_apiclip_to_view: { 01191 t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat(); 01192 return &t; 01193 } 01194 case Shader::SMO_view_to_apiclip: { 01195 t = _cs_transform->get_mat() * _projection_mat->get_mat(); 01196 return &t; 01197 } 01198 case Shader::SMO_view_x_to_view: { 01199 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01200 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01201 t = np.get_net_transform()->get_mat() * 01202 get_scene()->get_world_transform()->get_mat(); 01203 return &t; 01204 } 01205 case Shader::SMO_view_to_view_x: { 01206 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01207 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01208 t = get_scene()->get_camera_transform()->get_mat() * 01209 invert(np.get_net_transform()->get_mat()); 01210 return &t; 01211 } 01212 case Shader::SMO_apiview_x_to_view: { 01213 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01214 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01215 t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) * 01216 np.get_net_transform()->get_mat() * 01217 get_scene()->get_world_transform()->get_mat(); 01218 return &t; 01219 } 01220 case Shader::SMO_view_to_apiview_x: { 01221 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01222 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01223 t = (get_scene()->get_camera_transform()->get_mat() * 01224 invert(np.get_net_transform()->get_mat()) * 01225 LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system)); 01226 return &t; 01227 } 01228 case Shader::SMO_clip_x_to_view: { 01229 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01230 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01231 nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4f::ident_mat()); 01232 Lens *lens = DCAST(LensNode, np.node())->get_lens(); 01233 t = lens->get_projection_mat_inv(_current_stereo_channel) * 01234 LMatrix4f::convert_mat(lens->get_coordinate_system(), _coordinate_system) * 01235 np.get_net_transform()->get_mat() * 01236 get_scene()->get_world_transform()->get_mat(); 01237 return &t; 01238 } 01239 case Shader::SMO_view_to_clip_x: { 01240 const NodePath &np = _target_shader->get_shader_input_nodepath(name); 01241 nassertr(!np.is_empty(), &LMatrix4f::ident_mat()); 01242 nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4f::ident_mat()); 01243 Lens *lens = DCAST(LensNode, np.node())->get_lens(); 01244 t = get_scene()->get_camera_transform()->get_mat() * 01245 invert(np.get_net_transform()->get_mat()) * 01246 LMatrix4f::convert_mat(_coordinate_system, lens->get_coordinate_system()) * 01247 lens->get_projection_mat(_current_stereo_channel); 01248 return &t; 01249 } 01250 case Shader::SMO_apiclip_x_to_view: { 01251 // NOT IMPLEMENTED 01252 return &LMatrix4f::ident_mat(); 01253 } 01254 case Shader::SMO_view_to_apiclip_x: { 01255 // NOT IMPLEMENTED 01256 return &LMatrix4f::ident_mat(); 01257 } 01258 default: 01259 // should never get here 01260 return &LMatrix4f::ident_mat(); 01261 } 01262 } 01263 01264 //////////////////////////////////////////////////////////////////// 01265 // Function: GraphicsStateGuardian::prepare_display_region 01266 // Access: Public, Virtual 01267 // Description: Makes the specified DisplayRegion current. All 01268 // future drawing and clear operations will be 01269 // constrained within the given DisplayRegion. 01270 // 01271 // The stereo_channel parameter further qualifies the 01272 // channel that is to be rendered into, in the case of a 01273 // stereo display region. Normally, in the monocular 01274 // case, it is Lens::SC_mono. 01275 //////////////////////////////////////////////////////////////////// 01276 void GraphicsStateGuardian:: 01277 prepare_display_region(DisplayRegionPipelineReader *dr, 01278 Lens::StereoChannel stereo_channel) { 01279 _current_display_region = dr->get_object(); 01280 _current_stereo_channel = stereo_channel; 01281 _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render(); 01282 01283 _stereo_buffer_mask = ~0; 01284 01285 switch (stereo_channel) { 01286 case Lens::SC_left: 01287 _color_write_mask = dr->get_window()->get_left_eye_color_mask(); 01288 if (_current_properties->is_stereo()) { 01289 _stereo_buffer_mask = ~(RenderBuffer::T_front_right | RenderBuffer::T_back_right); 01290 } 01291 break; 01292 01293 case Lens::SC_right: 01294 _color_write_mask = dr->get_window()->get_right_eye_color_mask(); 01295 if (_current_properties->is_stereo()) { 01296 _stereo_buffer_mask = ~(RenderBuffer::T_front_left | RenderBuffer::T_back_left); 01297 } 01298 break; 01299 01300 case Lens::SC_mono: 01301 case Lens::SC_stereo: 01302 _color_write_mask = ColorWriteAttrib::C_all; 01303 } 01304 } 01305 01306 //////////////////////////////////////////////////////////////////// 01307 // Function: GraphicsStateGuardian::clear_before_callback 01308 // Access: Public, Virtual 01309 // Description: Resets any non-standard graphics state that might 01310 // give a callback apoplexy. Some drivers require that 01311 // the graphics state be restored to neutral before 01312 // performing certain operations. In OpenGL, for 01313 // instance, this closes any open vertex buffers. 01314 //////////////////////////////////////////////////////////////////// 01315 void GraphicsStateGuardian:: 01316 clear_before_callback() { 01317 } 01318 01319 //////////////////////////////////////////////////////////////////// 01320 // Function: GraphicsStateGuardian::clear_state_and_transform 01321 // Access: Public, Virtual 01322 // Description: Forgets the current graphics state and current 01323 // transform, so that the next call to 01324 // set_state_and_transform() will have to reload 01325 // everything. This is a good thing to call when you 01326 // are no longer sure what the graphics state is. This 01327 // should only be called from the draw thread. 01328 //////////////////////////////////////////////////////////////////// 01329 void GraphicsStateGuardian:: 01330 clear_state_and_transform() { 01331 // Re-issue the modelview and projection transforms. 01332 reissue_transforms(); 01333 01334 // Now clear the state flags to unknown. 01335 _state_rs = RenderState::make_empty(); 01336 _state_mask.clear(); 01337 } 01338 01339 //////////////////////////////////////////////////////////////////// 01340 // Function: GraphicsStateGuardian::remove_window 01341 // Access: Public, Virtual 01342 // Description: This is simply a transparent call to 01343 // GraphicsEngine::remove_window(). It exists primary 01344 // to support removing a window from that compiles 01345 // before the display module, and therefore has no 01346 // knowledge of a GraphicsEngine object. 01347 //////////////////////////////////////////////////////////////////// 01348 void GraphicsStateGuardian:: 01349 remove_window(GraphicsOutputBase *window) { 01350 nassertv(_engine != (GraphicsEngine *)NULL); 01351 GraphicsOutput *win; 01352 DCAST_INTO_V(win, window); 01353 _engine->remove_window(win); 01354 } 01355 01356 //////////////////////////////////////////////////////////////////// 01357 // Function: GraphicsStateGuardian::prepare_lens 01358 // Access: Public, Virtual 01359 // Description: Makes the current lens (whichever lens was most 01360 // recently specified with set_scene()) active, so 01361 // that it will transform future rendered geometry. 01362 // Normally this is only called from the draw process, 01363 // and usually it is called by set_scene(). 01364 // 01365 // The return value is true if the lens is acceptable, 01366 // false if it is not. 01367 //////////////////////////////////////////////////////////////////// 01368 bool GraphicsStateGuardian:: 01369 prepare_lens() { 01370 return false; 01371 } 01372 01373 //////////////////////////////////////////////////////////////////// 01374 // Function: GraphicsStateGuardian::calc_projection_mat 01375 // Access: Public, Virtual 01376 // Description: Given a lens, this function calculates the appropriate 01377 // projection matrix for this gsg. The result depends 01378 // on the peculiarities of the rendering API. 01379 //////////////////////////////////////////////////////////////////// 01380 CPT(TransformState) GraphicsStateGuardian:: 01381 calc_projection_mat(const Lens *lens) { 01382 if (lens == (Lens *)NULL) { 01383 return NULL; 01384 } 01385 01386 if (!lens->is_linear()) { 01387 return NULL; 01388 } 01389 01390 return TransformState::make_identity(); 01391 } 01392 01393 //////////////////////////////////////////////////////////////////// 01394 // Function: GraphicsStateGuardian::begin_frame 01395 // Access: Public, Virtual 01396 // Description: Called before each frame is rendered, to allow the 01397 // GSG a chance to do any internal cleanup before 01398 // beginning the frame. 01399 // 01400 // The return value is true if successful (in which case 01401 // the frame will be drawn and end_frame() will be 01402 // called later), or false if unsuccessful (in which 01403 // case nothing will be drawn and end_frame() will not 01404 // be called). 01405 //////////////////////////////////////////////////////////////////// 01406 bool GraphicsStateGuardian:: 01407 begin_frame(Thread *current_thread) { 01408 _prepared_objects->begin_frame(this, current_thread); 01409 01410 // We should reset the state to the default at the beginning of 01411 // every frame. Although this will incur additional overhead, 01412 // particularly in a simple scene, it helps ensure that states that 01413 // have changed properties since last time without changing 01414 // attribute pointers--like textures, lighting, or fog--will still 01415 // be accurately updated. 01416 _state_rs = RenderState::make_empty(); 01417 _state_mask.clear(); 01418 01419 return true; 01420 } 01421 01422 //////////////////////////////////////////////////////////////////// 01423 // Function: GraphicsStateGuardian::begin_scene 01424 // Access: Published, Virtual 01425 // Description: Called between begin_frame() and end_frame() to mark 01426 // the beginning of drawing commands for a "scene" 01427 // (usually a particular DisplayRegion) within a frame. 01428 // All 3-D drawing commands, except the clear operation, 01429 // must be enclosed within begin_scene() .. end_scene(). 01430 // This must be called in the draw thread. 01431 // 01432 // The return value is true if successful (in which case 01433 // the scene will be drawn and end_scene() will be 01434 // called later), or false if unsuccessful (in which 01435 // case nothing will be drawn and end_scene() will not 01436 // be called). 01437 //////////////////////////////////////////////////////////////////// 01438 bool GraphicsStateGuardian:: 01439 begin_scene() { 01440 return true; 01441 } 01442 01443 //////////////////////////////////////////////////////////////////// 01444 // Function: GraphicsStateGuardian::end_scene 01445 // Access: Published, Virtual 01446 // Description: Called between begin_frame() and end_frame() to mark 01447 // the end of drawing commands for a "scene" (usually a 01448 // particular DisplayRegion) within a frame. All 3-D 01449 // drawing commands, except the clear operation, must be 01450 // enclosed within begin_scene() .. end_scene(). 01451 //////////////////////////////////////////////////////////////////// 01452 void GraphicsStateGuardian:: 01453 end_scene() { 01454 // We should clear this pointer now, so that we don't keep unneeded 01455 // reference counts dangling. We keep around a "null" scene setup 01456 // object instead of using a null pointer to avoid special-case code 01457 // in set_state_and_transform. 01458 _scene_setup = _scene_null; 01459 01460 // Undo any lighting we had enabled last scene, to force the lights 01461 // to be reissued, in case their parameters or positions have 01462 // changed between scenes. 01463 int i; 01464 for (i = 0; i < _num_lights_enabled; ++i) { 01465 enable_light(i, false); 01466 } 01467 _num_lights_enabled = 0; 01468 01469 // Ditto for the clipping planes. 01470 for (i = 0; i < _num_clip_planes_enabled; ++i) { 01471 enable_clip_plane(i, false); 01472 } 01473 _num_clip_planes_enabled = 0; 01474 01475 // Put the state into the 'unknown' state, forcing a reload. 01476 _state_rs = RenderState::make_empty(); 01477 _state_mask.clear(); 01478 } 01479 01480 //////////////////////////////////////////////////////////////////// 01481 // Function: GraphicsStateGuardian::end_frame 01482 // Access: Public, Virtual 01483 // Description: Called after each frame is rendered, to allow the 01484 // GSG a chance to do any internal cleanup after 01485 // rendering the frame, and before the window flips. 01486 //////////////////////////////////////////////////////////////////// 01487 void GraphicsStateGuardian:: 01488 end_frame(Thread *current_thread) { 01489 _prepared_objects->end_frame(current_thread); 01490 01491 // Flush any PStatCollectors. 01492 _data_transferred_pcollector.flush_level(); 01493 01494 _primitive_batches_pcollector.flush_level(); 01495 _primitive_batches_tristrip_pcollector.flush_level(); 01496 _primitive_batches_trifan_pcollector.flush_level(); 01497 _primitive_batches_tri_pcollector.flush_level(); 01498 _primitive_batches_other_pcollector.flush_level(); 01499 _vertices_tristrip_pcollector.flush_level(); 01500 _vertices_trifan_pcollector.flush_level(); 01501 _vertices_tri_pcollector.flush_level(); 01502 _vertices_other_pcollector.flush_level(); 01503 01504 _state_pcollector.flush_level(); 01505 _texture_state_pcollector.flush_level(); 01506 _transform_state_pcollector.flush_level(); 01507 _draw_primitive_pcollector.flush_level(); 01508 01509 // Evict any textures and/or vbuffers that exceed our texture memory. 01510 _prepared_objects->_graphics_memory_lru.begin_epoch(); 01511 } 01512 01513 //////////////////////////////////////////////////////////////////// 01514 // Function: GraphicsStateGuardian::depth_offset_decals 01515 // Access: Public, Virtual 01516 // Description: Returns true if this GSG can implement decals using a 01517 // DepthOffsetAttrib, or false if that is unreliable 01518 // and the three-step rendering process should be used 01519 // instead. 01520 //////////////////////////////////////////////////////////////////// 01521 bool GraphicsStateGuardian:: 01522 depth_offset_decals() { 01523 return true; 01524 } 01525 01526 //////////////////////////////////////////////////////////////////// 01527 // Function: GraphicsStateGuardian::begin_decal_base_first 01528 // Access: Public, Virtual 01529 // Description: Called during draw to begin a three-step rendering 01530 // phase to draw decals. The first step, 01531 // begin_decal_base_first(), is called prior to drawing the 01532 // base geometry. It should set up whatever internal 01533 // state is appropriate, as well as returning a 01534 // RenderState object that should be applied to the base 01535 // geometry for rendering. 01536 //////////////////////////////////////////////////////////////////// 01537 CPT(RenderState) GraphicsStateGuardian:: 01538 begin_decal_base_first() { 01539 // Turn off writing the depth buffer to render the base geometry. 01540 static CPT(RenderState) decal_base_first; 01541 if (decal_base_first == (const RenderState *)NULL) { 01542 decal_base_first = RenderState::make 01543 (DepthWriteAttrib::make(DepthWriteAttrib::M_off), 01544 RenderState::get_max_priority()); 01545 } 01546 return decal_base_first; 01547 } 01548 01549 //////////////////////////////////////////////////////////////////// 01550 // Function: GraphicsStateGuardian::begin_decal_nested 01551 // Access: Public, Virtual 01552 // Description: Called during draw to begin a three-step rendering 01553 // phase to draw decals. The second step, 01554 // begin_decal_nested(), is called after drawing the 01555 // base geometry and prior to drawing any of the nested 01556 // decal geometry that is to be applied to the base 01557 // geometry. 01558 //////////////////////////////////////////////////////////////////// 01559 CPT(RenderState) GraphicsStateGuardian:: 01560 begin_decal_nested() { 01561 // We should keep the depth buffer off during this operation, so 01562 // that decals on decals will render properly. 01563 static CPT(RenderState) decal_nested; 01564 if (decal_nested == (const RenderState *)NULL) { 01565 decal_nested = RenderState::make 01566 (DepthWriteAttrib::make(DepthWriteAttrib::M_off), 01567 RenderState::get_max_priority()); 01568 } 01569 return decal_nested; 01570 } 01571 01572 //////////////////////////////////////////////////////////////////// 01573 // Function: GraphicsStateGuardian::begin_decal_base_second 01574 // Access: Public, Virtual 01575 // Description: Called during draw to begin a three-step rendering 01576 // phase to draw decals. The third step, 01577 // begin_decal_base_second(), is called after drawing the 01578 // base geometry and the nested decal geometry, and 01579 // prior to drawing the base geometry one more time (if 01580 // needed). 01581 // 01582 // It should return a RenderState object appropriate for 01583 // rendering the base geometry the second time, or NULL 01584 // if it is not necessary to re-render the base 01585 // geometry. 01586 //////////////////////////////////////////////////////////////////// 01587 CPT(RenderState) GraphicsStateGuardian:: 01588 begin_decal_base_second() { 01589 // Now let the depth buffer go back on, but turn off writing the 01590 // color buffer to render the base geometry after the second pass. 01591 // Also, turn off texturing since there's no need for it now. 01592 static CPT(RenderState) decal_base_second; 01593 if (decal_base_second == (const RenderState *)NULL) { 01594 decal_base_second = RenderState::make 01595 (ColorWriteAttrib::make(ColorWriteAttrib::C_off), 01596 // On reflection, we need to leave texturing on so the alpha 01597 // test mechanism can work (if it is enabled, e.g. we are 01598 // rendering an object with M_dual transparency). 01599 // TextureAttrib::make_off(), 01600 RenderState::get_max_priority()); 01601 } 01602 return decal_base_second; 01603 } 01604 01605 //////////////////////////////////////////////////////////////////// 01606 // Function: GraphicsStateGuardian::finish_decal 01607 // Access: Public, Virtual 01608 // Description: Called during draw to clean up after decals are 01609 // finished. 01610 //////////////////////////////////////////////////////////////////// 01611 void GraphicsStateGuardian:: 01612 finish_decal() { 01613 // No need to do anything special here. 01614 } 01615 01616 //////////////////////////////////////////////////////////////////// 01617 // Function: GraphicsStateGuardian::begin_draw_primitives() 01618 // Access: Public, Virtual 01619 // Description: Called before a sequence of draw_primitive() 01620 // functions are called, this should prepare the vertex 01621 // data for rendering. It returns true if the vertices 01622 // are ok, false to abort this group of primitives. 01623 //////////////////////////////////////////////////////////////////// 01624 bool GraphicsStateGuardian:: 01625 begin_draw_primitives(const GeomPipelineReader *geom_reader, 01626 const GeomMunger *munger, 01627 const GeomVertexDataPipelineReader *data_reader, 01628 bool force) { 01629 _munger = munger; 01630 _data_reader = data_reader; 01631 return _data_reader->has_vertex(); 01632 } 01633 01634 //////////////////////////////////////////////////////////////////// 01635 // Function: GraphicsStateGuardian::draw_triangles 01636 // Access: Public, Virtual 01637 // Description: Draws a series of disconnected triangles. 01638 //////////////////////////////////////////////////////////////////// 01639 bool GraphicsStateGuardian:: 01640 draw_triangles(const GeomPrimitivePipelineReader *, bool) { 01641 return false; 01642 } 01643 01644 //////////////////////////////////////////////////////////////////// 01645 // Function: GraphicsStateGuardian::draw_tristrips 01646 // Access: Public, Virtual 01647 // Description: Draws a series of triangle strips. 01648 //////////////////////////////////////////////////////////////////// 01649 bool GraphicsStateGuardian:: 01650 draw_tristrips(const GeomPrimitivePipelineReader *, bool) { 01651 return false; 01652 } 01653 01654 //////////////////////////////////////////////////////////////////// 01655 // Function: GraphicsStateGuardian::draw_trifans 01656 // Access: Public, Virtual 01657 // Description: Draws a series of triangle fans. 01658 //////////////////////////////////////////////////////////////////// 01659 bool GraphicsStateGuardian:: 01660 draw_trifans(const GeomPrimitivePipelineReader *, bool) { 01661 return false; 01662 } 01663 01664 //////////////////////////////////////////////////////////////////// 01665 // Function: GraphicsStateGuardian::draw_lines 01666 // Access: Public, Virtual 01667 // Description: Draws a series of disconnected line segments. 01668 //////////////////////////////////////////////////////////////////// 01669 bool GraphicsStateGuardian:: 01670 draw_lines(const GeomPrimitivePipelineReader *, bool) { 01671 return false; 01672 } 01673 01674 //////////////////////////////////////////////////////////////////// 01675 // Function: GraphicsStateGuardian::draw_linestrips 01676 // Access: Public, Virtual 01677 // Description: Draws a series of line strips. 01678 //////////////////////////////////////////////////////////////////// 01679 bool GraphicsStateGuardian:: 01680 draw_linestrips(const GeomPrimitivePipelineReader *, bool) { 01681 return false; 01682 } 01683 01684 //////////////////////////////////////////////////////////////////// 01685 // Function: GraphicsStateGuardian::draw_points 01686 // Access: Public, Virtual 01687 // Description: Draws a series of disconnected points. 01688 //////////////////////////////////////////////////////////////////// 01689 bool GraphicsStateGuardian:: 01690 draw_points(const GeomPrimitivePipelineReader *, bool) { 01691 return false; 01692 } 01693 01694 //////////////////////////////////////////////////////////////////// 01695 // Function: GraphicsStateGuardian::end_draw_primitives() 01696 // Access: Public, Virtual 01697 // Description: Called after a sequence of draw_primitive() 01698 // functions are called, this should do whatever cleanup 01699 // is appropriate. 01700 //////////////////////////////////////////////////////////////////// 01701 void GraphicsStateGuardian:: 01702 end_draw_primitives() { 01703 _munger = NULL; 01704 _data_reader = NULL; 01705 } 01706 01707 //////////////////////////////////////////////////////////////////// 01708 // Function: GraphicsStateGuardian::reset 01709 // Access: Public, Virtual 01710 // Description: Resets all internal state as if the gsg were newly 01711 // created. 01712 //////////////////////////////////////////////////////////////////// 01713 void GraphicsStateGuardian:: 01714 reset() { 01715 _needs_reset = false; 01716 _is_valid = false; 01717 01718 _state_rs = RenderState::make_empty(); 01719 _target_rs = NULL; 01720 _state_mask.clear(); 01721 _internal_transform = _cs_transform; 01722 _scene_null = new SceneSetup; 01723 _scene_setup = _scene_null; 01724 01725 _color_write_mask = ColorWriteAttrib::C_all; 01726 01727 _has_scene_graph_color = false; 01728 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f); 01729 _transform_stale = true; 01730 _color_blend_involves_color_scale = false; 01731 _texture_involves_color_scale = false; 01732 _vertex_colors_enabled = true; 01733 _lighting_enabled = false; 01734 _num_lights_enabled = 0; 01735 _num_clip_planes_enabled = 0; 01736 01737 _color_scale_enabled = false; 01738 _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); 01739 _has_texture_alpha_scale = false; 01740 01741 _has_material_force_color = false; 01742 _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f); 01743 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); 01744 01745 _tex_gen_modifies_mat = false; 01746 _last_max_stage_index = 0; 01747 01748 _is_valid = true; 01749 01750 if (_stencil_render_states) { 01751 delete _stencil_render_states; 01752 _stencil_render_states = 0; 01753 } 01754 _stencil_render_states = new StencilRenderStates (this); 01755 } 01756 01757 //////////////////////////////////////////////////////////////////// 01758 // Function: GraphicsStateGuardian::set_state_and_transform 01759 // Access: Public 01760 // Description: Simultaneously resets the render state and the 01761 // transform state. 01762 // 01763 // This transform specified is the "internal" net 01764 // transform, already converted into the GSG's internal 01765 // coordinate space by composing it to 01766 // get_cs_transform(). (Previously, this used to be the 01767 // "external" net transform, with the assumption that 01768 // that GSG would convert it internally, but that is no 01769 // longer the case.) 01770 // 01771 // Special case: if (state==NULL), then the target 01772 // state is already stored in _target. 01773 //////////////////////////////////////////////////////////////////// 01774 void GraphicsStateGuardian:: 01775 set_state_and_transform(const RenderState *state, 01776 const TransformState *trans) { 01777 } 01778 01779 //////////////////////////////////////////////////////////////////// 01780 // Function: GraphicsStateGuardian::clear 01781 // Access: Public 01782 // Description: Clears the framebuffer within the current 01783 // DisplayRegion, according to the flags indicated by 01784 // the given DrawableRegion object. 01785 // 01786 // This does not set the DisplayRegion first. You 01787 // should call prepare_display_region() to specify the 01788 // region you wish the clear operation to apply to. 01789 //////////////////////////////////////////////////////////////////// 01790 void GraphicsStateGuardian:: 01791 clear(DrawableRegion *clearable) { 01792 } 01793 01794 //////////////////////////////////////////////////////////////////// 01795 // Function: GraphicsStateGuardian::get_render_buffer 01796 // Access: Public 01797 // Description: Returns a RenderBuffer object suitable for operating 01798 // on the requested set of buffers. buffer_type is the 01799 // union of all the desired RenderBuffer::Type values. 01800 //////////////////////////////////////////////////////////////////// 01801 RenderBuffer GraphicsStateGuardian:: 01802 get_render_buffer(int buffer_type, const FrameBufferProperties &prop) { 01803 return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask); 01804 } 01805 01806 //////////////////////////////////////////////////////////////////// 01807 // Function: GraphicsStateGuardian::get_cs_transform 01808 // Access: Public, Virtual 01809 // Description: Returns a transform that converts from the GSG's 01810 // external coordinate system (as returned by 01811 // get_coordinate_system()) to its internal coordinate 01812 // system (as returned by 01813 // get_internal_coordinate_system()). This is used for 01814 // rendering. 01815 //////////////////////////////////////////////////////////////////// 01816 const TransformState *GraphicsStateGuardian:: 01817 get_cs_transform() const { 01818 return _cs_transform; 01819 } 01820 01821 //////////////////////////////////////////////////////////////////// 01822 // Function: GraphicsStateGuardian::do_issue_clip_plane 01823 // Access: Public 01824 // Description: This is fundametically similar to do_issue_light(), with 01825 // calls to apply_clip_plane() and enable_clip_planes(), 01826 // as appropriate. 01827 //////////////////////////////////////////////////////////////////// 01828 void GraphicsStateGuardian:: 01829 do_issue_clip_plane() { 01830 int num_enabled = 0; 01831 int num_on_planes = 0; 01832 01833 const ClipPlaneAttrib *target_clip_plane = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); 01834 if (target_clip_plane != (ClipPlaneAttrib *)NULL) { 01835 CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes); 01836 01837 num_on_planes = new_plane->get_num_on_planes(); 01838 for (int li = 0; li < num_on_planes; li++) { 01839 NodePath plane = new_plane->get_on_plane(li); 01840 nassertv(!plane.is_empty()); 01841 PlaneNode *plane_node; 01842 DCAST_INTO_V(plane_node, plane.node()); 01843 if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) { 01844 // Clipping should be enabled before we apply any planes. 01845 if (!_clip_planes_enabled) { 01846 enable_clip_planes(true); 01847 _clip_planes_enabled = true; 01848 } 01849 01850 enable_clip_plane(num_enabled, true); 01851 if (num_enabled == 0) { 01852 begin_bind_clip_planes(); 01853 } 01854 01855 bind_clip_plane(plane, num_enabled); 01856 num_enabled++; 01857 } 01858 } 01859 } 01860 01861 int i; 01862 for (i = num_enabled; i < _num_clip_planes_enabled; ++i) { 01863 enable_clip_plane(i, false); 01864 } 01865 _num_clip_planes_enabled = num_enabled; 01866 01867 // If no planes were set, disable clipping 01868 if (num_enabled == 0) { 01869 if (_clip_planes_enabled) { 01870 enable_clip_planes(false); 01871 _clip_planes_enabled = false; 01872 } 01873 } else { 01874 end_bind_clip_planes(); 01875 } 01876 } 01877 01878 //////////////////////////////////////////////////////////////////// 01879 // Function: GraphicsStateGuardian::do_issue_color 01880 // Access: Public 01881 // Description: This method is defined in the base class because it 01882 // is likely that this functionality will be used for 01883 // all (or at least most) kinds of 01884 // GraphicsStateGuardians--it's not specific to any one 01885 // rendering backend. 01886 // 01887 // The ColorAttribute just changes the interpretation of 01888 // the color on the vertices, and fiddles with 01889 // _vertex_colors_enabled, etc. 01890 //////////////////////////////////////////////////////////////////// 01891 void GraphicsStateGuardian:: 01892 do_issue_color() { 01893 const ColorAttrib *target_color = DCAST(ColorAttrib, _target_rs->get_attrib_def(ColorAttrib::get_class_slot())); 01894 switch (target_color->get_color_type()) { 01895 case ColorAttrib::T_flat: 01896 // Color attribute flat: it specifies a scene graph color that 01897 // overrides the vertex color. 01898 _scene_graph_color = target_color->get_color(); 01899 _has_scene_graph_color = true; 01900 _vertex_colors_enabled = false; 01901 break; 01902 01903 case ColorAttrib::T_off: 01904 // Color attribute off: it specifies that no scene graph color is 01905 // in effect, and vertex color is not important either. 01906 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f); 01907 _has_scene_graph_color = false; 01908 _vertex_colors_enabled = false; 01909 break; 01910 01911 case ColorAttrib::T_vertex: 01912 // Color attribute vertex: it specifies that vertex color should 01913 // be revealed. 01914 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f); 01915 _has_scene_graph_color = false; 01916 _vertex_colors_enabled = true; 01917 break; 01918 } 01919 01920 if (_color_scale_via_lighting) { 01921 _state_mask.clear_bit(LightAttrib::get_class_slot()); 01922 _state_mask.clear_bit(MaterialAttrib::get_class_slot()); 01923 01924 determine_light_color_scale(); 01925 } 01926 } 01927 01928 //////////////////////////////////////////////////////////////////// 01929 // Function: GraphicsStateGuardian::do_issue_color_scale 01930 // Access: Public, Virtual 01931 // Description: 01932 //////////////////////////////////////////////////////////////////// 01933 void GraphicsStateGuardian:: 01934 do_issue_color_scale() { 01935 // If the previous color scale had set a special texture, clear the 01936 // texture now. 01937 if (_has_texture_alpha_scale) { 01938 _state_mask.clear_bit(TextureAttrib::get_class_slot()); 01939 } 01940 01941 const ColorScaleAttrib *target_color_scale = DCAST(ColorScaleAttrib, _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot())); 01942 _color_scale_enabled = target_color_scale->has_scale(); 01943 _current_color_scale = target_color_scale->get_scale(); 01944 _has_texture_alpha_scale = false; 01945 01946 if (_color_blend_involves_color_scale) { 01947 _state_mask.clear_bit(TransparencyAttrib::get_class_slot()); 01948 } 01949 if (_texture_involves_color_scale) { 01950 _state_mask.clear_bit(TextureAttrib::get_class_slot()); 01951 } 01952 if (_color_scale_via_lighting) { 01953 _state_mask.clear_bit(LightAttrib::get_class_slot()); 01954 _state_mask.clear_bit(MaterialAttrib::get_class_slot()); 01955 01956 determine_light_color_scale(); 01957 } 01958 01959 if (_alpha_scale_via_texture && !_has_scene_graph_color && 01960 target_color_scale->has_alpha_scale()) { 01961 // This color scale will set a special texture--so again, clear 01962 // the texture. 01963 _state_mask.clear_bit(TextureAttrib::get_class_slot()); 01964 _state_mask.clear_bit(TexMatrixAttrib::get_class_slot()); 01965 01966 _has_texture_alpha_scale = true; 01967 } 01968 } 01969 01970 //////////////////////////////////////////////////////////////////// 01971 // Function: GraphicsStateGuardian::do_issue_light 01972 // Access: Protected, Virtual 01973 // Description: This implementation of do_issue_light() assumes 01974 // we have a limited number of hardware lights 01975 // available. This function assigns each light to a 01976 // different hardware light id, trying to keep each 01977 // light associated with the same id where possible, but 01978 // reusing id's when necessary. When it is no longer 01979 // possible to reuse existing id's (e.g. all id's are in 01980 // use), the next sequential id is assigned (if 01981 // available). 01982 // 01983 // It will call apply_light() each time a light is 01984 // assigned to a particular id for the first time in a 01985 // given frame, and it will subsequently call 01986 // enable_light() to enable or disable each light as the 01987 // frame is rendered, as well as enable_lighting() to 01988 // enable or disable overall lighting. 01989 //////////////////////////////////////////////////////////////////// 01990 void GraphicsStateGuardian:: 01991 do_issue_light() { 01992 // Initialize the current ambient light total and newly enabled 01993 // light list 01994 Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f); 01995 int i; 01996 01997 int num_enabled = 0; 01998 int num_on_lights = 0; 01999 02000 const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot())); 02001 if (display_cat.is_spam()) { 02002 display_cat.spam() 02003 << "do_issue_light: " << target_light << "\n"; 02004 } 02005 if (target_light != (LightAttrib *)NULL) { 02006 CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights); 02007 if (display_cat.is_spam()) { 02008 new_light->write(display_cat.spam(false), 2); 02009 } 02010 02011 num_on_lights = new_light->get_num_on_lights(); 02012 for (int li = 0; li < num_on_lights; li++) { 02013 NodePath light = new_light->get_on_light(li); 02014 nassertv(!light.is_empty()); 02015 Light *light_obj = light.node()->as_light(); 02016 nassertv(light_obj != (Light *)NULL); 02017 02018 // Lighting should be enabled before we apply any lights. 02019 if (!_lighting_enabled) { 02020 enable_lighting(true); 02021 _lighting_enabled = true; 02022 } 02023 02024 if (light_obj->get_type() == AmbientLight::get_class_type()) { 02025 // Ambient lights don't require specific light ids; simply add 02026 // in the ambient contribution to the current total 02027 cur_ambient_light += light_obj->get_color(); 02028 02029 } else { 02030 const Colorf &color = light_obj->get_color(); 02031 // Don't bother binding the light if it has no color to contribute. 02032 if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) { 02033 enable_light(num_enabled, true); 02034 if (num_enabled == 0) { 02035 begin_bind_lights(); 02036 } 02037 02038 light_obj->bind(this, light, num_enabled); 02039 num_enabled++; 02040 } 02041 } 02042 } 02043 } 02044 02045 for (i = num_enabled; i < _num_lights_enabled; ++i) { 02046 enable_light(i, false); 02047 } 02048 _num_lights_enabled = num_enabled; 02049 02050 // If no lights were set, disable lighting 02051 if (num_on_lights == 0) { 02052 if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f))) { 02053 // Unless we need lighting anyway to apply a color or color 02054 // scale. 02055 if (!_lighting_enabled) { 02056 enable_lighting(true); 02057 _lighting_enabled = true; 02058 } 02059 set_ambient_light(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 02060 02061 } else { 02062 if (_lighting_enabled) { 02063 enable_lighting(false); 02064 _lighting_enabled = false; 02065 } 02066 } 02067 02068 } else { 02069 set_ambient_light(cur_ambient_light); 02070 } 02071 02072 if (num_enabled != 0) { 02073 end_bind_lights(); 02074 } 02075 } 02076 02077 //////////////////////////////////////////////////////////////////// 02078 // Function: GraphicsStateGuardian::framebuffer_copy_to_texture 02079 // Access: Public, Virtual 02080 // Description: Copy the pixels within the indicated display 02081 // region from the framebuffer into texture memory. 02082 // 02083 // If z > -1, it is the cube map index into which to 02084 // copy. 02085 //////////////////////////////////////////////////////////////////// 02086 bool GraphicsStateGuardian:: 02087 framebuffer_copy_to_texture(Texture *, int, const DisplayRegion *, 02088 const RenderBuffer &) { 02089 return false; 02090 } 02091 02092 02093 //////////////////////////////////////////////////////////////////// 02094 // Function: GraphicsStateGuardian::framebuffer_copy_to_ram 02095 // Access: Public, Virtual 02096 // Description: Copy the pixels within the indicated display region 02097 // from the framebuffer into system memory, not texture 02098 // memory. Returns true on success, false on failure. 02099 // 02100 // This completely redefines the ram image of the 02101 // indicated texture. 02102 //////////////////////////////////////////////////////////////////// 02103 bool GraphicsStateGuardian:: 02104 framebuffer_copy_to_ram(Texture *, int, const DisplayRegion *, 02105 const RenderBuffer &) { 02106 return false; 02107 } 02108 02109 //////////////////////////////////////////////////////////////////// 02110 // Function: GraphicsStateGuardian::bind_light 02111 // Access: Public, Virtual 02112 // Description: Called the first time a particular light has been 02113 // bound to a given id within a frame, this should set 02114 // up the associated hardware light with the light's 02115 // properties. 02116 //////////////////////////////////////////////////////////////////// 02117 void GraphicsStateGuardian:: 02118 bind_light(PointLight *light_obj, const NodePath &light, int light_id) { 02119 } 02120 02121 //////////////////////////////////////////////////////////////////// 02122 // Function: GraphicsStateGuardian::bind_light 02123 // Access: Public, Virtual 02124 // Description: Called the first time a particular light has been 02125 // bound to a given id within a frame, this should set 02126 // up the associated hardware light with the light's 02127 // properties. 02128 //////////////////////////////////////////////////////////////////// 02129 void GraphicsStateGuardian:: 02130 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) { 02131 } 02132 02133 //////////////////////////////////////////////////////////////////// 02134 // Function: GraphicsStateGuardian::bind_light 02135 // Access: Public, Virtual 02136 // Description: Called the first time a particular light has been 02137 // bound to a given id within a frame, this should set 02138 // up the associated hardware light with the light's 02139 // properties. 02140 //////////////////////////////////////////////////////////////////// 02141 void GraphicsStateGuardian:: 02142 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) { 02143 } 02144 02145 #ifdef DO_PSTATS 02146 //////////////////////////////////////////////////////////////////// 02147 // Function: GraphicsStateGuardian::init_frame_pstats 02148 // Access: Public, Static 02149 // Description: Initializes the relevant PStats data at the beginning 02150 // of the frame. 02151 //////////////////////////////////////////////////////////////////// 02152 void GraphicsStateGuardian:: 02153 init_frame_pstats() { 02154 if (PStatClient::is_connected()) { 02155 _data_transferred_pcollector.clear_level(); 02156 _vertex_buffer_switch_pcollector.clear_level(); 02157 _index_buffer_switch_pcollector.clear_level(); 02158 02159 _primitive_batches_pcollector.clear_level(); 02160 _primitive_batches_tristrip_pcollector.clear_level(); 02161 _primitive_batches_trifan_pcollector.clear_level(); 02162 _primitive_batches_tri_pcollector.clear_level(); 02163 _primitive_batches_other_pcollector.clear_level(); 02164 _vertices_tristrip_pcollector.clear_level(); 02165 _vertices_trifan_pcollector.clear_level(); 02166 _vertices_tri_pcollector.clear_level(); 02167 _vertices_other_pcollector.clear_level(); 02168 02169 _state_pcollector.clear_level(); 02170 _transform_state_pcollector.clear_level(); 02171 _texture_state_pcollector.clear_level(); 02172 } 02173 } 02174 #endif // DO_PSTATS 02175 02176 02177 //////////////////////////////////////////////////////////////////// 02178 // Function: GraphicsStateGuardian::create_gamma_table 02179 // Access: Public, Static 02180 // Description: Create a gamma table. 02181 //////////////////////////////////////////////////////////////////// 02182 void GraphicsStateGuardian:: 02183 create_gamma_table (float gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) { 02184 int i; 02185 02186 if (gamma <= 0.0) { 02187 // avoid divide by zero and negative exponents 02188 gamma = 1.0; 02189 } 02190 02191 for (i = 0; i < 256; i++) { 02192 double g; 02193 double x; 02194 float gamma_correction; 02195 02196 x = ((double) i / 255.0); 02197 gamma_correction = 1.0 / gamma; 02198 x = pow (x, (double) gamma_correction); 02199 if (x > 1.00) { 02200 x = 1.0; 02201 } 02202 02203 g = x * 65535.0; 02204 red_table [i] = (int)g; 02205 green_table [i] = (int)g; 02206 blue_table [i] = (int)g; 02207 } 02208 } 02209 02210 //////////////////////////////////////////////////////////////////// 02211 // Function: GraphicsStateGuardian::reissue_transforms 02212 // Access: Protected, Virtual 02213 // Description: Called by clear_state_and_transform() to ensure that 02214 // the current modelview and projection matrices are 02215 // properly loaded in the graphics state, after a 02216 // callback might have mucked them up. 02217 //////////////////////////////////////////////////////////////////// 02218 void GraphicsStateGuardian:: 02219 reissue_transforms() { 02220 } 02221 02222 //////////////////////////////////////////////////////////////////// 02223 // Function: GraphicsStateGuardian::enable_lighting 02224 // Access: Protected, Virtual 02225 // Description: Intended to be overridden by a derived class to 02226 // enable or disable the use of lighting overall. This 02227 // is called by do_issue_light() according to whether any 02228 // lights are in use or not. 02229 //////////////////////////////////////////////////////////////////// 02230 void GraphicsStateGuardian:: 02231 enable_lighting(bool enable) { 02232 } 02233 02234 //////////////////////////////////////////////////////////////////// 02235 // Function: GraphicsStateGuardian::set_ambient_light 02236 // Access: Protected, Virtual 02237 // Description: Intended to be overridden by a derived class to 02238 // indicate the color of the ambient light that should 02239 // be in effect. This is called by do_issue_light() after 02240 // all other lights have been enabled or disabled. 02241 //////////////////////////////////////////////////////////////////// 02242 void GraphicsStateGuardian:: 02243 set_ambient_light(const Colorf &color) { 02244 } 02245 02246 //////////////////////////////////////////////////////////////////// 02247 // Function: GraphicsStateGuardian::enable_light 02248 // Access: Protected, Virtual 02249 // Description: Intended to be overridden by a derived class to 02250 // enable the indicated light id. A specific Light will 02251 // already have been bound to this id via bind_light(). 02252 //////////////////////////////////////////////////////////////////// 02253 void GraphicsStateGuardian:: 02254 enable_light(int light_id, bool enable) { 02255 } 02256 02257 //////////////////////////////////////////////////////////////////// 02258 // Function: GraphicsStateGuardian::begin_bind_lights 02259 // Access: Protected, Virtual 02260 // Description: Called immediately before bind_light() is called, 02261 // this is intended to provide the derived class a hook 02262 // in which to set up some state (like transform) that 02263 // might apply to several lights. 02264 // 02265 // The sequence is: begin_bind_lights() will be called, 02266 // then one or more bind_light() calls, then 02267 // end_bind_lights(). 02268 //////////////////////////////////////////////////////////////////// 02269 void GraphicsStateGuardian:: 02270 begin_bind_lights() { 02271 } 02272 02273 //////////////////////////////////////////////////////////////////// 02274 // Function: GraphicsStateGuardian::end_bind_lights 02275 // Access: Protected, Virtual 02276 // Description: Called after before bind_light() has been called one 02277 // or more times (but before any geometry is issued or 02278 // additional state is changed), this is intended to 02279 // clean up any temporary changes to the state that may 02280 // have been made by begin_bind_lights(). 02281 //////////////////////////////////////////////////////////////////// 02282 void GraphicsStateGuardian:: 02283 end_bind_lights() { 02284 } 02285 02286 //////////////////////////////////////////////////////////////////// 02287 // Function: GraphicsStateGuardian::enable_clip_planes 02288 // Access: Protected, Virtual 02289 // Description: Intended to be overridden by a derived class to 02290 // enable or disable the use of clipping planes overall. 02291 // This is called by do_issue_clip_plane() according to 02292 // whether any planes are in use or not. 02293 //////////////////////////////////////////////////////////////////// 02294 void GraphicsStateGuardian:: 02295 enable_clip_planes(bool enable) { 02296 } 02297 02298 //////////////////////////////////////////////////////////////////// 02299 // Function: GraphicsStateGuardian::enable_clip_plane 02300 // Access: Protected, Virtual 02301 // Description: Intended to be overridden by a derived class to 02302 // enable the indicated plane id. A specific PlaneNode 02303 // will already have been bound to this id via 02304 // bind_clip_plane(). 02305 //////////////////////////////////////////////////////////////////// 02306 void GraphicsStateGuardian:: 02307 enable_clip_plane(int plane_id, bool enable) { 02308 } 02309 02310 //////////////////////////////////////////////////////////////////// 02311 // Function: GraphicsStateGuardian::begin_bind_clip_planes 02312 // Access: Protected, Virtual 02313 // Description: Called immediately before bind_clip_plane() is called, 02314 // this is intended to provide the derived class a hook 02315 // in which to set up some state (like transform) that 02316 // might apply to several planes. 02317 // 02318 // The sequence is: begin_bind_clip_planes() will be 02319 // called, then one or more bind_clip_plane() calls, 02320 // then end_bind_clip_planes(). 02321 //////////////////////////////////////////////////////////////////// 02322 void GraphicsStateGuardian:: 02323 begin_bind_clip_planes() { 02324 } 02325 02326 //////////////////////////////////////////////////////////////////// 02327 // Function: GraphicsStateGuardian::bind_clip_plane 02328 // Access: Public, Virtual 02329 // Description: Called the first time a particular clipping plane has been 02330 // bound to a given id within a frame, this should set 02331 // up the associated hardware (or API) clipping plane 02332 // with the plane's properties. 02333 //////////////////////////////////////////////////////////////////// 02334 void GraphicsStateGuardian:: 02335 bind_clip_plane(const NodePath &plane, int plane_id) { 02336 } 02337 02338 //////////////////////////////////////////////////////////////////// 02339 // Function: GraphicsStateGuardian::end_bind_clip_planes 02340 // Access: Protected, Virtual 02341 // Description: Called after before bind_clip_plane() has been called one 02342 // or more times (but before any geometry is issued or 02343 // additional state is changed), this is intended to 02344 // clean up any temporary changes to the state that may 02345 // have been made by begin_bind_clip_planes(). 02346 //////////////////////////////////////////////////////////////////// 02347 void GraphicsStateGuardian:: 02348 end_bind_clip_planes() { 02349 } 02350 02351 //////////////////////////////////////////////////////////////////// 02352 // Function: GraphicsStateGuardian::determine_target_texture 02353 // Access: Protected 02354 // Description: Assigns _target_texture and _target_tex_gen 02355 // based on the _target_rs. 02356 //////////////////////////////////////////////////////////////////// 02357 void GraphicsStateGuardian:: 02358 determine_target_texture() { 02359 const TextureAttrib *target_texture = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot())); 02360 const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot())); 02361 02362 nassertv(target_texture != (TextureAttrib *)NULL && 02363 target_tex_gen != (TexGenAttrib *)NULL); 02364 int max_texture_stages = get_max_texture_stages(); 02365 _target_texture = target_texture->filter_to_max(max_texture_stages); 02366 _target_tex_gen = target_tex_gen; 02367 02368 if (_has_texture_alpha_scale) { 02369 PT(TextureStage) stage = get_alpha_scale_texture_stage(); 02370 PT(Texture) texture = TexturePool::get_alpha_scale_map(); 02371 02372 _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture)); 02373 _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage 02374 (stage, TexGenAttrib::M_constant, TexCoord3f(_current_color_scale[3], 0.0f, 0.0f))); 02375 } 02376 02377 nassertv(_target_texture->get_num_on_stages() <= max_texture_stages); 02378 } 02379 02380 //////////////////////////////////////////////////////////////////// 02381 // Function: GraphicsStateGuardian::free_pointers 02382 // Access: Protected, Virtual 02383 // Description: Frees some memory that was explicitly allocated 02384 // within the glgsg. 02385 //////////////////////////////////////////////////////////////////// 02386 void GraphicsStateGuardian:: 02387 free_pointers() { 02388 } 02389 02390 //////////////////////////////////////////////////////////////////// 02391 // Function: GraphicsStateGuardian::close_gsg 02392 // Access: Protected, Virtual 02393 // Description: This is called by the associated GraphicsWindow when 02394 // close_window() is called. It should null out the 02395 // _win pointer and possibly free any open resources 02396 // associated with the GSG. 02397 //////////////////////////////////////////////////////////////////// 02398 void GraphicsStateGuardian:: 02399 close_gsg() { 02400 // Protect from multiple calls, and also inform any other functions 02401 // not to try to create new stuff while we're going down. 02402 if (_closing_gsg) { 02403 return; 02404 } 02405 _closing_gsg = true; 02406 02407 if (display_cat.is_debug()) { 02408 display_cat.debug() 02409 << this << " close_gsg " << get_type() << "\n"; 02410 } 02411 free_pointers(); 02412 02413 // As tempting as it may be to try to release all the textures and 02414 // geoms now, we can't, because we might not be the currently-active 02415 // GSG (this is particularly important in OpenGL, which maintains 02416 // one currently-active GL state in each thread). If we start 02417 // deleting textures, we'll be inadvertently deleting textures from 02418 // some other OpenGL state. 02419 02420 // Fortunately, it doesn't really matter, since the graphics API 02421 // will be responsible for cleaning up anything we don't clean up 02422 // explicitly. We'll just let them drop. 02423 02424 // However, if any objects have recently been released, we have to 02425 // ensure they are actually deleted properly. 02426 Thread *current_thread = Thread::get_current_thread(); 02427 _prepared_objects->begin_frame(this, current_thread); 02428 _prepared_objects->end_frame(current_thread); 02429 } 02430 02431 //////////////////////////////////////////////////////////////////// 02432 // Function: GraphicsStateGuardian::panic_deactivate 02433 // Access: Protected 02434 // Description: This is called internally when it is determined that 02435 // things are just fubar. It temporarily deactivates 02436 // the GSG just so things don't get out of hand, and 02437 // throws an event so the application can deal with this 02438 // if it needs to. 02439 //////////////////////////////////////////////////////////////////// 02440 void GraphicsStateGuardian:: 02441 panic_deactivate() { 02442 if (_active) { 02443 display_cat.error() 02444 << "Deactivating " << get_type() << ".\n"; 02445 set_active(false); 02446 throw_event("panic-deactivate-gsg", this); 02447 } 02448 } 02449 02450 //////////////////////////////////////////////////////////////////// 02451 // Function: GraphicsStateGuardian::determine_light_color_scale 02452 // Access: Protected 02453 // Description: Called whenever the color or color scale is changed, 02454 // if _color_scale_via_lighting is true. This will 02455 // rederive _material_force_color and _light_color_scale 02456 // appropriately. 02457 //////////////////////////////////////////////////////////////////// 02458 void GraphicsStateGuardian:: 02459 determine_light_color_scale() { 02460 if (_has_scene_graph_color) { 02461 // If we have a scene graph color, it, plus the color scale, goes 02462 // directly into the material; we don't color scale the 02463 // lights--this allows an alpha color scale to work properly. 02464 _has_material_force_color = true; 02465 _material_force_color = _scene_graph_color; 02466 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); 02467 if (!_color_blend_involves_color_scale && _color_scale_enabled) { 02468 _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0], 02469 _scene_graph_color[1] * _current_color_scale[1], 02470 _scene_graph_color[2] * _current_color_scale[2], 02471 _scene_graph_color[3] * _current_color_scale[3]); 02472 } 02473 02474 } else { 02475 // Otherise, leave the materials alone, but we might still scale 02476 // the lights. 02477 _has_material_force_color = false; 02478 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); 02479 if (!_color_blend_involves_color_scale && _color_scale_enabled) { 02480 _light_color_scale = _current_color_scale; 02481 } 02482 } 02483 } 02484 02485 //////////////////////////////////////////////////////////////////// 02486 // Function: GraphicsStateGuardian::get_unlit_state 02487 // Access: Protected, Static 02488 // Description: 02489 //////////////////////////////////////////////////////////////////// 02490 CPT(RenderState) GraphicsStateGuardian:: 02491 get_unlit_state() { 02492 static CPT(RenderState) state = NULL; 02493 if (state == (const RenderState *)NULL) { 02494 state = RenderState::make(LightAttrib::make_all_off()); 02495 } 02496 return state; 02497 } 02498 02499 //////////////////////////////////////////////////////////////////// 02500 // Function: GraphicsStateGuardian::get_unclipped_state 02501 // Access: Protected, Static 02502 // Description: 02503 //////////////////////////////////////////////////////////////////// 02504 CPT(RenderState) GraphicsStateGuardian:: 02505 get_unclipped_state() { 02506 static CPT(RenderState) state = NULL; 02507 if (state == (const RenderState *)NULL) { 02508 state = RenderState::make(ClipPlaneAttrib::make_all_off()); 02509 } 02510 return state; 02511 } 02512 02513 //////////////////////////////////////////////////////////////////// 02514 // Function: GraphicsStateGuardian::get_untextured_state 02515 // Access: Protected, Static 02516 // Description: 02517 //////////////////////////////////////////////////////////////////// 02518 CPT(RenderState) GraphicsStateGuardian:: 02519 get_untextured_state() { 02520 static CPT(RenderState) state = NULL; 02521 if (state == (const RenderState *)NULL) { 02522 state = RenderState::make(TextureAttrib::make_off()); 02523 } 02524 return state; 02525 } 02526 02527 //////////////////////////////////////////////////////////////////// 02528 // Function: GraphicsStateGuardian::async_reload_texture 02529 // Access: Protected 02530 // Description: Should be called when a texture is encountered that 02531 // needs to have its RAM image reloaded, and 02532 // get_incomplete_render() is true. This will fire off 02533 // a thread on the current Loader object that will 02534 // request the texture to load its image. The image 02535 // will be available at some point in the future (no 02536 // event will be generated). 02537 //////////////////////////////////////////////////////////////////// 02538 void GraphicsStateGuardian:: 02539 async_reload_texture(TextureContext *tc) { 02540 nassertv(_loader != (Loader *)NULL); 02541 02542 int priority = 0; 02543 if (_current_display_region != (DisplayRegion *)NULL) { 02544 priority = _current_display_region->get_texture_reload_priority(); 02545 } 02546 02547 string task_name = string("reload:") + tc->get_texture()->get_name(); 02548 PT(AsyncTaskManager) task_mgr = _loader->get_task_manager(); 02549 02550 // See if we are already loading this task. 02551 AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name); 02552 int num_tasks = orig_tasks.get_num_tasks(); 02553 for (int ti = 0; ti < num_tasks; ++ti) { 02554 AsyncTask *task = orig_tasks.get_task(ti); 02555 if (task->is_exact_type(TextureReloadRequest::get_class_type()) && 02556 DCAST(TextureReloadRequest, task)->get_texture() == tc->get_texture()) { 02557 // This texture is already queued to be reloaded. Don't queue 02558 // it again, just make sure the priority is updated, and return. 02559 task->set_priority(max(task->get_priority(), priority)); 02560 return; 02561 } 02562 } 02563 02564 // This texture has not yet been queued to be reloaded. Queue it up 02565 // now. 02566 PT(AsyncTask) request = 02567 new TextureReloadRequest(task_name, 02568 _prepared_objects, tc->get_texture(), 02569 _supports_compressed_texture); 02570 request->set_priority(priority); 02571 _loader->load_async(request); 02572 } 02573 02574 //////////////////////////////////////////////////////////////////// 02575 // Function: GraphicsStateGuardian::make_shadow_buffer 02576 // Access: Protected 02577 // Description: Creates a depth buffer for shadow mapping. This 02578 // is a convenience function for the ShaderGenerator; 02579 // putting this directly in the ShaderGenerator would 02580 // cause circular dependency issues. 02581 // Returns the depth texture. 02582 //////////////////////////////////////////////////////////////////// 02583 PT(Texture) GraphicsStateGuardian:: 02584 make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { 02585 // Make sure everything is valid. 02586 nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) || 02587 light_np.node()->is_of_type(Spotlight::get_class_type()), NULL); 02588 PT(LightLensNode) light = DCAST(LightLensNode, light_np.node()); 02589 if (light == NULL || !light->_shadow_caster) { 02590 return NULL; 02591 } 02592 02593 nassertr(light->_sbuffers.count(this) == 0, NULL); 02594 02595 display_cat.debug() << "Constructing shadow buffer for light '" << light->get_name() 02596 << "', size=" << light->_sb_xsize << "x" << light->_sb_ysize 02597 << ", sort=" << light->_sb_sort << "\n"; 02598 FrameBufferProperties fbp; 02599 fbp.set_depth_bits(1); // We only need depth 02600 PT(GraphicsOutput) sbuffer = get_engine()->make_output(get_pipe(), light->get_name(), 02601 light->_sb_sort, fbp, WindowProperties::size(light->_sb_xsize, light->_sb_ysize), 02602 GraphicsPipe::BF_refuse_window, this, DCAST(GraphicsOutput, host)); 02603 nassertr(sbuffer != NULL, NULL); 02604 02605 // Create a texture and fill it in with some data to workaround an OpenGL error 02606 PT(Texture) tex = new Texture(light->get_name()); 02607 tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_float, Texture::F_depth_component); 02608 tex->make_ram_image(); 02609 sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, 02610 GraphicsOutput::RTP_depth); 02611 // Set the wrap mode to BORDER_COLOR 02612 tex->set_wrap_u(Texture::WM_border_color); 02613 tex->set_wrap_v(Texture::WM_border_color); 02614 tex->set_border_color(LVecBase4f(1, 1, 1, 1)); 02615 02616 if (get_supports_shadow_filter()) { 02617 // If we have the ARB_shadow extension, enable shadow filtering. 02618 tex->set_minfilter(Texture::FT_shadow); 02619 tex->set_magfilter(Texture::FT_shadow); 02620 } else { 02621 // We only accept linear - this tells the GPU to use hardware PCF. 02622 tex->set_minfilter(Texture::FT_linear); 02623 tex->set_magfilter(Texture::FT_linear); 02624 } 02625 sbuffer->make_display_region(0, 1, 0, 1)->set_camera(light_np); 02626 light->_sbuffers[this] = sbuffer; 02627 02628 return tex; 02629 } 02630