Panda3D
cullResult.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 cullResult.cxx
10  * @author drose
11  * @date 2002-02-28
12  */
13 
14 #include "cullResult.h"
15 #include "cullBinManager.h"
16 #include "cullBinAttrib.h"
17 #include "textureAttrib.h"
18 #include "lightAttrib.h"
19 #include "colorAttrib.h"
20 #include "alphaTestAttrib.h"
21 #include "depthWriteAttrib.h"
22 #include "colorScaleAttrib.h"
23 #include "fogAttrib.h"
24 #include "transparencyAttrib.h"
25 #include "renderState.h"
26 #include "rescaleNormalAttrib.h"
27 #include "clockObject.h"
28 #include "config_pgraph.h"
29 #include "depthOffsetAttrib.h"
30 #include "colorBlendAttrib.h"
31 #include "shaderAttrib.h"
32 
33 TypeHandle CullResult::_type_handle;
34 
35 /*
36  * This value is used instead of 1.0 to represent the alpha level of a pixel
37  * that is to be considered "opaque" for the purposes of M_dual. Ideally, 1.0
38  * is the only correct value for this. Realistically, we have to fudge it
39  * lower for two reasons: (1) The modelers tend to paint textures with very
40  * slight transparency levels in places that are not intended to be
41  * transparent, without realizing it. These very faint transparency regions
42  * are normally (almost) invisible, but when rendered with M_dual they may be
43  * revealed as regions of poor alpha sorting. (2) There seems to be some
44  * problem in DX where, in certain circumstances apparently related to
45  * automatic texture management, it spontaneously drops out the bottom two
46  * bits of an eight-bit alpha channel, causing a value of 255 to become a
47  * value of 252 instead. We use 256 as the denominator here (instead of, say,
48  * 255) because a fractional power of two will have a terminating
49  * representation in base 2, and thus will be more likely to have a precise
50  * value in whatever internal representation the graphics API will use.
51  */
52 static const PN_stdfloat dual_opaque_level = 252.0 / 256.0;
53 static const double bin_color_flash_rate = 1.0; // 1 state change per second
54 
55 /**
56  *
57  */
58 CullResult::
59 CullResult(GraphicsStateGuardianBase *gsg,
60  const PStatCollector &draw_region_pcollector) :
61  _gsg(gsg),
62  _draw_region_pcollector(draw_region_pcollector)
63 {
64 #ifdef DO_MEMORY_USAGE
65  MemoryUsage::update_type(this, get_class_type());
66 #endif
67 
68 #ifndef NDEBUG
69  _show_transparency = show_transparency.get_value();
70 #endif
71 }
72 
73 /**
74  * Returns a newly-allocated CullResult object that contains a copy of just
75  * the subset of the data from this CullResult object that is worth keeping
76  * around for next frame.
77  */
78 PT(CullResult) CullResult::
79 make_next() const {
80  PT(CullResult) new_result = new CullResult(_gsg, _draw_region_pcollector);
81  new_result->_bins.reserve(_bins.size());
82 
84 
85  for (size_t i = 0; i < _bins.size(); ++i) {
86  CullBin *old_bin = _bins[i];
87  if (old_bin == nullptr ||
88  old_bin->get_bin_type() != bin_manager->get_bin_type(i)) {
89  new_result->_bins.push_back(nullptr);
90  } else {
91  new_result->_bins.push_back(old_bin->make_next());
92  }
93  }
94 
95  return new_result;
96 }
97 
98 /**
99  * Adds the indicated CullableObject to the appropriate bin. The bin becomes
100  * the owner of the object pointer, and will eventually delete it.
101  */
102 void CullResult::
103 add_object(CullableObject *object, const CullTraverser *traverser) {
104  static const LColor flash_alpha_color(0.92, 0.96, 0.10, 1.0f);
105  static const LColor flash_binary_color(0.21f, 0.67f, 0.24, 1.0f);
106  static const LColor flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f);
107  static const LColor flash_dual_color(0.92, 0.01f, 0.01f, 1.0f);
108 
109  nassertv(object->_draw_callback != nullptr || object->_geom != nullptr);
110 
111  bool force = !traverser->get_effective_incomplete_render();
112  Thread *current_thread = traverser->get_current_thread();
114 
115  // This is probably a good time to check for an auto rescale setting.
116  const RescaleNormalAttrib *rescale;
117  object->_state->get_attrib_def(rescale);
118  if (rescale->get_mode() == RescaleNormalAttrib::M_auto) {
119  RescaleNormalAttrib::Mode mode;
120 
121  if (object->_internal_transform->has_identity_scale()) {
122  mode = RescaleNormalAttrib::M_none;
123  } else if (object->_internal_transform->has_uniform_scale()) {
124  mode = RescaleNormalAttrib::M_rescale;
125  } else {
126  mode = RescaleNormalAttrib::M_normalize;
127  }
128 
129  object->_state = object->_state->compose(get_rescale_normal_state(mode));
130  }
131 
132  // Check for a special wireframe setting.
133  const RenderModeAttrib *rmode;
134  if (object->_state->get_attrib(rmode)) {
135  if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) {
136  CullableObject *wireframe_part = new CullableObject(*object);
137  const ShaderAttrib *shader = nullptr;
138  object->_state->get_attrib(shader);
139  wireframe_part->_state = get_wireframe_overlay_state(rmode, shader);
140 
141  if (wireframe_part->munge_geom
142  (_gsg, _gsg->get_geom_munger(wireframe_part->_state, current_thread),
143  traverser, force)) {
144  int wireframe_bin_index = bin_manager->find_bin("fixed");
145  CullBin *bin = get_bin(wireframe_bin_index);
146  nassertv(bin != nullptr);
147  check_flash_bin(wireframe_part->_state, bin_manager, wireframe_bin_index);
148  bin->add_object(wireframe_part, current_thread);
149  } else {
150  delete wireframe_part;
151  }
152 
153  object->_state = object->_state->compose(get_wireframe_filled_state());
154  }
155  }
156 
157  // Check to see if there's a special transparency setting.
158  const TransparencyAttrib *trans;
159  if (object->_state->get_attrib(trans)) {
160  switch (trans->get_mode()) {
161  case TransparencyAttrib::M_alpha:
162  case TransparencyAttrib::M_premultiplied_alpha:
163  // M_alpha implies an alpha-write test, so we don't waste time writing
164  // 0-valued pixels.
165  object->_state = object->_state->compose(get_alpha_state());
166  check_flash_transparency(object->_state, flash_alpha_color);
167  break;
168 
169  case TransparencyAttrib::M_binary:
170  // M_binary is implemented by explicitly setting the alpha test.
171  object->_state = object->_state->compose(get_binary_state());
172  check_flash_transparency(object->_state, flash_binary_color);
173  break;
174 
175  case TransparencyAttrib::M_multisample:
176  case TransparencyAttrib::M_multisample_mask:
177  // The multisample modes are implemented using M_binary if the GSG in
178  // use doesn't support multisample.
179  if (!_gsg->get_supports_multisample()) {
180  object->_state = object->_state->compose(get_binary_state());
181  }
182  check_flash_transparency(object->_state, flash_multisample_color);
183  break;
184 
185  case TransparencyAttrib::M_dual:
186 #ifndef NDEBUG
187  check_flash_transparency(object->_state, flash_dual_color);
188 #endif
189  if (!m_dual) {
190  // If m_dual is configured off, it becomes M_alpha.
191  break;
192  }
193 
194  // M_dual is implemented by drawing the opaque parts first, without
195  // transparency, then drawing the transparent parts later. This means
196  // we must copy the object and add it to both bins. We can only do this
197  // if we do not have an explicit bin already applied; otherwise, M_dual
198  // falls back to M_alpha.
199  {
200  const CullBinAttrib *bin_attrib;
201  if (!object->_state->get_attrib(bin_attrib) ||
202  bin_attrib->get_bin_name().empty()) {
203  // We make a copy of the object to draw the transparent part; this
204  // gets placed in the transparent bin.
205 #ifndef NDEBUG
206  if (m_dual_transparent)
207 #endif
208  {
209  CullableObject *transparent_part = new CullableObject(*object);
210  CPT(RenderState) transparent_state = get_dual_transparent_state();
211  transparent_part->_state = object->_state->compose(transparent_state);
212  if (transparent_part->munge_geom
213  (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread),
214  traverser, force)) {
215  int transparent_bin_index = transparent_part->_state->get_bin_index();
216  CullBin *bin = get_bin(transparent_bin_index);
217  nassertv(bin != nullptr);
218  check_flash_bin(transparent_part->_state, bin_manager, transparent_bin_index);
219  bin->add_object(transparent_part, current_thread);
220  } else {
221  delete transparent_part;
222  }
223  }
224 
225  // Now we can draw the opaque part. This will end up in the opaque
226  // bin.
227  object->_state = object->_state->compose(get_dual_opaque_state());
228 #ifndef NDEBUG
229  if (!m_dual_opaque) {
230  delete object;
231  return;
232  }
233 #endif
234  }
235  // The object is assigned to a specific bin; M_dual becomes M_alpha.
236  }
237  break;
238 
239  default:
240  // Other kinds of transparency need no special handling.
241  break;
242  }
243  }
244 
245  int bin_index = object->_state->get_bin_index();
246  CullBin *bin = get_bin(bin_index);
247  nassertv(bin != nullptr);
248  check_flash_bin(object->_state, bin_manager, bin_index);
249 
250  // Munge vertices as needed for the GSG's requirements, and the object's
251  // current state.
252  if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
253  // The object may or may not now be fully resident, but this may not
254  // matter, since the GSG may have the necessary buffers already loaded.
255  // We'll let the GSG ultimately decide whether to render it.
256  bin->add_object(object, current_thread);
257  } else {
258  delete object;
259  }
260 }
261 
262 /**
263  * Called after all the geoms have been added, this indicates that the cull
264  * process is finished for this frame and gives the bins a chance to do any
265  * post-processing (like sorting) before moving on to draw.
266  */
268 finish_cull(SceneSetup *scene_setup, Thread *current_thread) {
270 
271  for (size_t i = 0; i < _bins.size(); ++i) {
272  if (!bin_manager->get_bin_active(i)) {
273  // If the bin isn't active, don't sort it, and don't draw it. In fact,
274  // clear it.
275  _bins[i] = nullptr;
276 
277  } else {
278  CullBin *bin = _bins[i];
279  if (bin != nullptr) {
280  bin->finish_cull(scene_setup, current_thread);
281  }
282  }
283  }
284 }
285 
286 /**
287  * Asks all the bins to draw themselves in the correct order.
288  */
290 draw(Thread *current_thread) {
291  bool force = !_gsg->get_effective_incomplete_render();
292 
293  // Ask the bin manager for the correct order to draw all the bins.
295  int num_bins = bin_manager->get_num_bins();
296  for (int i = 0; i < num_bins; i++) {
297  int bin_index = bin_manager->get_bin(i);
298  nassertv(bin_index >= 0);
299 
300  if (bin_index < (int)_bins.size() && _bins[bin_index] != nullptr) {
301 
302  _gsg->push_group_marker(_bins[bin_index]->get_name());
303  _bins[bin_index]->draw(force, current_thread);
304  _gsg->pop_group_marker();
305  }
306  }
307 }
308 
309 /**
310  * Returns a special scene graph constructed to represent the results of the
311  * cull. This will be a hierarchy of nodes, one node for each bin, each of
312  * which will in term be a parent of a number of GeomNodes, representing the
313  * geometry drawn in each bin.
314  *
315  * This is useful mainly for high-level debugging and abstraction tools; it
316  * should not be mistaken for the low-level cull result itself. For the low-
317  * level cull result, use draw() to efficiently draw the culled scene.
318  */
319 PT(PandaNode) CullResult::
320 make_result_graph() {
321  PT(PandaNode) root_node = new PandaNode("cull_result");
322 
323  // Ask the bin manager for the correct order to draw all the bins.
325  int num_bins = bin_manager->get_num_bins();
326  for (int i = 0; i < num_bins; i++) {
327  int bin_index = bin_manager->get_bin(i);
328  nassertr(bin_index >= 0, nullptr);
329 
330  if (bin_index < (int)_bins.size() && _bins[bin_index] != nullptr) {
331  root_node->add_child(_bins[bin_index]->make_result_graph());
332  }
333  }
334 
335  return root_node;
336 }
337 
338 /**
339  * Intended to be called by CullBinManager::remove_bin(), this informs all the
340  * CullResults in the world to remove the indicated bin_index from their cache
341  * if it has been cached.
342  */
344 bin_removed(int bin_index) {
345  // Do something here.
346  nassertv(false);
347 }
348 
349 /**
350  * Allocates a new CullBin for the given bin_index and stores it for next
351  * time.
352  */
353 CullBin *CullResult::
354 make_new_bin(int bin_index) {
356  PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg,
357  _draw_region_pcollector);
358  CullBin *bin_ptr = bin.p();
359 
360  if (bin_ptr != nullptr) {
361  // Now store it in the vector.
362  while (bin_index >= (int)_bins.size()) {
363  _bins.push_back(nullptr);
364  }
365  nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), nullptr);
366 
367  // Prevent unnecessary refunref by swapping the PointerTos.
368  std::swap(_bins[bin_index], bin);
369  }
370 
371  return bin_ptr;
372 }
373 
374 /**
375  * Returns a RenderState containing the given rescale normal attribute.
376  */
377 const RenderState *CullResult::
378 get_rescale_normal_state(RescaleNormalAttrib::Mode mode) {
379  static CPT(RenderState) states[RescaleNormalAttrib::M_auto + 1];
380  if (states[mode].is_null()) {
381  states[mode] = RenderState::make(RescaleNormalAttrib::make(mode),
382  RenderState::get_max_priority());
383  }
384  return states[mode].p();
385 }
386 
387 /**
388  * Returns a RenderState that changes the alpha test to > 0, for implementing
389  * M_alpha.
390  */
391 const RenderState *CullResult::
392 get_alpha_state() {
393  static CPT(RenderState) state = nullptr;
394  if (state == nullptr) {
395  // We don't monkey with the priority, since we want to allow the user to
396  // override this if he desires.
397  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f));
398  }
399  return state.p();
400 }
401 
402 /**
403  * Returns a RenderState that applies the effects of M_binary.
404  */
405 const RenderState *CullResult::
406 get_binary_state() {
407  static CPT(RenderState) state = nullptr;
408  if (state == nullptr) {
409  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, 0.5f),
410  TransparencyAttrib::make(TransparencyAttrib::M_none),
411  RenderState::get_max_priority());
412  }
413  return state.p();
414 }
415 
416 #ifndef NDEBUG
417 /**
418  * Update the object's state to flash the geometry with a solid color.
419  */
420 void CullResult::
421 apply_flash_color(CPT(RenderState) &state, const LColor &flash_color) {
422  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
423  if ((cycle & 1) == 0) {
424  state = state->remove_attrib(TextureAttrib::get_class_slot());
425  state = state->remove_attrib(LightAttrib::get_class_slot());
426  state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
427  state = state->remove_attrib(FogAttrib::get_class_slot());
428  state = state->add_attrib(ColorAttrib::make_flat(flash_color),
429  RenderState::get_max_priority());
430  }
431 }
432 #endif // NDEBUG
433 
434 /**
435  * Returns a RenderState that renders only the transparent parts of an object,
436  * in support of M_dual.
437  */
438 const RenderState *CullResult::
439 get_dual_transparent_state() {
440  static CPT(RenderState) state = nullptr;
441  if (state == nullptr) {
442  // The alpha test for > 0 prevents us from drawing empty pixels, and hence
443  // filling up the depth buffer with large empty spaces that may obscure
444  // other things. However, this does mean we draw pixels twice where the
445  // alpha == 1.0 (since they were already drawn in the opaque pass). This
446  // is not normally a problem.
447  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
448  TransparencyAttrib::make(TransparencyAttrib::M_alpha),
449  DepthWriteAttrib::make(DepthWriteAttrib::M_off),
450  RenderState::get_max_priority());
451  }
452 
453 #ifndef NDEBUG
454  if (m_dual_flash) {
455  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
456  if ((cycle & 1) == 0) {
457  static CPT(RenderState) flash_state = nullptr;
458  if (flash_state == nullptr) {
459  flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)),
460  RenderState::get_max_priority());
461 
462  flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
463  RenderState::get_max_priority());
464 
465  flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
466  RenderState::get_max_priority());
467  }
468  return flash_state.p();
469  }
470  }
471 #endif // NDEBUG
472 
473  return state.p();
474 }
475 
476 /**
477  * Returns a RenderState that renders only the opaque parts of an object, in
478  * support of M_dual.
479  */
480 const RenderState *CullResult::
481 get_dual_opaque_state() {
482  static CPT(RenderState) state = nullptr;
483  if (state == nullptr) {
484  state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, dual_opaque_level),
485  TransparencyAttrib::make(TransparencyAttrib::M_none),
486  RenderState::get_max_priority());
487  }
488 
489 #ifndef NDEBUG
490  if (m_dual_flash) {
491  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
492  if ((cycle & 1) == 0) {
493  static CPT(RenderState) flash_state = nullptr;
494  if (flash_state == nullptr) {
495  flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.2, 0.2, 0.8f, 1.0f)),
496  RenderState::get_max_priority());
497  flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
498  RenderState::get_max_priority());
499 
500  }
501  return flash_state.p();
502  }
503  }
504 #endif // NDEBUG
505 
506  return state.p();
507 }
508 
509 /**
510  * Returns a RenderState that is composed with the filled part of an
511  * M_filled_wireframe model.
512  */
513 const RenderState *CullResult::
514 get_wireframe_filled_state() {
515  static CPT(RenderState) state = RenderState::make(
516  RenderModeAttrib::make(RenderModeAttrib::M_filled),
517  RenderState::get_max_priority());
518  return state.p();
519 }
520 
521 /**
522  * Returns a RenderState that renders only the wireframe part of an
523  * M_filled_wireframe model.
524  */
525 CPT(RenderState) CullResult::
526 get_wireframe_overlay_state(const RenderModeAttrib *rmode) {
527  return get_wireframe_overlay_state(rmode, nullptr);
528 }
529 
530 /**
531  * Returns a RenderState that renders only the wireframe part of an
532  * M_filled_wireframe model.
533  * If a shader attrib is provided, a constant color is used in ColorBlendAttrib
534  * to emulate the flat color.
535  */
536 CPT(RenderState) CullResult::
537 get_wireframe_overlay_state(const RenderModeAttrib *rmode, const ShaderAttrib *shader) {
538  CPT(RenderState) state = RenderState::make(
539  DepthOffsetAttrib::make(1, 0, 0.99999f),
540  RenderModeAttrib::make(RenderModeAttrib::M_wireframe,
541  rmode->get_thickness(),
542  rmode->get_perspective()));
543  if (filled_wireframe_apply_shader) {
544  state = state->add_attrib(ColorBlendAttrib::make(ColorBlendAttrib::M_add,
545  ColorBlendAttrib::O_zero,
546  ColorBlendAttrib::O_constant_color,
547  ColorBlendAttrib::M_add,
548  ColorBlendAttrib::O_one,
549  ColorBlendAttrib::O_one_minus_incoming_alpha,
550  rmode->get_wireframe_color()));
551  state = state->add_attrib(shader);
552  } else {
553  state = state->add_attrib(ColorBlendAttrib::make(ColorBlendAttrib::M_add,
554  ColorBlendAttrib::O_incoming_alpha,
555  ColorBlendAttrib::O_one_minus_incoming_alpha));
556  state = state->add_attrib(ColorAttrib::make_flat(rmode->get_wireframe_color()));
557  }
558  return state;
559 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
get_value
Returns the variable's value.
Assigns geometry to a particular bin by name.
Definition: cullBinAttrib.h:27
get_bin_name
Returns the name of the bin this attribute specifies.
Definition: cullBinAttrib.h:39
This is a global object that maintains the collection of named CullBins in the world.
BinType get_bin_type(int bin_index) const
Returns the type of the bin with the indicated bin_index (where bin_index was retrieved by get_bin() ...
static CullBinManager * get_global_ptr()
Returns the pointer to the global CullBinManager object.
bool get_bin_active(int bin_index) const
Returns the active flag of the bin with the indicated bin_index (where bin_index was retrieved by get...
get_bin
Returns the bin_index of the nth bin in the set, where n is a number between 0 and get_num_bins().
get_num_bins
Returns the number of bins in the world.
int find_bin(const std::string &name) const
Returns the bin_index associated with the bin of the given name, or -1 if no bin has that name.
A collection of Geoms and their associated state, for a particular scene.
Definition: cullBin.h:40
This stores the result of a BinCullHandler traversal: an ordered collection of CullBins,...
Definition: cullResult.h:44
void draw(Thread *current_thread)
Asks all the bins to draw themselves in the correct order.
Definition: cullResult.cxx:290
static void bin_removed(int bin_index)
Intended to be called by CullBinManager::remove_bin(), this informs all the CullResults in the world ...
Definition: cullResult.cxx:344
CullBin * get_bin(int bin_index)
Returns the CullBin associated with the indicated bin_index, or NULL if the bin_index is invalid.
Definition: cullResult.I:27
void finish_cull(SceneSetup *scene_setup, Thread *current_thread)
Called after all the geoms have been added, this indicates that the cull process is finished for this...
Definition: cullResult.cxx:268
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
bool get_effective_incomplete_render() const
Returns true if the cull traversal is effectively in incomplete_render state, considering both the GS...
The smallest atom of cull.
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force)
Uses the indicated GeomMunger to transform the geom and/or its vertices.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
A lightweight class that represents a single element that may be timed and/or counted via stats.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
Specifies how polygons are to be drawn.
get_perspective
Returns the perspective flag.
get_thickness
Returns the line width or point thickness.
get_wireframe_color
Returns the color that is used in M_filled_wireframe mode to distinguish the wireframe from the rest ...
get_mode
Returns the render mode.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
Specifies how polygons are to be drawn.
get_mode
Returns the render mode.
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
A thread; that is, a lightweight process.
Definition: thread.h:46
This controls the enabling of transparency.
get_mode
Returns the transparency mode.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(RenderState) CullResult
Returns a RenderState that renders only the wireframe part of an M_filled_wireframe model.
Definition: cullResult.cxx:525
PT(CullResult) CullResult
Returns a newly-allocated CullResult object that contains a copy of just the subset of the data from ...
Definition: cullResult.cxx:78
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.