00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "cullResult.h"
00016 #include "cullBinManager.h"
00017 #include "cullBinAttrib.h"
00018 #include "textureAttrib.h"
00019 #include "lightAttrib.h"
00020 #include "colorAttrib.h"
00021 #include "alphaTestAttrib.h"
00022 #include "depthWriteAttrib.h"
00023 #include "colorScaleAttrib.h"
00024 #include "fogAttrib.h"
00025 #include "transparencyAttrib.h"
00026 #include "renderState.h"
00027 #include "clockObject.h"
00028 #include "config_pgraph.h"
00029
00030 TypeHandle CullResult::_type_handle;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 static const PN_stdfloat dual_opaque_level = 252.0 / 256.0;
00055 static const double bin_color_flash_rate = 1.0;
00056
00057
00058
00059
00060
00061
00062 CullResult::
00063 CullResult(GraphicsStateGuardianBase *gsg,
00064 const PStatCollector &draw_region_pcollector) :
00065 _gsg(gsg),
00066 _draw_region_pcollector(draw_region_pcollector)
00067 {
00068 #ifdef DO_MEMORY_USAGE
00069 MemoryUsage::update_type(this, get_class_type());
00070 #endif
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 PT(CullResult) CullResult::
00082 make_next() const {
00083 PT(CullResult) new_result = new CullResult(_gsg, _draw_region_pcollector);
00084 new_result->_bins.reserve(_bins.size());
00085
00086 CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00087
00088 for (size_t i = 0; i < _bins.size(); ++i) {
00089 CullBin *old_bin = _bins[i];
00090 if (old_bin == (CullBin *)NULL ||
00091 old_bin->get_bin_type() != bin_manager->get_bin_type(i)) {
00092 new_result->_bins.push_back((CullBin *)NULL);
00093 } else {
00094 new_result->_bins.push_back(old_bin->make_next());
00095 }
00096 }
00097
00098 return new_result;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 void CullResult::
00109 add_object(CullableObject *object, const CullTraverser *traverser) {
00110 static const LColor flash_alpha_color(0.92, 0.96, 0.10, 1.0f);
00111 static const LColor flash_binary_color(0.21f, 0.67f, 0.24, 1.0f);
00112 static const LColor flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f);
00113 static const LColor flash_dual_color(0.92, 0.01f, 0.01f, 1.0f);
00114
00115 bool force = !traverser->get_effective_incomplete_render();
00116 Thread *current_thread = traverser->get_current_thread();
00117
00118
00119 const RenderState *state = object->_state;
00120 nassertv(state != (const RenderState *)NULL);
00121
00122 const TransparencyAttrib *trans = DCAST(TransparencyAttrib, state->get_attrib(TransparencyAttrib::get_class_slot()));
00123 if (trans != (const TransparencyAttrib *)NULL) {
00124 switch (trans->get_mode()) {
00125 case TransparencyAttrib::M_alpha:
00126
00127
00128 object->_state = state->compose(get_alpha_state());
00129 #ifndef NDEBUG
00130 check_flash_transparency(object->_state, flash_alpha_color);
00131 #endif
00132 break;
00133
00134 case TransparencyAttrib::M_binary:
00135
00136 object->_state = state->compose(get_binary_state());
00137 #ifndef NDEBUG
00138 check_flash_transparency(object->_state, flash_binary_color);
00139 #endif
00140 break;
00141
00142 case TransparencyAttrib::M_multisample:
00143 case TransparencyAttrib::M_multisample_mask:
00144
00145
00146 if (!_gsg->get_supports_multisample()) {
00147 object->_state = state->compose(get_binary_state());
00148 }
00149 #ifndef NDEBUG
00150 check_flash_transparency(object->_state, flash_multisample_color);
00151 #endif
00152 break;
00153
00154 case TransparencyAttrib::M_dual:
00155 #ifndef NDEBUG
00156 check_flash_transparency(object->_state, flash_dual_color);
00157 state = object->_state;
00158 #endif
00159 if (!m_dual) {
00160
00161 break;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 {
00171 const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, state->get_attrib(CullBinAttrib::get_class_slot()));
00172 if (bin_attrib == (CullBinAttrib *)NULL ||
00173 bin_attrib->get_bin_name().empty()) {
00174
00175
00176 #ifndef NDEBUG
00177 if (m_dual_transparent)
00178 #endif
00179 {
00180 CullableObject *transparent_part = new CullableObject(*object);
00181 CPT(RenderState) transparent_state = object->has_decals() ?
00182 get_dual_transparent_state_decals() :
00183 get_dual_transparent_state();
00184 transparent_part->_state = state->compose(transparent_state);
00185 if (transparent_part->munge_geom
00186 (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread),
00187 traverser, force)) {
00188 CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
00189 nassertv(bin != (CullBin *)NULL);
00190 #ifndef NDEBUG
00191 check_flash_bin(transparent_part->_state, bin);
00192 #endif
00193 bin->add_object(transparent_part, current_thread);
00194 } else {
00195 delete transparent_part;
00196 }
00197 }
00198
00199
00200
00201 object->_state = state->compose(get_dual_opaque_state());
00202 #ifndef NDEBUG
00203 if (!m_dual_opaque) {
00204 delete object;
00205 return;
00206 }
00207 #endif
00208 }
00209
00210
00211 }
00212 break;
00213
00214 default:
00215
00216 break;
00217 }
00218 }
00219
00220 CullBin *bin = get_bin(object->_state->get_bin_index());
00221 nassertv(bin != (CullBin *)NULL);
00222
00223 #ifndef NDEBUG
00224 check_flash_bin(object->_state, bin);
00225 #endif
00226
00227
00228
00229 if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
00230
00231
00232
00233
00234 bin->add_object(object, current_thread);
00235 } else {
00236 delete object;
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 void CullResult::
00250 finish_cull(SceneSetup *scene_setup, Thread *current_thread) {
00251 CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00252
00253 for (size_t i = 0; i < _bins.size(); ++i) {
00254 if (!bin_manager->get_bin_active(i)) {
00255
00256
00257 _bins[i] = NULL;
00258
00259 } else {
00260 CullBin *bin = _bins[i];
00261 if (bin != (CullBin *)NULL) {
00262 bin->finish_cull(scene_setup, current_thread);
00263 }
00264 }
00265 }
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 void CullResult::
00275 draw(Thread *current_thread) {
00276 bool force = !_gsg->get_effective_incomplete_render();
00277
00278
00279 CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00280 int num_bins = bin_manager->get_num_bins();
00281 for (int i = 0; i < num_bins; i++) {
00282 int bin_index = bin_manager->get_bin(i);
00283 nassertv(bin_index >= 0);
00284
00285 if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
00286 _bins[bin_index]->draw(force, current_thread);
00287 }
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 PT(PandaNode) CullResult::
00308 make_result_graph() {
00309 PT(PandaNode) root_node = new PandaNode("cull_result");
00310
00311
00312 CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00313 int num_bins = bin_manager->get_num_bins();
00314 for (int i = 0; i < num_bins; i++) {
00315 int bin_index = bin_manager->get_bin(i);
00316 nassertr(bin_index >= 0, NULL);
00317
00318 if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
00319 root_node->add_child(_bins[bin_index]->make_result_graph());
00320 }
00321 }
00322
00323 return root_node;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 void CullResult::
00335 bin_removed(int bin_index) {
00336
00337 nassertv(false);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 CullBin *CullResult::
00347 make_new_bin(int bin_index) {
00348 CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00349 PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg,
00350 _draw_region_pcollector);
00351 if (bin != (CullBin *)NULL) {
00352
00353 while (bin_index >= (int)_bins.size()) {
00354 _bins.push_back((CullBin *)NULL);
00355 }
00356 nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), NULL);
00357 _bins[bin_index] = bin;
00358 }
00359
00360 return bin;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 CPT(RenderState) CullResult::
00370 get_alpha_state() {
00371 static CPT(RenderState) state = NULL;
00372 if (state == (const RenderState *)NULL) {
00373
00374
00375 state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f));
00376 }
00377 return state;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386 CPT(RenderState) CullResult::
00387 get_binary_state() {
00388 static CPT(RenderState) state = NULL;
00389 if (state == (const RenderState *)NULL) {
00390 state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, 0.5f),
00391 TransparencyAttrib::make(TransparencyAttrib::M_none),
00392 RenderState::get_max_priority());
00393 }
00394 return state;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 void CullResult::
00405 check_flash_bin(CPT(RenderState) &state, CullBin *bin) {
00406 if (bin->has_flash_color()) {
00407 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
00408 if ((cycle & 1) == 0) {
00409 state = state->remove_attrib(TextureAttrib::get_class_slot());
00410 state = state->remove_attrib(LightAttrib::get_class_slot());
00411 state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
00412 state = state->remove_attrib(FogAttrib::get_class_slot());
00413 state = state->add_attrib(ColorAttrib::make_flat(bin->get_flash_color()),
00414 RenderState::get_max_priority());
00415 }
00416 }
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426 void CullResult::
00427 check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) {
00428 if (show_transparency) {
00429 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
00430 if ((cycle & 1) == 0) {
00431 state = state->remove_attrib(TextureAttrib::get_class_slot());
00432 state = state->remove_attrib(LightAttrib::get_class_slot());
00433 state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
00434 state = state->remove_attrib(FogAttrib::get_class_slot());
00435 state = state->add_attrib(ColorAttrib::make_flat(transparency),
00436 RenderState::get_max_priority());
00437 }
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 CPT(RenderState) CullResult::
00450 get_dual_transparent_state() {
00451 static CPT(RenderState) state = NULL;
00452 if (state == (const RenderState *)NULL) {
00453
00454
00455
00456
00457
00458
00459
00460
00461 state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
00462 TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00463 DepthWriteAttrib::make(DepthWriteAttrib::M_off),
00464 RenderState::get_max_priority());
00465 }
00466
00467 #ifndef NDEBUG
00468 if (m_dual_flash) {
00469 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
00470 if ((cycle & 1) == 0) {
00471 static CPT(RenderState) flash_state = NULL;
00472 if (flash_state == (const RenderState *)NULL) {
00473 flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)),
00474 RenderState::get_max_priority());
00475
00476 flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
00477 RenderState::get_max_priority());
00478
00479 flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
00480 RenderState::get_max_priority());
00481 }
00482 return flash_state;
00483 }
00484 }
00485 #endif // NDEBUG
00486
00487 return state;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497 CPT(RenderState) CullResult::
00498 get_dual_transparent_state_decals() {
00499 static CPT(RenderState) state = NULL;
00500 if (state == (const RenderState *)NULL) {
00501
00502
00503
00504
00505 state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, dual_opaque_level),
00506 TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00507 DepthWriteAttrib::make(DepthWriteAttrib::M_off),
00508 RenderState::get_max_priority());
00509 }
00510
00511 #ifndef NDEBUG
00512 if (m_dual_flash) {
00513 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
00514 if ((cycle & 1) == 0) {
00515 static CPT(RenderState) flash_state = NULL;
00516 if (flash_state == (const RenderState *)NULL) {
00517 flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)),
00518 RenderState::get_max_priority());
00519 flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
00520 RenderState::get_max_priority());
00521
00522 }
00523 return flash_state;
00524 }
00525 }
00526 #endif // NDEBUG
00527
00528 return state;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537 CPT(RenderState) CullResult::
00538 get_dual_opaque_state() {
00539 static CPT(RenderState) state = NULL;
00540 if (state == (const RenderState *)NULL) {
00541 state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, dual_opaque_level),
00542 TransparencyAttrib::make(TransparencyAttrib::M_none),
00543 RenderState::get_max_priority());
00544 }
00545
00546 #ifndef NDEBUG
00547 if (m_dual_flash) {
00548 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
00549 if ((cycle & 1) == 0) {
00550 static CPT(RenderState) flash_state = NULL;
00551 if (flash_state == (const RenderState *)NULL) {
00552 flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.2, 0.2, 0.8f, 1.0f)),
00553 RenderState::get_max_priority());
00554 flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
00555 RenderState::get_max_priority());
00556
00557 }
00558 return flash_state;
00559 }
00560 }
00561 #endif // NDEBUG
00562
00563 return state;
00564 }
00565