// ---------------------------------------------------------------------------- void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List, std::vector<scene::ISceneNode *> *ImmediateDraw, const scene::ICameraSceneNode *cam, ShadowMatrices& shadow_matrices) { core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end(); for (; I != E; ++I) { if (LODNode *node = dynamic_cast<LODNode *>(*I)) node->updateVisibility(); (*I)->updateAbsolutePosition(); if (!(*I)->isVisible()) continue; if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I)) { if (!isCulledPrecise(cam, *I)) m_particles_list.push_back(node); continue; } if (STKBillboard *node = dynamic_cast<STKBillboard *>(*I)) { if (!isCulledPrecise(cam, *I)) m_billboard_list.push_back(node); continue; } handleSTKCommon((*I), ImmediateDraw, cam, shadow_matrices); parseSceneManager((*I)->getChildren(), ImmediateDraw, cam, shadow_matrices); } }
// ---------------------------------------------------------------------------- void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List, const scene::ICameraSceneNode *cam) { core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end(); for (; I != E; ++I) { if (LODNode *node = dynamic_cast<LODNode *>(*I)) { node->updateVisibility(); } (*I)->updateAbsolutePosition(); if (!(*I)->isVisible()) continue; if (STKParticle *node = dynamic_cast<STKParticle*>(*I)) { if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz())) CPUParticleManager::getInstance()->addParticleNode(node); continue; } if (scene::IBillboardSceneNode *node = dynamic_cast<scene::IBillboardSceneNode*>(*I)) { if (!isCulledPrecise(cam, *I)) CPUParticleManager::getInstance()->addBillboardNode(node); continue; } if (STKTextBillboard *tb = dynamic_cast<STKTextBillboard*>(*I)) { if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz())) TextBillboardDrawer::addTextBillboard(tb); continue; } SP::SPMeshNode* node = dynamic_cast<SP::SPMeshNode*>(*I); if (node) { SP::addObject(node); } parseSceneManager((*I)->getChildren(), cam); } }
// ---------------------------------------------------------------------------- void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw, const scene::ICameraSceneNode *cam, ShadowMatrices& shadow_matrices) { STKMeshCommon* node = dynamic_cast<STKMeshCommon*>(Node); if (!node) return; node->updateNoGL(); m_deferred_update.push_back(node); if (node->isImmediateDraw()) { ImmediateDraw->push_back(Node); return; } bool culled_for_cams[6] = { true, true, true, true, true, true }; culled_for_cams[0] = isCulledPrecise(cam, Node, irr_driver->getBoundingBoxesViz()); if (UserConfigParams::m_gi && !shadow_matrices.isRSMMapAvail()) { culled_for_cams[1] = isCulledPrecise(shadow_matrices.getSunCam(), Node); } if (CVS->isShadowEnabled()) { for (unsigned i = 0; i < 4; i++) { culled_for_cams[i + 2] = isCulledPrecise(shadow_matrices.getShadowCamNodes()[i], Node); } } // Transparent if (World::getWorld() && World::getWorld()->isFogEnabled()) { const Track * const track = World::getWorld()->getTrack(); // Todo : put everything in a ubo const float fogmax = track->getFogMax(); const float startH = track->getFogStartHeight(); const float endH = track->getFogEndHeight(); const float start = track->getFogStart(); const float end = track->getFogEnd(); const video::SColor tmpcol = track->getFogColor(); video::SColorf col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT]) pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, fogmax, startH, endH, start, end, col); for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE]) pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, fogmax, startH, endH, start, end, col); } else { for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT]) pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f); for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE]) pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f); } // Use sun color to determine custom alpha for ghost karts float custom_alpha = 1.0f; if (World::getWorld()) { const video::SColor& c = World::getWorld()->getTrack()->getSunColor(); float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() + 0.0722f * c.getBlue(); custom_alpha = y > 128.0f ? 0.5f : 0.35f; } for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_STD]) pushVector(ListTranslucentStandard::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_TAN]) pushVector(ListTranslucentTangents::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_2TC]) pushVector(ListTranslucent2TCoords::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT]) pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation()); if (!culled_for_cams[0]) { for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { if (node->glow()) { m_glow_pass_mesh[mesh->mb].m_mesh = mesh; m_glow_pass_mesh[mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } if (Mat == Material::SHADERTYPE_SPLATTING) { // Notice: splatting will be drawn using non-instanced shader only // It's only used one place (in overworld) and may be removed eventually core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix); } else { // Only take render info into account if the node is not static (animated) // So they can have different animation std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb, dynamic_cast<STKMeshSceneNode*>(Node) == NULL ? mesh->m_render_info : NULL); m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh; m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); } } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } if (!CVS->isShadowEnabled()) return; for (unsigned cascade = 0; cascade < 4; ++cascade) { if (culled_for_cams[cascade + 2]) continue; for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh; m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } if (!UserConfigParams::m_gi || shadow_matrices.isRSMMapAvail()) return; if (!culled_for_cams[1]) { for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { if (Mat == Material::SHADERTYPE_SPLATTING) { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix); } else { m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh; m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } }