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