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  */
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  */
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  */
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  */
812 PN_stdfloat GraphicsStateGuardian::
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::
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  return &LMatrix4::ones_mat();
1021  }
1022  PN_stdfloat start, end;
1023  fog->get_linear_range(start, end);
1024  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1025  fog->get_exp_density(), start, end, 1.0f / (end - start));
1026  return &t;
1027  }
1028  case Shader::SMO_attr_fogcolor: {
1029  const FogAttrib *target_fog = (const FogAttrib *)
1030  _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1031  Fog *fog = target_fog->get_fog();
1032  if (fog == nullptr) {
1033  return &LMatrix4::ones_mat();
1034  }
1035  LVecBase4 c = fog->get_color();
1036  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1037  return &t;
1038  }
1039  case Shader::SMO_alight_x: {
1040  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1041  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1042  AmbientLight *lt;
1043  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1044  LColor const &c = lt->get_color();
1045  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1046  return &t;
1047  }
1048  case Shader::SMO_satten_x: {
1049  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1050  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1051  Spotlight *lt;
1052  DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
1053  LVecBase3 const &a = lt->get_attenuation();
1054  PN_stdfloat x = lt->get_exponent();
1055  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
1056  return &t;
1057  }
1058  case Shader::SMO_dlight_x: {
1059  // The dlight matrix contains COLOR, SPECULAR, DIRECTION, PSEUDOHALFANGLE
1060  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1061  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1062  DirectionalLight *lt;
1063  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1064  LColor const &c = lt->get_color();
1065  LColor const &s = lt->get_specular_color();
1066  t = np.get_net_transform()->get_mat() *
1067  _scene_setup->get_world_transform()->get_mat();
1068  LVecBase3 d = -(t.xform_vec(lt->get_direction()));
1069  d.normalize();
1070  LVecBase3 h = d + LVecBase3(0,-1,0);
1071  h.normalize();
1072  t.set(c[0], c[1], c[2], c[3],
1073  s[0], s[1], s[2], c[3],
1074  d[0], d[1], d[2], 0,
1075  h[0], h[1], h[2], 0);
1076  return &t;
1077  }
1078  case Shader::SMO_plight_x: {
1079  // The plight matrix contains COLOR, SPECULAR, POINT, ATTENUATION
1080  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1081  nassertr(!np.is_empty(), &LMatrix4::ones_mat());
1082  PointLight *lt;
1083  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1084  LColor const &c = lt->get_color();
1085  LColor const &s = lt->get_specular_color();
1086  t = np.get_net_transform()->get_mat() *
1087  _scene_setup->get_world_transform()->get_mat();
1088  LVecBase3 p = (t.xform_point(lt->get_point()));
1089  LVecBase3 a = lt->get_attenuation();
1090  Lens *lens = lt->get_lens(0);
1091  PN_stdfloat lnear = lens->get_near();
1092  PN_stdfloat lfar = lens->get_far();
1093  t.set(c[0], c[1], c[2], c[3],
1094  s[0], s[1], s[2], s[3],
1095  p[0], p[1], p[2], lnear,
1096  a[0], a[1], a[2], lfar);
1097  return &t;
1098  }
1099  case Shader::SMO_slight_x: {
1100  // The slight matrix contains COLOR, SPECULAR, POINT, DIRECTION
1101  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1102  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1103  Spotlight *lt;
1104  DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
1105  Lens *lens = lt->get_lens();
1106  nassertr(lens != nullptr, &LMatrix4::zeros_mat());
1107  LColor const &c = lt->get_color();
1108  LColor const &s = lt->get_specular_color();
1109  PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
1110  t = np.get_net_transform()->get_mat() *
1111  _scene_setup->get_world_transform()->get_mat();
1112  LVecBase3 p = t.xform_point(lens->get_nodal_point());
1113  LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
1114  t.set(c[0], c[1], c[2], c[3],
1115  s[0], s[1], s[2], s[3],
1116  p[0], p[1], p[2], 0,
1117  d[0], d[1], d[2], cutoff);
1118  return &t;
1119  }
1120  case Shader::SMO_light_ambient: {
1121  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1122  const LightAttrib *target_light = (const LightAttrib *)
1123  _target_rs->get_attrib_def(LightAttrib::get_class_slot());
1124 
1125  if (!target_light->has_any_on_light()) {
1126  // There are no lights at all. This means, to follow the fixed-
1127  // function model, we pretend there is an all-white ambient light.
1128  t.set_row(3, LVecBase4(1, 1, 1, 1));
1129  } else {
1130  t.set_row(3, target_light->get_ambient_contribution());
1131  }
1132  return &t;
1133  }
1134  case Shader::SMO_texmat_i: {
1135  const TexMatrixAttrib *tma;
1136  const TextureAttrib *ta;
1137  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1138  index < ta->get_num_on_stages()) {
1139  return &tma->get_mat(ta->get_on_stage(index));
1140  } else {
1141  return &LMatrix4::ident_mat();
1142  }
1143  }
1144  case Shader::SMO_inv_texmat_i: {
1145  const TexMatrixAttrib *tma;
1146  const TextureAttrib *ta;
1147  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1148  index < ta->get_num_on_stages()) {
1149  t = tma->get_transform(ta->get_on_stage(index))->get_inverse()->get_mat();
1150  return &t;
1151  } else {
1152  return &LMatrix4::ident_mat();
1153  }
1154  }
1155  case Shader::SMO_texscale_i: {
1156  const TexMatrixAttrib *tma;
1157  const TextureAttrib *ta;
1158  if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1159  index < ta->get_num_on_stages()) {
1160  LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
1161  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
1162  return &t;
1163  } else {
1164  return &LMatrix4::ident_mat();
1165  }
1166  }
1167  case Shader::SMO_texcolor_i: {
1168  const TextureAttrib *ta;
1169  if (_target_rs->get_attrib(ta) && index < ta->get_num_on_stages()) {
1170  TextureStage *ts = ta->get_on_stage(index);
1171  t.set_row(3, ts->get_color());
1172  return &t;
1173  } else {
1174  return &LMatrix4::zeros_mat();
1175  }
1176  }
1177  case Shader::SMO_tex_is_alpha_i: {
1178  // This is a hack so we can support both F_alpha and other formats in the
1179  // default shader, to fix font rendering in GLES2
1180  const TextureAttrib *ta;
1181  if (_target_rs->get_attrib(ta) &&
1182  index < ta->get_num_on_stages()) {
1183  TextureStage *ts = ta->get_on_stage(index);
1184  PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
1185  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
1186  return &t;
1187  } else {
1188  return &LMatrix4::zeros_mat();
1189  }
1190  }
1191  case Shader::SMO_plane_x: {
1192  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1193  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1194  const PlaneNode *plane_node;
1195  DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
1196  LPlane p = plane_node->get_plane();
1197  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
1198  return &t;
1199  }
1200  case Shader::SMO_clipplane_x: {
1201  const ClipPlaneAttrib *cpa;
1202  _target_rs->get_attrib_def(cpa);
1203  int planenr = atoi(name->get_name().c_str());
1204  if (planenr >= cpa->get_num_on_planes()) {
1205  return &LMatrix4::zeros_mat();
1206  }
1207  const NodePath &np = cpa->get_on_plane(planenr);
1208  nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
1209  const PlaneNode *plane_node;
1210  DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
1211 
1212  // Transform plane to world space
1213  CPT(TransformState) transform = np.get_net_transform();
1214  LPlane plane = plane_node->get_plane();
1215  if (!transform->is_identity()) {
1216  plane.xform(transform->get_mat());
1217  }
1218  t.set_row(3, plane);
1219  return &t;
1220  }
1221  case Shader::SMO_apiview_clipplane_i: {
1222  const ClipPlaneAttrib *cpa;
1223  _target_rs->get_attrib_def(cpa);
1224  if (index >= cpa->get_num_on_planes()) {
1225  return &LMatrix4::zeros_mat();
1226  }
1227 
1228  const NodePath &plane = cpa->get_on_plane(index);
1229  nassertr(!plane.is_empty(), &LMatrix4::zeros_mat());
1230  const PlaneNode *plane_node;
1231  DCAST_INTO_R(plane_node, plane.node(), &LMatrix4::zeros_mat());
1232 
1233  CPT(TransformState) transform =
1234  _scene_setup->get_cs_world_transform()->compose(
1235  plane.get_transform(_scene_setup->get_scene_root().get_parent()));
1236 
1237  LPlane xformed_plane = plane_node->get_plane() * transform->get_mat();
1238  t.set_row(3, xformed_plane);
1239  return &t;
1240  }
1241  case Shader::SMO_mat_constant_x: {
1242  return &_target_shader->get_shader_input_matrix(name, t);
1243  }
1244  case Shader::SMO_vec_constant_x: {
1245  const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
1246  const PN_stdfloat *data = input.get_data();
1247  t.set(data[0], data[1], data[2], data[3],
1248  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  return &t;
1252  }
1253  case Shader::SMO_world_to_view: {
1254  return &(_scene_setup->get_world_transform()->get_mat());
1255  }
1256  case Shader::SMO_view_to_world: {
1257  return &(_scene_setup->get_camera_transform()->get_mat());
1258  }
1259  case Shader::SMO_model_to_view: {
1260  t = _inv_cs_transform->compose(_internal_transform)->get_mat();
1261  return &t;
1262  }
1263  case Shader::SMO_model_to_apiview: {
1264  return &(_internal_transform->get_mat());
1265  }
1266  case Shader::SMO_view_to_model: {
1267  t = _internal_transform->invert_compose(_cs_transform)->get_mat();
1268  return &t;
1269  }
1270  case Shader::SMO_apiview_to_model: {
1271  t = _internal_transform->get_inverse()->get_mat();
1272  return &t;
1273  }
1274  case Shader::SMO_apiview_to_view: {
1275  return &(_inv_cs_transform->get_mat());
1276  }
1277  case Shader::SMO_view_to_apiview: {
1278  return &(_cs_transform->get_mat());
1279  }
1280  case Shader::SMO_clip_to_view: {
1281  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1282  return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
1283  } else {
1284  t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
1285  LMatrix4::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
1286  return &t;
1287  }
1288  }
1289  case Shader::SMO_view_to_clip: {
1290  if (_current_lens->get_coordinate_system() == _coordinate_system) {
1291  return &(_current_lens->get_projection_mat(_current_stereo_channel));
1292  } else {
1293  t = LMatrix4::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
1294  _current_lens->get_projection_mat(_current_stereo_channel);
1295  return &t;
1296  }
1297  }
1298  case Shader::SMO_apiclip_to_view: {
1299  t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
1300  return &t;
1301  }
1302  case Shader::SMO_view_to_apiclip: {
1303  t = _cs_transform->get_mat() * _projection_mat->get_mat();
1304  return &t;
1305  }
1306  case Shader::SMO_apiclip_to_apiview: {
1307  return &(_projection_mat_inv->get_mat());
1308  }
1309  case Shader::SMO_apiview_to_apiclip: {
1310  return &(_projection_mat->get_mat());
1311  }
1312  case Shader::SMO_view_x_to_view: {
1313  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1314  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1315  t = np.get_net_transform()->get_mat() *
1316  _scene_setup->get_world_transform()->get_mat();
1317  return &t;
1318  }
1319  case Shader::SMO_view_to_view_x: {
1320  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1321  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1322  t = _scene_setup->get_camera_transform()->get_mat() *
1323  np.get_net_transform()->get_inverse()->get_mat();
1324  return &t;
1325  }
1326  case Shader::SMO_apiview_x_to_view: {
1327  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1328  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1329  t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
1330  np.get_net_transform()->get_mat() *
1331  _scene_setup->get_world_transform()->get_mat();
1332  return &t;
1333  }
1334  case Shader::SMO_view_to_apiview_x: {
1335  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1336  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1337  t = (_scene_setup->get_camera_transform()->get_mat() *
1338  np.get_net_transform()->get_inverse()->get_mat() *
1339  LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
1340  return &t;
1341  }
1342  case Shader::SMO_clip_x_to_view: {
1343  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1344  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1345  const LensNode *node;
1346  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1347  const Lens *lens = node->get_lens();
1348  t = lens->get_projection_mat_inv(_current_stereo_channel) *
1349  LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
1350  np.get_net_transform()->get_mat() *
1351  _scene_setup->get_world_transform()->get_mat();
1352  return &t;
1353  }
1354  case Shader::SMO_view_to_clip_x: {
1355  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1356  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1357  const LensNode *node;
1358  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1359  const Lens *lens = node->get_lens();
1360  t = _scene_setup->get_camera_transform()->get_mat() *
1361  np.get_net_transform()->get_inverse()->get_mat() *
1362  LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
1363  lens->get_projection_mat(_current_stereo_channel);
1364  return &t;
1365  }
1366  case Shader::SMO_apiclip_x_to_view: {
1367  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1368  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1369  const LensNode *node;
1370  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1371  const Lens *lens = node->get_lens();
1372  t = calc_projection_mat(lens)->get_inverse()->get_mat() *
1373  get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
1374  np.get_net_transform()->get_mat() *
1375  _scene_setup->get_world_transform()->get_mat();
1376  return &t;
1377  }
1378  case Shader::SMO_view_to_apiclip_x: {
1379  const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1380  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1381  const LensNode *node;
1382  DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
1383  const Lens *lens = node->get_lens();
1384  t = _scene_setup->get_camera_transform()->get_mat() *
1385  np.get_net_transform()->get_inverse()->get_mat() *
1386  get_cs_transform_for(lens->get_coordinate_system())->get_mat() *
1387  calc_projection_mat(lens)->get_mat();
1388  return &t;
1389  }
1390  case Shader::SMO_mat_constant_x_attrib: {
1391  if (_target_shader->has_shader_input(name)) {
1392  // There is an input specifying precisely this whole thing, with dot and
1393  // all. Support this, even if only for backward compatibility.
1394  return &_target_shader->get_shader_input_matrix(name, t);
1395  }
1396 
1397  const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
1398  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1399 
1400  return fetch_specified_member(np, name->get_basename(), t);
1401  }
1402  case Shader::SMO_vec_constant_x_attrib: {
1403  if (_target_shader->has_shader_input(name)) {
1404  // There is an input specifying precisely this whole thing, with dot and
1405  // all. Support this, even if only for backward compatibility.
1406  const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
1407  t.set(data[0], data[1], data[2], data[3],
1408  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  return &t;
1412  }
1413 
1414  const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
1415  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1416 
1417  return fetch_specified_member(np, name->get_basename(), t);
1418  }
1419  case Shader::SMO_light_source_i_attrib: {
1420  const LightAttrib *target_light;
1421  _target_rs->get_attrib_def(target_light);
1422 
1423  // We don't count ambient lights, which would be pretty silly to handle
1424  // via this mechanism.
1425  size_t num_lights = target_light->get_num_non_ambient_lights();
1426  if (index >= 0 && (size_t)index < num_lights) {
1427  NodePath light = target_light->get_on_light((size_t)index);
1428  nassertr(!light.is_empty(), &LMatrix4::ident_mat());
1429  Light *light_obj = light.node()->as_light();
1430  nassertr(light_obj != nullptr, &LMatrix4::ident_mat());
1431 
1432  return fetch_specified_member(light, name, t);
1433 
1434  } else if (index == 0) {
1435  // Apply the default OpenGL lights otherwise.
1436  // Special exception for light 0, which defaults to white.
1437  string basename = name->get_basename();
1438  return &LMatrix4::ones_mat();
1439  }
1440  return fetch_specified_member(NodePath(), name, t);
1441  }
1442  case Shader::SMO_light_source_i_packed: {
1443  // The light matrix contains COLOR, ATTENUATION, POSITION, VIEWVECTOR
1444  const LightAttrib *target_light;
1445  _target_rs->get_attrib_def(target_light);
1446 
1447  // We don't count ambient lights, which would be pretty silly to handle
1448  // via this mechanism.
1449  size_t num_lights = target_light->get_num_non_ambient_lights();
1450  if (index >= 0 && (size_t)index < num_lights) {
1451  NodePath np = target_light->get_on_light((size_t)index);
1452  nassertr(!np.is_empty(), &LMatrix4::ident_mat());
1453  PandaNode *node = np.node();
1454  Light *light = node->as_light();
1455  nassertr(light != nullptr, &LMatrix4::zeros_mat());
1456  t.set_row(0, light->get_color());
1457  t.set_row(1, light->get_attenuation());
1458 
1459  LMatrix4 mat = np.get_net_transform()->get_mat() *
1460  _scene_setup->get_world_transform()->get_mat();
1461 
1462  if (node->is_of_type(DirectionalLight::get_class_type())) {
1463  LVecBase3 d = mat.xform_vec(((const DirectionalLight *)node)->get_direction());
1464  d.normalize();
1465  t.set_row(2, LVecBase4(d, 0));
1466  t.set_row(3, LVecBase4(-d, 0));
1467 
1468  } else if (node->is_of_type(LightLensNode::get_class_type())) {
1469  const Lens *lens = ((const LightLensNode *)node)->get_lens();
1470 
1471  LPoint3 p = mat.xform_point(lens->get_nodal_point());
1472  t.set_row(3, LVecBase4(p));
1473 
1474  // For shadowed point light we need to store near/far.
1475  // For spotlight we need to store cutoff angle.
1476  if (node->is_of_type(Spotlight::get_class_type())) {
1477  PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
1478  LVecBase3 d = -(mat.xform_vec(lens->get_view_vector()));
1479  t.set_cell(1, 3, ((const Spotlight *)node)->get_exponent());
1480  t.set_row(2, LVecBase4(d, cutoff));
1481 
1482  } else if (node->is_of_type(PointLight::get_class_type())) {
1483  t.set_cell(1, 3, lens->get_far());
1484  t.set_cell(3, 3, lens->get_near());
1485 
1486  if (node->is_of_type(SphereLight::get_class_type())) {
1487  t.set_cell(2, 3, ((const SphereLight *)node)->get_radius());
1488  }
1489  }
1490  }
1491  } else if (index == 0) {
1492  // Apply the default OpenGL lights otherwise.
1493  // Special exception for light 0, which defaults to white.
1494  t.set_row(0, LVecBase4(1, 1, 1, 1));
1495  }
1496  return &t;
1497  }
1498  default:
1499  nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
1500  return &LMatrix4::ident_mat();
1501  }
1502 }
1503 
1504 /**
1505  * Given a NodePath passed into a shader input that is a structure, fetches
1506  * the value for the given member.
1507  */
1508 const LMatrix4 *GraphicsStateGuardian::
1509 fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) {
1510  // This system is not ideal. It will be improved in the future.
1511  static const CPT_InternalName IN_color("color");
1512  static const CPT_InternalName IN_ambient("ambient");
1513  static const CPT_InternalName IN_diffuse("diffuse");
1514  static const CPT_InternalName IN_specular("specular");
1515  static const CPT_InternalName IN_position("position");
1516  static const CPT_InternalName IN_halfVector("halfVector");
1517  static const CPT_InternalName IN_spotDirection("spotDirection");
1518  static const CPT_InternalName IN_spotCutoff("spotCutoff");
1519  static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
1520  static const CPT_InternalName IN_spotExponent("spotExponent");
1521  static const CPT_InternalName IN_attenuation("attenuation");
1522  static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
1523  static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
1524  static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
1525  static const CPT_InternalName IN_shadowViewMatrix("shadowViewMatrix");
1526 
1527  PandaNode *node = nullptr;
1528  if (!np.is_empty()) {
1529  node = np.node();
1530  }
1531 
1532  if (attrib == IN_color) {
1533  if (node == nullptr) {
1534  return &LMatrix4::ident_mat();
1535  }
1536  Light *light = node->as_light();
1537  nassertr(light != nullptr, &LMatrix4::ident_mat());
1538  LColor c = light->get_color();
1539  t.set_row(3, c);
1540  return &t;
1541 
1542  } else if (attrib == IN_ambient) {
1543  if (node == nullptr) {
1544  return &LMatrix4::ident_mat();
1545  }
1546  Light *light = node->as_light();
1547  nassertr(light != nullptr, &LMatrix4::ident_mat());
1548  if (node->is_ambient_light()) {
1549  LColor c = light->get_color();
1550  t.set_row(3, c);
1551  } else {
1552  // Non-ambient lights don't currently have an ambient color in Panda3D.
1553  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1554  }
1555  return &t;
1556 
1557  } else if (attrib == IN_diffuse) {
1558  if (node == nullptr) {
1559  return &LMatrix4::ident_mat();
1560  }
1561  Light *light = node->as_light();
1562  nassertr(light != nullptr, &LMatrix4::ones_mat());
1563  if (node->is_ambient_light()) {
1564  // Ambient light has no diffuse color.
1565  t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1566  } else {
1567  LColor c = light->get_color();
1568  t.set_row(3, c);
1569  }
1570  return &t;
1571 
1572  } else if (attrib == IN_specular) {
1573  if (node == nullptr) {
1574  return &LMatrix4::ident_mat();
1575  }
1576  Light *light = node->as_light();
1577  nassertr(light != nullptr, &LMatrix4::ones_mat());
1578  t.set_row(3, light->get_specular_color());
1579  return &t;
1580 
1581  } else if (attrib == IN_position) {
1582  if (np.is_empty()) {
1583  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1584  return &t;
1585  } else if (node->is_ambient_light()) {
1586  // Ambient light has no position.
1587  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1588  return &t;
1589  } else if (node->is_of_type(DirectionalLight::get_class_type())) {
1590  DirectionalLight *light;
1591  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1592 
1593  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1594  LVector3 dir = -(light->get_direction() * transform->get_mat());
1595  dir *= _scene_setup->get_cs_world_transform()->get_mat();
1596  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
1597  return &t;
1598  } else {
1599  LightLensNode *light;
1600  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1601  Lens *lens = light->get_lens();
1602  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1603 
1604  CPT(TransformState) transform =
1605  _scene_setup->get_cs_world_transform()->compose(
1606  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1607 
1608  const LMatrix4 &light_mat = transform->get_mat();
1609  LPoint3 pos = lens->get_nodal_point() * light_mat;
1610  t = LMatrix4::translate_mat(pos);
1611  return &t;
1612  }
1613 
1614  } else if (attrib == IN_halfVector) {
1615  if (np.is_empty()) {
1616  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1617  return &t;
1618  } else if (node->is_ambient_light()) {
1619  // Ambient light has no half-vector.
1620  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1621  return &t;
1622  } else if (node->is_of_type(DirectionalLight::get_class_type())) {
1623  DirectionalLight *light;
1624  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1625 
1626  CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
1627  LVector3 dir = -(light->get_direction() * transform->get_mat());
1628  dir *= _scene_setup->get_cs_world_transform()->get_mat();
1629  dir.normalize();
1630  dir += LVector3(0, 0, 1);
1631  dir.normalize();
1632  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
1633  return &t;
1634  } else {
1635  LightLensNode *light;
1636  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1637  Lens *lens = light->get_lens();
1638  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1639 
1640  CPT(TransformState) transform =
1641  _scene_setup->get_cs_world_transform()->compose(
1642  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1643 
1644  const LMatrix4 &light_mat = transform->get_mat();
1645  LPoint3 pos = lens->get_nodal_point() * light_mat;
1646  pos.normalize();
1647  pos += LVector3(0, 0, 1);
1648  pos.normalize();
1649  t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
1650  return &t;
1651  }
1652 
1653  } else if (attrib == IN_spotDirection) {
1654  if (node == nullptr) {
1655  t.set_row(3, LVector3(0.0f, 0.0f, -1.0f));
1656  return &t;
1657  } else if (node->is_ambient_light()) {
1658  // Ambient light has no spot direction.
1659  t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
1660  return &t;
1661  } else {
1662  LightLensNode *light;
1663  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1664  Lens *lens = light->get_lens();
1665  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1666 
1667  CPT(TransformState) transform =
1668  _scene_setup->get_cs_world_transform()->compose(
1669  np.get_transform(_scene_setup->get_scene_root().get_parent()));
1670 
1671  const LMatrix4 &light_mat = transform->get_mat();
1672  LVector3 dir = lens->get_view_vector() * light_mat;
1673  t.set_row(3, dir);
1674  return &t;
1675  }
1676 
1677  } else if (attrib == IN_spotCutoff) {
1678  if (node != nullptr &&
1679  node->is_of_type(Spotlight::get_class_type())) {
1680  LightLensNode *light;
1681  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1682  Lens *lens = light->get_lens();
1683  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1684 
1685  float cutoff = lens->get_hfov() * 0.5f;
1686  t.set_row(3, LVecBase4(cutoff));
1687  return &t;
1688  } else {
1689  // Other lights have no cut-off.
1690  t.set_row(3, LVecBase4(180));
1691  return &t;
1692  }
1693 
1694  } else if (attrib == IN_spotCosCutoff) {
1695  if (node != nullptr &&
1696  node->is_of_type(Spotlight::get_class_type())) {
1697  LightLensNode *light;
1698  DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1699  Lens *lens = light->get_lens();
1700  nassertr(lens != nullptr, &LMatrix4::ident_mat());
1701 
1702  float cutoff = lens->get_hfov() * 0.5f;
1703  t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
1704  return &t;
1705  } else {
1706  // Other lights have no cut-off.
1707  t.set_row(3, LVecBase4(-1));
1708  return &t;
1709  }
1710 
1711  } else if (attrib == IN_spotExponent) {
1712  if (node == nullptr) {
1713  return &LMatrix4::zeros_mat();
1714  }
1715  Light *light = node->as_light();
1716  nassertr(light != nullptr, &LMatrix4::ident_mat());
1717 
1718  t.set_row(3, LVecBase4(light->get_exponent()));
1719  return &t;
1720 
1721  } else if (attrib == IN_attenuation) {
1722  if (node != nullptr) {
1723  Light *light = node->as_light();
1724  nassertr(light != nullptr, &LMatrix4::ones_mat());
1725 
1726  t.set_row(3, LVecBase4(light->get_attenuation(), 0));
1727  } else {
1728  t.set_row(3, LVecBase4(1, 0, 0, 0));
1729  }
1730  return &t;
1731 
1732  } else if (attrib == IN_constantAttenuation) {
1733  if (node == nullptr) {
1734  return &LMatrix4::ones_mat();
1735  }
1736  Light *light = node->as_light();
1737  nassertr(light != nullptr, &LMatrix4::ones_mat());
1738 
1739  t.set_row(3, LVecBase4(light->get_attenuation()[0]));
1740  return &t;
1741 
1742  } else if (attrib == IN_linearAttenuation) {
1743  if (node == nullptr) {
1744  return &LMatrix4::zeros_mat();
1745  }
1746  Light *light = node->as_light();
1747  nassertr(light != nullptr, &LMatrix4::ident_mat());
1748 
1749  t.set_row(3, LVecBase4(light->get_attenuation()[1]));
1750  return &t;
1751 
1752  } else if (attrib == IN_quadraticAttenuation) {
1753  if (node == nullptr) {
1754  return &LMatrix4::zeros_mat();
1755  }
1756  Light *light = node->as_light();
1757  nassertr(light != nullptr, &LMatrix4::ident_mat());
1758 
1759  t.set_row(3, LVecBase4(light->get_attenuation()[2]));
1760  return &t;
1761 
1762  } else if (attrib == IN_shadowViewMatrix) {
1763  static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f,
1764  0.0f, 0.5f, 0.0f, 0.0f,
1765  0.0f, 0.0f, 0.5f, 0.0f,
1766  0.5f, 0.5f, 0.5f, 1.0f);
1767 
1768  if (node == nullptr) {
1769  return &biasmat;
1770  }
1771 
1772  LensNode *lnode;
1773  DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat());
1774  Lens *lens = lnode->get_lens();
1775 
1776  t = _inv_cs_transform->get_mat() *
1777  _scene_setup->get_camera_transform()->get_mat() *
1778  np.get_net_transform()->get_inverse()->get_mat() *
1779  LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system());
1780 
1781  if (!node->is_of_type(PointLight::get_class_type())) {
1782  t *= lens->get_projection_mat() * biasmat;
1783  }
1784  return &t;
1785 
1786  } else {
1787  display_cat.error()
1788  << "Shader input requests invalid attribute " << *attrib
1789  << " from node " << np << "\n";
1790  return &LMatrix4::ident_mat();
1791  }
1792 }
1793 
1794 /**
1795  * Like fetch_specified_value, but for texture inputs.
1796  */
1797 PT(Texture) GraphicsStateGuardian::
1798 fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
1799  int &view) {
1800  switch (spec._part) {
1801  case Shader::STO_named_input:
1802  // Named texture input.
1803  if (!_target_shader->has_shader_input(spec._name)) {
1804  // Is this a member of something, like a node?
1805  const InternalName *parent = spec._name->get_parent();
1806  if (parent != InternalName::get_root() &&
1807  _target_shader->has_shader_input(parent)) {
1808 
1809  // Yes, grab the node.
1810  const string &basename = spec._name->get_basename();
1811  NodePath np = _target_shader->get_shader_input_nodepath(parent);
1812 
1813  if (basename == "shadowMap") {
1814  PT(Texture) tex = get_shadow_map(np);
1815  if (tex != nullptr) {
1816  sampler = tex->get_default_sampler();
1817  }
1818  return tex;
1819 
1820  } else {
1821  if (spec._stage == 0) {
1822  display_cat.error()
1823  << "Shader input " << *parent
1824  << " has no member named " << basename << ".\n";
1825  spec._stage = -1;
1826  }
1827  }
1828  } else {
1829  // This used to be legal for some reason, so don't trigger the assert.
1830  // Prevent flood, though, so abuse the _stage flag to indicate whether
1831  // we've already errored about this.
1832  if (spec._stage == 0) {
1833  display_cat.error()
1834  << "Shader input " << *spec._name << " is not present.\n";
1835  spec._stage = -1;
1836  }
1837  }
1838  } else {
1839  // Just a regular texture input.
1840  return _target_shader->get_shader_input_texture(spec._name, &sampler);
1841  }
1842  break;
1843 
1844  case Shader::STO_stage_i:
1845  {
1846  // We get the TextureAttrib directly from the _target_rs, not the
1847  // filtered TextureAttrib in _target_texture.
1848  const TextureAttrib *texattrib;
1849  _target_rs->get_attrib_def(texattrib);
1850 
1851  if (spec._stage < texattrib->get_num_on_stages()) {
1852  TextureStage *stage = texattrib->get_on_stage(spec._stage);
1853  sampler = texattrib->get_on_sampler(stage);
1854  view += stage->get_tex_view_offset();
1855  return texattrib->get_on_texture(stage);
1856  }
1857  }
1858  break;
1859 
1860  case Shader::STO_light_i_shadow_map:
1861  {
1862  const LightAttrib *target_light;
1863  _target_rs->get_attrib_def(target_light);
1864 
1865  // We don't count ambient lights, which would be pretty silly to handle
1866  // via this mechanism.
1867  size_t num_lights = target_light->get_num_non_ambient_lights();
1868  if (spec._stage >= 0 && (size_t)spec._stage < num_lights) {
1869  NodePath light = target_light->get_on_light((size_t)spec._stage);
1870  nassertr(!light.is_empty(), nullptr);
1871  Light *light_obj = light.node()->as_light();
1872  nassertr(light_obj != nullptr, nullptr);
1873 
1874  PT(Texture) tex = get_shadow_map(light);
1875  if (tex != nullptr) {
1876  sampler = tex->get_default_sampler();
1877  }
1878  return tex;
1879  } else {
1880  // There is no such light assigned. Bind a dummy shadow map.
1881  PT(Texture) tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
1882  if (tex != nullptr) {
1883  sampler = tex->get_default_sampler();
1884  }
1885  return tex;
1886  }
1887  }
1888  break;
1889 
1890  default:
1891  nassertr(false, nullptr);
1892  break;
1893  }
1894 
1895  return nullptr;
1896 }
1897 
1898 /**
1899  * Return a pointer to struct ShaderPtrData
1900  */
1901 const Shader::ShaderPtrData *GraphicsStateGuardian::
1902 fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
1903  return (_target_shader->get_shader_input_ptr(spec._arg));
1904 }
1905 
1906 /**
1907  * Makes the specified DisplayRegion current. All future drawing and clear
1908  * operations will be constrained within the given DisplayRegion.
1909  */
1912  _current_display_region = dr->get_object();
1913  _current_stereo_channel = dr->get_stereo_channel();
1914  _current_tex_view_offset = dr->get_tex_view_offset();
1915  _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render();
1916 
1917  _stereo_buffer_mask = ~0;
1918 
1919  Lens::StereoChannel output_channel = dr->get_stereo_channel();
1920  if (dr->get_window()->get_swap_eyes()) {
1921  // Reverse the output channel.
1922  switch (output_channel) {
1923  case Lens::SC_left:
1924  output_channel = Lens::SC_right;
1925  break;
1926 
1927  case Lens::SC_right:
1928  output_channel = Lens::SC_left;
1929  break;
1930 
1931  default:
1932  break;
1933  }
1934  }
1935 
1936  switch (output_channel) {
1937  case Lens::SC_left:
1938  _color_write_mask = dr->get_window()->get_left_eye_color_mask();
1939  if (_current_properties->is_stereo()) {
1940  _stereo_buffer_mask = ~RenderBuffer::T_right;
1941  }
1942  break;
1943 
1944  case Lens::SC_right:
1945  _color_write_mask = dr->get_window()->get_right_eye_color_mask();
1946  if (_current_properties->is_stereo()) {
1947  _stereo_buffer_mask = ~RenderBuffer::T_left;
1948  }
1949  break;
1950 
1951  case Lens::SC_mono:
1952  case Lens::SC_stereo:
1953  _color_write_mask = ColorWriteAttrib::C_all;
1954  }
1955 }
1956 
1957 /**
1958  * Resets any non-standard graphics state that might give a callback apoplexy.
1959  * Some drivers require that the graphics state be restored to neutral before
1960  * performing certain operations. In OpenGL, for instance, this closes any
1961  * open vertex buffers.
1962  */
1965 }
1966 
1967 /**
1968  * Forgets the current graphics state and current transform, so that the next
1969  * call to set_state_and_transform() will have to reload everything. This is
1970  * a good thing to call when you are no longer sure what the graphics state
1971  * is. This should only be called from the draw thread.
1972  */
1975  // Re-issue the modelview and projection transforms.
1976  reissue_transforms();
1977 
1978  // Now clear the state flags to unknown.
1979  _state_rs = RenderState::make_empty();
1980  _state_mask.clear();
1981 }
1982 
1983 /**
1984  * This is simply a transparent call to GraphicsEngine::remove_window(). It
1985  * exists primary to support removing a window from that compiles before the
1986  * display module, and therefore has no knowledge of a GraphicsEngine object.
1987  */
1990  nassertv(_engine != nullptr);
1991  GraphicsOutput *win;
1992  DCAST_INTO_V(win, window);
1993  _engine->remove_window(win);
1994 }
1995 
1996 /**
1997  * Makes the current lens (whichever lens was most recently specified with
1998  * set_scene()) active, so that it will transform future rendered geometry.
1999  * Normally this is only called from the draw process, and usually it is
2000  * called by set_scene().
2001  *
2002  * The return value is true if the lens is acceptable, false if it is not.
2003  */
2006  return false;
2007 }
2008 
2009 /**
2010  * Given a lens, this function calculates the appropriate projection matrix
2011  * for this gsg. The result depends on the peculiarities of the rendering
2012  * API.
2013  */
2014 CPT(TransformState) GraphicsStateGuardian::
2015 calc_projection_mat(const Lens *lens) {
2016  if (lens == nullptr) {
2017  return nullptr;
2018  }
2019 
2020  if (!lens->is_linear()) {
2021  return nullptr;
2022  }
2023 
2024  return TransformState::make_identity();
2025 }
2026 
2027 /**
2028  * Called before each frame is rendered, to allow the GSG a chance to do any
2029  * internal cleanup before beginning the frame.
2030  *
2031  * The return value is true if successful (in which case the frame will be
2032  * drawn and end_frame() will be called later), or false if unsuccessful (in
2033  * which case nothing will be drawn and end_frame() will not be called).
2034  */
2036 begin_frame(Thread *current_thread) {
2037  _prepared_objects->begin_frame(this, current_thread);
2038 
2039  // We should reset the state to the default at the beginning of every frame.
2040  // Although this will incur additional overhead, particularly in a simple
2041  // scene, it helps ensure that states that have changed properties since
2042  // last time without changing attribute pointers--like textures, lighting,
2043  // or fog--will still be accurately updated.
2044  _state_rs = RenderState::make_empty();
2045  _state_mask.clear();
2046 
2047 #ifdef DO_PSTATS
2048  // We have to do this here instead of in GraphicsEngine because we need a
2049  // current context to issue timer queries.
2051  if (_last_query_frame < frame) {
2052  _last_query_frame = frame;
2053  _timer_queries_pcollector.clear_level();
2054 
2055  // Now is a good time to flush previous frame's queries. We may not
2056  // actually have all of the previous frame's results in yet, but that's
2057  // okay; the GPU data is allowed to lag a few frames behind.
2059 
2060  if (_timer_queries_active) {
2061  // Issue a stop and start event for collector 0, marking the beginning
2062  // of the new frame.
2063  issue_timer_query(0x8000);
2064  issue_timer_query(0x0000);
2065  }
2066  }
2067 #endif
2068 
2069  return !_needs_reset;
2070 }
2071 
2072 /**
2073  * Called between begin_frame() and end_frame() to mark the beginning of
2074  * drawing commands for a "scene" (usually a particular DisplayRegion) within
2075  * a frame. All 3-D drawing commands, except the clear operation, must be
2076  * enclosed within begin_scene() .. end_scene(). This must be called in the
2077  * draw thread.
2078  *
2079  * The return value is true if successful (in which case the scene will be
2080  * drawn and end_scene() will be called later), or false if unsuccessful (in
2081  * which case nothing will be drawn and end_scene() will not be called).
2082  */
2085  return true;
2086 }
2087 
2088 /**
2089  * Called between begin_frame() and end_frame() to mark the end of drawing
2090  * commands for a "scene" (usually a particular DisplayRegion) within a frame.
2091  * All 3-D drawing commands, except the clear operation, must be enclosed
2092  * within begin_scene() .. end_scene().
2093  */
2096  // We should clear this pointer now, so that we don't keep unneeded
2097  // reference counts dangling. We keep around a "null" scene setup object
2098  // instead of using a null pointer to avoid special-case code in
2099  // set_state_and_transform.
2100  _scene_setup = _scene_null;
2101 
2102  // Undo any lighting we had enabled last scene, to force the lights to be
2103  // reissued, in case their parameters or positions have changed between
2104  // scenes.
2105  int i;
2106  for (i = 0; i < _num_lights_enabled; ++i) {
2107  enable_light(i, false);
2108  }
2109  _num_lights_enabled = 0;
2110 
2111  // Ditto for the clipping planes.
2112  for (i = 0; i < _num_clip_planes_enabled; ++i) {
2113  enable_clip_plane(i, false);
2114  }
2115  _num_clip_planes_enabled = 0;
2116 
2117  // Put the state into the 'unknown' state, forcing a reload.
2118  _state_rs = RenderState::make_empty();
2119  _state_mask.clear();
2120 }
2121 
2122 /**
2123  * Called after each frame is rendered, to allow the GSG a chance to do any
2124  * internal cleanup after rendering the frame, and before the window flips.
2125  */
2127 end_frame(Thread *current_thread) {
2128  _prepared_objects->end_frame(current_thread);
2129 
2130  // Flush any PStatCollectors.
2131  _data_transferred_pcollector.flush_level();
2132 
2133  _primitive_batches_pcollector.flush_level();
2134  _primitive_batches_tristrip_pcollector.flush_level();
2135  _primitive_batches_trifan_pcollector.flush_level();
2136  _primitive_batches_tri_pcollector.flush_level();
2137  _primitive_batches_patch_pcollector.flush_level();
2138  _primitive_batches_other_pcollector.flush_level();
2139  _vertices_tristrip_pcollector.flush_level();
2140  _vertices_trifan_pcollector.flush_level();
2141  _vertices_tri_pcollector.flush_level();
2142  _vertices_patch_pcollector.flush_level();
2143  _vertices_other_pcollector.flush_level();
2144 
2145  _state_pcollector.flush_level();
2146  _texture_state_pcollector.flush_level();
2147  _transform_state_pcollector.flush_level();
2148  _draw_primitive_pcollector.flush_level();
2149 
2150  // Evict any textures andor vbuffers that exceed our texture memory.
2151  _prepared_objects->_graphics_memory_lru.begin_epoch();
2152 }
2153 
2154 /**
2155  * Called by the graphics engine on the draw thread to check the status of the
2156  * running timer queries and submit their results to the PStats server.
2157  */
2160 #ifdef DO_PSTATS
2161  // This uses the lower-level PStats interfaces for now because of all the
2162  // unnecessary overhead that would otherwise be incurred when adding such a
2163  // large amount of data at once.
2164 
2165  PStatClient *client = PStatClient::get_global_pstats();
2166 
2167  if (!client->client_is_connected()) {
2168  _timer_queries_active = false;
2169  return;
2170  }
2171 
2172  if (!_timer_queries_active) {
2173  if (pstats_gpu_timing && _supports_timer_query) {
2174  // Check if timer queries should be enabled.
2175  _timer_queries_active = true;
2176  } else {
2177  return;
2178  }
2179  }
2180 
2181  // Currently, we use one thread per GSG, for convenience. In the future, we
2182  // may want to try and use one thread per graphics card.
2183  if (_pstats_gpu_thread == -1) {
2184  _pstats_gpu_thread = client->make_gpu_thread(get_driver_renderer()).get_index();
2185  }
2186  PStatThread gpu_thread(client, _pstats_gpu_thread);
2187 
2188  // Get the results of all the timer queries.
2189  int first = 0;
2190  if (!_pending_timer_queries.empty()) {
2191  int count = _pending_timer_queries.size();
2192  if (count == 0) {
2193  return;
2194  }
2195 
2196  PStatGPUTimer timer(this, _wait_timer_pcollector);
2197 
2198  if (_last_num_queried > 0) {
2199  // We know how many queries were available last frame, and this usually
2200  // stays fairly constant, so use this as a starting point.
2201  int i = std::min(_last_num_queried, count) - 1;
2202 
2203  if (_pending_timer_queries[i]->is_answer_ready()) {
2204  first = count;
2205  while (i < count - 1) {
2206  if (!_pending_timer_queries[++i]->is_answer_ready()) {
2207  first = i;
2208  break;
2209  }
2210  }
2211  } else {
2212  first = 0;
2213  while (i > 0) {
2214  if (_pending_timer_queries[--i]->is_answer_ready()) {
2215  first = i + 1;
2216  break;
2217  }
2218  }
2219  }
2220  } else {
2221  // We figure out which tasks the GPU has already finished by doing a
2222  // binary search for the first query that does not have an answer ready.
2223  // We know then that everything before that must be ready.
2224  while (count > 0) {
2225  int step = count / 2;
2226  int i = first + step;
2227  if (_pending_timer_queries[i]->is_answer_ready()) {
2228  first += step + 1;
2229  count -= step + 1;
2230  } else {
2231  count = step;
2232  }
2233  }
2234  }
2235 
2236  if (first <= 0) {
2237  return;
2238  }
2239 
2240  _last_num_queried = first;
2241 
2242  for (int i = 0; i < first; ++i) {
2243  CPT(TimerQueryContext) query = _pending_timer_queries[i];
2244 
2245  double time_data = query->get_timestamp(); // + _timer_delta;
2246 
2247  if (query->_pstats_index == _command_latency_pcollector.get_index()) {
2248  // Special case for the latency pcollector.
2249  PStatCollectorDef *cdef;
2250  cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
2251  _pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
2252 
2253  } else if (query->_pstats_index & 0x8000) {
2254  _pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
2255 
2256  } else {
2257  _pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
2258  }
2259 
2260  // We found an end-frame marker (a stop event for collector 0). This
2261  // means that the GPU actually caught up with that frame, and we can
2262  // flush the GPU thread's frame data to the pstats server.
2263  if (query->_pstats_index == 0x8000) {
2264  gpu_thread.add_frame(_pstats_gpu_data);
2265  _pstats_gpu_data.clear();
2266  }
2267  }
2268  }
2269 
2270  if (first > 0) {
2271  // Do this out of the scope of _wait_timer_pcollector.
2272  _pending_timer_queries.erase(
2273  _pending_timer_queries.begin(),
2274  _pending_timer_queries.begin() + first
2275  );
2276  _timer_queries_pcollector.add_level_now(first);
2277  }
2278 #endif
2279 }
2280 
2281 /**
2282  * Returns true if this GSG can implement decals using a DepthOffsetAttrib, or
2283  * false if that is unreliable and the three-step rendering process should be
2284  * used instead.
2285  */
2288  return true;
2289 }
2290 
2291 /**
2292  * Called during draw to begin a three-step rendering phase to draw decals.
2293  * The first step, begin_decal_base_first(), is called prior to drawing the
2294  * base geometry. It should set up whatever internal state is appropriate, as
2295  * well as returning a RenderState object that should be applied to the base
2296  * geometry for rendering.
2297  */
2298 CPT(RenderState) GraphicsStateGuardian::
2299 begin_decal_base_first() {
2300  // Turn off writing the depth buffer to render the base geometry.
2301  static CPT(RenderState) decal_base_first;
2302  if (decal_base_first == nullptr) {
2303  decal_base_first = RenderState::make
2304  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2305  RenderState::get_max_priority());
2306  }
2307  return decal_base_first;
2308 }
2309 
2310 /**
2311  * Called during draw to begin a three-step rendering phase to draw decals.
2312  * The second step, begin_decal_nested(), is called after drawing the base
2313  * geometry and prior to drawing any of the nested decal geometry that is to
2314  * be applied to the base geometry.
2315  */
2316 CPT(RenderState) GraphicsStateGuardian::
2317 begin_decal_nested() {
2318  // We should keep the depth buffer off during this operation, so that decals
2319  // on decals will render properly.
2320  static CPT(RenderState) decal_nested;
2321  if (decal_nested == nullptr) {
2322  decal_nested = RenderState::make
2323  (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2324  RenderState::get_max_priority());
2325  }
2326  return decal_nested;
2327 }
2328 
2329 /**
2330  * Called during draw to begin a three-step rendering phase to draw decals.
2331  * The third step, begin_decal_base_second(), is called after drawing the base
2332  * geometry and the nested decal geometry, and prior to drawing the base
2333  * geometry one more time (if needed).
2334  *
2335  * It should return a RenderState object appropriate for rendering the base
2336  * geometry the second time, or NULL if it is not necessary to re-render the
2337  * base geometry.
2338  */
2339 CPT(RenderState) GraphicsStateGuardian::
2340 begin_decal_base_second() {
2341  // Now let the depth buffer go back on, but turn off writing the color
2342  // buffer to render the base geometry after the second pass. Also, turn off
2343  // texturing since there's no need for it now.
2344  static CPT(RenderState) decal_base_second;
2345  if (decal_base_second == nullptr) {
2346  decal_base_second = RenderState::make
2347  (ColorWriteAttrib::make(ColorWriteAttrib::C_off),
2348  // On reflection, we need to leave texturing on so the alpha test
2349  // mechanism can work (if it is enabled, e.g. we are rendering an
2350  // object with M_dual transparency). TextureAttrib::make_off(),
2351  RenderState::get_max_priority());
2352  }
2353  return decal_base_second;
2354 }
2355 
2356 /**
2357  * Called during draw to clean up after decals are finished.
2358  */
2361  // No need to do anything special here.
2362 }
2363 
2364 /**
2365  * Called before a sequence of draw_primitive() functions are called, this
2366  * should prepare the vertex data for rendering. It returns true if the
2367  * vertices are ok, false to abort this group of primitives.
2368  */
2371  const GeomVertexDataPipelineReader *data_reader,
2372  bool force) {
2373  _data_reader = data_reader;
2374 
2375  // Always draw if we have a shader, since the shader might use a different
2376  // mechanism for fetching vertex data.
2377  return _data_reader->has_vertex() || (_target_shader && _target_shader->has_shader());
2378 }
2379 
2380 /**
2381  * Draws a series of disconnected triangles.
2382  */
2385  return false;
2386 }
2387 
2388 
2389 /**
2390  * Draws a series of disconnected triangles with adjacency information.
2391  */
2394  return false;
2395 }
2396 
2397 /**
2398  * Draws a series of triangle strips.
2399  */
2402  return false;
2403 }
2404 
2405 /**
2406  * Draws a series of triangle strips with adjacency information.
2407  */
2410  return false;
2411 }
2412 
2413 /**
2414  * Draws a series of triangle fans.
2415  */
2418  return false;
2419 }
2420 
2421 /**
2422  * Draws a series of "patches", which can only be processed by a tessellation
2423  * shader.
2424  */
2427  return false;
2428 }
2429 
2430 /**
2431  * Draws a series of disconnected line segments.
2432  */
2435  return false;
2436 }
2437 
2438 /**
2439  * Draws a series of disconnected line segments with adjacency information.
2440  */
2443  return false;
2444 }
2445 
2446 /**
2447  * Draws a series of line strips.
2448  */
2451  return false;
2452 }
2453 
2454 /**
2455  * Draws a series of line strips with adjacency information.
2456  */
2459  return false;
2460 }
2461 
2462 /**
2463  * Draws a series of disconnected points.
2464  */
2467  return false;
2468 }
2469 
2470 /**
2471  * Called after a sequence of draw_primitive() functions are called, this
2472  * should do whatever cleanup is appropriate.
2473  */
2476  _data_reader = nullptr;
2477 }
2478 
2479 /**
2480  * Resets all internal state as if the gsg were newly created.
2481  */
2484  _needs_reset = false;
2485  _is_valid = false;
2486 
2487  _state_rs = RenderState::make_empty();
2488  _target_rs = nullptr;
2489  _state_mask.clear();
2490  _internal_transform = _cs_transform;
2491  _scene_null = new SceneSetup;
2492  _scene_setup = _scene_null;
2493 
2494  _color_write_mask = ColorWriteAttrib::C_all;
2495 
2496  _has_scene_graph_color = false;
2497  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2498  _transform_stale = true;
2499  _color_blend_involves_color_scale = false;
2500  _texture_involves_color_scale = false;
2501  _vertex_colors_enabled = true;
2502  _lighting_enabled = false;
2503  _num_lights_enabled = 0;
2504  _num_clip_planes_enabled = 0;
2505  _clip_planes_enabled = false;
2506 
2507  _color_scale_enabled = false;
2508  _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2509  _has_texture_alpha_scale = false;
2510 
2511  _has_material_force_color = false;
2512  _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2513  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2514 
2515  _tex_gen_modifies_mat = false;
2516  _last_max_stage_index = 0;
2517 
2518  _is_valid = true;
2519 }
2520 
2521 /**
2522  * Simultaneously resets the render state and the transform state.
2523  *
2524  * This transform specified is the "internal" net transform, already converted
2525  * into the GSG's internal coordinate space by composing it to
2526  * get_cs_transform(). (Previously, this used to be the "external" net
2527  * transform, with the assumption that that GSG would convert it internally,
2528  * but that is no longer the case.)
2529  *
2530  * Special case: if (state==NULL), then the target state is already stored in
2531  * _target.
2532  */
2535  const TransformState *trans) {
2536 }
2537 
2538 /**
2539  * Clears the framebuffer within the current DisplayRegion, according to the
2540  * flags indicated by the given DrawableRegion object.
2541  *
2542  * This does not set the DisplayRegion first. You should call
2543  * prepare_display_region() to specify the region you wish the clear operation
2544  * to apply to.
2545  */
2547 clear(DrawableRegion *clearable) {
2548 }
2549 
2550 /**
2551  * Returns a RenderBuffer object suitable for operating on the requested set
2552  * of buffers. buffer_type is the union of all the desired RenderBuffer::Type
2553  * values.
2554  */
2556 get_render_buffer(int buffer_type, const FrameBufferProperties &prop) {
2557  return RenderBuffer(this, buffer_type & prop.get_buffer_mask() & _stereo_buffer_mask);
2558 }
2559 
2560 /**
2561  * Returns what the cs_transform would be set to after a call to
2562  * set_coordinate_system(cs). This is another way of saying the cs_transform
2563  * when rendering the scene for a camera with the indicated coordinate system.
2564  */
2565 CPT(TransformState) GraphicsStateGuardian::
2566 get_cs_transform_for(CoordinateSystem cs) const {
2567  if (_coordinate_system == cs) {
2568  // We've already calculated this.
2569  return _cs_transform;
2570 
2571  } else if (_internal_coordinate_system == CS_default ||
2572  _internal_coordinate_system == cs) {
2573  return TransformState::make_identity();
2574 
2575  } else {
2576  return TransformState::make_mat
2577  (LMatrix4::convert_mat(cs, _internal_coordinate_system));
2578  }
2579 }
2580 
2581 /**
2582  * Returns a transform that converts from the GSG's external coordinate system
2583  * (as returned by get_coordinate_system()) to its internal coordinate system
2584  * (as returned by get_internal_coordinate_system()). This is used for
2585  * rendering.
2586  */
2587 CPT(TransformState) GraphicsStateGuardian::
2588 get_cs_transform() const {
2589  return _cs_transform;
2590 }
2591 
2592 /**
2593  * This is fundametically similar to do_issue_light(), with calls to
2594  * apply_clip_plane() and enable_clip_planes(), as appropriate.
2595  */
2596 void GraphicsStateGuardian::
2597 do_issue_clip_plane() {
2598  int num_enabled = 0;
2599  int num_on_planes = 0;
2600 
2601  const ClipPlaneAttrib *target_clip_plane = (const ClipPlaneAttrib *)
2602  _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot());
2603 
2604  if (target_clip_plane != nullptr) {
2605  CPT(ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
2606 
2607  num_on_planes = new_plane->get_num_on_planes();
2608  for (int li = 0; li < num_on_planes; li++) {
2609  NodePath plane = new_plane->get_on_plane(li);
2610  nassertv(!plane.is_empty());
2611  PlaneNode *plane_node;
2612  DCAST_INTO_V(plane_node, plane.node());
2613  if ((plane_node->get_clip_effect() & PlaneNode::CE_visible) != 0) {
2614  // Clipping should be enabled before we apply any planes.
2615  if (!_clip_planes_enabled) {
2616  enable_clip_planes(true);
2617  _clip_planes_enabled = true;
2618  }
2619 
2620  enable_clip_plane(num_enabled, true);
2621  if (num_enabled == 0) {
2622  begin_bind_clip_planes();
2623  }
2624 
2625  bind_clip_plane(plane, num_enabled);
2626  num_enabled++;
2627  }
2628  }
2629  }
2630 
2631  int i;
2632  for (i = num_enabled; i < _num_clip_planes_enabled; ++i) {
2633  enable_clip_plane(i, false);
2634  }
2635  _num_clip_planes_enabled = num_enabled;
2636 
2637  // If no planes were set, disable clipping
2638  if (num_enabled == 0) {
2639  if (_clip_planes_enabled) {
2640  enable_clip_planes(false);
2641  _clip_planes_enabled = false;
2642  }
2643  } else {
2644  end_bind_clip_planes();
2645  }
2646 }
2647 
2648 /**
2649  * This method is defined in the base class because it is likely that this
2650  * functionality will be used for all (or at least most) kinds of
2651  * GraphicsStateGuardians--it's not specific to any one rendering backend.
2652  *
2653  * The ColorAttribute just changes the interpretation of the color on the
2654  * vertices, and fiddles with _vertex_colors_enabled, etc.
2655  */
2658  const ColorAttrib *target_color = (const ColorAttrib *)
2659  _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
2660 
2661  switch (target_color->get_color_type()) {
2662  case ColorAttrib::T_flat:
2663  // Color attribute flat: it specifies a scene graph color that overrides
2664  // the vertex color.
2665  _scene_graph_color = target_color->get_color();
2666  _has_scene_graph_color = true;
2667  _vertex_colors_enabled = false;
2668  break;
2669 
2670  case ColorAttrib::T_off:
2671  // Color attribute off: it specifies that no scene graph color is in
2672  // effect, and vertex color is not important either.
2673  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2674  _has_scene_graph_color = false;
2675  _vertex_colors_enabled = false;
2676  break;
2677 
2678  case ColorAttrib::T_vertex:
2679  // Color attribute vertex: it specifies that vertex color should be
2680  // revealed.
2681  _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2682  _has_scene_graph_color = false;
2683  _vertex_colors_enabled = true;
2684  break;
2685  }
2686 
2687  if (_color_scale_via_lighting) {
2688  _state_mask.clear_bit(LightAttrib::get_class_slot());
2689  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2690 
2691  determine_light_color_scale();
2692  }
2693 }
2694 
2695 /**
2696  *
2697  */
2698 void GraphicsStateGuardian::
2699 do_issue_color_scale() {
2700  // If the previous color scale had set a special texture, clear the texture
2701  // now.
2702  if (_has_texture_alpha_scale) {
2703  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2704  }
2705 
2706  const ColorScaleAttrib *target_color_scale = (const ColorScaleAttrib *)
2707  _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
2708 
2709  _color_scale_enabled = target_color_scale->has_scale();
2710  _current_color_scale = target_color_scale->get_scale();
2711  _has_texture_alpha_scale = false;
2712 
2713  if (_color_blend_involves_color_scale) {
2714  _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
2715  }
2716  if (_texture_involves_color_scale) {
2717  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2718  }
2719  if (_color_scale_via_lighting) {
2720  _state_mask.clear_bit(LightAttrib::get_class_slot());
2721  _state_mask.clear_bit(MaterialAttrib::get_class_slot());
2722 
2723  determine_light_color_scale();
2724  }
2725 
2726  if (_alpha_scale_via_texture && !_has_scene_graph_color &&
2727  _vertex_colors_enabled && target_color_scale->has_alpha_scale()) {
2728  // This color scale will set a special texture--so again, clear the
2729  // texture.
2730  _state_mask.clear_bit(TextureAttrib::get_class_slot());
2731  _state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
2732 
2733  _has_texture_alpha_scale = true;
2734  }
2735 }
2736 
2737 /**
2738  * This implementation of do_issue_light() assumes we have a limited number of
2739  * hardware lights available. This function assigns each light to a different
2740  * hardware light id, trying to keep each light associated with the same id
2741  * where possible, but reusing id's when necessary. When it is no longer
2742  * possible to reuse existing id's (e.g. all id's are in use), the next
2743  * sequential id is assigned (if available).
2744  *
2745  * It will call apply_light() each time a light is assigned to a particular id
2746  * for the first time in a given frame, and it will subsequently call
2747  * enable_light() to enable or disable each light as the frame is rendered, as
2748  * well as enable_lighting() to enable or disable overall lighting.
2749  */
2752  // Initialize the current ambient light total and newly enabled light list
2753  LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
2754  int i;
2755 
2756  int num_enabled = 0;
2757  bool any_on_lights = false;
2758 
2759  const LightAttrib *target_light;
2760  _target_rs->get_attrib_def(target_light);
2761 
2762  if (display_cat.is_spam()) {
2763  display_cat.spam()
2764  << "do_issue_light: " << target_light << "\n";
2765  }
2766  if (target_light != nullptr) {
2767  // LightAttrib guarantees that the on lights are sorted, and that
2768  // non-ambient lights come before ambient lights.
2769  any_on_lights = target_light->has_any_on_light();
2770  size_t filtered_lights = std::min((size_t)_max_lights, target_light->get_num_non_ambient_lights());
2771  for (size_t li = 0; li < filtered_lights; ++li) {
2772  NodePath light = target_light->get_on_light(li);
2773  nassertv(!light.is_empty());
2774  Light *light_obj = light.node()->as_light();
2775  nassertv(light_obj != nullptr);
2776 
2777  // Lighting should be enabled before we apply any lights.
2778  if (!_lighting_enabled) {
2779  enable_lighting(true);
2780  _lighting_enabled = true;
2781  }
2782 
2783  const LColor &color = light_obj->get_color();
2784  // Don't bother binding the light if it has no color to contribute.
2785  if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
2786  enable_light(num_enabled, true);
2787  if (num_enabled == 0) {
2788  begin_bind_lights();
2789  }
2790 
2791  light_obj->bind(this, light, num_enabled);
2792  num_enabled++;
2793  }
2794  }
2795  }
2796 
2797  for (i = num_enabled; i < _num_lights_enabled; ++i) {
2798  enable_light(i, false);
2799  }
2800  _num_lights_enabled = num_enabled;
2801 
2802  // If no lights were set, disable lighting
2803  if (!any_on_lights) {
2804  if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f))) {
2805  // Unless we need lighting anyway to apply a color or color scale.
2806  if (!_lighting_enabled) {
2807  enable_lighting(true);
2808  _lighting_enabled = true;
2809  }
2810  set_ambient_light(LColor(1.0f, 1.0f, 1.0f, 1.0f));
2811 
2812  } else {
2813  if (_lighting_enabled) {
2814  enable_lighting(false);
2815  _lighting_enabled = false;
2816  }
2817  }
2818 
2819  } else {
2820  // Don't forget to still enable lighting if we have only an ambient light.
2821  if (!_lighting_enabled) {
2822  enable_lighting(true);
2823  _lighting_enabled = true;
2824  }
2825 
2826  set_ambient_light(target_light->get_ambient_contribution());
2827  }
2828 
2829  if (num_enabled != 0) {
2830  end_bind_lights();
2831  }
2832 }
2833 
2834 /**
2835  * Copy the pixels within the indicated display region from the framebuffer
2836  * into texture memory.
2837  *
2838  * If z > -1, it is the cube map index into which to copy.
2839  */
2842  const RenderBuffer &) {
2843  return false;
2844 }
2845 
2846 
2847 /**
2848  * Copy the pixels within the indicated display region from the framebuffer
2849  * into system memory, not texture memory. Returns true on success, false on
2850  * failure.
2851  *
2852  * This completely redefines the ram image of the indicated texture.
2853  */
2856  const RenderBuffer &) {
2857  return false;
2858 }
2859 
2860 /**
2861  * Called the first time a particular light has been bound to a given id
2862  * within a frame, this should set up the associated hardware light with the
2863  * light's properties.
2864  */
2866 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
2867 }
2868 
2869 /**
2870  * Called the first time a particular light has been bound to a given id
2871  * within a frame, this should set up the associated hardware light with the
2872  * light's properties.
2873  */
2875 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
2876 }
2877 
2878 /**
2879  * Called the first time a particular light has been bound to a given id
2880  * within a frame, this should set up the associated hardware light with the
2881  * light's properties.
2882  */
2884 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
2885 }
2886 
2887 #ifdef DO_PSTATS
2888 /**
2889  * Initializes the relevant PStats data at the beginning of the frame.
2890  */
2891 void GraphicsStateGuardian::
2892 init_frame_pstats() {
2893  if (PStatClient::is_connected()) {
2894  _data_transferred_pcollector.clear_level();
2895  _vertex_buffer_switch_pcollector.clear_level();
2896  _index_buffer_switch_pcollector.clear_level();
2897 
2898  _primitive_batches_pcollector.clear_level();
2899  _primitive_batches_tristrip_pcollector.clear_level();
2900  _primitive_batches_trifan_pcollector.clear_level();
2901  _primitive_batches_tri_pcollector.clear_level();
2902  _primitive_batches_patch_pcollector.clear_level();
2903  _primitive_batches_other_pcollector.clear_level();
2904  _vertices_tristrip_pcollector.clear_level();
2905  _vertices_trifan_pcollector.clear_level();
2906  _vertices_tri_pcollector.clear_level();
2907  _vertices_patch_pcollector.clear_level();
2908  _vertices_other_pcollector.clear_level();
2909 
2910  _state_pcollector.clear_level();
2911  _transform_state_pcollector.clear_level();
2912  _texture_state_pcollector.clear_level();
2913  }
2914 }
2915 #endif // DO_PSTATS
2916 
2917 
2918 /**
2919  * Create a gamma table.
2920  */
2922 create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
2923  int i;
2924 
2925  if (gamma <= 0.0) {
2926  // avoid divide by zero and negative exponents
2927  gamma = 1.0;
2928  }
2929 
2930  for (i = 0; i < 256; i++) {
2931  double g;
2932  double x;
2933  PN_stdfloat gamma_correction;
2934 
2935  x = ((double) i / 255.0);
2936  gamma_correction = 1.0 / gamma;
2937  x = pow (x, (double) gamma_correction);
2938  if (x > 1.00) {
2939  x = 1.0;
2940  }
2941 
2942  g = x * 65535.0;
2943  red_table [i] = (int)g;
2944  green_table [i] = (int)g;
2945  blue_table [i] = (int)g;
2946  }
2947 }
2948 
2949 /**
2950  * Called by clear_state_and_transform() to ensure that the current modelview
2951  * and projection matrices are properly loaded in the graphics state, after a
2952  * callback might have mucked them up.
2953  */
2954 void GraphicsStateGuardian::
2955 reissue_transforms() {
2956 }
2957 
2958 /**
2959  * Intended to be overridden by a derived class to enable or disable the use
2960  * of lighting overall. This is called by do_issue_light() according to
2961  * whether any lights are in use or not.
2962  */
2963 void GraphicsStateGuardian::
2964 enable_lighting(bool enable) {
2965 }
2966 
2967 /**
2968  * Intended to be overridden by a derived class to indicate the color of the
2969  * ambient light that should be in effect. This is called by do_issue_light()
2970  * after all other lights have been enabled or disabled.
2971  */
2972 void GraphicsStateGuardian::
2973 set_ambient_light(const LColor &color) {
2974 }
2975 
2976 /**
2977  * Intended to be overridden by a derived class to enable the indicated light
2978  * id. A specific Light will already have been bound to this id via
2979  * bind_light().
2980  */
2981 void GraphicsStateGuardian::
2982 enable_light(int light_id, bool enable) {
2983 }
2984 
2985 /**
2986  * Called immediately before bind_light() is called, this is intended to
2987  * provide the derived class a hook in which to set up some state (like
2988  * transform) that might apply to several lights.
2989  *
2990  * The sequence is: begin_bind_lights() will be called, then one or more
2991  * bind_light() calls, then end_bind_lights().
2992  */
2993 void GraphicsStateGuardian::
2994 begin_bind_lights() {
2995 }
2996 
2997 /**
2998  * Called after before bind_light() has been called one or more times (but
2999  * before any geometry is issued or additional state is changed), this is
3000  * intended to clean up any temporary changes to the state that may have been
3001  * made by begin_bind_lights().
3002  */
3003 void GraphicsStateGuardian::
3004 end_bind_lights() {
3005 }
3006 
3007 /**
3008  * Intended to be overridden by a derived class to enable or disable the use
3009  * of clipping planes overall. This is called by do_issue_clip_plane()
3010  * according to whether any planes are in use or not.
3011  */
3012 void GraphicsStateGuardian::
3013 enable_clip_planes(bool enable) {
3014 }
3015 
3016 /**
3017  * Intended to be overridden by a derived class to enable the indicated plane
3018  * id. A specific PlaneNode will already have been bound to this id via
3019  * bind_clip_plane().
3020  */
3021 void GraphicsStateGuardian::
3022 enable_clip_plane(int plane_id, bool enable) {
3023 }
3024 
3025 /**
3026  * Called immediately before bind_clip_plane() is called, this is intended to
3027  * provide the derived class a hook in which to set up some state (like
3028  * transform) that might apply to several planes.
3029  *
3030  * The sequence is: begin_bind_clip_planes() will be called, then one or more
3031  * bind_clip_plane() calls, then end_bind_clip_planes().
3032  */
3033 void GraphicsStateGuardian::
3034 begin_bind_clip_planes() {
3035 }
3036 
3037 /**
3038  * Called the first time a particular clipping plane has been bound to a given
3039  * id within a frame, this should set up the associated hardware (or API)
3040  * clipping plane with the plane's properties.
3041  */
3042 void GraphicsStateGuardian::
3043 bind_clip_plane(const NodePath &plane, int plane_id) {
3044 }
3045 
3046 /**
3047  * Called after before bind_clip_plane() has been called one or more times
3048  * (but before any geometry is issued or additional state is changed), this is
3049  * intended to clean up any temporary changes to the state that may have been
3050  * made by begin_bind_clip_planes().
3051  */
3052 void GraphicsStateGuardian::
3053 end_bind_clip_planes() {
3054 }
3055 
3056 /**
3057  * Assigns _target_texture and _target_tex_gen based on the _target_rs.
3058  */
3059 void GraphicsStateGuardian::
3060 determine_target_texture() {
3061  const TextureAttrib *target_texture = (const TextureAttrib *)
3062  _target_rs->get_attrib_def(TextureAttrib::get_class_slot());
3063  const TexGenAttrib *target_tex_gen = (const TexGenAttrib *)
3064  _target_rs->get_attrib_def(TexGenAttrib::get_class_slot());
3065 
3066  nassertv(target_texture != nullptr &&
3067  target_tex_gen != nullptr);
3068  _target_texture = target_texture;
3069  _target_tex_gen = target_tex_gen;
3070 
3071  if (_has_texture_alpha_scale) {
3073  PT(Texture) texture = TexturePool::get_alpha_scale_map();
3074 
3075  _target_texture = DCAST(TextureAttrib, _target_texture->add_on_stage(stage, texture));
3076  _target_tex_gen = DCAST(TexGenAttrib, _target_tex_gen->add_stage
3077  (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
3078  }
3079 
3080  int max_texture_stages = get_max_texture_stages();
3081  _target_texture = _target_texture->filter_to_max(max_texture_stages);
3082  nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
3083 }
3084 
3085 /**
3086  * Assigns _target_shader based on the _target_rs.
3087  */
3088 void GraphicsStateGuardian::
3089 determine_target_shader() {
3090  if (_target_rs->_generated_shader != nullptr) {
3091  _target_shader = (const ShaderAttrib *)_target_rs->_generated_shader.p();
3092  } else {
3093  _target_shader = (const ShaderAttrib *)
3094  _target_rs->get_attrib_def(ShaderAttrib::get_class_slot());
3095  }
3096 }
3097 
3098 /**
3099  * Frees some memory that was explicitly allocated within the glgsg.
3100  */
3101 void GraphicsStateGuardian::
3102 free_pointers() {
3103 }
3104 
3105 /**
3106  * This is called by the associated GraphicsWindow when close_window() is
3107  * called. It should null out the _win pointer and possibly free any open
3108  * resources associated with the GSG.
3109  */
3110 void GraphicsStateGuardian::
3111 close_gsg() {
3112  // Protect from multiple calls, and also inform any other functions not to
3113  // try to create new stuff while we're going down.
3114  if (_closing_gsg) {
3115  return;
3116  }
3117  _closing_gsg = true;
3118 
3119  if (display_cat.is_debug()) {
3120  display_cat.debug()
3121  << this << " close_gsg " << get_type() << "\n";
3122  }
3123 
3124  // As tempting as it may be to try to release all the textures and geoms
3125  // now, we can't, because we might not be the currently-active GSG (this is
3126  // particularly important in OpenGL, which maintains one currently-active GL
3127  // state in each thread). If we start deleting textures, we'll be
3128  // inadvertently deleting textures from some other OpenGL state.
3129 
3130  // Fortunately, it doesn't really matter, since the graphics API will be
3131  // responsible for cleaning up anything we don't clean up explicitly. We'll
3132  // just let them drop.
3133 
3134  // Make sure that all the contexts belonging to the GSG are deleted.
3135  _prepared_objects.clear();
3136 #ifdef DO_PSTATS
3137  _pending_timer_queries.clear();
3138 #endif
3139 
3140  free_pointers();
3141 }
3142 
3143 /**
3144  * This is called internally when it is determined that things are just fubar.
3145  * It temporarily deactivates the GSG just so things don't get out of hand,
3146  * and throws an event so the application can deal with this if it needs to.
3147  */
3148 void GraphicsStateGuardian::
3149 panic_deactivate() {
3150  if (_active) {
3151  display_cat.error()
3152  << "Deactivating " << get_type() << ".\n";
3153  set_active(false);
3154  throw_event("panic-deactivate-gsg", this);
3155  }
3156 }
3157 
3158 /**
3159  * Called whenever the color or color scale is changed, if
3160  * _color_scale_via_lighting is true. This will rederive
3161  * _material_force_color and _light_color_scale appropriately.
3162  */
3163 void GraphicsStateGuardian::
3164 determine_light_color_scale() {
3165  if (_has_scene_graph_color) {
3166  // If we have a scene graph color, it, plus the color scale, goes directly
3167  // into the material; we don't color scale the lights--this allows an
3168  // alpha color scale to work properly.
3169  _has_material_force_color = true;
3170  _material_force_color = _scene_graph_color;
3171  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3172  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3173  _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
3174  _scene_graph_color[1] * _current_color_scale[1],
3175  _scene_graph_color[2] * _current_color_scale[2],
3176  _scene_graph_color[3] * _current_color_scale[3]);
3177  }
3178 
3179  } else if (!_vertex_colors_enabled) {
3180  // We don't have a scene graph color, but we don't want to enable vertex
3181  // colors either, so we still need to force a white material color in
3182  // absence of any other color.
3183  _has_material_force_color = true;
3184  _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
3185  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3186  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3187  _material_force_color.componentwise_mult(_current_color_scale);
3188  }
3189 
3190  } else {
3191  // Otherise, leave the materials alone, but we might still scale the
3192  // lights.
3193  _has_material_force_color = false;
3194  _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3195  if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3196  _light_color_scale = _current_color_scale;
3197  }
3198  }
3199 }
3200 
3201 /**
3202  *
3203  */
3204 CPT(RenderState) GraphicsStateGuardian::
3205 get_unlit_state() {
3206  static CPT(RenderState) state = nullptr;
3207  if (state == nullptr) {
3208  state = RenderState::make(LightAttrib::make_all_off());
3209  }
3210  return state;
3211 }
3212 
3213 /**
3214  *
3215  */
3216 CPT(RenderState) GraphicsStateGuardian::
3217 get_unclipped_state() {
3218  static CPT(RenderState) state = nullptr;
3219  if (state == nullptr) {
3220  state = RenderState::make(ClipPlaneAttrib::make_all_off());
3221  }
3222  return state;
3223 }
3224 
3225 /**
3226  *
3227  */
3228 CPT(RenderState) GraphicsStateGuardian::
3229 get_untextured_state() {
3230  static CPT(RenderState) state = nullptr;
3231  if (state == nullptr) {
3232  state = RenderState::make(TextureAttrib::make_off());
3233  }
3234  return state;
3235 }
3236 
3237 /**
3238  * Should be called when a texture is encountered that needs to have its RAM
3239  * image reloaded, and get_incomplete_render() is true. This will fire off a
3240  * thread on the current Loader object that will request the texture to load
3241  * its image. The image will be available at some point in the future.
3242  * @returns a future object that can be used to check its status.
3243  */
3244 AsyncFuture *GraphicsStateGuardian::
3245 async_reload_texture(TextureContext *tc) {
3246  nassertr(_loader != nullptr, nullptr);
3247 
3248  int priority = 0;
3249  if (_current_display_region != nullptr) {
3250  priority = _current_display_region->get_texture_reload_priority();
3251  }
3252 
3253  string task_name = string("reload:") + tc->get_texture()->get_name();
3254  PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
3255 
3256  // See if we are already loading this task.
3257  AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
3258  size_t num_tasks = orig_tasks.get_num_tasks();
3259  for (size_t ti = 0; ti < num_tasks; ++ti) {
3260  AsyncTask *task = orig_tasks.get_task(ti);
3261  if (task->is_exact_type(TextureReloadRequest::get_class_type()) &&
3262  ((TextureReloadRequest *)task)->get_texture() == tc->get_texture()) {
3263  // This texture is already queued to be reloaded. Don't queue it again,
3264  // just make sure the priority is updated, and return.
3265  task->set_priority(std::max(task->get_priority(), priority));
3266  return (AsyncFuture *)task;
3267  }
3268  }
3269 
3270  // This texture has not yet been queued to be reloaded. Queue it up now.
3271  PT(AsyncTask) request =
3272  new TextureReloadRequest(task_name,
3273  _prepared_objects, tc->get_texture(),
3274  _supports_compressed_texture);
3275  request->set_priority(priority);
3276  _loader->load_async(request);
3277  return (AsyncFuture *)request.p();
3278 }
3279 
3280 /**
3281  * Returns a shadow map for the given light source. If none exists, it is
3282  * created, using the given host window to create the buffer, or the current
3283  * window if that is set to NULL.
3284  */
3285 PT(Texture) GraphicsStateGuardian::
3286 get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
3287  PandaNode *node = light_np.node();
3288  bool is_point = node->is_of_type(PointLight::get_class_type());
3289  nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
3290  node->is_of_type(Spotlight::get_class_type()) ||
3291  is_point, nullptr);
3292 
3293  LightLensNode *light = (LightLensNode *)node;
3294  if (light == nullptr || !light->_shadow_caster) {
3295  // This light does not have a shadow caster. Return a dummy shadow map
3296  // that is filled with a depth value of 1.
3297  if (node->is_of_type(PointLight::get_class_type())) {
3298  return get_dummy_shadow_map(Texture::TT_cube_map);
3299  } else {
3300  return get_dummy_shadow_map(Texture::TT_2d_texture);
3301  }
3302  }
3303 
3304  // The light's shadow map should have been created by set_shadow_caster().
3305  nassertr(light->_shadow_map != nullptr, nullptr);
3306 
3307  // See if we already have a buffer. If not, create one.
3308  if (light->_sbuffers.count(this) != 0) {
3309  // There's already a buffer - use that.
3310  return light->_shadow_map;
3311  }
3312 
3313  if (display_cat.is_debug()) {
3314  display_cat.debug()
3315  << "Constructing shadow buffer for light '" << light->get_name()
3316  << "', size=" << light->_sb_size[0] << "x" << light->_sb_size[1]
3317  << ", sort=" << light->_sb_sort << "\n";
3318  }
3319 
3320  if (host == nullptr) {
3321  nassertr(_current_display_region != nullptr, nullptr);
3322  host = _current_display_region->get_window();
3323  }
3324  nassertr(host != nullptr, nullptr);
3325 
3326  // Nope, the light doesn't have a buffer for our GSG. Make one.
3327  GraphicsOutput *sbuffer = make_shadow_buffer(light, light->_shadow_map,
3328  DCAST(GraphicsOutput, host));
3329 
3330  // Assign display region(s) to the buffer and camera
3331  if (is_point) {
3332  for (int i = 0; i < 6; ++i) {
3333  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3334  dr->set_lens_index(i);
3335  dr->set_target_tex_page(i);
3336  dr->set_camera(light_np);
3337  dr->set_clear_depth_active(true);
3338  }
3339  } else {
3340  PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1);
3341  dr->set_camera(light_np);
3342  dr->set_clear_depth_active(true);
3343  }
3344 
3345  light->_sbuffers[this] = sbuffer;
3346  return light->_shadow_map;
3347 }
3348 
3349 /**
3350  * Returns a dummy shadow map that can be used for a light of the given type
3351  * that does not cast shadows.
3352  */
3353 PT(Texture) GraphicsStateGuardian::
3354 get_dummy_shadow_map(Texture::TextureType texture_type) const {
3355  if (texture_type != Texture::TT_cube_map) {
3356  static PT(Texture) dummy_2d;
3357  if (dummy_2d == nullptr) {
3358  dummy_2d = new Texture("dummy-shadow-2d");
3359  dummy_2d->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_depth_component);
3360  dummy_2d->set_clear_color(1);
3362  // If we have the ARB_shadow extension, enable shadow filtering.
3363  dummy_2d->set_minfilter(SamplerState::FT_shadow);
3364  dummy_2d->set_magfilter(SamplerState::FT_shadow);
3365  } else {
3366  dummy_2d->set_minfilter(SamplerState::FT_linear);
3367  dummy_2d->set_magfilter(SamplerState::FT_linear);
3368  }
3369  }
3370  return dummy_2d;
3371  } else {
3372  static PT(Texture) dummy_cube;
3373  if (dummy_cube == nullptr) {
3374  dummy_cube = new Texture("dummy-shadow-cube");
3375  dummy_cube->setup_cube_map(1, Texture::T_unsigned_byte, Texture::F_depth_component);
3376  dummy_cube->set_clear_color(1);
3377  // Note: cube map shadow filtering doesn't seem to work in Cg.
3378  dummy_cube->set_minfilter(SamplerState::FT_linear);
3379  dummy_cube->set_magfilter(SamplerState::FT_linear);
3380  }
3381  return dummy_cube;
3382  }
3383 }
3384 
3385 /**
3386  * Creates a depth buffer for shadow mapping. A derived GSG can override this
3387  * if it knows that a particular buffer type works best for shadow rendering.
3388  */
3389 GraphicsOutput *GraphicsStateGuardian::
3390 make_shadow_buffer(LightLensNode *light, Texture *tex, GraphicsOutput *host) {
3391  bool is_point = light->is_of_type(PointLight::get_class_type());
3392 
3393  // Determine the properties for creating the depth buffer.
3395  fbp.set_depth_bits(shadow_depth_bits);
3396 
3397  WindowProperties props = WindowProperties::size(light->_sb_size);
3398  int flags = GraphicsPipe::BF_refuse_window;
3399  if (is_point) {
3400  flags |= GraphicsPipe::BF_size_square;
3401  }
3402 
3403  // Create the buffer. This is a bit tricky because make_output() can only
3404  // be called from the app thread, but it won't cause issues as long as the
3405  // pipe can precertify the buffer, which it can in most cases.
3407  light->get_name(), light->_sb_sort, fbp, props, flags, this, host);
3408 
3409  if (sbuffer != nullptr) {
3410  sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
3411  }
3412  return sbuffer;
3413 }
3414 
3415 /**
3416  * Ensures that an appropriate shader has been generated for the given state.
3417  * This is stored in the _generated_shader field on the RenderState.
3418  */
3421 #ifdef HAVE_CG
3422  const ShaderAttrib *shader_attrib;
3423  state->get_attrib_def(shader_attrib);
3424 
3425  if (shader_attrib->auto_shader()) {
3426  if (_shader_generator == nullptr) {
3427  if (!_supports_basic_shaders) {
3428  return;
3429  }
3430  _shader_generator = new ShaderGenerator(this);
3431  }
3432  if (state->_generated_shader == nullptr ||
3433  state->_generated_shader_seq != _generated_shader_seq) {
3435 
3436  // Currently we overload this flag to request vertex animation for the
3437  // shader generator.
3438  const ShaderAttrib *sattr;
3439  state->get_attrib_def(sattr);
3440  if (sattr->get_flag(ShaderAttrib::F_hardware_skinning)) {
3441  spec.set_hardware(4, true);
3442  }
3443 
3444  // Cache the generated ShaderAttrib on the shader state.
3445  state->_generated_shader = _shader_generator->synthesize_shader(state, spec);
3446  state->_generated_shader_seq = _generated_shader_seq;
3447  }
3448  }
3449 #endif
3450 }
3451 
3452 /**
3453  * Returns true if the GSG implements the extension identified by the given
3454  * string. This currently is only implemented by the OpenGL back-end.
3455  */
3457 has_extension(const string &extension) const {
3458  return false;
3459 }
3460 
3461 /**
3462  * Returns the vendor of the video card driver
3463  */
3466  return string();
3467 }
3468 
3469 /**
3470  * Returns GL_Renderer
3471  */
3473  return string();
3474 }
3475 
3476 /**
3477  * Returns driver version This has an implementation-defined meaning, and may
3478  * be "" if the particular graphics implementation does not provide a way to
3479  * query this information.
3480  */
3483  return string();
3484 }
3485 
3486 /**
3487  * Returns major version of the video driver. This has an implementation-
3488  * defined meaning, and may be -1 if the particular graphics implementation
3489  * does not provide a way to query this information.
3490  */
3493  return -1;
3494 }
3495 
3496 /**
3497  * Returns the minor version of the video driver. This has an implementation-
3498  * defined meaning, and may be -1 if the particular graphics implementation
3499  * does not provide a way to query this information.
3500  */
3503  return -1;
3504 }
3505 
3506 /**
3507  * Returns the major version of the shader model.
3508  */
3511  return -1;
3512 }
3513 
3514 /**
3515  * Returns the minor version of the shader model.
3516  */
3519  return -1;
3520 }
3521 
3522 std::ostream &
3523 operator << (std::ostream &out, GraphicsStateGuardian::ShaderModel sm) {
3524  static const char *sm_strings[] = {"none", "1.1", "2.0", "2.x", "3.0", "4.0", "5.0", "5.1"};
3525  nassertr(sm >= 0 && sm <= GraphicsStateGuardian::SM_51, out);
3526  out << sm_strings[sm];
3527  return out;
3528 }
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:2384
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:2534
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:2751
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:2475
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:2442
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:2866
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:2547
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:2483
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:2657
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:2841
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:2417
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:2458
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:2370
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:2434
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:2556
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:2450
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:2036
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:2127
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:1509
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:1989
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:2084
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:3457
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:2426
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:2855
GraphicsStateGuardian::draw_points
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected points.
Definition: graphicsStateGuardian.cxx:2466
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:2393
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:1911
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:2159
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:1974
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:2095
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:2922
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:1964
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:2401
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:3420
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:64
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:2005
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:2014
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:2409
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:2287
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:2360
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