Panda3D
graphicsStateGuardian.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file graphicsStateGuardian.cxx
10  * @author drose
11  * @date 1999-02-02
12  * @author fperazzi, PandaSE
13  * @date 2010-05-05
14  * _max_2d_texture_array_layers, _supports_2d_texture_array,
15  * get_supports_cg_profile)
16  */
17 
18 #include "graphicsStateGuardian.h"
19 #include "graphicsEngine.h"
20 #include "config_display.h"
21 #include "textureContext.h"
22 #include "vertexBufferContext.h"
23 #include "indexBufferContext.h"
24 #include "renderBuffer.h"
25 #include "light.h"
26 #include "planeNode.h"
27 #include "throw_event.h"
28 #include "clockObject.h"
29 #include "pStatTimer.h"
30 #include "pStatGPUTimer.h"
31 #include "geomTristrips.h"
32 #include "geomTrifans.h"
33 #include "geomLinestrips.h"
34 #include "colorWriteAttrib.h"
35 #include "shader.h"
36 #include "pnotify.h"
37 #include "drawableRegion.h"
38 #include "displayRegion.h"
39 #include "graphicsOutput.h"
40 #include "texturePool.h"
41 #include "geomMunger.h"
42 #include "stateMunger.h"
43 #include "ambientLight.h"
44 #include "directionalLight.h"
45 #include "pointLight.h"
46 #include "sphereLight.h"
47 #include "spotlight.h"
48 #include "textureReloadRequest.h"
49 #include "shaderAttrib.h"
50 #include "materialAttrib.h"
51 #include "depthWriteAttrib.h"
52 #include "lightAttrib.h"
53 #include "texGenAttrib.h"
54 #include "shaderGenerator.h"
55 #include "lightLensNode.h"
56 #include "colorAttrib.h"
57 #include "colorScaleAttrib.h"
58 #include "clipPlaneAttrib.h"
59 #include "fogAttrib.h"
60 #include "config_pstatclient.h"
61 
62 #include <limits.h>
63 
64 using std::string;
65 
66 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Buffer switch:Vertex");
67 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Buffer switch:Index");
68 PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector("Buffer switch:Shader");
69 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
70 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
71 PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector("Draw:Transfer data:Shader buffer");
72 PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer");
73 PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer");
74 PStatCollector GraphicsStateGuardian::_create_shader_buffer_pcollector("Draw:Transfer data:Create Shader buffer");
75 PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
76 PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
77 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
78 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
79 PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches");
80 PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector("Primitive batches:Triangle strips");
81 PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector("Primitive batches:Triangle fans");
82 PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector("Primitive batches:Triangles");
83 PStatCollector GraphicsStateGuardian::_primitive_batches_patch_pcollector("Primitive batches:Patches");
84 PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector("Primitive batches:Other");
85 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips");
86 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans");
87 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles");
88 PStatCollector GraphicsStateGuardian::_vertices_patch_pcollector("Vertices:Patches");
89 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector("Vertices:Other");
90 PStatCollector GraphicsStateGuardian::_state_pcollector("State changes");
91 PStatCollector GraphicsStateGuardian::_transform_state_pcollector("State changes:Transforms");
92 PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:Textures");
93 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive:Draw");
94 PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector("Draw:Set State");
95 PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush");
96 PStatCollector GraphicsStateGuardian::_compute_dispatch_pcollector("Draw:Compute dispatch");
97 
98 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
99 PStatCollector GraphicsStateGuardian::_wait_timer_pcollector("Wait:Timer Queries");
100 PStatCollector GraphicsStateGuardian::_timer_queries_pcollector("Timer queries");
101 PStatCollector GraphicsStateGuardian::_command_latency_pcollector("Command latency");
102 
103 PStatCollector GraphicsStateGuardian::_prepare_pcollector("Draw:Prepare");
104 PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector("Draw:Prepare:Texture");
105 PStatCollector GraphicsStateGuardian::_prepare_sampler_pcollector("Draw:Prepare:Sampler");
106 PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector("Draw:Prepare:Geom");
107 PStatCollector GraphicsStateGuardian::_prepare_shader_pcollector("Draw:Prepare:Shader");
108 PStatCollector GraphicsStateGuardian::_prepare_vertex_buffer_pcollector("Draw:Prepare:Vertex buffer");
109 PStatCollector GraphicsStateGuardian::_prepare_index_buffer_pcollector("Draw:Prepare:Index buffer");
110 PStatCollector GraphicsStateGuardian::_prepare_shader_buffer_pcollector("Draw:Prepare:Shader buffer");
111 
112 PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform");
113 PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test");
114 PStatCollector GraphicsStateGuardian::_draw_set_state_antialias_pcollector("Draw:Set State:Antialias");
115 PStatCollector GraphicsStateGuardian::_draw_set_state_clip_plane_pcollector("Draw:Set State:Clip plane");
116 PStatCollector GraphicsStateGuardian::_draw_set_state_color_pcollector("Draw:Set State:Color");
117 PStatCollector GraphicsStateGuardian::_draw_set_state_cull_face_pcollector("Draw:Set State:Cull face");
118 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_offset_pcollector("Draw:Set State:Depth offset");
119 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_test_pcollector("Draw:Set State:Depth test");
120 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_write_pcollector("Draw:Set State:Depth write");
121 PStatCollector GraphicsStateGuardian::_draw_set_state_render_mode_pcollector("Draw:Set State:Render mode");
122 PStatCollector GraphicsStateGuardian::_draw_set_state_rescale_normal_pcollector("Draw:Set State:Rescale normal");
123 PStatCollector GraphicsStateGuardian::_draw_set_state_shade_model_pcollector("Draw:Set State:Shade model");
124 PStatCollector GraphicsStateGuardian::_draw_set_state_blending_pcollector("Draw:Set State:Blending");
125 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_pcollector("Draw:Set State:Shader");
126 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_parameters_pcollector("Draw:Set State:Shader Parameters");
127 PStatCollector GraphicsStateGuardian::_draw_set_state_texture_pcollector("Draw:Set State:Texture");
128 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_matrix_pcollector("Draw:Set State:Tex matrix");
129 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_gen_pcollector("Draw:Set State:Tex gen");
130 PStatCollector GraphicsStateGuardian::_draw_set_state_material_pcollector("Draw:Set State:Material");
131 PStatCollector GraphicsStateGuardian::_draw_set_state_light_pcollector("Draw:Set State:Light");
132 PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector("Draw:Set State:Stencil");
133 PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector("Draw:Set State:Fog");
134 PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector("Draw:Set State:Scissor");
135 
136 PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = nullptr;
137 
138 TypeHandle GraphicsStateGuardian::_type_handle;
139 
140 /**
141  *
142  */
143 
144 GraphicsStateGuardian::
145 GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
146  GraphicsEngine *engine, GraphicsPipe *pipe) :
147  _internal_coordinate_system(internal_coordinate_system),
148  _pipe(pipe),
149  _engine(engine)
150 {
151  _coordinate_system = CS_invalid;
152  _internal_transform = TransformState::make_identity();
153 
154  if (_internal_coordinate_system == CS_default) {
155  _internal_coordinate_system = get_default_coordinate_system();
156  }
157 
158  set_coordinate_system(get_default_coordinate_system());
159 
160  _data_reader = nullptr;
161  _current_display_region = nullptr;
162  _current_stereo_channel = Lens::SC_mono;
163  _current_tex_view_offset = 0;
164  _current_lens = nullptr;
165  _projection_mat = TransformState::make_identity();
166  _projection_mat_inv = TransformState::make_identity();
167 
168  _needs_reset = true;
169  _is_valid = false;
170  _current_properties = nullptr;
171  _closing_gsg = false;
172  _active = true;
173  _prepared_objects = new PreparedGraphicsObjects;
174  _stereo_buffer_mask = ~0;
175  _incomplete_render = allow_incomplete_render;
176  _effective_incomplete_render = false;
177  _loader = Loader::get_global_ptr();
178 
179  _is_hardware = false;
180  _prefers_triangle_strips = false;
181  _max_vertices_per_array = INT_MAX;
182  _max_vertices_per_primitive = INT_MAX;
183 
184  // Initially, we set this to 1 (the default--no multitexturing supported).
185  // A derived GSG may set this differently if it supports multitexturing.
186  _max_texture_stages = 1;
187 
188  // Also initially, we assume there are no limits on texture sizes, and that
189  // 3-d and cube-map textures are not supported.
190  _max_texture_dimension = -1;
191  _max_3d_texture_dimension = 0;
192  _max_2d_texture_array_layers = 0;
193  _max_cube_map_dimension = 0;
194  _max_buffer_texture_size = 0;
195 
196  // Assume we don't support these fairly advanced texture combiner modes.
197  _supports_texture_combine = false;
198  _supports_texture_saved_result = false;
199  _supports_texture_dot3 = false;
200 
201  _supports_3d_texture = false;
202  _supports_2d_texture_array = false;
203  _supports_cube_map = false;
204  _supports_buffer_texture = false;
205  _supports_cube_map_array = false;
206  _supports_tex_non_pow2 = false;
207  _supports_texture_srgb = false;
208  _supports_compressed_texture = false;
209  _compressed_texture_formats.clear();
210  _compressed_texture_formats.set_bit(Texture::CM_off);
211 
212  // Assume no limits on number of lights or clip planes.
213  _max_lights = -1;
214  _max_clip_planes = -1;
215 
216  // Assume no vertex blending capability.
217  _max_vertex_transforms = 0;
218  _max_vertex_transform_indices = 0;
219 
220  _supports_occlusion_query = false;
221  _supports_timer_query = false;
222 
223 #ifdef DO_PSTATS
224  _timer_queries_active = false;
225  _last_query_frame = 0;
226  _last_num_queried = 0;
227  // _timer_delta = 0.0;
228 
229  _pstats_gpu_thread = -1;
230 #endif
231 
232  // Initially, we set this to false; a GSG that knows it has this property
233  // should set it to true.
234  _copy_texture_inverted = false;
235 
236  // Similarly with these capabilities flags.
237  _supports_multisample = false;
238  _supports_generate_mipmap = false;
239  _supports_depth_texture = false;
240  _supports_depth_stencil = false;
241  _supports_shadow_filter = false;
242  _supports_sampler_objects = false;
243  _supports_basic_shaders = false;
244  _supports_geometry_shaders = false;
245  _supports_tessellation_shaders = false;
246  _supports_compute_shaders = false;
247  _supports_glsl = false;
248  _supports_hlsl = false;
249 
250  _supports_stencil = false;
251  _supports_stencil_wrap = false;
252  _supports_two_sided_stencil = false;
253  _supports_geometry_instancing = false;
254  _supports_indirect_draw = false;
255 
256  // We are safe assuming it has luminance support
257  _supports_luminance_texture = true;
258 
259  // Assume a maximum of 1 render target in absence of MRT.
260  _max_color_targets = 1;
261  _supports_dual_source_blending = false;
262 
263  _supported_geom_rendering = 0;
264 
265  // If this is true, then we can apply a color andor color scale by twiddling
266  // the material andor ambient light (which could mean enabling lighting even
267  // without a LightAttrib).
268  _color_scale_via_lighting = color_scale_via_lighting;
269 
270  // Similarly for applying a texture to achieve uniform alpha scaling.
271  _alpha_scale_via_texture = alpha_scale_via_texture;
272 
273  // Few GSG's can do this, since it requires touching each vertex as it is
274  // rendered.
275  _runtime_color_scale = false;
276 
277  // The default is no shader support.
278  _auto_detect_shader_model = SM_00;
279  _shader_model = SM_00;
280 
281  _gamma = 1.0f;
282  _texture_quality_override = Texture::QL_default;
283 
284  // Give it a unique identifier. Unlike a pointer, we can guarantee that
285  // this value will never be reused.
286  static size_t next_index = 0;
287  _id = next_index++;
288 }
289 
290 /**
291  *
292  */
293 GraphicsStateGuardian::
294 ~GraphicsStateGuardian() {
295  remove_gsg(this);
297 
298  // Remove the munged states for this GSG. This requires going through all
299  // states, although destructing a GSG should be rare enough for this not to
300  // matter too much.
301  // Note that if uniquify-states is false, we can't iterate over all the
302  // states, and some GSGs will linger. Let's hope this isn't a problem.
303  LightReMutexHolder holder(*RenderState::_states_lock);
304  size_t size = RenderState::_states->get_num_entries();
305  for (size_t si = 0; si < size; ++si) {
306  const RenderState *state = RenderState::_states->get_key(si);
307  state->_mungers.remove(_id);
308  state->_munged_states.remove(_id);
309  }
310 }
311 
312 /**
313  * Returns the graphics engine that created this GSG. Since there is normally
314  * only one GraphicsEngine object in an application, this is usually the same
315  * as the global GraphicsEngine.
316  */
318 get_engine() const {
319  nassertr(_engine != nullptr, GraphicsEngine::get_global_ptr());
320  return _engine;
321 }
322 
323 /**
324  * Returns true if this particular GSG supports using the multisample bits to
325  * provide antialiasing, and also supports M_multisample and
326  * M_multisample_mask transparency modes. If this is not true for a
327  * particular GSG, Panda will map the M_multisample modes to M_binary.
328  *
329  * This method is declared virtual solely so that it can be queried from
330  * cullResult.cxx.
331  */
333 get_supports_multisample() const {
334  return _supports_multisample;
335 }
336 
337 /**
338  * Returns the union of Geom::GeomRendering values that this particular GSG
339  * can support directly. If a Geom needs to be rendered that requires some
340  * additional properties, the StandardMunger and/or the CullableObject will
341  * convert it as needed.
342  *
343  * This method is declared virtual solely so that it can be queried from
344  * cullableObject.cxx.
345  */
348  return _supported_geom_rendering;
349 }
350 
351 /**
352  * Returns true if this particular GSG supports the specified Cg Shader
353  * Profile.
354  */
356 get_supports_cg_profile(const string &name) const {
357  return false;
358 }
359 
360 /**
361  * Changes the coordinate system in effect on this particular gsg. This is
362  * also called the "external" coordinate system, since it is the coordinate
363  * system used by the scene graph, external to to GSG.
364  *
365  * Normally, this will be the default coordinate system, but it might be set
366  * differently at runtime. It will automatically be copied from the current
367  * lens's coordinate system as each DisplayRegion is rendered.
368  */
370 set_coordinate_system(CoordinateSystem cs) {
371  if (cs == CS_default) {
372  cs = get_default_coordinate_system();
373  }
374  if (_coordinate_system == cs) {
375  return;
376  }
377  _coordinate_system = cs;
378 
379  // Changing the external coordinate system changes the cs_transform.
380  if (_internal_coordinate_system == CS_default ||
381  _internal_coordinate_system == _coordinate_system) {
382  _cs_transform = TransformState::make_identity();
383  _inv_cs_transform = TransformState::make_identity();
384 
385  } else {
386  _cs_transform =
387  TransformState::make_mat
388  (LMatrix4::convert_mat(_coordinate_system,
389  _internal_coordinate_system));
390  _inv_cs_transform =
391  TransformState::make_mat
392  (LMatrix4::convert_mat(_internal_coordinate_system,
393  _coordinate_system));
394  }
395 }
396 
397 /**
398  * Returns the coordinate system used internally by the GSG. This may be the
399  * same as the external coordinate system reported by get_coordinate_system(),
400  * or it may be something different.
401  *
402  * In any case, vertices that have been transformed before being handed to the
403  * GSG (that is, vertices with a contents value of C_clip_point) will be
404  * expected to be in this coordinate system.
405  */
406 CoordinateSystem GraphicsStateGuardian::
408  return _internal_coordinate_system;
409 }
410 
411 /**
412  * Returns the set of texture and geom objects that have been prepared with
413  * this GSG (and possibly other GSG's that share objects).
414  */
417  return _prepared_objects;
418 }
419 
420 /**
421  * Set gamma. Returns true on success.
422  */
424 set_gamma(PN_stdfloat gamma) {
425  _gamma = gamma;
426 
427  return false;
428 }
429 
430 /**
431  * Get the current gamma setting.
432  */
433 PN_stdfloat GraphicsStateGuardian::
434 get_gamma() const {
435  return _gamma;
436 }
437 
438 /**
439  * Restore original gamma setting.
440  */
442 restore_gamma() {
443 }
444 
445 /**
446  * Calls the indicated function on all currently-prepared textures, or until
447  * the callback function returns false.
448  */
450 traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
451  void *callback_arg) {
452  ReMutexHolder holder(_prepared_objects->_lock);
453  PreparedGraphicsObjects::Textures::const_iterator ti;
454  for (ti = _prepared_objects->_prepared_textures.begin();
455  ti != _prepared_objects->_prepared_textures.end();
456  ++ti) {
457  bool result = (*func)(*ti, callback_arg);
458  if (!result) {
459  return;
460  }
461  }
462 }
463 
464 /**
465  * Sets the "flash texture". This is a debug feature; when enabled, the
466  * specified texture will begin flashing in the scene, helping you to find it
467  * visually.
468  *
469  * The texture also flashes with a color code: blue for mipmap level 0, yellow
470  * for mipmap level 1, and red for mipmap level 2 or higher (even for textures
471  * that don't have mipmaps). This gives you an idea of the choice of the
472  * texture size. If it is blue, the texture is being drawn the proper size or
473  * magnified; if it is yellow, it is being minified a little bit; and if it
474  * red, it is being minified considerably. If you see a red texture when you
475  * are right in front of it, you should consider reducing the size of the
476  * texture to avoid wasting texture memory.
477  *
478  * Not all rendering backends support the flash_texture feature. Presently,
479  * it is only supported by OpenGL.
480  */
483 #ifndef NDEBUG
484  _flash_texture = tex;
485 #endif
486 }
487 
488 /**
489  * Resets the "flash texture", so that no textures will flash. See
490  * set_flash_texture().
491  */
494 #ifndef NDEBUG
495  _flash_texture = nullptr;
496 #endif
497 }
498 
499 /**
500  * Returns the current "flash texture", if any, or NULL if none. See
501  * set_flash_texture().
502  */
504 get_flash_texture() const {
505 #ifndef NDEBUG
506  return _flash_texture;
507 #else
508  return nullptr;
509 #endif
510 }
511 
512 /**
513  * Sets the SceneSetup object that indicates the initial camera position, etc.
514  * This must be called before traversal begins. Returns true if the scene is
515  * acceptable, false if something's wrong. This should be called in the draw
516  * thread only.
517  */
519 set_scene(SceneSetup *scene_setup) {
520  _scene_setup = scene_setup;
521  _current_lens = scene_setup->get_lens();
522  if (_current_lens == nullptr) {
523  return false;
524  }
525 
526  set_coordinate_system(_current_lens->get_coordinate_system());
527 
528  _projection_mat = calc_projection_mat(_current_lens);
529  if (_projection_mat == nullptr) {
530  return false;
531  }
532  _projection_mat_inv = _projection_mat->get_inverse();
533  return prepare_lens();
534 }
535 
536 /**
537  * Returns the current SceneSetup object.
538  */
540 get_scene() const {
541  return _scene_setup;
542 }
543 
544 /**
545  * Creates whatever structures the GSG requires to represent the texture
546  * internally, and returns a newly-allocated TextureContext object with this
547  * data. It is the responsibility of the calling function to later call
548  * release_texture() with this same pointer (which will also delete the
549  * pointer).
550  *
551  * This function should not be called directly to prepare a texture. Instead,
552  * call Texture::prepare().
553  */
555 prepare_texture(Texture *, int view) {
556  return nullptr;
557 }
558 
559 /**
560  * Ensures that the current Texture data is refreshed onto the GSG. This
561  * means updating the texture properties and/or re-uploading the texture
562  * image, if necessary. This should only be called within the draw thread.
563  *
564  * If force is true, this function will not return until the texture has been
565  * fully uploaded. If force is false, the function may choose to upload a
566  * simple version of the texture instead, if the texture is not fully resident
567  * (and if get_incomplete_render() is true).
568  */
571  return true;
572 }
573 
574 /**
575  * Frees the resources previously allocated via a call to prepare_texture(),
576  * including deleting the TextureContext itself, if it is non-NULL.
577  */
580 }
581 
582 /**
583  * This method should only be called by the GraphicsEngine. Do not call it
584  * directly; call GraphicsEngine::extract_texture_data() instead.
585  *
586  * This method will be called in the draw thread to download the texture
587  * memory's image into its ram_image value. It returns true on success, false
588  * otherwise.
589  */
592  return false;
593 }
594 
595 /**
596  * Creates whatever structures the GSG requires to represent the sampler
597  * internally, and returns a newly-allocated SamplerContext object with this
598  * data. It is the responsibility of the calling function to later call
599  * release_sampler() with this same pointer (which will also delete the
600  * pointer).
601  *
602  * This function should not be called directly to prepare a sampler. Instead,
603  * call Texture::prepare().
604  */
606 prepare_sampler(const SamplerState &sampler) {
607  return nullptr;
608 }
609 
610 /**
611  * Frees the resources previously allocated via a call to prepare_sampler(),
612  * including deleting the SamplerContext itself, if it is non-NULL.
613  */
616 }
617 
618 /**
619  * Prepares the indicated Geom for retained-mode rendering, by creating
620  * whatever structures are necessary in the GSG (for instance, vertex
621  * buffers). Returns the newly-allocated GeomContext that can be used to
622  * render the geom.
623  */
625 prepare_geom(Geom *) {
626  return nullptr;
627 }
628 
629 /**
630  * Frees the resources previously allocated via a call to prepare_geom(),
631  * including deleting the GeomContext itself, if it is non-NULL.
632  *
633  * This function should not be called directly to prepare a Geom. Instead,
634  * call Geom::prepare().
635  */
638 }
639 
640 /**
641  * Compile a vertex/fragment shader body.
642  */
644 prepare_shader(Shader *shader) {
645  return nullptr;
646 }
647 
648 /**
649  * Releases the resources allocated by prepare_shader
650  */
653 }
654 
655 /**
656  * Prepares the indicated buffer for retained-mode rendering.
657  */
660  return nullptr;
661 }
662 
663 /**
664  * Frees the resources previously allocated via a call to prepare_data(),
665  * including deleting the VertexBufferContext itself, if necessary.
666  */
669 }
670 
671 /**
672  * Prepares the indicated buffer for retained-mode rendering.
673  */
676  return nullptr;
677 }
678 
679 /**
680  * Frees the resources previously allocated via a call to prepare_data(),
681  * including deleting the IndexBufferContext itself, if necessary.
682  */
685 }
686 
687 /**
688  * Prepares the indicated buffer for retained-mode rendering.
689  */
692  return nullptr;
693 }
694 
695 /**
696  * Frees the resources previously allocated via a call to prepare_data(),
697  * including deleting the BufferContext itself, if necessary.
698  */
701 }
702 
703 /**
704  * Begins a new occlusion query. After this call, you may call
705  * begin_draw_primitives() and draw_triangles()/draw_whatever() repeatedly.
706  * Eventually, you should call end_occlusion_query() before the end of the
707  * frame; that will return a new OcclusionQueryContext object that will tell
708  * you how many pixels represented by the bracketed geometry passed the depth
709  * test.
710  *
711  * It is not valid to call begin_occlusion_query() between another
712  * begin_occlusion_query() .. end_occlusion_query() sequence.
713  */
716  nassertv(_current_occlusion_query == nullptr);
717 }
718 
719 /**
720  * Ends a previous call to begin_occlusion_query(). This call returns the
721  * OcclusionQueryContext object that will (eventually) report the number of
722  * pixels that passed the depth test between the call to
723  * begin_occlusion_query() and end_occlusion_query().
724  */
725 PT(OcclusionQueryContext) GraphicsStateGuardian::
726 end_occlusion_query() {
727  nassertr(_current_occlusion_query != nullptr, nullptr);
728  PT(OcclusionQueryContext) result = _current_occlusion_query;
729  _current_occlusion_query = nullptr;
730  return result;
731 }
732 
733 /**
734  * Adds a timer query to the command stream, associated with the given PStats
735  * collector index.
736  */
737 PT(TimerQueryContext) GraphicsStateGuardian::
738 issue_timer_query(int pstats_index) {
739  return nullptr;
740 }
741 
742 /**
743  * Dispatches a currently bound compute shader using the given work group
744  * counts.
745  */
747 dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) {
748  nassert_raise("Compute shaders not supported by GSG");
749 }
750 
751 /**
752  * Looks up or creates a GeomMunger object to munge vertices appropriate to
753  * this GSG for the indicated state.
754  */
755 PT(GeomMunger) GraphicsStateGuardian::
756 get_geom_munger(const RenderState *state, Thread *current_thread) {
757  RenderState::Mungers &mungers = state->_mungers;
758 
759  if (!mungers.is_empty()) {
760  // Before we even look up the map, see if the _last_mi value points to
761  // this GSG. This is likely because we tend to visit the same state
762  // multiple times during a frame. Also, this might well be the only GSG
763  // in the world anyway.
764  int mi = state->_last_mi;
765  if (mi >= 0 && (size_t)mi < mungers.get_num_entries() && mungers.get_key(mi) == _id) {
766  PT(GeomMunger) munger = mungers.get_data(mi);
767  if (munger->is_registered()) {
768  return munger;
769  }
770  }
771 
772  // Nope, we have to look it up in the map.
773  mi = mungers.find(_id);
774  if (mi >= 0) {
775  PT(GeomMunger) munger = mungers.get_data(mi);
776  if (munger->is_registered()) {
777  state->_last_mi = mi;
778  return munger;
779  } else {
780  // This GeomMunger is no longer registered. Remove it from the map.
781  mungers.remove_element(mi);
782  }
783  }
784  }
785 
786  // Nothing in the map; create a new entry.
787  PT(GeomMunger) munger = make_geom_munger(state, current_thread);
788  nassertr(munger != nullptr && munger->is_registered(), munger);
789  nassertr(munger->is_of_type(StateMunger::get_class_type()), munger);
790 
791  state->_last_mi = mungers.store(_id, munger);
792  return munger;
793 }
794 
795 /**
796  * Creates a new GeomMunger object to munge vertices appropriate to this GSG
797  * for the indicated state.
798  */
799 PT(GeomMunger) GraphicsStateGuardian::
800 make_geom_munger(const RenderState *state, Thread *current_thread) {
801  // The default implementation returns no munger at all, but presumably,
802  // every kind of GSG needs some special munging action, so real GSG's will
803  // override this to return something more useful.
804  return nullptr;
805 }
806 
807 /**
808  * This function will compute the distance to the indicated point, assumed to
809  * be in eye coordinates, from the camera plane. The point is assumed to be
810  * in the GSG's internal coordinate system.
811  */
813 compute_distance_to(const LPoint3 &point) const {
814  switch (_internal_coordinate_system) {
815  case CS_zup_right:
816  return point[1];
817 
818  case CS_yup_right:
819  return -point[2];
820 
821  case CS_zup_left:
822  return -point[1];
823 
824  case CS_yup_left:
825  return point[2];
826 
827  default:
828  gsg_cat.error()
829  << "Invalid coordinate system in compute_distance_to: "
830  << (int)_internal_coordinate_system << "\n";
831  return 0.0f;
832  }
833 }
834 
835 /**
836  * The gsg contains a large number of useful matrices:
837  *
838  * * the world transform, * the modelview matrix, * the cs_transform, * etc,
839  * etc.
840  *
841  * A shader can request any of these values, and furthermore, it can request
842  * that various compositions, inverses, and transposes be performed. The
843  * ShaderMatSpec is a data structure indicating what datum is desired and what
844  * conversions to perform. This routine, fetch_specified_value, is
845  * responsible for doing the actual retrieval and conversions.
846  *
847  * Some values, like the following, aren't matrices:
848  *
849  * * window size * texture coordinates of card center
850  *
851  * This routine can fetch these values as well, by shoehorning them into a
852  * matrix. In this way, we avoid the need for a separate routine to fetch
853  * these values.
854  *
855  * The "altered" bits indicate what parts of the state_and_transform have
856  * changed since the last time this particular ShaderMatSpec was evaluated.
857  * This may allow data to be cached and not reevaluated.
858  *
859  */
860 const LMatrix4 *GraphicsStateGuardian::
861 fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
862  LVecBase3 v;
863 
864  if (altered & spec._dep[0]) {
865  const LMatrix4 *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0], spec._index);
866  if (t != &spec._cache[0]) {
867  spec._cache[0] = *t;
868  }
869  }
870  if (altered & spec._dep[1]) {
871  const LMatrix4 *t = fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1], spec._index);
872  if (t != &spec._cache[1]) {
873  spec._cache[1] = *t;
874  }
875  }
876 
877  switch(spec._func) {
878  case Shader::SMF_compose:
879  spec._value.multiply(spec._cache[0], spec._cache[1]);
880  return &spec._value;
881  case Shader::SMF_transform_dlight:
882  spec._value = spec._cache[0];
883  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2));
884  v.normalize();
885  spec._value.set_row(2, v);
886  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
887  v.normalize();
888  spec._value.set_row(3, v);
889  return &spec._value;
890  case Shader::SMF_transform_plight:
891  {
892  // Careful not to touch the w component, which contains the near value.
893  spec._value = spec._cache[0];
894  LPoint3 point = spec._cache[1].xform_point(spec._cache[0].get_row3(2));
895  spec._value(2, 0) = point[0];
896  spec._value(2, 1) = point[1];
897  spec._value(2, 2) = point[2];
898  return &spec._value;
899  }
900  case Shader::SMF_transform_slight:
901  spec._value = spec._cache[0];
902  spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
903  v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
904  v.normalize();
905  spec._value.set_row(3, v);
906  return &spec._value;
907  case Shader::SMF_first:
908  return &spec._cache[0];
909  default:
910  // should never get here
911  spec._value = LMatrix4::ident_mat();
912  return &spec._value;
913  }
914 }
915 
916 /**
917  * See fetch_specified_value
918  */
919 const LMatrix4 *GraphicsStateGuardian::
920 fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
921  LMatrix4 &t, int index) {
922  switch (part) {
923  case Shader::SMO_identity: {
924  return &LMatrix4::ident_mat();
925  }
926  case Shader::SMO_window_size:
927  case Shader::SMO_pixel_size: {
928  LVecBase2i pixel_size = _current_display_region->get_pixel_size();
929  t = LMatrix4::translate_mat(pixel_size[0], pixel_size[1], 0);
930  return &t;
931  }
932  case Shader::SMO_frame_time: {
933  PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
934  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
935  return &t;
936  }
937  case Shader::SMO_frame_delta: {
938  PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
939  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
940  return &t;
941  }
942  case Shader::SMO_texpad_x: {
943  Texture *tex = _target_shader->get_shader_input_texture(name);
944  nassertr(tex != nullptr, &LMatrix4::zeros_mat());
945  int sx = tex->get_x_size() - tex->get_pad_x_size();
946  int sy = tex->get_y_size() - tex->get_pad_y_size();
947  int sz = tex->get_z_size() - tex->get_pad_z_size();
948  double cx = (sx * 0.5) / tex->get_x_size();
949  double cy = (sy * 0.5) / tex->get_y_size();
950  double cz = (sz * 0.5) / tex->get_z_size();
951  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cx, cy, cz, 0);
952  return &t;
953  }
954  case Shader::SMO_texpix_x: {
955  Texture *tex = _target_shader->get_shader_input_texture(name);
956  nassertr(tex != nullptr, &LMatrix4::zeros_mat());
957  double px = 1.0 / tex->get_x_size();
958  double py = 1.0 / tex->get_y_size();
959  double pz = 1.0 / tex->get_z_size();
960  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, px, py, pz, 0);
961  return &t;
962  }
963  case Shader::SMO_attr_material: {
964  const MaterialAttrib *target_material = (const MaterialAttrib *)
965  _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
966  // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
967  if (target_material->is_off()) {
968  t.set(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
969  return &t;
970  }
971  Material *m = target_material->get_material();
972  LVecBase4 const &amb = m->get_ambient();
973  LVecBase4 const &dif = m->get_diffuse();
974  LVecBase4 const &emm = m->get_emission();
975  LVecBase4 spc = m->get_specular();
976  spc[3] = m->get_shininess();
977  t.set(amb[0], amb[1], amb[2], amb[3],
978  dif[0], dif[1], dif[2], dif[3],
979  emm[0], emm[1], emm[2], emm[3],
980  spc[0], spc[1], spc[2], spc[3]);
981  return &t;
982  }
983  case Shader::SMO_attr_material2: {
984  const MaterialAttrib *target_material = (const MaterialAttrib *)
985  _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
986  if (target_material->is_off()) {
987  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
988  return &t;
989  }
990  Material *m = target_material->get_material();
991  t.set_row(0, m->get_base_color());
992  t.set_row(3, LVecBase4(m->get_metallic(), m->get_refractive_index(), 0, m->get_roughness()));
993  return &t;
994  }
995  case Shader::SMO_attr_color: {
996  const ColorAttrib *target_color = (const ColorAttrib *)
997  _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
998  if (target_color->get_color_type() != ColorAttrib::T_flat) {
999  return &LMatrix4::ones_mat();
1000  }
1001  LVecBase4 c = target_color->get_color();
1002  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1003  return &t;
1004  }
1005  case Shader::SMO_attr_colorscale: {
1006  const ColorScaleAttrib *target_color = (const ColorScaleAttrib *)
1007  _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
1008  if (target_color->is_identity()) {
1009  return &LMatrix4::ones_mat();
1010  }
1011  LVecBase4 cs = target_color->get_scale();
1012  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cs[0], cs[1], cs[2], cs[3]);
1013  return &t;
1014  }
1015  case Shader::SMO_attr_fog: {
1016  const FogAttrib *target_fog = (const FogAttrib *)
1017  _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1018  Fog *fog = target_fog->get_fog();
1019  if (fog == nullptr) {
1020  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1);
1021  return &t;
1022  }
1023  PN_stdfloat start, end;
1024  fog->get_linear_range(start, end);
1025  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1026  fog->get_exp_density(), start, end, 1.0f / (end - start));
1027  return &t;
1028  }
1029  case Shader::SMO_attr_fogcolor: {
1030  const FogAttrib *target_fog = (const FogAttrib *)
1031  _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1032  Fog *fog = target_fog->get_fog();
1033  if (fog == nullptr) {
1034  return &LMatrix4::ones_mat();
1035  }
1036  LVecBase4 c = fog->get_color();
1037  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1038  return &t;
1039  }
1040  case Shader::SMO_alight_x: {
1041  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1042  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1043  AmbientLight *lt;
1044  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1045  LColor const &c = lt->get_color();
1046  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1047  return &t;
1048  }
1049  case Shader::SMO_satten_x: {
1050  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1051  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1052  Spotlight *lt;
1053  DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
1054  LVecBase3 const &a = lt->get_attenuation();
1055  PN_stdfloat x = lt->get_exponent();
1056  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
1057  return &t;
1058  }
1059  case Shader::SMO_dlight_x: {
1060  // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE
1061  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1062  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1063  DirectionalLight *lt;
1064  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1065  LColor const &c = lt->get_color();
1066  LColor const &s = lt->get_specular_color();
1067  t = np.get_net_transform()->get_mat() *
1068  _scene_setup->get_world_transform()->get_mat();
1069  LVecBase3 d = -(t.xform_vec(lt->get_direction()));
1070  d.normalize();
1071  LVecBase3 h = d + LVecBase3(0,-1,0);
1072  h.normalize();
1073  t.set(c[0], c[1], c[2], c[3],
1074  s[0], s[1], s[2], c[3],
1075  d[0], d[1], d[2], 0,
1076  h[0], h[1], h[2], 0);
1077  return &t;
1078  }
1079  case Shader::SMO_plight_x: {
1080  // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION
1081  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1082  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1083  PointLight *lt;
1084  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1085  LColor const &c = lt->get_color();
1086  LColor const &s = lt->get_specular_color();
1087  t = np.get_net_transform()->get_mat() *
1088  _scene_setup->get_world_transform()->get_mat();
1089  LVecBase3 p = (t.xform_point(lt->get_point()));
1090  LVecBase3 a = lt->get_attenuation();
1091  Lens *lens = lt->get_lens(0);
1092  PN_stdfloat lnear = lens->get_near();
1093  PN_stdfloat lfar = lens->get_far();
1094  t.set(c[0], c[1], c[2], c[3],
1095  s[0], s[1], s[2], s[3],
1096  p[0], p[1], p[2], lnear,
1097  a[0], a[1], a[2], lfar);
1098  return &t;
1099  }
1100  case Shader::SMO_slight_x: {
1101  // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION
1102  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1103  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1104  Spotlight *lt;
1105  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1106  Lens *lens = lt->get_lens();
1107  nassertr(lens != nullptr, &LMatrix4::zeros_mat());
1108  LColor const &c = lt->get_color();
1109  LColor const &s = lt->get_specular_color();
1110  PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
1111  t = np.get_net_transform()->get_mat() *
1112  _scene_setup->get_world_transform()->get_mat();
1113  LVecBase3 p = t.xform_point(lens->get_nodal_point());
1114  LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
1115  t.set(c[0], c[1], c[2], c[3],
1116  s[0], s[1], s[2], s[3],
1117  p[0], p[1], p[2], 0,
1118  d[0], d[1], d[2], cutoff);
1119  return &t;
1120  }
1121  case Shader::SMO_light_ambient: {
1122  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1123  const LightAttrib *target_light = (const LightAttrib *)
1124  _target_rs->get_attrib_def(LightAttrib::get_class_slot());
1125 
1126  if (!target_light->has_any_on_light()) {
1127  // There are no lights at all. This means, to follow the fixed-
1128  // function model, we pretend there is an all-white ambient light.
1129  t.set_row(3, LVecBase4(1, 1, 1, 1));
1130  } else {
1131  t.set_row(3, target_light->get_ambient_contribution());
1132  }
1133  return &t;
1134  }
1135  case Shader::SMO_texmat_i: {
1136  const TexMatrixAttrib *tma;
1137  const TextureAttrib *ta;
1138  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1139  index < ta->get_num_on_stages()) {
1140  return &tma->get_mat(ta->get_on_stage(index));
1141  } else {
1142  return &LMatrix4::ident_mat();
1143  }
1144  }
1145  case Shader::SMO_inv_texmat_i: {
1146  const TexMatrixAttrib *tma;
1147  const TextureAttrib *ta;
1148  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1149  index < ta->get_num_on_stages()) {
1150  t = tma->get_transform(ta->get_on_stage(index))->get_inverse()->get_mat();
1151  return &t;
1152  } else {
1153  return &LMatrix4::ident_mat();
1154  }
1155  }
1156  case Shader::SMO_texscale_i: {
1157  const TexMatrixAttrib *tma;
1158  const TextureAttrib *ta;
1159  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1160  index < ta->get_num_on_stages()) {
1161  LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
1162  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
1163  return &t;
1164  } else {
1165  return &LMatrix4::ident_mat();
1166  }
1167  }
1168  case Shader::SMO_texcolor_i: {
1169  const TextureAttrib *ta;
1170  if (_target_rs->get_attrib(ta) && index < ta->get_num_on_stages()) {
1171  TextureStage *ts = ta->get_on_stage(index);
1172  t.set_row(3, ts->get_color());
1173  return &t;
1174  } else {
1175  return &LMatrix4::zeros_mat();
1176  }
1177  }
1178  case Shader::SMO_tex_is_alpha_i: {
1179  // This is a hack so we can support both F_alpha and other formats in the
1180  // default shader, to fix font rendering in GLES2
1181  const TextureAttrib *ta;
1182  if (_target_rs->get_attrib(ta) &&
1183  index < ta->get_num_on_stages()) {
1184  TextureStage *ts = ta->get_on_stage(index);
1185  PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
1186  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
1187  return &t;
1188  } else {
1189  return &LMatrix4::zeros_mat();
1190  }
1191  }
1192  case Shader::SMO_plane_x: {
1193  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1194  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1195  const PlaneNode *plane_node;
1196  DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
1197  LPlane p = plane_node->get_plane();
1198  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
1199  return &t;
1200  }
1201  case Shader::SMO_clipplane_x: {
1202  const ClipPlaneAttrib *cpa;
1203  _target_rs->get_attrib_def(cpa);
1204  int planenr = atoi(name->get_name().c_str());
1205  if (planenr >= cpa->get_num_on_planes()) {
1206  return &LMatrix4::zeros_mat();
1207  }
1208  const NodePath &np = cpa->get_on_plane(planenr);
1209  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1210  const PlaneNode *plane_node;
1211  DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
1212 
1213  // Transform plane to world space
1214  CPT(TransformState) transform = np.get_net_transform();
1215  LPlane plane = plane_node->get_plane();
1216  if (!transform->is_identity()) {
1217  plane.xform(transform->get_mat());
1218  }
1219  t.set_row(3, plane);
1220  return &t;
1221  }
1222  case Shader::SMO_apiview_clipplane_i: {
1223  const ClipPlaneAttrib *cpa;
1224  _target_rs->get_attrib_def(cpa);
1225  if (index >= cpa->get_num_on_planes()) {
1226  return &LMatrix4::zeros_mat();
1227  }
1228 
1229  const NodePath &plane = cpa->get_on_plane(index);
1230  nassertr(!plane.is_empty(), &LMatrix4::zeros_mat());
1231  const PlaneNode *plane_node;
1232  DCAST_INTO_R(plane_node, plane.node(), &LMatrix4::zeros_mat());
1233 
1234  CPT(TransformState) transform =
1235  _scene_setup->get_cs_world_transform()->compose(
1236  plane.get_transform(_scene_setup->get_scene_root().get_parent()));
1237 
1238  LPlane xformed_plane = plane_node->get_plane() * transform->get_mat();
1239  t.set_row(3, xformed_plane);
1240  return &t;
1241  }
1242  case Shader::SMO_mat_constant_x: {
1243  return &_target_shader->get_shader_input_matrix(name, t);
1244  }
1245  case Shader::SMO_vec_constant_x: {
1246  const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
1247  const PN_stdfloat *data = input.get_data();
1248  t.set(data[0], data[1], data[2], data[3],
1249  data[0], data[1], data[2], data[3],
1250  data[0], data[1], data[2], data[3],
1251  data[0], data[1], data[2], data[3]);
1252  return &t;
1253  }
1254  case Shader::SMO_world_to_view: {
1255  return &(_scene_setup->get_world_transform()->get_mat());
1256  }
1257  case Shader::SMO_view_to_world: {
1258  return &(_scene_setup->get_camera_transform()->get_mat());
1259  }
1260  case Shader::SMO_model_to_view: {
1261  t = _inv_cs_transform->compose(_internal_transform)->get_mat();
1262  return &t;
1263  }
1264  case Shader::SMO_model_to_apiview: {
1265  return &(_internal_transform->get_mat());
1266  }
1267  case Shader::SMO_view_to_model: {
1268  t = _internal_transform->invert_compose(_cs_transform)->get_mat();
1269  return &t;
1270  }
1271  case Shader::SMO_apiview_to_model: {
1272  t = _internal_transform->get_inverse()->get_mat();
1273  return &t;
1274  }
1275  case Shader::SMO_apiview_to_view: {
1276  return &(_inv_cs_transform->get_mat());
1277  }
1278  case Shader::SMO_view_to_apiview: {
1279  return &(_cs_transform->get_mat());
1280  }
1281  case Shader::SMO_clip_to_view: {
1282  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1283  return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
1284  } else {
1285  t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
1286  LMatrix4::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
1287  return &t;
1288  }
1289  }
1290  case Shader::SMO_view_to_clip: {
1291  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1292  return &(_current_lens->get_projection_mat(_current_stereo_channel));
1293  } else {
1294  t = LMatrix4::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
1295  _current_lens->get_projection_mat(_current_stereo_channel);
1296  return &t;
1297  }
1298  }
1299  case Shader::SMO_apiclip_to_view: {
1300  t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
1301  return &t;
1302  }
1303  case Shader::SMO_view_to_apiclip: {
1304  t = _cs_transform->get_mat() * _projection_mat->get_mat();
1305  return &t;
1306  }
1307  case Shader::SMO_apiclip_to_apiview: {
1308  return &(_projection_mat_inv->get_mat());
1309  }
1310  case Shader::SMO_apiview_to_apiclip: {
1311  return &(_projection_mat->get_mat());
1312  }
1313  case Shader::SMO_view_x_to_view: {
1314  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1315  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1316  t = np.get_net_transform()->get_mat() *
1317  _scene_setup->get_world_transform()->get_mat();
1318  return &t;
1319  }
1320  case Shader::SMO_view_to_view_x: {
1321  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1322  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1323  t = _scene_setup->get_camera_transform()->get_mat() *
1324  np.get_net_transform()->get_inverse()->get_mat();
1325  return &t;
1326  }
1327  case Shader::SMO_apiview_x_to_view: {
1328  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1329  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1330  t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
1331  np.get_net_transform()->get_mat() *
1332  _scene_setup->get_world_transform()->get_mat();
1333  return &t;
1334  }
1335  case Shader::SMO_view_to_apiview_x: {
1336  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1337  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1338  t = (_scene_setup->get_camera_transform()->get_mat() *
1339  np.get_net_transform()->get_inverse()->get_mat() *
1340  LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
1341  return &t;
1342  }
1343  case Shader::SMO_clip_x_to_view: {
1344  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1345  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1346  const LensNode *node;
1347  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1348  const Lens *lens = node->get_lens();
1349  t = lens->get_projection_mat_inv(_current_stereo_channel) *
1350  LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
1351  np.get_net_transform()->get_mat() *
1352  _scene_setup->get_world_transform()->get_mat();
1353  return &t;
1354  }
1355  case Shader::SMO_view_to_clip_x: {
1356  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1357  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1358  const LensNode *node;
1359  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1360  const Lens *lens = node->get_lens();
1361  t = _scene_setup->get_camera_transform()->get_mat() *
1362  np.get_net_transform()->get_inverse()->get_mat() *
1363  LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
1364  lens->get_projection_mat(_current_stereo_channel);
1365  return &t;
1366  }
1367  case Shader::SMO_apiclip_x_to_view: {
1368  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1369  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1370  const LensNode *node;
1371  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1372  const Lens *lens = node->get_lens();
1373  t = calc_projection_mat(lens)->get_inverse()->get_mat() *
1374  get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
1375  np.get_net_transform()->get_mat() *
1376  _scene_setup->get_world_transform()->get_mat();
1377  return &t;
1378  }
1379  case Shader::SMO_view_to_apiclip_x: {
1380  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1381  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1382  const LensNode *node;
1383  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1384  const Lens *lens = node->get_lens();
1385  t = _scene_setup->get_camera_transform()->get_mat() *
1386  np.get_net_transform()->get_inverse()->get_mat() *
1387  get_cs_transform_for(lens->get_coordinate_system())->get_mat() *
1388  calc_projection_mat(lens)->get_mat();
1389  return &t;
1390  }
1391  case Shader::SMO_mat_constant_x_attrib: {
1392  if (_target_shader->has_shader_input(name)) {
1393  // There is an input specifying precisely this whole thing, with dot and
1394  // all. Support this, even if only for backward compatibility.
1395  return &_target_shader->get_shader_input_matrix(name, t);
1396  }
1397 
1398  const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
1399  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1400 
1401  return fetch_specified_member(np, name->get_basename(), t);
1402  }
1403  case Shader::SMO_vec_constant_x_attrib: {
1404  if (_target_shader->has_shader_input(name)) {
1405  // There is an input specifying precisely this whole thing, with dot and
1406  // all. Support this, even if only for backward compatibility.
1407  const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
1408  t.set(data[0], data[1], data[2], data[3],
1409  data[0], data[1], data[2], data[3],
1410  data[0], data[1], data[2], data[3],
1411  data[0], data[1], data[2], data[3]);
1412  return &t;
1413  }
1414 
1415  const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
1416  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1417 
1418  return fetch_specified_member(np, name->get_basename(), t);
1419  }
1420  case Shader::SMO_light_source_i_attrib: {
1421  const LightAttrib *target_light;
1422  _target_rs->get_attrib_def(target_light);
1423 
1424  // We don't count ambient lights, which would be pretty silly to handle
1425  // via this mechanism.
1426  size_t num_lights = target_light->get_num_non_ambient_lights();
1427  if (index >= 0 && (size_t)index < num_lights) {
1428  NodePath light = target_light->get_on_light((size_t)index);
1429  nassertr(!light.is_empty(), &LMatrix4::ident_mat());
1430  Light *light_obj = light.node()->as_light();
1431  nassertr(light_obj != nullptr, &LMatrix4::ident_mat());
1432 
1433  return fetch_specified_member(light, name, t);
1434 
1435  } else if (index == 0) {
1436  // Apply the default OpenGL lights otherwise.
1437  // Special exception for light 0, which defaults to white.
1438  string basename = name->get_basename();
1439  return &LMatrix4::ones_mat();
1440  }
1441  return fetch_specified_member(NodePath(), name, t);
1442  }
1443  case Shader::SMO_light_source_i_packed: {
1444  // The light matrix contains COLOR, ATTENUATION, POSITION, VIEWVECTOR
1445  const LightAttrib *target_light;
1446  _target_rs->get_attrib_def(target_light);
1447 
1448  // We don't count ambient lights, which would be pretty silly to handle
1449  // via this mechanism.
1450  size_t num_lights = target_light->get_num_non_ambient_lights();
1451  if (index >= 0 && (size_t)index < num_lights) {
1452  NodePath np = target_light->get_on_light((size_t)index);
1453  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1454  PandaNode *node = np.node();
1455  Light *light = node->as_light();
1456  nassertr(light != nullptr, &LMatrix4::zeros_mat());
1457  t.set_row(0, light->get_color());
1458  t.set_row(1, light->get_attenuation());
1459 
1460  LMatrix4 mat = np.get_net_transform()->get_mat() *
1461  _scene_setup->get_world_transform()->get_mat();
1462 
1463  if (node->is_of_type(DirectionalLight::get_class_type())) {
1464  LVecBase3 d = mat.xform_vec(((const DirectionalLight *)node)->get_direction());
1465  d.normalize();
1466  t.set_row(2, LVecBase4(d, 0));
1467  t.set_row(3, LVecBase4(-d, 0));
1468 
1469  } else if (node->is_of_type(LightLensNode::get_class_type())) {
1470  const Lens *lens = ((const LightLensNode *)node)->get_lens();
1471 
1472  LPoint3 p = mat.xform_point(lens->get_nodal_point());
1473  t.set_row(3, LVecBase4(p));
1474 
1475  // For shadowed point light we need to store near/far.
1476  // For spotlight we need to store cutoff angle.
1477  if (node->is_of_type(Spotlight::get_class_type())) {
1478  PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
1479  LVecBase3 d = -(mat.xform_vec(lens->get_view_vector()));
1480  t.set_cell(1, 3, ((const Spotlight *)node)->get_exponent());
1481  t.set_row(2, LVecBase4(d, cutoff));
1482 
1483  } else if (node->is_of_type(PointLight::get_class_type())) {
1484  t.set_cell(1, 3, lens->get_far());
1485  t.set_cell(3, 3, lens->get_near());
1486 
1487  if (node->is_of_type(SphereLight::get_class_type())) {
1488  t.set_cell(2, 3, ((const SphereLight *)node)->get_radius());
1489  }
1490  }
1491  }
1492  } else if (index == 0) {
1493  // Apply the default OpenGL lights otherwise.
1494  // Special exception for light 0, which defaults to white.
1495  t.set_row(0, LVecBase4(1, 1, 1, 1));
1496  }
1497  return &t;
1498  }
1499  default:
1500  nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
1501  return &LMatrix4::ident_mat();
1502  }
1503 }
1504 
1505 /**
1506  * Given a NodePath passed into a shader input that is a structure, fetches
1507  * the value for the given member.
1508  */
1510 fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) {
1511  // This system is not ideal. It will be improved in the future.
1512  static const CPT_InternalName IN_color("color");
1513  static const CPT_InternalName IN_ambient("ambient");
1514  static const CPT_InternalName IN_diffuse("diffuse");
1515  static const CPT_InternalName IN_specular("specular");
1516  static const CPT_InternalName IN_position("position");
1517  static const CPT_InternalName IN_halfVector("halfVector");
1518  static const CPT_InternalName IN_spotDirection("spotDirection");
1519  static const CPT_InternalName IN_spotCutoff("spotCutoff");
1520  static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
1521  static const CPT_InternalName IN_spotExponent("spotExponent");
1522  static const CPT_InternalName IN_attenuation("attenuation");
1523  static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
1524  static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
1525  static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
1526  static const CPT_InternalName IN_shadowViewMatrix("shadowViewMatrix");
1527 
1528  PandaNode *node = nullptr;
1529  if (!np.is_empty()) {
1530  node = np.node();
1531  }
1532 
1533  if (attrib == IN_color) {
1534  if (node == nullptr) {
1535  return &LMatrix4::ident_mat();
1536  }
1537  Light *light = node->as_light();
1538  nassertr(light != nullptr, &LMatrix4::ident_mat());
1539  LColor c = light->get_color();
1540  t.set_row(3, c);
1541  return &t;
1542 
1543  } else if (attrib == IN_ambient) {
1544  if (node == nullptr) {
1545  return &LMatrix4::ident_mat();
1546  }
1547  Light *light = node->as_light();
1548  nassertr(light != nullptr, &LMatrix4::ident_mat());
1549  if (node->is_ambient_light()) {
1550  LColor c = light->get_color();
1551  t.set_row(3, c);
1552  } else {
1553  // Non-ambient lights don't currently have an ambient color in Panda3D.
1554  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1555  }
1556  return &t;
1557 
1558  } else if (attrib == IN_diffuse) {
1559  if (node == nullptr) {
1560  return &LMatrix4::ident_mat();
1561  }
1562  Light *light = node->as_light();
1563  nassertr(light != nullptr, &LMatrix4::ones_mat());
1564  if (node->is_ambient_light()) {
1565  // Ambient light has no diffuse color.
1566  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1567  } else {
1568  LColor c = light->get_color();
1569  t.set_row(3, c);
1570  }
1571  return &t;
1572 
1573  } else if (attrib == IN_specular) {
1574  if (node == nullptr) {
1575  return &LMatrix4::ident_mat();
1576  }
1577  Light *light = node->as_light();
1578  nassertr(light != nullptr, &LMatrix4::ones_mat());
1579  t.set_row(3, light->get_specular_color());
1580  return &t;
1581 
1582  } else if (attrib == IN_position) {
1583  if (np.is_empty()) {
1584  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1585  return &t;
1586  } else if (node->is_ambient_light()) {
1587  // Ambient light has no position.
1588  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1589  return &t;
1590  } else if (node->is_of_type(DirectionalLight::get_class_type())) {
1591  DirectionalLight *light;
1592  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1593 
1594  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1595  LVector3 dir = -(light->get_direction() * transform->get_mat());
1596  dir *= _scene_setup->get_cs_world_transform()->get_mat();
1597  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
1598  return &t;
1599  } else {
1600  LightLensNode *light;
1601  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1602  Lens *lens = light->get_lens();
1603  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1604 
1605  CPT(TransformState) transform =
1606  _scene_setup->get_cs_world_transform()->compose(
1607  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1608 
1609  const LMatrix4 &light_mat = transform->get_mat();
1610  LPoint3 pos = lens->get_nodal_point() * light_mat;
1611  t = LMatrix4::translate_mat(pos);
1612  return &t;
1613  }
1614 
1615  } else if (attrib == IN_halfVector) {
1616  if (np.is_empty()) {
1617  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1618  return &t;
1619  } else if (node->is_ambient_light()) {
1620  // Ambient light has no half-vector.
1621  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1622  return &t;
1623  } else if (node->is_of_type(DirectionalLight::get_class_type())) {
1624  DirectionalLight *light;
1625  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1626 
1627  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1628  LVector3 dir = -(light->get_direction() * transform->get_mat());
1629  dir *= _scene_setup->get_cs_world_transform()->get_mat();
1630  dir.normalize();
1631  dir += LVector3(0, 0, 1);
1632  dir.normalize();
1633  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
1634  return &t;
1635  } else {
1636  LightLensNode *light;
1637  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1638  Lens *lens = light->get_lens();
1639  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1640 
1641  CPT(TransformState) transform =
1642  _scene_setup->get_cs_world_transform()->compose(
1643  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1644 
1645  const LMatrix4 &light_mat = transform->get_mat();
1646  LPoint3 pos = lens->get_nodal_point() * light_mat;
1647  pos.normalize();
1648  pos += LVector3(0, 0, 1);
1649  pos.normalize();
1650  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
1651  return &t;
1652  }
1653 
1654  } else if (attrib == IN_spotDirection) {
1655  if (node == nullptr) {
1656  t.set_row(3, LVector3(0.0f, 0.0f, -1.0f));
1657  return &t;
1658  } else if (node->is_ambient_light()) {
1659  // Ambient light has no spot direction.
1660  t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
1661  return &t;
1662  } else {
1663  LightLensNode *light;
1664  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1665  Lens *lens = light->get_lens();
1666  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1667 
1668  CPT(TransformState) transform =
1669  _scene_setup->get_cs_world_transform()->compose(
1670  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1671 
1672  const LMatrix4 &light_mat = transform->get_mat();
1673  LVector3 dir = lens->get_view_vector() * light_mat;
1674  t.set_row(3, dir);
1675  return &t;
1676  }
1677 
1678  } else if (attrib == IN_spotCutoff) {
1679  if (node != nullptr &&
1680  node->is_of_type(Spotlight::get_class_type())) {
1681  LightLensNode *light;
1682  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1683  Lens *lens = light->get_lens();
1684  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1685 
1686  float cutoff = lens->get_hfov() * 0.5f;
1687  t.set_row(3, LVecBase4(cutoff));
1688  return &t;
1689  } else {
1690  // Other lights have no cut-off.
1691  t.set_row(3, LVecBase4(180));
1692  return &t;
1693  }
1694 
1695  } else if (attrib == IN_spotCosCutoff) {
1696  if (node != nullptr &&
1697  node->is_of_type(Spotlight::get_class_type())) {
1698  LightLensNode *light;
1699  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1700  Lens *lens = light->get_lens();
1701  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1702 
1703  float cutoff = lens->get_hfov() * 0.5f;
1704  t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
1705  return &t;
1706  } else {
1707  // Other lights have no cut-off.
1708  t.set_row(3, LVecBase4(-1));
1709  return &t;
1710  }
1711 
1712  } else if (attrib == IN_spotExponent) {
1713  if (node == nullptr) {
1714  return &LMatrix4::zeros_mat();
1715  }
1716  Light *light = node->as_light();
1717  nassertr(light != nullptr, &LMatrix4::ident_mat());
1718 
1719  t.set_row(3, LVecBase4(light->get_exponent()));
1720  return &t;
1721 
1722  } else if (attrib == IN_attenuation) {
1723  if (node != nullptr) {
1724  Light *light = node->as_light();
1725  nassertr(light != nullptr, &LMatrix4::ones_mat());
1726 
1727  t.set_row(3, LVecBase4(light->get_attenuation(), 0));
1728  } else {
1729  t.set_row(3, LVecBase4(1, 0, 0, 0));
1730  }
1731  return &t;
1732 
1733  } else if (attrib == IN_constantAttenuation) {
1734  if (node == nullptr) {
1735  return &LMatrix4::ones_mat();
1736  }
1737  Light *light = node->as_light();
1738  nassertr(light != nullptr, &LMatrix4::ones_mat());
1739 
1740  t.set_row(3, LVecBase4(light->get_attenuation()[0]));
1741  return &t;
1742 
1743  } else if (attrib == IN_linearAttenuation) {
1744  if (node == nullptr) {
1745  return &LMatrix4::zeros_mat();
1746  }
1747  Light *light = node->as_light();
1748  nassertr(light != nullptr, &LMatrix4::ident_mat());
1749 
1750  t.set_row(3, LVecBase4(light->get_attenuation()[1]));
1751  return &t;
1752 
1753  } else if (attrib == IN_quadraticAttenuation) {
1754  if (node == nullptr) {
1755  return &LMatrix4::zeros_mat();
1756  }
1757  Light *light = node->as_light();
1758  nassertr(light != nullptr, &LMatrix4::ident_mat());
1759 
1760  t.set_row(3, LVecBase4(light->get_attenuation()[2]));
1761  return &t;
1762 
1763  } else if (attrib == IN_shadowViewMatrix) {
1764  static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f,
1765  0.0f, 0.5f, 0.0f, 0.0f,
1766  0.0f, 0.0f, 0.5f, 0.0f,
1767  0.5f, 0.5f, 0.5f, 1.0f);
1768 
1769  if (node == nullptr) {
1770  return &biasmat;
1771  }
1772 
1773  LensNode *lnode;
1774  DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat());
1775  Lens *lens = lnode->get_lens();
1776 
1777  t = _inv_cs_transform->get_mat() *
1778  _scene_setup->get_camera_transform()->get_mat() *
1779  np.get_net_transform()->get_inverse()->get_mat() *
1780  LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system());
1781 
1782  if (!node->is_of_type(PointLight::get_class_type())) {
1783  t *= lens->get_projection_mat() * biasmat;
1784  }
1785  return &t;
1786 
1787  } else {
1788  display_cat.error()
1789  << "Shader input requests invalid attribute " << *attrib
1790  << " from node " << np << "\n";
1791  return &LMatrix4::ident_mat();
1792  }
1793 }
1794 
1795 /**
1796  * Like fetch_specified_value, but for texture inputs.
1797  */
1798 PT(Texture) GraphicsStateGuardian::
1799 fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
1800  int &view) {
1801  switch (spec._part) {
1802  case Shader::STO_named_input:
1803  // Named texture input.
1804  if (!_target_shader->has_shader_input(spec._name)) {
1805  // Is this a member of something, like a node?
1806  const InternalName *parent = spec._name->get_parent();
1807  if (parent != InternalName::get_root() &&
1808  _target_shader->has_shader_input(parent)) {
1809 
1810  // Yes, grab the node.
1811  const string &basename = spec._name->get_basename();
1812  NodePath np = _target_shader->get_shader_input_nodepath(parent);
1813 
1814  if (basename == "shadowMap") {
1815  PT(Texture) tex = get_shadow_map(np);
1816  if (tex != nullptr) {
1817  sampler = tex->get_default_sampler();
1818  }
1819  return tex;
1820 
1821  } else {
1822  if (spec._stage == 0) {
1823  display_cat.error()
1824  << "Shader input " << *parent
1825  << " has no member named " << basename << ".\n";
1826  spec._stage = -1;
1827  }
1828  }
1829  } else {
1830  // This used to be legal for some reason, so don't trigger the assert.
1831  // Prevent flood, though, so abuse the _stage flag to indicate whether
1832  // we've already errored about this.
1833  if (spec._stage == 0) {
1834  display_cat.error()
1835  << "Shader input " << *spec._name << " is not present.\n";
1836  spec._stage = -1;
1837  }
1838  }
1839  } else {
1840  // Just a regular texture input.
1841  return _target_shader->get_shader_input_texture(spec._name, &sampler);
1842  }
1843  break;
1844 
1845  case Shader::STO_stage_i:
1846  {
1847  // We get the TextureAttrib directly from the _target_rs, not the
1848  // filtered TextureAttrib in _target_texture.
1849  const TextureAttrib *texattrib;
1850  _target_rs->get_attrib_def(texattrib);
1851 
1852  if (spec._stage < texattrib->get_num_on_stages()) {
1853  TextureStage *stage = texattrib->get_on_stage(spec._stage);
1854  sampler = texattrib->get_on_sampler(stage);
1855  view += stage->get_tex_view_offset();
1856  return texattrib->get_on_texture(stage);
1857  }
1858  }
1859  break;
1860 
1861  case Shader::STO_light_i_shadow_map:
1862  {
1863  const LightAttrib *target_light;
1864  _target_rs->get_attrib_def(target_light);
1865 
1866  // We don't count ambient lights, which would be pretty silly to handle
1867  // via this mechanism.
1868  size_t num_lights = target_light->get_num_non_ambient_lights();
1869  if (spec._stage >= 0 && (size_t)spec._stage < num_lights) {
1870  NodePath light = target_light->get_on_light((size_t)spec._stage);
1871  nassertr(!light.is_empty(), nullptr);
1872  Light *light_obj = light.node()->as_light();
1873  nassertr(light_obj != nullptr, nullptr);
1874 
1875  PT(Texture) tex;
1876  LightLensNode *lln = DCAST(LightLensNode, light.node());
1877  if (lln != nullptr && lln->_shadow_caster) {
1878  tex = get_shadow_map(light);
1879  } else {
1880  tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
1881  }
1882 
1883  if (tex != nullptr) {
1884  sampler = tex->get_default_sampler();
1885  }
1886  return tex;
1887  } else {
1888  // There is no such light assigned. Bind a dummy shadow map.
1889  PT(Texture) tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
1890  if (tex != nullptr) {
1891  sampler = tex->get_default_sampler();
1892  }
1893  return tex;
1894  }
1895  }
1896  break;
1897 
1898  default:
1899  nassertr(false, nullptr);
1900  break;
1901  }
1902 
1903  return nullptr;
1904 }
1905 
1906 /**
1907  * Return a pointer to struct ShaderPtrData
1908  */
1909 const Shader::ShaderPtrData *GraphicsStateGuardian::
1910 fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
1911  return (_target_shader->get_shader_input_ptr(spec._arg));
1912 }
1913 
1914 /**
1915  * Makes the specified DisplayRegion current. All future drawing and clear
1916  * operations will be constrained within the given DisplayRegion.
1917  */
1920  _current_display_region = dr->get_object();
1921  _current_stereo_channel = dr->get_stereo_channel();
1922  _current_tex_view_offset = dr->get_tex_view_offset();
1923  _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render();
1924 
1925  _stereo_buffer_mask = ~0;
1926 
1927  Lens::StereoChannel output_channel = dr->get_stereo_channel();
1928  if (dr->get_window()->get_swap_eyes()) {
1929  // Reverse the output channel.
1930  switch (output_channel) {
1931  case Lens::SC_left:
1932  output_channel = Lens::SC_right;
1933  break;
1934 
1935  case Lens::SC_right:
1936  output_channel = Lens::SC_left;
1937  break;
1938 
1939  default:
1940  break;
1941  }
1942  }
1943 
1944  switch (output_channel) {
1945  case Lens::SC_left:
1946  _color_write_mask = dr->get_window()->get_left_eye_color_mask();
1947  if (_current_properties->is_stereo()) {
1948  _stereo_buffer_mask = ~RenderBuffer::T_right;
1949  }
1950  break;
1951 
1952  case Lens::SC_right:
1953  _color_write_mask = dr->get_window()->get_right_eye_color_mask();
1954  if (_current_properties->is_stereo()) {
1955  _stereo_buffer_mask = ~RenderBuffer::T_left;
1956  }
1957  break;
1958 
1959  case Lens::SC_mono:
1960  case Lens::SC_stereo:
1961  _color_write_mask = ColorWriteAttrib::C_all;
1962  }
1963 }
1964 
1965 /**
1966  * Resets any non-standard graphics state that might give a callback apoplexy.
1967  * Some drivers require that the graphics state be restored to neutral before
1968  * performing certain operations. In OpenGL, for instance, this closes any
1969  * open vertex buffers.
1970  */
1973 }
1974 
1975 /**
1976  * Forgets the current graphics state and current transform, so that the next
1977  * call to set_state_and_transform() will have to reload everything. This is
1978  * a good thing to call when you are no longer sure what the graphics state
1979  * is. This should only be called from the draw thread.
1980  */
1983  // Re-issue the modelview and projection transforms.
1984  reissue_transforms();
1985 
1986  // Now clear the state flags to unknown.
1987  _state_rs = RenderState::make_empty();
1988  _state_mask.clear();
1989 }
1990 
1991 /**
1992  * This is simply a transparent call to GraphicsEngine::remove_window(). It
1993  * exists primary to support removing a window from that compiles before the
1994  * display module, and therefore has no knowledge of a GraphicsEngine object.
1995  */
1998  nassertv(_engine != nullptr);
1999  GraphicsOutput *win;
2000  DCAST_INTO_V(win, window);
2001  _engine->remove_window(win);
2002 }
2003 
2004 /**
2005  * Makes the current lens (whichever lens was most recently specified with
2006  * set_scene()) active, so that it will transform future rendered geometry.
2007  * Normally this is only called from the draw process, and usually it is
2008  * called by set_scene().
2009  *
2010  * The return value is true if the lens is acceptable, false if it is not.
2011  */
2013 prepare_lens() {
2014  return false;
2015 }
2016 
2017 /**
2018  * Given a lens, this function calculates the appropriate projection matrix
2019  * for this gsg. The result depends on the peculiarities of the rendering
2020  * API.
2021  */
2022 CPT(TransformState) GraphicsStateGuardian::
2023 calc_projection_mat(const Lens *lens) {
2024  if (lens == nullptr) {
2025  return nullptr;
2026  }
2027 
2028  if (!lens->is_linear()) {
2029  return nullptr;
2030  }
2031 
2032  return TransformState::make_identity();
2033 }
2034 
2035 /**
2036  * Called before each frame is rendered, to allow the GSG a chance to do any
2037  * internal cleanup before beginning the frame.
2038  *
2039  * The return value is true if successful (in which case the frame will be
2040  * drawn and end_frame() will be called later), or false if unsuccessful (in
2041  * which case nothing will be drawn and end_frame() will not be called).
2042  */
2044 begin_frame(Thread *current_thread) {
2045  _prepared_objects->begin_frame(this, current_thread);
2046 
2047  // We should reset the state to the default at the beginning of every frame.
2048  // Although this will incur additional overhead, particularly in a simple
2049  // scene, it helps ensure that states that have changed properties since
2050  // last time without changing attribute pointers--like textures, lighting,
2051  // or fog--will still be accurately updated.
2052  _state_rs = RenderState::make_empty();
2053  _state_mask.clear();
2054 
2055 #ifdef DO_PSTATS
2056  // We have to do this here instead of in GraphicsEngine because we need a
2057  // current context to issue timer queries.
2059  if (_last_query_frame < frame) {
2060  _last_query_frame = frame;
2061  _timer_queries_pcollector.clear_level();
2062 
2063  // Now is a good time to flush previous frame's queries. We may not
2064  // actually have all of the previous frame's results in yet, but that's
2065  // okay; the GPU data is allowed to lag a few frames behind.
2067 
2068  if (_timer_queries_active) {
2069  // Issue a stop and start event for collector 0, marking the beginning
2070  // of the new frame.
2071  issue_timer_query(0x8000);
2072  issue_timer_query(0x0000);
2073  }
2074  }
2075 #endif
2076 
2077  return !_needs_reset;
2078 }
2079 
2080 /**
2081  * Called between begin_frame() and end_frame() to mark the beginning of
2082  * drawing commands for a "scene" (usually a particular DisplayRegion) within
2083  * a frame. All 3-D drawing commands, except the clear operation, must be
2084  * enclosed within begin_scene() .. end_scene(). This must be called in the
2085  * draw thread.
2086  *
2087  * The return value is true if successful (in which case the scene will be
2088  * drawn and end_scene() will be called later), or false if unsuccessful (in
2089  * which case nothing will be drawn and end_scene() will not be called).
2090  */
2092 begin_scene() {
2093  return true;
2094 }
2095 
2096 /**
2097  * Called between begin_frame() and end_frame() to mark the end of drawing
2098  * commands for a "scene" (usually a particular DisplayRegion) within a frame.
2099  * All 3-D drawing commands, except the clear operation, must be enclosed
2100  * within begin_scene() .. end_scene().
2101  */
2103 end_scene() {
2104  // We should clear this pointer now, so that we don't keep unneeded
2105  // reference counts dangling. We keep around a "null" scene setup object
2106  // instead of using a null pointer to avoid special-case code in
2107  // set_state_and_transform.
2108  _scene_setup = _scene_null;
2109 
2110  // Undo any lighting we had enabled last scene, to force the lights to be
2111  // reissued, in case their parameters or positions have changed between
2112  // scenes.
2113  int i;
2114  for (i = 0; i < _num_lights_enabled; ++i) {
2115  enable_light(i, false);
2116  }
2117  _num_lights_enabled = 0;
2118 
2119  // Ditto for the clipping planes.
2120  for (i = 0; i < _num_clip_planes_enabled; ++i) {
2121  enable_clip_plane(i, false);
2122  }
2123  _num_clip_planes_enabled = 0;
2124 
2125  // Put the state into the 'unknown' state, forcing a reload.
2126  _state_rs = RenderState::make_empty();
2127  _state_mask.clear();
2128 }
2129 
2130 /**
2131  * Called after each frame is rendered, to allow the GSG a chance to do any
2132  * internal cleanup after rendering the frame, and before the window flips.
2133  */
2135 end_frame(Thread *current_thread) {
2136  _prepared_objects->end_frame(current_thread);
2137 
2138  // Flush any PStatCollectors.
2139  _data_transferred_pcollector.flush_level();
2140 
2141  _primitive_batches_pcollector.flush_level();
2142  _primitive_batches_tristrip_pcollector.flush_level();
2143  _primitive_batches_trifan_pcollector.flush_level();
2144  _primitive_batches_tri_pcollector.flush_level();
2145  _primitive_batches_patch_pcollector.flush_level();
2146  _primitive_batches_other_pcollector.flush_level();
2147  _vertices_tristrip_pcollector.flush_level();
2148  _vertices_trifan_pcollector.flush_level();
2149  _vertices_tri_pcollector.flush_level();
2150  _vertices_patch_pcollector.flush_level();
2151  _vertices_other_pcollector.flush_level();
2152 
2153  _state_pcollector.flush_level();
2154  _texture_state_pcollector.flush_level();
2155  _transform_state_pcollector.flush_level();
2156  _draw_primitive_pcollector.flush_level();
2157 
2158  // Evict any textures andor vbuffers that exceed our texture memory.
2159  _prepared_objects->_graphics_memory_lru.begin_epoch();
2160 }
2161 
2162 /**
2163  * Called by the graphics engine on the draw thread to check the status of the
2164  * running timer queries and submit their results to the PStats server.
2165  */
2168 #ifdef DO_PSTATS
2169  // This uses the lower-level PStats interfaces for now because of all the
2170  // unnecessary overhead that would otherwise be incurred when adding such a
2171  // large amount of data at once.
2172 
2173  PStatClient *client = PStatClient::get_global_pstats();
2174 
2175  if (!client->client_is_connected()) {
2176  _timer_queries_active = false;
2177  return;
2178  }
2179 
2180  if (!_timer_queries_active) {
2181  if (pstats_gpu_timing && _supports_timer_query) {
2182  // Check if timer queries should be enabled.
2183  _timer_queries_active = true;
2184  } else {
2185  return;
2186  }
2187  }
2188 
2189  // Currently, we use one thread per GSG, for convenience. In the future, we
2190  // may want to try and use one thread per graphics card.
2191  if (_pstats_gpu_thread == -1) {
2192  _pstats_gpu_thread = client->make_gpu_thread(get_driver_renderer()).get_index();
2193  }
2194  PStatThread gpu_thread(client, _pstats_gpu_thread);
2195 
2196  // Get the results of all the timer queries.
2197  int first = 0;
2198  if (!_pending_timer_queries.empty()) {
2199  int count = _pending_timer_queries.size();
2200  if (count == 0) {
2201  return;
2202  }
2203 
2204  PStatGPUTimer timer(this, _wait_timer_pcollector);
2205 
2206  if (_last_num_queried > 0) {
2207  // We know how many queries were available last frame, and this usually
2208  // stays fairly constant, so use this as a starting point.
2209  int i = std::min(_last_num_queried, count) - 1;
2210 
2211  if (_pending_timer_queries[i]->is_answer_ready()) {
2212  first = count;
2213  while (i < count - 1) {
2214  if (!_pending_timer_queries[++i]->is_answer_ready()) {
2215  first = i;
2216  break;
2217  }
2218  }
2219  } else {
2220  first = 0;
2221  while (i > 0) {
2222  if (_pending_timer_queries[--i]->is_answer_ready()) {
2223  first = i + 1;
2224  break;
2225  }
2226  }
2227  }
2228  } else {
2229  // We figure out which tasks the GPU has already finished by doing a
2230  // binary search for the first query that does not have an answer ready.
2231  // We know then that everything before that must be ready.
2232  while (count > 0) {
2233  int step = count / 2;
2234  int i = first + step;
2235  if (_pending_timer_queries[i]->is_answer_ready()) {
2236  first += step + 1;
2237  count -= step + 1;
2238  } else {
2239  count = step;
2240  }
2241  }
2242  }
2243 
2244  if (first <= 0) {
2245  return;
2246  }
2247 
2248  _last_num_queried = first;
2249 
2250  for (int i = 0; i < first; ++i) {
2251  CPT(TimerQueryContext) query = _pending_timer_queries[i];
2252 
2253  double time_data = query->get_timestamp(); // + _timer_delta;
2254 
2255  if (query->_pstats_index == _command_latency_pcollector.get_index()) {
2256  // Special case for the latency pcollector.
2257  PStatCollectorDef *cdef;
2258  cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
2259  _pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
2260 
2261  } else if (query->_pstats_index & 0x8000) {
2262  _pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
2263 
2264  } else {
2265  _pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
2266  }
2267 
2268  // We found an end-frame marker (a stop event for collector 0). This
2269  // means that the GPU actually caught up with that frame, and we can
2270  // flush the GPU thread's frame data to the pstats server.
2271  if (query->_pstats_index == 0x8000) {
2272  gpu_thread.add_frame(_pstats_gpu_data);
2273  _pstats_gpu_data.clear();
2274  }
2275  }
2276  }
2277 
2278  if (first > 0) {
2279  // Do this out of the scope of _wait_timer_pcollector.
2280  _pending_timer_queries.erase(
2281  _pending_timer_queries.begin(),
2282  _pending_timer_queries.begin() + first
2283  );
2284  _timer_queries_pcollector.add_level_now(first);
2285  }
2286 #endif
2287 }
2288 
2289 /**
2290  * Returns true if this GSG can implement decals using a DepthOffsetAttrib, or
2291  * false if that is unreliable and the three-step rendering process should be
2292  * used instead.
2293  */
2296  return true;
2297 }
2298 
2299 /**
2300  * Called during draw to begin a three-step rendering phase to draw decals.
2301  * The first step, begin_decal_base_first(), is called prior to drawing the
2302  * base geometry. It should set up whatever internal state is appropriate, as
2303  * well as returning a RenderState object that should be applied to the base
2304  * geometry for rendering.
2305  */
2306 CPT(RenderState) GraphicsStateGuardian::
2307 begin_decal_base_first() {
2308  // Turn off writing the depth buffer to render the base geometry.
2309  static CPT(RenderState) decal_base_first;
2310  if (decal_base_first == nullptr) {
2311  decal_base_first = RenderState::make
2312  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2313  RenderState::get_max_priority());
2314  }
2315  return decal_base_first;
2316 }
2317 
2318 /**
2319  * Called during draw to begin a three-step rendering phase to draw decals.
2320  * The second step, begin_decal_nested(), is called after drawing the base
2321  * geometry and prior to drawing any of the nested decal geometry that is to
2322  * be applied to the base geometry.
2323  */
2324 CPT(RenderState) GraphicsStateGuardian::
2325 begin_decal_nested() {
2326  // We should keep the depth buffer off during this operation, so that decals
2327  // on decals will render properly.
2328  static CPT(RenderState) decal_nested;
2329  if (decal_nested == nullptr) {
2330  decal_nested = RenderState::make
2331  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2332  RenderState::get_max_priority());
2333  }
2334  return decal_nested;
2335 }
2336 
2337 /**
2338  * Called during draw to begin a three-step rendering phase to draw decals.
2339  * The third step, begin_decal_base_second(), is called after drawing the base
2340  * geometry and the nested decal geometry, and prior to drawing the base
2341  * geometry one more time (if needed).
2342  *
2343  * It should return a RenderState object appropriate for rendering the base
2344  * geometry the second time, or NULL if it is not necessary to re-render the
2345  * base geometry.
2346  */
2347 CPT(RenderState) GraphicsStateGuardian::
2348 begin_decal_base_second() {
2349  // Now let the depth buffer go back on, but turn off writing the color
2350  // buffer to render the base geometry after the second pass. Also, turn off
2351  // texturing since there's no need for it now.
2352  static CPT(RenderState) decal_base_second;
2353  if (decal_base_second == nullptr) {
2354  decal_base_second = RenderState::make
2355  (ColorWriteAttrib::make(ColorWriteAttrib::C_off),
2356  // On reflection, we need to leave texturing on so the alpha test
2357  // mechanism can work (if it is enabled, e.g. we are rendering an
2358  // object with M_dual transparency). TextureAttrib::make_off(),
2359  RenderState::get_max_priority());
2360  }
2361  return decal_base_second;
2362 }
2363 
2364 /**
2365  * Called during draw to clean up after decals are finished.
2366  */
2368 finish_decal() {
2369  // No need to do anything special here.
2370 }
2371 
2372 /**
2373  * Called before a sequence of draw_primitive() functions are called, this
2374  * should prepare the vertex data for rendering. It returns true if the
2375  * vertices are ok, false to abort this group of primitives.
2376  */
2378 begin_draw_primitives(const GeomPipelineReader *geom_reader,
2379  const GeomVertexDataPipelineReader *data_reader,
2380  bool force) {
2381  _data_reader = data_reader;
2382 
2383  // Always draw if we have a shader, since the shader might use a different
2384  // mechanism for fetching vertex data.
2385  return _data_reader->has_vertex() || (_target_shader && _target_shader->has_shader());
2386 }
2387 
2388 /**
2389  * Draws a series of disconnected triangles.
2390  */
2393  return false;
2394 }
2395 
2396 
2397 /**
2398  * Draws a series of disconnected triangles with adjacency information.
2399  */
2402  return false;
2403 }
2404 
2405 /**
2406  * Draws a series of triangle strips.
2407  */
2410  return false;
2411 }
2412 
2413 /**
2414  * Draws a series of triangle strips with adjacency information.
2415  */
2418  return false;
2419 }
2420 
2421 /**
2422  * Draws a series of triangle fans.
2423  */
2426  return false;
2427 }
2428 
2429 /**
2430  * Draws a series of "patches", which can only be processed by a tessellation
2431  * shader.
2432  */
2435  return false;
2436 }
2437 
2438 /**
2439  * Draws a series of disconnected line segments.
2440  */
2442 draw_lines(const GeomPrimitivePipelineReader *, bool) {
2443  return false;
2444 }
2445 
2446 /**
2447  * Draws a series of disconnected line segments with adjacency information.
2448  */
2451  return false;
2452 }
2453 
2454 /**
2455  * Draws a series of line strips.
2456  */
2459  return false;
2460 }
2461 
2462 /**
2463  * Draws a series of line strips with adjacency information.
2464  */
2467  return false;
2468 }
2469 
2470 /**
2471  * Draws a series of disconnected points.
2472  */
2475  return false;
2476 }
2477 
2478 /**
2479  * Called after a sequence of draw_primitive() functions are called, this
2480  * should do whatever cleanup is appropriate.
2481  */
2484  _data_reader = nullptr;
2485 }
2486 
2487 /**
2488  * Resets all internal state as if the gsg were newly created.
2489  */
2491 reset() {
2492  _needs_reset = false;
2493  _is_valid = false;
2494 
2495  _state_rs = RenderState::make_empty();
2496  _target_rs = nullptr;
2497  _state_mask.clear();
2498  _internal_transform = _cs_transform;
2499  _scene_null = new SceneSetup;
2500  _scene_setup = _scene_null;
2501 
2502  _color_write_mask = ColorWriteAttrib::C_all;
2503 
2504  _has_scene_graph_color = false;
2505  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2506  _transform_stale = true;
2507  _color_blend_involves_color_scale = false;
2508  _texture_involves_color_scale = false;
2509  _vertex_colors_enabled = true;
2510  _lighting_enabled = false;
2511  _num_lights_enabled = 0;
2512  _num_clip_planes_enabled = 0;
2513  _clip_planes_enabled = false;
2514 
2515  _color_scale_enabled = false;
2516  _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2517  _has_texture_alpha_scale = false;
2518 
2519  _has_material_force_color = false;
2520  _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2521  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2522 
2523  _tex_gen_modifies_mat = false;
2524  _last_max_stage_index = 0;
2525 
2526  _is_valid = true;
2527 }
2528 
2529 /**
2530  * Simultaneously resets the render state and the transform state.
2531  *
2532  * This transform specified is the "internal" net transform, already converted
2533  * into the GSG's internal coordinate space by composing it to
2534  * get_cs_transform(). (Previously, this used to be the "external" net
2535  * transform, with the assumption that that GSG would convert it internally,
2536  * but that is no longer the case.)
2537  *
2538  * Special case: if (state==NULL), then the target state is already stored in
2539  * _target.
2540  */
2543  const TransformState *trans) {
2544 }
2545 
2546 /**
2547  * Clears the framebuffer within the current DisplayRegion, according to the
2548  * flags indicated by the given DrawableRegion object.
2549  *
2550  * This does not set the DisplayRegion first. You should call
2551  * prepare_display_region() to specify the region you wish the clear operation
2552  * to apply to.
2553  */
2555 clear(DrawableRegion *clearable) {
2556 }
2557 
2558 /**
2559  * Returns a RenderBuffer object suitable for operating on the requested set
2560  * of buffers. buffer_type is the union of all the desired RenderBuffer::Type
2561  * values.
2562  */
2564 get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
2565  return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
2566 }
2567 
2568 /**
2569  * Returns what the cs_transform would be set to after a call to
2570  * set_coordinate_system(cs). This is another way of saying the cs_transform
2571  * when rendering the scene for a camera with the indicated coordinate system.
2572  */
2573 CPT(TransformState) GraphicsStateGuardian::
2574 get_cs_transform_for(CoordinateSystem cs) const {
2575  if (_coordinate_system == cs) {
2576  // We've already calculated this.
2577  return _cs_transform;
2578 
2579  } else if (_internal_coordinate_system == CS_default ||
2580  _internal_coordinate_system == cs) {
2581  return TransformState::make_identity();
2582 
2583  } else {
2584  return TransformState::make_mat
2585  (LMatrix4::convert_mat(cs, _internal_coordinate_system));
2586  }
2587 }
2588 
2589 /**
2590  * Returns a transform that converts from the GSG's external coordinate system
2591  * (as returned by get_coordinate_system()) to its internal coordinate system
2592  * (as returned by get_internal_coordinate_system()). This is used for
2593  * rendering.
2594  */
2595 CPT(TransformState) GraphicsStateGuardian::
2596 get_cs_transform() const {
2597  return _cs_transform;
2598 }
2599 
2600 /**
2601  * This is fundametically similar to do_issue_light(), with calls to
2602  * apply_clip_plane() and enable_clip_planes(), as appropriate.
2603  */
2604 void GraphicsStateGuardian::
2605 do_issue_clip_plane() {
2606  int num_enabled = 0;
2607  int num_on_planes = 0;
2608 
2609  const ClipPlaneAttrib *target_clip_plane = (const ClipPlaneAttrib *)
2610  _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot());
2611 
2612  if (target_clip_plane != nullptr) {
2613  CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
2614 
2615  num_on_planes = new_plane->get_num_on_planes();
2616  for (int li = 0; li < num_on_planes; li++) {
2617  NodePath plane = new_plane->get_on_plane(li);
2618  nassertv(!plane.is_empty());
2619  PlaneNode *plane_node;
2620  DCAST_INTO_V(plane_node, plane.node());
2621  if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) {
2622  // Clipping should be enabled before we apply any planes.
2623  if (!_clip_planes_enabled) {
2624  enable_clip_planes(true);
2625  _clip_planes_enabled = true;
2626  }
2627 
2628  enable_clip_plane(num_enabled, true);
2629  if (num_enabled == 0) {
2630  begin_bind_clip_planes();
2631  }
2632 
2633  bind_clip_plane(plane, num_enabled);
2634  num_enabled++;
2635  }
2636  }
2637  }
2638 
2639  int i;
2640  for (i = num_enabled; i < _num_clip_planes_enabled; ++i) {
2641  enable_clip_plane(i, false);
2642  }
2643  _num_clip_planes_enabled = num_enabled;
2644 
2645  // If no planes were set, disable clipping
2646  if (num_enabled == 0) {
2647  if (_clip_planes_enabled) {
2648  enable_clip_planes(false);
2649  _clip_planes_enabled = false;
2650  }
2651  } else {
2652  end_bind_clip_planes();
2653  }
2654 }
2655 
2656 /**
2657  * This method is defined in the base class because it is likely that this
2658  * functionality will be used for all (or at least most) kinds of
2659  * GraphicsStateGuardians--it's not specific to any one rendering backend.
2660  *
2661  * The ColorAttribute just changes the interpretation of the color on the
2662  * vertices, and fiddles with _vertex_colors_enabled, etc.
2663  */
2665 do_issue_color() {
2666  const ColorAttrib *target_color = (const ColorAttrib *)
2667  _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
2668 
2669  switch (target_color->get_color_type()) {
2670  case ColorAttrib::T_flat:
2671  // Color attribute flat: it specifies a scene graph color that overrides
2672  // the vertex color.
2673  _scene_graph_color = target_color->get_color();
2674  _has_scene_graph_color = true;
2675  _vertex_colors_enabled = false;
2676  break;
2677 
2678  case ColorAttrib::T_off:
2679  // Color attribute off: it specifies that no scene graph color is in
2680  // effect, and vertex color is not important either.
2681  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2682  _has_scene_graph_color = false;
2683  _vertex_colors_enabled = false;
2684  break;
2685 
2686  case ColorAttrib::T_vertex:
2687  // Color attribute vertex: it specifies that vertex color should be
2688  // revealed.
2689  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2690  _has_scene_graph_color = false;
2691  _vertex_colors_enabled = true;
2692  break;
2693  }
2694 
2695  if (_color_scale_via_lighting) {
2696  _state_mask.clear_bit(LightAttrib::get_class_slot());
2697  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2698 
2699  determine_light_color_scale();
2700  }
2701 }
2702 
2703 /**
2704  *
2705  */
2706 void GraphicsStateGuardian::
2707 do_issue_color_scale() {
2708  // If the previous color scale had set a special texture, clear the texture
2709  // now.
2710  if (_has_texture_alpha_scale) {
2711  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2712  }
2713 
2714  const ColorScaleAttrib *target_color_scale = (const ColorScaleAttrib *)
2715  _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
2716 
2717  _color_scale_enabled = target_color_scale->has_scale();
2718  _current_color_scale = target_color_scale->get_scale();
2719  _has_texture_alpha_scale = false;
2720 
2721  if (_color_blend_involves_color_scale) {
2722  _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
2723  }
2724  if (_texture_involves_color_scale) {
2725  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2726  }
2727  if (_color_scale_via_lighting) {
2728  _state_mask.clear_bit(LightAttrib::get_class_slot());
2729  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2730 
2731  determine_light_color_scale();
2732  }
2733 
2734  if (_alpha_scale_via_texture && !_has_scene_graph_color &&
2735  _vertex_colors_enabled && target_color_scale->has_alpha_scale()) {
2736  // This color scale will set a special texture--so again, clear the
2737  // texture.
2738  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2739  _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
2740 
2741  _has_texture_alpha_scale = true;
2742  }
2743 }
2744 
2745 /**
2746  * This implementation of do_issue_light() assumes we have a limited number of
2747  * hardware lights available. This function assigns each light to a different
2748  * hardware light id, trying to keep each light associated with the same id
2749  * where possible, but reusing id's when necessary. When it is no longer
2750  * possible to reuse existing id's (e.g. all id's are in use), the next
2751  * sequential id is assigned (if available).
2752  *
2753  * It will call apply_light() each time a light is assigned to a particular id
2754  * for the first time in a given frame, and it will subsequently call
2755  * enable_light() to enable or disable each light as the frame is rendered, as
2756  * well as enable_lighting() to enable or disable overall lighting.
2757  */
2759 do_issue_light() {
2760  // Initialize the current ambient light total and newly enabled light list
2761  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
2762  int i;
2763 
2764  int num_enabled = 0;
2765  bool any_on_lights = false;
2766 
2767  const LightAttrib *target_light;
2768  _target_rs->get_attrib_def(target_light);
2769 
2770  if (display_cat.is_spam()) {
2771  display_cat.spam()
2772  << "do_issue_light: " << target_light << "\n";
2773  }
2774  if (target_light != nullptr) {
2775  // LightAttrib guarantees that the on lights are sorted, and that
2776  // non-ambient lights come before ambient lights.
2777  any_on_lights = target_light->has_any_on_light();
2778  size_t filtered_lights = std::min((size_t)_max_lights, target_light->get_num_non_ambient_lights());
2779  for (size_t li = 0; li < filtered_lights; ++li) {
2780  NodePath light = target_light->get_on_light(li);
2781  nassertv(!light.is_empty());
2782  Light *light_obj = light.node()->as_light();
2783  nassertv(light_obj != nullptr);
2784 
2785  // Lighting should be enabled before we apply any lights.
2786  if (!_lighting_enabled) {
2787  enable_lighting(true);
2788  _lighting_enabled = true;
2789  }
2790 
2791  const LColor &color = light_obj->get_color();
2792  // Don't bother binding the light if it has no color to contribute.
2793  if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
2794  enable_light(num_enabled, true);
2795  if (num_enabled == 0) {
2796  begin_bind_lights();
2797  }
2798 
2799  light_obj->bind(this, light, num_enabled);
2800  num_enabled++;
2801  }
2802  }
2803  }
2804 
2805  for (i = num_enabled; i < _num_lights_enabled; ++i) {
2806  enable_light(i, false);
2807  }
2808  _num_lights_enabled = num_enabled;
2809 
2810  // If no lights were set, disable lighting
2811  if (!any_on_lights) {
2812  if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f))) {
2813  // Unless we need lighting anyway to apply a color or color scale.
2814  if (!_lighting_enabled) {
2815  enable_lighting(true);
2816  _lighting_enabled = true;
2817  }
2818  set_ambient_light(LColor(1.0f, 1.0f, 1.0f, 1.0f));
2819 
2820  } else {
2821  if (_lighting_enabled) {
2822  enable_lighting(false);
2823  _lighting_enabled = false;
2824  }
2825  }
2826 
2827  } else {
2828  // Don't forget to still enable lighting if we have only an ambient light.
2829  if (!_lighting_enabled) {
2830  enable_lighting(true);
2831  _lighting_enabled = true;
2832  }
2833 
2834  set_ambient_light(target_light->get_ambient_contribution());
2835  }
2836 
2837  if (num_enabled != 0) {
2838  end_bind_lights();
2839  }
2840 }
2841 
2842 /**
2843  * Copy the pixels within the indicated display region from the framebuffer
2844  * into texture memory.
2845  *
2846  * If z > -1, it is the cube map index into which to copy.
2847  */
2850  const RenderBuffer &) {
2851  return false;
2852 }
2853 
2854 
2855 /**
2856  * Copy the pixels within the indicated display region from the framebuffer
2857  * into system memory, not texture memory. Returns true on success, false on
2858  * failure.
2859  *
2860  * This completely redefines the ram image of the indicated texture.
2861  */
2863 framebuffer_copy_to_ram(Texture *, int, int, const DisplayRegion *,
2864  const RenderBuffer &) {
2865  return false;
2866 }
2867 
2868 /**
2869  * Called the first time a particular light has been bound to a given id
2870  * within a frame, this should set up the associated hardware light with the
2871  * light's properties.
2872  */
2874 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
2875 }
2876 
2877 /**
2878  * Called the first time a particular light has been bound to a given id
2879  * within a frame, this should set up the associated hardware light with the
2880  * light's properties.
2881  */
2883 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
2884 }
2885 
2886 /**
2887  * Called the first time a particular light has been bound to a given id
2888  * within a frame, this should set up the associated hardware light with the
2889  * light's properties.
2890  */
2892 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
2893 }
2894 
2895 #ifdef DO_PSTATS
2896 /**
2897  * Initializes the relevant PStats data at the beginning of the frame.
2898  */
2899 void GraphicsStateGuardian::
2900 init_frame_pstats() {
2901  if (PStatClient::is_connected()) {
2902  _data_transferred_pcollector.clear_level();
2903  _vertex_buffer_switch_pcollector.clear_level();
2904  _index_buffer_switch_pcollector.clear_level();
2905 
2906  _primitive_batches_pcollector.clear_level();
2907  _primitive_batches_tristrip_pcollector.clear_level();
2908  _primitive_batches_trifan_pcollector.clear_level();
2909  _primitive_batches_tri_pcollector.clear_level();
2910  _primitive_batches_patch_pcollector.clear_level();
2911  _primitive_batches_other_pcollector.clear_level();
2912  _vertices_tristrip_pcollector.clear_level();
2913  _vertices_trifan_pcollector.clear_level();
2914  _vertices_tri_pcollector.clear_level();
2915  _vertices_patch_pcollector.clear_level();
2916  _vertices_other_pcollector.clear_level();
2917 
2918  _state_pcollector.clear_level();
2919  _transform_state_pcollector.clear_level();
2920  _texture_state_pcollector.clear_level();
2921  }
2922 }
2923 #endif // DO_PSTATS
2924 
2925 
2926 /**
2927  * Create a gamma table.
2928  */
2930 create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
2931  int i;
2932 
2933  if (gamma <= 0.0) {
2934  // avoid divide by zero and negative exponents
2935  gamma = 1.0;
2936  }
2937 
2938  for (i = 0; i < 256; i++) {
2939  double g;
2940  double x;
2941  PN_stdfloat gamma_correction;
2942 
2943  x = ((double) i / 255.0);
2944  gamma_correction = 1.0 / gamma;
2945  x = pow (x, (double) gamma_correction);
2946  if (x > 1.00) {
2947  x = 1.0;
2948  }
2949 
2950  g = x * 65535.0;
2951  red_table [i] = (int)g;
2952  green_table [i] = (int)g;
2953  blue_table [i] = (int)g;
2954  }
2955 }
2956 
2957 /**
2958  * Called by clear_state_and_transform() to ensure that the current modelview
2959  * and projection matrices are properly loaded in the graphics state, after a
2960  * callback might have mucked them up.
2961  */
2962 void GraphicsStateGuardian::
2963 reissue_transforms() {
2964 }
2965 
2966 /**
2967  * Intended to be overridden by a derived class to enable or disable the use
2968  * of lighting overall. This is called by do_issue_light() according to
2969  * whether any lights are in use or not.
2970  */
2971 void GraphicsStateGuardian::
2972 enable_lighting(bool enable) {
2973 }
2974 
2975 /**
2976  * Intended to be overridden by a derived class to indicate the color of the
2977  * ambient light that should be in effect. This is called by do_issue_light()
2978  * after all other lights have been enabled or disabled.
2979  */
2980 void GraphicsStateGuardian::
2981 set_ambient_light(const LColor &color) {
2982 }
2983 
2984 /**
2985  * Intended to be overridden by a derived class to enable the indicated light
2986  * id. A specific Light will already have been bound to this id via
2987  * bind_light().
2988  */
2989 void GraphicsStateGuardian::
2990 enable_light(int light_id, bool enable) {
2991 }
2992 
2993 /**
2994  * Called immediately before bind_light() is called, this is intended to
2995  * provide the derived class a hook in which to set up some state (like
2996  * transform) that might apply to several lights.
2997  *
2998  * The sequence is: begin_bind_lights() will be called, then one or more
2999  * bind_light() calls, then end_bind_lights().
3000  */
3001 void GraphicsStateGuardian::
3002 begin_bind_lights() {
3003 }
3004 
3005 /**
3006  * Called after before bind_light() has been called one or more times (but
3007  * before any geometry is issued or additional state is changed), this is
3008  * intended to clean up any temporary changes to the state that may have been
3009  * made by begin_bind_lights().
3010  */
3011 void GraphicsStateGuardian::
3012 end_bind_lights() {
3013 }
3014 
3015 /**
3016  * Intended to be overridden by a derived class to enable or disable the use
3017  * of clipping planes overall. This is called by do_issue_clip_plane()
3018  * according to whether any planes are in use or not.
3019  */
3020 void GraphicsStateGuardian::
3021 enable_clip_planes(bool enable) {
3022 }
3023 
3024 /**
3025  * Intended to be overridden by a derived class to enable the indicated plane
3026  * id. A specific PlaneNode will already have been bound to this id via
3027  * bind_clip_plane().
3028  */
3029 void GraphicsStateGuardian::
3030 enable_clip_plane(int plane_id, bool enable) {
3031 }
3032 
3033 /**
3034  * Called immediately before bind_clip_plane() is called, this is intended to
3035  * provide the derived class a hook in which to set up some state (like
3036  * transform) that might apply to several planes.
3037  *
3038  * The sequence is: begin_bind_clip_planes() will be called, then one or more
3039  * bind_clip_plane() calls, then end_bind_clip_planes().
3040  */
3041 void GraphicsStateGuardian::
3042 begin_bind_clip_planes() {
3043 }
3044 
3045 /**
3046  * Called the first time a particular clipping plane has been bound to a given
3047  * id within a frame, this should set up the associated hardware (or API)
3048  * clipping plane with the plane's properties.
3049  */
3050 void GraphicsStateGuardian::
3051 bind_clip_plane(const NodePath &plane, int plane_id) {
3052 }
3053 
3054 /**
3055  * Called after before bind_clip_plane() has been called one or more times
3056  * (but before any geometry is issued or additional state is changed), this is
3057  * intended to clean up any temporary changes to the state that may have been
3058  * made by begin_bind_clip_planes().
3059  */
3060 void GraphicsStateGuardian::
3061 end_bind_clip_planes() {
3062 }
3063 
3064 /**
3065  * Assigns _target_texture and _target_tex_gen based on the _target_rs.
3066  */
3067 void GraphicsStateGuardian::
3068 determine_target_texture() {
3069  const TextureAttrib *target_texture = (const TextureAttrib *)
3070  _target_rs->get_attrib_def(TextureAttrib::get_class_slot());
3071  const TexGenAttrib *target_tex_gen = (const TexGenAttrib *)
3072  _target_rs->get_attrib_def(TexGenAttrib::get_class_slot());
3073 
3074  nassertv(target_texture != nullptr &&
3075  target_tex_gen != nullptr);
3076  _target_texture = target_texture;
3077  _target_tex_gen = target_tex_gen;
3078 
3079  if (_has_texture_alpha_scale) {
3081  PT(Texture) texture = TexturePool::get_alpha_scale_map();
3082 
3083  _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
3084  _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
3085  (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
3086  }
3087 
3088  int max_texture_stages = get_max_texture_stages();
3089  _target_texture = _target_texture->filter_to_max(max_texture_stages);
3090  nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
3091 }
3092 
3093 /**
3094  * Assigns _target_shader based on the _target_rs.
3095  */
3096 void GraphicsStateGuardian::
3097 determine_target_shader() {
3098  if (_target_rs->_generated_shader != nullptr) {
3099  _target_shader = (const ShaderAttrib *)_target_rs->_generated_shader.p();
3100  } else {
3101  _target_shader = (const ShaderAttrib *)
3102  _target_rs->get_attrib_def(ShaderAttrib::get_class_slot());
3103  }
3104 }
3105 
3106 /**
3107  * Frees some memory that was explicitly allocated within the glgsg.
3108  */
3109 void GraphicsStateGuardian::
3110 free_pointers() {
3111 }
3112 
3113 /**
3114  * This is called by the associated GraphicsWindow when close_window() is
3115  * called. It should null out the _win pointer and possibly free any open
3116  * resources associated with the GSG.
3117  */
3118 void GraphicsStateGuardian::
3119 close_gsg() {
3120  // Protect from multiple calls, and also inform any other functions not to
3121  // try to create new stuff while we're going down.
3122  if (_closing_gsg) {
3123  return;
3124  }
3125  _closing_gsg = true;
3126 
3127  if (display_cat.is_debug()) {
3128  display_cat.debug()
3129  << this << " close_gsg " << get_type() << "\n";
3130  }
3131 
3132  // As tempting as it may be to try to release all the textures and geoms
3133  // now, we can't, because we might not be the currently-active GSG (this is
3134  // particularly important in OpenGL, which maintains one currently-active GL
3135  // state in each thread). If we start deleting textures, we'll be
3136  // inadvertently deleting textures from some other OpenGL state.
3137 
3138  // Fortunately, it doesn't really matter, since the graphics API will be
3139  // responsible for cleaning up anything we don't clean up explicitly. We'll
3140  // just let them drop.
3141 
3142  // Make sure that all the contexts belonging to the GSG are deleted.
3143  _prepared_objects.clear();
3144 #ifdef DO_PSTATS
3145  _pending_timer_queries.clear();
3146 #endif
3147 
3148  free_pointers();
3149 }
3150 
3151 /**
3152  * This is called internally when it is determined that things are just fubar.
3153  * It temporarily deactivates the GSG just so things don't get out of hand,
3154  * and throws an event so the application can deal with this if it needs to.
3155  */
3156 void GraphicsStateGuardian::
3157 panic_deactivate() {
3158  if (_active) {
3159  display_cat.error()
3160  << "Deactivating " << get_type() << ".\n";
3161  set_active(false);
3162  throw_event("panic-deactivate-gsg", this);
3163  }
3164 }
3165 
3166 /**
3167  * Called whenever the color or color scale is changed, if
3168  * _color_scale_via_lighting is true. This will rederive
3169  * _material_force_color and _light_color_scale appropriately.
3170  */
3171 void GraphicsStateGuardian::
3172 determine_light_color_scale() {
3173  if (_has_scene_graph_color) {
3174  // If we have a scene graph color, it, plus the color scale, goes directly
3175  // into the material; we don't color scale the lights--this allows an
3176  // alpha color scale to work properly.
3177  _has_material_force_color = true;
3178  _material_force_color = _scene_graph_color;
3179  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3180  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3181  _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
3182  _scene_graph_color[1] * _current_color_scale[1],
3183  _scene_graph_color[2] * _current_color_scale[2],
3184  _scene_graph_color[3] * _current_color_scale[3]);
3185  }
3186 
3187  } else if (!_vertex_colors_enabled) {
3188  // We don't have a scene graph color, but we don't want to enable vertex
3189  // colors either, so we still need to force a white material color in
3190  // absence of any other color.
3191  _has_material_force_color = true;
3192  _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
3193  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3194  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3195  _material_force_color.componentwise_mult(_current_color_scale);
3196  }
3197 
3198  } else {
3199  // Otherise, leave the materials alone, but we might still scale the
3200  // lights.
3201  _has_material_force_color = false;
3202  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3203  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3204  _light_color_scale = _current_color_scale;
3205  }
3206  }
3207 }
3208 
3209 /**
3210  *
3211  */
3212 CPT(RenderState) GraphicsStateGuardian::
3213 get_unlit_state() {
3214  static CPT(RenderState) state = nullptr;
3215  if (state == nullptr) {
3216  state = RenderState::make(LightAttrib::make_all_off());
3217  }
3218  return state;
3219 }
3220 
3221 /**
3222  *
3223  */
3224 CPT(RenderState) GraphicsStateGuardian::
3225 get_unclipped_state() {
3226  static CPT(RenderState) state = nullptr;
3227  if (state == nullptr) {
3228  state = RenderState::make(ClipPlaneAttrib::make_all_off());
3229  }
3230  return state;
3231 }
3232 
3233 /**
3234  *
3235  */
3236 CPT(RenderState) GraphicsStateGuardian::
3237 get_untextured_state() {
3238  static CPT(RenderState) state = nullptr;
3239  if (state == nullptr) {
3240  state = RenderState::make(TextureAttrib::make_off());
3241  }
3242  return state;
3243 }
3244 
3245 /**
3246  * Should be called when a texture is encountered that needs to have its RAM
3247  * image reloaded, and get_incomplete_render() is true. This will fire off a
3248  * thread on the current Loader object that will request the texture to load
3249  * its image. The image will be available at some point in the future.
3250  * @returns a future object that can be used to check its status.
3251  */
3252 AsyncFuture *GraphicsStateGuardian::
3253 async_reload_texture(TextureContext *tc) {
3254  nassertr(_loader != nullptr, nullptr);
3255 
3256  int priority = 0;
3257  if (_current_display_region != nullptr) {
3258  priority = _current_display_region->get_texture_reload_priority();
3259  }
3260 
3261  string task_name = string("reload:") + tc->get_texture()->get_name();
3262  PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
3263 
3264  // See if we are already loading this task.
3265  AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
3266  size_t num_tasks = orig_tasks.get_num_tasks();
3267  for (size_t ti = 0; ti < num_tasks; ++ti) {
3268  AsyncTask *task = orig_tasks.get_task(ti);
3269  if (task->is_exact_type(TextureReloadRequest::get_class_type()) &&
3270  ((TextureReloadRequest *)task)->get_texture() == tc->get_texture()) {
3271  // This texture is already queued to be reloaded. Don't queue it again,
3272  // just make sure the priority is updated, and return.
3273  task->set_priority(std::max(task->get_priority(), priority));
3274  return (AsyncFuture *)task;
3275  }
3276  }
3277 
3278  // This texture has not yet been queued to be reloaded. Queue it up now.
3279  PT(AsyncTask) request =
3280  new TextureReloadRequest(task_name,
3281  _prepared_objects, tc->get_texture(),
3282  _supports_compressed_texture);
3283  request->set_priority(priority);
3284  _loader->load_async(request);
3285  return (AsyncFuture *)request.p();
3286 }
3287 
3288 /**
3289  * Returns a shadow map for the given light source. If none exists, it is
3290  * created, using the given host window to create the buffer, or the current
3291  * window if that is set to NULL.
3292  */
3293 PT(Texture) GraphicsStateGuardian::
3294 get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
3295  PandaNode *node = light_np.node();
3296  bool is_point = node->is_of_type(PointLight::get_class_type());
3297  nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
3298  node->is_of_type(Spotlight::get_class_type()) ||
3299  is_point, nullptr);
3300 
3301  LightLensNode *light = (LightLensNode *)node;
3302  if (light == nullptr || !light->_shadow_caster) {
3303  // This light does not have a shadow caster. Return a dummy shadow map
3304  // that is filled with a depth value of 1.
3305  if (node->is_of_type(PointLight::get_class_type())) {
3306  return get_dummy_shadow_map(Texture::TT_cube_map);
3307  } else {
3308  return get_dummy_shadow_map(Texture::TT_2d_texture);
3309  }
3310  }
3311 
3312  // The light's shadow map should have been created by set_shadow_caster().
3313  nassertr(light->_shadow_map != nullptr, nullptr);
3314 
3315  // See if we already have a buffer. If not, create one.
3316  if (light->_sbuffers.count(this) != 0) {
3317  // There's already a buffer - use that.
3318  return light->_shadow_map;
3319  }
3320 
3321  if (display_cat.is_debug()) {
3322  display_cat.debug()
3323  << "Constructing shadow buffer for light '" << light->get_name()
3324  << "', size=" << light->_sb_size[0] << "x" << light->_sb_size[1]
3325  << ", sort=" << light->_sb_sort << "\n";
3326  }
3327 
3328  if (host == nullptr) {
3329  nassertr(_current_display_region != nullptr, nullptr);
3330  host = _current_display_region->get_window();
3331  }
3332  nassertr(host != nullptr, nullptr);
3333 
3334  // Nope, the light doesn't have a buffer for our GSG. Make one.
3335  GraphicsOutput *sbuffer = make_shadow_buffer(light, light->_shadow_map,
3336  DCAST(GraphicsOutput, host));
3337 
3338  // Assign display region(s) to the buffer and camera
3339  if (is_point) {
3340  for (int i = 0; i < 6; ++i) {
3341  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3342  dr->set_lens_index(i);
3343  dr->set_target_tex_page(i);
3344  dr->set_camera(light_np);
3345  dr->set_clear_depth_active(true);
3346  }
3347  } else {
3348  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3349  dr->set_camera(light_np);
3350  dr->set_clear_depth_active(true);
3351  }
3352 
3353  light->_sbuffers[this] = sbuffer;
3354  return light->_shadow_map;
3355 }
3356 
3357 /**
3358  * Returns a dummy shadow map that can be used for a light of the given type
3359  * that does not cast shadows.
3360  */
3361 PT(Texture) GraphicsStateGuardian::
3362 get_dummy_shadow_map(Texture::TextureType texture_type) const {
3363  if (texture_type != Texture::TT_cube_map) {
3364  static PT(Texture) dummy_2d;
3365  if (dummy_2d == nullptr) {
3366  dummy_2d = new Texture("dummy-shadow-2d");
3367  dummy_2d->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_depth_component);
3368  dummy_2d->set_clear_color(1);
3370  // If we have the ARB_shadow extension, enable shadow filtering.
3371  dummy_2d->set_minfilter(SamplerState::FT_shadow);
3372  dummy_2d->set_magfilter(SamplerState::FT_shadow);
3373  } else {
3374  dummy_2d->set_minfilter(SamplerState::FT_linear);
3375  dummy_2d->set_magfilter(SamplerState::FT_linear);
3376  }
3377  }
3378  return dummy_2d;
3379  } else {
3380  static PT(Texture) dummy_cube;
3381  if (dummy_cube == nullptr) {
3382  dummy_cube = new Texture("dummy-shadow-cube");
3383  dummy_cube->setup_cube_map(1, Texture::T_unsigned_byte, Texture::F_depth_component);
3384  dummy_cube->set_clear_color(1);
3385  // Note: cube map shadow filtering doesn't seem to work in Cg.
3386  dummy_cube->set_minfilter(SamplerState::FT_linear);
3387  dummy_cube->set_magfilter(SamplerState::FT_linear);
3388  }
3389  return dummy_cube;
3390  }
3391 }
3392 
3393 /**
3394  * Creates a depth buffer for shadow mapping. A derived GSG can override this
3395  * if it knows that a particular buffer type works best for shadow rendering.
3396  */
3397 GraphicsOutput *GraphicsStateGuardian::
3398 make_shadow_buffer(LightLensNode *light, Texture *tex, GraphicsOutput *host) {
3399  bool is_point = light->is_of_type(PointLight::get_class_type());
3400 
3401  // Determine the properties for creating the depth buffer.
3403  fbp.set_depth_bits(shadow_depth_bits);
3404 
3405  WindowProperties props = WindowProperties::size(light->_sb_size);
3406  int flags = GraphicsPipe::BF_refuse_window;
3407  if (is_point) {
3408  flags |= GraphicsPipe::BF_size_square;
3409  }
3410 
3411  // Create the buffer. This is a bit tricky because make_output() can only
3412  // be called from the app thread, but it won't cause issues as long as the
3413  // pipe can precertify the buffer, which it can in most cases.
3415  light->get_name(), light->_sb_sort, fbp, props, flags, this, host);
3416 
3417  if (sbuffer != nullptr) {
3418  sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
3419  }
3420  return sbuffer;
3421 }
3422 
3423 /**
3424  * Ensures that an appropriate shader has been generated for the given state.
3425  * This is stored in the _generated_shader field on the RenderState.
3426  */
3428 ensure_generated_shader(const RenderState *state) {
3429 #ifdef HAVE_CG
3430  const ShaderAttrib *shader_attrib;
3431  state->get_attrib_def(shader_attrib);
3432 
3433  if (shader_attrib->auto_shader()) {
3434  if (_shader_generator == nullptr) {
3435  if (!_supports_basic_shaders) {
3436  return;
3437  }
3438  _shader_generator = new ShaderGenerator(this);
3439  }
3440  if (state->_generated_shader == nullptr ||
3441  state->_generated_shader_seq != _generated_shader_seq) {
3443 
3444  // Currently we overload this flag to request vertex animation for the
3445  // shader generator.
3446  const ShaderAttrib *sattr;
3447  state->get_attrib_def(sattr);
3448  if (sattr->get_flag(ShaderAttrib::F_hardware_skinning)) {
3449  spec.set_hardware(4, true);
3450  }
3451 
3452  // Cache the generated ShaderAttrib on the shader state.
3453  state->_generated_shader = _shader_generator->synthesize_shader(state, spec);
3454  state->_generated_shader_seq = _generated_shader_seq;
3455  }
3456  }
3457 #endif
3458 }
3459 
3460 /**
3461  * Returns true if the GSG implements the extension identified by the given
3462  * string. This currently is only implemented by the OpenGL back-end.
3463  */
3465 has_extension(const string &extension) const {
3466  return false;
3467 }
3468 
3469 /**
3470  * Returns the vendor of the video card driver
3471  */
3474  return string();
3475 }
3476 
3477 /**
3478  * Returns GL_Renderer
3479  */
3481  return string();
3482 }
3483 
3484 /**
3485  * Returns driver version This has an implementation-defined meaning, and may
3486  * be "" if the particular graphics implementation does not provide a way to
3487  * query this information.
3488  */
3491  return string();
3492 }
3493 
3494 /**
3495  * Returns major version of the video driver. This has an implementation-
3496  * defined meaning, and may be -1 if the particular graphics implementation
3497  * does not provide a way to query this information.
3498  */
3501  return -1;
3502 }
3503 
3504 /**
3505  * Returns the minor version of the video driver. This has an implementation-
3506  * defined meaning, and may be -1 if the particular graphics implementation
3507  * does not provide a way to query this information.
3508  */
3511  return -1;
3512 }
3513 
3514 /**
3515  * Returns the major version of the shader model.
3516  */
3519  return -1;
3520 }
3521 
3522 /**
3523  * Returns the minor version of the shader model.
3524  */
3527  return -1;
3528 }
3529 
3530 std::ostream &
3531 operator << (std::ostream &out, GraphicsStateGuardian::ShaderModel sm) {
3532  static const char *sm_strings[] = {"none", "1.1", "2.0", "2.x", "3.0", "4.0", "5.0", "5.1"};
3533  nassertr(sm >= 0 && sm <= GraphicsStateGuardian::SM_51, out);
3534  out << sm_strings[sm];
3535  return out;
3536 }
Geom
A container for geometry primitives.
Definition: geom.h:54
lightLensNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::get_z_size
get_z_size
Returns the depth of the texture image in texels.
Definition: texture.h:342
clipPlaneAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PreparedGraphicsObjects
A table of objects that are saved within the graphics context for reference by handle later.
Definition: preparedGraphicsObjects.h:58
Light::get_exponent
virtual PN_stdfloat get_exponent() const
For spotlights, returns the exponent that controls the amount of light falloff from the center of the...
Definition: light.cxx:137
GraphicsStateGuardian::release_index_buffer
virtual void release_index_buffer(IndexBufferContext *ibc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the IndexBu...
Definition: graphicsStateGuardian.cxx:684
geomTrifans.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
texturePool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::release_shader
virtual void release_shader(ShaderContext *sc)
Releases the resources allocated by prepare_shader.
Definition: graphicsStateGuardian.cxx:652
GraphicsEngine::remove_window
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
Definition: graphicsEngine.cxx:520
VertexBufferContext
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: vertexBufferContext.h:33
textureContext.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
shaderGenerator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_driver_version
get_driver_version
Returns driver version This has an implementation-defined meaning, and may be "" if the particular gr...
Definition: graphicsStateGuardian.h:282
GeomVertexArrayData
This is the data for one array of a GeomVertexData structure.
Definition: geomVertexArrayData.h:58
GraphicsOutput::add_render_texture
void add_render_texture(Texture *tex, RenderTextureMode mode, RenderTexturePlane bitplane=RTP_COUNT)
Creates a new Texture object, suitable for rendering the contents of this buffer into,...
Definition: graphicsOutput.cxx:237
GraphicsStateGuardian::draw_triangles
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles.
Definition: graphicsStateGuardian.cxx:2392
ClipPlaneAttrib
This functions similarly to a LightAttrib.
Definition: clipPlaneAttrib.h:31
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Lens::get_projection_mat
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film,...
Definition: lens.I:563
TextureStage::get_color
get_color
return the color for this stage
Definition: textureStage.h:198
GraphicsOutput::make_mono_display_region
DisplayRegion * make_mono_display_region()
Creates a new DisplayRegion that covers the entire window.
Definition: graphicsOutput.I:541
FrameBufferProperties::get_buffer_mask
int get_buffer_mask() const
Converts the non-aux bitplanes of the framebuffer into a RenderBuffer::Type.
Definition: frameBufferProperties.cxx:305
GraphicsStateGuardian::set_state_and_transform
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
Definition: graphicsStateGuardian.cxx:2542
Shader
Definition: shader.h:49
stateMunger.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AsyncTaskCollection::get_num_tasks
get_num_tasks
Returns the number of AsyncTasks in the collection.
Definition: asyncTaskCollection.h:46
GraphicsOutput::get_right_eye_color_mask
unsigned int get_right_eye_color_mask() const
Returns the color mask in effect when rendering a right-eye view in red_blue stereo mode.
Definition: graphicsOutput.I:376
GraphicsStateGuardian::get_pipe
get_pipe
Returns the graphics pipe on which this GSG was created.
Definition: graphicsStateGuardian.h:117
Lens::get_nodal_point
get_nodal_point
Returns the center point of the lens: the point from which the lens is viewing.
Definition: lens.h:129
GraphicsStateGuardian::do_issue_light
virtual void do_issue_light()
This implementation of do_issue_light() assumes we have a limited number of hardware lights available...
Definition: graphicsStateGuardian.cxx:2759
PStatThread::add_frame
void add_frame(const PStatFrameData &frame_data)
This is a slightly lower-level version of new_frame that also specifies the data to send for this fra...
Definition: pStatThread.cxx:38
colorWriteAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_supports_multisample
get_supports_multisample
Returns true if this particular GSG supports using the multisample bits to provide antialiasing,...
Definition: graphicsStateGuardian.h:203
DirectionalLight::get_direction
get_direction
Returns the direction in which the light is aimed.
Definition: directionalLight.h:53
GraphicsStateGuardian::end_draw_primitives
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
Definition: graphicsStateGuardian.cxx:2483
ReMutexHolder
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:25
PandaNode::is_ambient_light
virtual bool is_ambient_light() const
Returns true if this is an AmbientLight, false if it is not a light, or it is some other kind of ligh...
Definition: pandaNode.cxx:2104
SimpleHashMap::get_data
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
Definition: simpleHashMap.I:387
GraphicsStateGuardian::set_flash_texture
set_flash_texture
Sets the "flash texture".
Definition: graphicsStateGuardian.h:266
GraphicsStateGuardian::draw_lines_adj
virtual bool draw_lines_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments with adjacency information.
Definition: graphicsStateGuardian.cxx:2450
Lens::is_linear
virtual bool is_linear() const
Returns true if the lens represents a linear projection (e.g.
Definition: lens.cxx:540
geomMunger.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClipPlaneAttrib::get_num_on_planes
get_num_on_planes
Returns the number of planes that are enabled by the attribute.
Definition: clipPlaneAttrib.h:74
GraphicsOutput::get_left_eye_color_mask
unsigned int get_left_eye_color_mask() const
Returns the color mask in effect when rendering a left-eye view in red_blue stereo mode.
Definition: graphicsOutput.I:366
Spotlight::get_specular_color
get_specular_color
Returns the color of specular highlights generated by the light.
Definition: spotlight.h:56
AsyncTaskCollection
A list of tasks, for instance as returned by some of the AsyncTaskManager query functions.
Definition: asyncTaskCollection.h:27
GraphicsStateGuardian::bind_light
virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id)
Called the first time a particular light has been bound to a given id within a frame,...
Definition: graphicsStateGuardian.cxx:2874
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
Fog::get_color
get_color
Returns the color of the fog.
Definition: fog.h:68
RenderBuffer
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
Definition: renderBuffer.h:27
GraphicsStateGuardian::clear
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
Definition: graphicsStateGuardian.cxx:2555
AsyncTask::set_priority
set_priority
Specifies a priority value for this task.
Definition: asyncTask.h:116
GraphicsEngine::make_output
GraphicsOutput * make_output(GraphicsPipe *pipe, const std::string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=nullptr, GraphicsOutput *host=nullptr)
Creates a new window (or buffer) and returns it.
Definition: graphicsEngine.cxx:257
IndexBufferContext
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: indexBufferContext.h:33
GraphicsStateGuardian::reset
virtual void reset()
Resets all internal state as if the gsg were newly created.
Definition: graphicsStateGuardian.cxx:2491
ShaderAttrib::auto_shader
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Definition: shaderAttrib.I:71
PointLight
A light originating from a single point in space, and shining in all directions.
Definition: pointLight.h:25
GraphicsStateGuardian::do_issue_color
void do_issue_color()
This method is defined in the base class because it is likely that this functionality will be used fo...
Definition: graphicsStateGuardian.cxx:2665
GraphicsStateGuardian::framebuffer_copy_to_texture
virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into texture memory.
Definition: graphicsStateGuardian.cxx:2849
TextureAttrib::get_on_texture
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
Definition: textureAttrib.h:69
Material
Defines the way an object appears in the presence of lighting.
Definition: material.h:43
GraphicsStateGuardian::draw_trifans
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle fans.
Definition: graphicsStateGuardian.cxx:2425
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_driver_shader_version_minor
get_driver_shader_version_minor
Returns the minor version of the shader model.
Definition: graphicsStateGuardian.h:286
GraphicsStateGuardian::draw_linestrips_adj
virtual bool draw_linestrips_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of line strips with adjacency information.
Definition: graphicsStateGuardian.cxx:2466
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DirectionalLight::get_specular_color
get_specular_color
Returns the color of specular highlights generated by the light.
Definition: directionalLight.h:45
SimpleHashMap::remove
bool remove(const Key &key)
Removes the indicated key and its associated data from the table.
Definition: simpleHashMap.I:254
TimerQueryContext
Definition: timerQueryContext.h:25
GraphicsStateGuardian::get_engine
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
Definition: graphicsStateGuardian.cxx:318
ClockObject::get_global_clock
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
GraphicsStateGuardian::begin_draw_primitives
virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomVertexDataPipelineReader *data_reader, bool force)
Called before a sequence of draw_primitive() functions are called, this should prepare the vertex dat...
Definition: graphicsStateGuardian.cxx:2378
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ShaderBuffer
This is a generic buffer object that lives in graphics memory.
Definition: shaderBuffer.h:33
SamplerContext
This is a special class object that holds a handle to the sampler state object given by the graphics ...
Definition: samplerContext.h:34
graphicsEngine.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatCollectorDef
Defines the details about the Collectors: the name, the suggested color, etc.
Definition: pStatCollectorDef.h:29
PointLight::get_specular_color
get_specular_color
Returns the color of specular highlights generated by the light.
Definition: pointLight.h:45
SimpleHashMap::get_key
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
Definition: simpleHashMap.I:375
Lens::get_projection_mat_inv
const LMatrix4 & get_projection_mat_inv(StereoChannel channel=SC_mono) const
Returns the matrix that transforms from a 2-d point on the film to a 3-d vector in space,...
Definition: lens.I:573
DisplayRegion
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
ShaderAttrib
Definition: shaderAttrib.h:39
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
FogAttrib
Applies a Fog to the geometry at and below this node.
Definition: fogAttrib.h:25
MaterialAttrib::is_off
bool is_off() const
Returns true if the MaterialAttrib is an 'off' MaterialAttrib, indicating that it should disable the ...
Definition: materialAttrib.I:26
GraphicsStateGuardian::get_gamma
get_gamma
Get the current gamma setting.
Definition: graphicsStateGuardian.h:251
TransformState::get_mat
get_mat
Returns the matrix that describes the transform.
Definition: transformState.h:156
NodePath::get_transform
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Definition: nodePath.cxx:758
InternalName::get_basename
get_basename
Return the name represented by just this particular InternalName object, ignoring its parents names.
Definition: internalName.h:62
GraphicsStateGuardian::draw_lines
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments.
Definition: graphicsStateGuardian.cxx:2442
Texture
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
Texture::get_x_size
get_x_size
Returns the width of the texture image in texels.
Definition: texture.h:334
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
AsyncTask::get_priority
get_priority
Returns the task's current priority value.
Definition: asyncTask.h:116
GeomVertexAnimationSpec::set_hardware
void set_hardware(int num_transforms, bool indexed_transforms)
Specifies that vertex animation is to be performed by the graphics hardware (or at least by the graph...
Definition: geomVertexAnimationSpec.I:102
GraphicsOutput::get_swap_eyes
get_swap_eyes
Returns the current setting of the "swap eyes" flag.
Definition: graphicsOutput.h:167
BitMask::clear
void clear()
Sets all the bits in the BitMask off.
Definition: bitMask.I:395
Material::get_specular
get_specular
Returns the specular color setting, if it has been set.
Definition: material.h:118
Lens::get_hfov
PN_stdfloat get_hfov() const
Returns the horizontal component of fov only.
Definition: lens.I:344
Light
The abstract interface to all kinds of lights.
Definition: light.h:38
TextureContext::get_texture
Texture * get_texture() const
Returns the pointer to the associated Texture object.
Definition: textureContext.I:29
GraphicsStateGuardian::get_supported_geom_rendering
virtual int get_supported_geom_rendering() const
Returns the union of Geom::GeomRendering values that this particular GSG can support directly.
Definition: graphicsStateGuardian.cxx:347
GeomContext
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: geomContext.h:34
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
Light::get_attenuation
virtual const LVecBase3 & get_attenuation() const
Returns the terms of the attenuation equation for the light.
Definition: light.cxx:157
GraphicsStateGuardian::get_supports_cg_profile
virtual bool get_supports_cg_profile(const std::string &name) const
Returns true if this particular GSG supports the specified Cg Shader Profile.
Definition: graphicsStateGuardian.cxx:356
GraphicsStateGuardian::get_render_buffer
RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop)
Returns a RenderBuffer object suitable for operating on the requested set of buffers.
Definition: graphicsStateGuardian.cxx:2564
SimpleHashMap< size_t, PT(GeomMunger), size_t_hash >
textureReloadRequest.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_scene
get_scene
Returns the current SceneSetup object.
Definition: graphicsStateGuardian.h:290
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AsyncFuture
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
Definition: asyncFuture.h:61
Lens::get_coordinate_system
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Definition: lens.h:74
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
GraphicsStateGuardian::draw_linestrips
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of line strips.
Definition: graphicsStateGuardian.cxx:2458
GraphicsStateGuardian::begin_frame
virtual bool begin_frame(Thread *current_thread)
Called before each frame is rendered, to allow the GSG a chance to do any internal cleanup before beg...
Definition: graphicsStateGuardian.cxx:2044
GraphicsStateGuardian::end_frame
virtual void end_frame(Thread *current_thread)
Called after each frame is rendered, to allow the GSG a chance to do any internal cleanup after rende...
Definition: graphicsStateGuardian.cxx:2135
Material::get_refractive_index
get_refractive_index
Returns the index of refraction, or 1 if none has been set for this material.
Definition: material.h:126
indexBufferContext.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SceneSetup
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
AmbientLight
A light source that seems to illuminate all points in space at once.
Definition: ambientLight.h:26
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Fog::get_exp_density
get_exp_density
Returns the density of the fog for exponential calculations.
Definition: fog.h:86
light.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
materialAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::fetch_specified_member
const LMatrix4 * fetch_specified_member(const NodePath &np, CPT_InternalName member, LMatrix4 &t)
Given a NodePath passed into a shader input that is a structure, fetches the value for the given memb...
Definition: graphicsStateGuardian.cxx:1510
GraphicsStateGuardian::prepare_texture
virtual TextureContext * prepare_texture(Texture *tex, int view)
Creates whatever structures the GSG requires to represent the texture internally, and returns a newly...
Definition: graphicsStateGuardian.cxx:555
Spotlight::get_attenuation
get_attenuation
Returns the terms of the attenuation equation for the light.
Definition: spotlight.h:60
texGenAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ColorScaleAttrib::has_alpha_scale
bool has_alpha_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the alpha component (ignoring RGB),...
Definition: colorScaleAttrib.I:70
GraphicsStateGuardian::prepare_shader
virtual ShaderContext * prepare_shader(Shader *shader)
Compile a vertex/fragment shader body.
Definition: graphicsStateGuardian.cxx:644
planeNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_driver_renderer
get_driver_renderer
Returns GL_Renderer.
Definition: graphicsStateGuardian.h:281
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
SamplerState
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:36
GraphicsStateGuardian::remove_window
virtual void remove_window(GraphicsOutputBase *window)
This is simply a transparent call to GraphicsEngine::remove_window().
Definition: graphicsStateGuardian.cxx:1997
PlaneNode::get_plane
const LPlane & get_plane() const
Returns the plane represented by the PlaneNode.
Definition: planeNode.I:54
GeomPipelineReader
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Definition: geom.h:405
displayRegion.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Material::get_roughness
get_roughness
Returns the roughness previously specified by set_roughness.
Definition: material.h:123
GeomVertexAnimationSpec
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
Definition: geomVertexAnimationSpec.h:38
InternalName::get_name
get_name
Returns the complete name represented by the InternalName and all of its parents.
Definition: internalName.h:61
SimpleHashMap::find
int find(const Key &key) const
Searches for the indicated key in the table.
Definition: simpleHashMap.I:156
GraphicsStateGuardian::restore_gamma
virtual void restore_gamma()
Restore original gamma setting.
Definition: graphicsStateGuardian.cxx:442
Shader::ShaderTexSpec
Definition: shader.h:415
AsyncTaskCollection::get_task
get_task
Returns the nth AsyncTask in the collection.
Definition: asyncTaskCollection.h:46
GraphicsStateGuardian::begin_scene
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
Definition: graphicsStateGuardian.cxx:2092
Material::get_diffuse
get_diffuse
Returns the diffuse color setting, if it has been set.
Definition: material.h:116
fogAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ShaderContext
The ShaderContext is meant to contain the compiled version of a shader string.
Definition: shaderContext.h:31
Shader::ShaderPtrSpec
Definition: shader.h:432
GraphicsStateGuardian::has_extension
virtual bool has_extension(const std::string &extension) const
Returns true if the GSG implements the extension identified by the given string.
Definition: graphicsStateGuardian.cxx:3465
GraphicsStateGuardian::set_scene
set_scene
Sets the SceneSetup object that indicates the initial camera position, etc.
Definition: graphicsStateGuardian.h:290
GraphicsStateGuardian::release_shader_buffer
virtual void release_shader_buffer(BufferContext *ibc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the BufferC...
Definition: graphicsStateGuardian.cxx:700
Fog::get_linear_range
void get_linear_range(PN_stdfloat &onset, PN_stdfloat &opaque)
Retrieves the current onset and offset ranges.
Definition: fog.cxx:173
colorScaleAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::draw_patches
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of "patches", which can only be processed by a tessellation shader.
Definition: graphicsStateGuardian.cxx:2434
sphereLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Fog
Specifies how atmospheric fog effects are applied to geometry.
Definition: fog.h:41
InternalName::get_parent
get_parent
Return the parent of this InternalName.
Definition: internalName.h:60
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
ColorScaleAttrib::has_scale
has_scale
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
Definition: colorScaleAttrib.h:47
TexturePool::get_alpha_scale_map
static Texture * get_alpha_scale_map()
Returns a standard Texture object that has been created with Texture::generate_alpha_scale_map().
Definition: texturePool.I:144
GraphicsStateGuardian::prepare_sampler
virtual SamplerContext * prepare_sampler(const SamplerState &sampler)
Creates whatever structures the GSG requires to represent the sampler internally, and returns a newly...
Definition: graphicsStateGuardian.cxx:606
GraphicsStateGuardian::framebuffer_copy_to_ram
virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into system memory,...
Definition: graphicsStateGuardian.cxx:2863
GraphicsStateGuardian::draw_points
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected points.
Definition: graphicsStateGuardian.cxx:2474
ShaderGenerator
Definition: shaderGenerator.h:198
DrawableRegion
This is a base class for GraphicsWindow (actually, GraphicsOutput) and DisplayRegion,...
Definition: drawableRegion.h:29
Light::get_color
get_color
Returns the basic color of the light.
Definition: light.h:49
GraphicsStateGuardian::get_driver_shader_version_major
get_driver_shader_version_major
Returns the major version of the shader model.
Definition: graphicsStateGuardian.h:285
PointLight::get_attenuation
get_attenuation
Returns the terms of the attenuation equation for the light.
Definition: pointLight.h:49
Lens::get_near
get_near
Returns the position of the near plane (or cylinder, sphere, whatever).
Definition: lens.h:113
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
Spotlight
A light originating from a single point in space, and shining in a particular direction,...
Definition: spotlight.h:32
DisplayRegion::set_lens_index
set_lens_index
Sets the lens index, allows for multiple lenses to be attached to a camera.
Definition: displayRegion.h:123
GraphicsStateGuardian::draw_triangles_adj
virtual bool draw_triangles_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles with adjacency information.
Definition: graphicsStateGuardian.cxx:2401
shaderAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AsyncTask
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:32
CPT_InternalName
This is a const pointer to an InternalName, and should be used in lieu of a CPT(InternalName) in func...
Definition: internalName.h:193
depthWriteAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureReloadRequest
This loader request will call Texture::get_ram_image() in a sub-thread, to force the texture's image ...
Definition: textureReloadRequest.h:31
SimpleHashMap::store
int store(const Key &key, const Value &data)
Records the indicated key/data pair in the map.
Definition: simpleHashMap.I:177
Material::get_shininess
get_shininess
Returns the shininess exponent of the material.
Definition: material.h:122
GraphicsStateGuardian::prepare_display_region
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
Definition: graphicsStateGuardian.cxx:1919
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
MaterialAttrib
Indicates which, if any, material should be applied to geometry.
Definition: materialAttrib.h:27
PStatClient
Manages the communications to report statistics via a network connection to a remote PStatServer.
Definition: pStatClient.h:263
TextureStage::get_tex_view_offset
get_tex_view_offset
Returns the current setting of the tex_view_offset.
Definition: textureStage.h:203
GraphicsStateGuardian::flush_timer_queries
void flush_timer_queries()
Called by the graphics engine on the draw thread to check the status of the running timer queries and...
Definition: graphicsStateGuardian.cxx:2167
DirectionalLight
A light shining from infinitely far away in a particular direction, like sunlight.
Definition: directionalLight.h:25
GraphicsStateGuardian::clear_state_and_transform
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
Definition: graphicsStateGuardian.cxx:1982
ambientLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::get_driver_version_major
get_driver_version_major
Returns major version of the video driver.
Definition: graphicsStateGuardian.h:283
GraphicsStateGuardian::release_geom
virtual void release_geom(GeomContext *gc)
Frees the resources previously allocated via a call to prepare_geom(), including deleting the GeomCon...
Definition: graphicsStateGuardian.cxx:637
GraphicsStateGuardian::end_scene
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
Definition: graphicsStateGuardian.cxx:2103
GraphicsStateGuardian::create_gamma_table
static void create_gamma_table(PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table)
Create a gamma table.
Definition: graphicsStateGuardian.cxx:2930
GraphicsStateGuardian::begin_occlusion_query
virtual void begin_occlusion_query()
Begins a new occlusion query.
Definition: graphicsStateGuardian.cxx:715
GraphicsStateGuardian::prepare_shader_buffer
virtual BufferContext * prepare_shader_buffer(ShaderBuffer *data)
Prepares the indicated buffer for retained-mode rendering.
Definition: graphicsStateGuardian.cxx:691
GraphicsStateGuardian::clear_flash_texture
void clear_flash_texture()
Resets the "flash texture", so that no textures will flash.
Definition: graphicsStateGuardian.cxx:493
TextureAttrib::get_num_on_stages
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
Definition: textureAttrib.h:55
GraphicsStateGuardian::prepare_geom
virtual GeomContext * prepare_geom(Geom *geom)
Prepares the indicated Geom for retained-mode rendering, by creating whatever structures are necessar...
Definition: graphicsStateGuardian.cxx:625
PStatClient::is_connected
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise.
Definition: pStatClient.h:291
LensNode::get_lens
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
Definition: lensNode.I:47
ColorAttrib::get_color_type
get_color_type
Returns the type of color specified by this ColorAttrib.
Definition: colorAttrib.h:46
GraphicsStateGuardian::compute_distance_to
PN_stdfloat compute_distance_to(const LPoint3 &point) const
This function will compute the distance to the indicated point, assumed to be in eye coordinates,...
Definition: graphicsStateGuardian.cxx:813
Material::get_ambient
get_ambient
Returns the ambient color setting, if it has been set.
Definition: material.h:114
AsyncTaskManager
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
Definition: asyncTaskManager.h:48
GraphicsStateGuardian::extract_texture_data
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
Definition: graphicsStateGuardian.cxx:591
LightAttrib::has_any_on_light
bool has_any_on_light() const
Returns true if any light is turned on by the attrib, false otherwise.
Definition: lightAttrib.I:62
MaterialAttrib::get_material
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
Definition: materialAttrib.h:40
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
config_pstatclient.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClockObject::get_frame_count
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
GraphicsStateGuardian::get_supports_shadow_filter
get_supports_shadow_filter
Returns true if this particular GSG supports the filter mode FT_shadow for depth textures.
Definition: graphicsStateGuardian.h:208
OcclusionQueryContext
Returned from a GSG in response to begin_occlusion_query() .
Definition: occlusionQueryContext.h:25
ClockObject::get_dt
get_dt
Returns the elapsed time for the previous frame: the number of seconds elapsed between the last two c...
Definition: clockObject.h:99
Lens::get_view_vector
const LVector3 & get_view_vector() const
Returns the axis along which the lens is facing.
Definition: lens.cxx:214
GraphicsStateGuardian::get_internal_coordinate_system
virtual CoordinateSystem get_internal_coordinate_system() const
Returns the coordinate system used internally by the GSG.
Definition: graphicsStateGuardian.cxx:407
GraphicsStateGuardian::fetch_specified_value
const LMatrix4 * fetch_specified_value(Shader::ShaderMatSpec &spec, int altered)
The gsg contains a large number of useful matrices:
Definition: graphicsStateGuardian.cxx:861
vertexBufferContext.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
drawableRegion.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SimpleHashMap::is_empty
bool is_empty() const
Returns true if the table is empty; i.e.
Definition: simpleHashMap.I:454
GraphicsStateGuardian::prepare_vertex_buffer
virtual VertexBufferContext * prepare_vertex_buffer(GeomVertexArrayData *data)
Prepares the indicated buffer for retained-mode rendering.
Definition: graphicsStateGuardian.cxx:659
WindowProperties::size
static WindowProperties size(const LVecBase2i &size)
Returns a WindowProperties structure with only the size specified.
Definition: windowProperties.cxx:142
pStatGPUTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LensNode
A node that contains a Lens.
Definition: lensNode.h:29
DisplayRegionPipelineReader::get_tex_view_offset
int get_tex_view_offset()
Returns the current texture view offset for this DisplayRegion.
Definition: displayRegion.I:749
GraphicsOutputBase
An abstract base class for GraphicsOutput, for all the usual reasons.
Definition: graphicsOutputBase.h:25
TextureAttrib::get_on_sampler
get_on_sampler
Returns the sampler associated with the indicated stage, or the one associated with its texture if no...
Definition: textureAttrib.h:72
ClockObject::get_frame_time
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
BufferContext
This is a base class for those kinds of SavedContexts that occupy an easily-measured (and substantial...
Definition: bufferContext.h:38
ColorScaleAttrib
Applies a scale to colors in the scene graph and on vertices.
Definition: colorScaleAttrib.h:27
ClipPlaneAttrib::get_on_plane
get_on_plane
Returns the nth plane enabled by the attribute, sorted in render order.
Definition: clipPlaneAttrib.h:74
GraphicsStateGuardian::get_driver_version_minor
get_driver_version_minor
Returns the minor version of the video driver.
Definition: graphicsStateGuardian.h:284
geomLinestrips.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::clear_before_callback
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
Definition: graphicsStateGuardian.cxx:1972
NodePath::get_mat
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
Definition: nodePath.I:776
DisplayRegionPipelineReader::get_window
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
Definition: displayRegion.I:701
PandaNode::as_light
virtual Light * as_light()
Cross-casts the node to a Light pointer, if it is one of the four kinds of Light nodes,...
Definition: pandaNode.cxx:2095
TextureAttrib::get_on_stage
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Definition: textureAttrib.h:55
TexMatrixAttrib
Applies a transform matrix to UV's before they are rendered.
Definition: texMatrixAttrib.h:30
DisplayRegion::set_camera
set_camera
Sets the camera that is associated with this DisplayRegion.
Definition: displayRegion.h:94
LightAttrib::get_on_light
get_on_light
Returns the nth light turned on by the attribute, sorted in render order.
Definition: lightAttrib.h:74
GraphicsStateGuardian::draw_tristrips
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips.
Definition: graphicsStateGuardian.cxx:2409
Spotlight::get_exponent
get_exponent
Returns the exponent that controls the amount of light falloff from the center of the spotlight.
Definition: spotlight.h:51
LightLensNode
A derivative of Light and of Camera.
Definition: lightLensNode.h:33
DisplayRegionPipelineReader::get_stereo_channel
Lens::StereoChannel get_stereo_channel() const
Returns whether the DisplayRegion is specified as the left or right channel of a stereo pair,...
Definition: displayRegion.I:736
TexGenAttrib
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Definition: texGenAttrib.h:32
GraphicsStateGuardian::get_alpha_scale_texture_stage
static TextureStage * get_alpha_scale_texture_stage()
Returns the TextureStage that will be used to apply an alpha scale, if get_alpha_scale_via_texture() ...
Definition: graphicsStateGuardian.I:779
TextureContext
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: textureContext.h:33
geomTristrips.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PlaneNode
A node that contains a plane.
Definition: planeNode.h:36
shader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FogAttrib::get_fog
get_fog
If the FogAttrib is not an 'off' FogAttrib, returns the fog that is associated.
Definition: fogAttrib.h:38
GraphicsStateGuardian::set_active
set_active
Sets the active flag associated with the GraphicsStateGuardian.
Definition: graphicsStateGuardian.h:97
pointLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Texture::get_pad_y_size
int get_pad_y_size() const
Returns size of the pad region.
Definition: texture.I:629
Texture::get_pad_x_size
int get_pad_x_size() const
Returns size of the pad region.
Definition: texture.I:620
GraphicsStateGuardian::release_vertex_buffer
virtual void release_vertex_buffer(VertexBufferContext *vbc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the VertexB...
Definition: graphicsStateGuardian.cxx:668
GraphicsStateGuardian::ensure_generated_shader
virtual void ensure_generated_shader(const RenderState *state)
Ensures that an appropriate shader has been generated for the given state.
Definition: graphicsStateGuardian.cxx:3428
GraphicsStateGuardian::get_prepared_objects
get_prepared_objects
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
Definition: graphicsStateGuardian.h:246
GraphicsStateGuardian::prepare_index_buffer
virtual IndexBufferContext * prepare_index_buffer(GeomPrimitive *data)
Prepares the indicated buffer for retained-mode rendering.
Definition: graphicsStateGuardian.cxx:675
SphereLight
A sphere light is like a point light, except that it represents a sphere with a radius,...
Definition: sphereLight.h:28
Loader::get_global_ptr
static Loader * get_global_ptr()
Returns a pointer to the global Loader.
Definition: loader.I:212
PlaneNode::get_clip_effect
int get_clip_effect() const
Returns the clip_effect bits for this clip plane.
Definition: planeNode.I:128
ColorScaleAttrib::is_identity
bool is_identity() const
Returns true if the ColorScaleAttrib is an identity attrib, false if it is either an off attrib or it...
Definition: colorScaleAttrib.I:43
lightAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
directionalLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPrimitivePipelineReader
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
Definition: geomPrimitive.h:352
GraphicsStateGuardian::set_gamma
set_gamma
Set gamma.
Definition: graphicsStateGuardian.h:251
Texture::get_y_size
get_y_size
Returns the height of the texture image in texels.
Definition: texture.h:338
GeomMunger::unregister_mungers_for_gsg
static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg)
Removes all the mungers from the registry that are associated with the indicated GSG.
Definition: geomMunger.I:52
GraphicsStateGuardian::get_flash_texture
get_flash_texture
Returns the current "flash texture", if any, or NULL if none.
Definition: graphicsStateGuardian.h:266
Light::get_specular_color
virtual const LColor & get_specular_color() const
Returns the color of specular highlights generated by the light.
Definition: light.cxx:146
GraphicsStateGuardian::get_driver_vendor
get_driver_vendor
Returns the vendor of the video card driver.
Definition: graphicsStateGuardian.h:280
LightAttrib
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
Definition: lightAttrib.h:30
GraphicsStateGuardian::traverse_prepared_textures
void traverse_prepared_textures(TextureCallback *func, void *callback_arg)
Calls the indicated function on all currently-prepared textures, or until the callback function retur...
Definition: graphicsStateGuardian.cxx:450
Shader::ShaderMatSpec
Definition: shader.h:403
LightAttrib::get_num_non_ambient_lights
size_t get_num_non_ambient_lights() const
Returns the number of non-ambient lights that are turned on by this attribute.
Definition: lightAttrib.I:35
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
GraphicsStateGuardian::dispatch_compute
virtual void dispatch_compute(int size_x, int size_y, int size_z)
Dispatches a currently bound compute shader using the given work group counts.
Definition: graphicsStateGuardian.cxx:747
PStatGPUTimer
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
Definition: pStatGPUTimer.h:36
TextureAttrib
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
NodePath::node
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
config_display.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ColorAttrib
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
PointLight::get_point
get_point
Returns the point in space at which the light is located.
Definition: pointLight.h:57
Lens::get_far
get_far
Returns the position of the far plane (or cylinder, sphere, whatever).
Definition: lens.h:114
TypedObject::is_exact_type
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
PStatThread
A lightweight class that represents a single thread of execution to PStats.
Definition: pStatThread.h:28
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
SceneSetup::get_lens
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition: sceneSetup.I:131
DisplayRegionPipelineReader
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
Definition: displayRegion.h:311
GraphicsStateGuardian::prepare_lens
virtual bool prepare_lens()
Makes the current lens (whichever lens was most recently specified with set_scene()) active,...
Definition: graphicsStateGuardian.cxx:2013
PT
PT(OcclusionQueryContext) GraphicsStateGuardian
Ends a previous call to begin_occlusion_query().
Definition: graphicsStateGuardian.cxx:725
CPT
CPT(TransformState) GraphicsStateGuardian
Given a lens, this function calculates the appropriate projection matrix for this gsg.
Definition: graphicsStateGuardian.cxx:2022
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
Shader::ShaderPtrData
Definition: shader.h:355
Material::get_emission
get_emission
Returns the emission color setting, if it has been set.
Definition: material.h:120
Texture::get_pad_z_size
int get_pad_z_size() const
Returns size of the pad region.
Definition: texture.I:638
graphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::release_texture
virtual void release_texture(TextureContext *tc)
Frees the resources previously allocated via a call to prepare_texture(), including deleting the Text...
Definition: graphicsStateGuardian.cxx:579
GraphicsStateGuardian::draw_tristrips_adj
virtual bool draw_tristrips_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips with adjacency information.
Definition: graphicsStateGuardian.cxx:2417
SimpleHashMap::get_num_entries
size_t get_num_entries() const
Returns the number of active entries in the table.
Definition: simpleHashMap.I:445
graphicsOutput.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::fetch_specified_part
const LMatrix4 * fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LMatrix4 &t, int index)
See fetch_specified_value.
Definition: graphicsStateGuardian.cxx:920
ColorScaleAttrib::get_scale
get_scale
Returns the scale to be applied to colors.
Definition: colorScaleAttrib.h:47
Material::get_metallic
get_metallic
Returns the metallic setting, if it has been set.
Definition: material.h:124
spotlight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian::depth_offset_decals
virtual bool depth_offset_decals()
Returns true if this GSG can implement decals using a DepthOffsetAttrib, or false if that is unreliab...
Definition: graphicsStateGuardian.cxx:2295
BitMask::clear_bit
void clear_bit(int index)
Sets the nth bit off.
Definition: bitMask.I:129
GraphicsStateGuardian::set_coordinate_system
set_coordinate_system
Changes the coordinate system in effect on this particular gsg.
Definition: graphicsStateGuardian.h:243
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
GraphicsStateGuardian::get_max_texture_stages
get_max_texture_stages
Returns the maximum number of simultaneous textures that may be applied to geometry with multitexturi...
Definition: graphicsStateGuardian.h:181
GeomPrimitive
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
ColorAttrib::get_color
get_color
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
Definition: colorAttrib.h:47
GeomVertexDataPipelineReader
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
Definition: geomVertexData.h:442
SimpleHashMap::remove_element
void remove_element(size_t n)
Removes the nth entry from the table.
Definition: simpleHashMap.I:435
Material::get_base_color
get_base_color
Returns the base_color color setting, if it has been set.
Definition: material.h:112
NodePath::is_empty
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
renderBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardianBase::remove_gsg
static void remove_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG destructor to remove a GSG from the available list.
Definition: graphicsStateGuardianBase.cxx:131
GeomMunger
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
GraphicsStateGuardian::update_texture
virtual bool update_texture(TextureContext *tc, bool force)
Ensures that the current Texture data is refreshed onto the GSG.
Definition: graphicsStateGuardian.cxx:570
GraphicsStateGuardian::finish_decal
virtual void finish_decal()
Called during draw to clean up after decals are finished.
Definition: graphicsStateGuardian.cxx:2368
GraphicsStateGuardian::release_sampler
virtual void release_sampler(SamplerContext *sc)
Frees the resources previously allocated via a call to prepare_sampler(), including deleting the Samp...
Definition: graphicsStateGuardian.cxx:615