From e9c17df90095c7061975b668ff675e377675bf1e Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Wed, 23 Apr 2014 01:43:00 -0700 Subject: [PATCH] Implemented texture pre-streaming for lod swaps --HG-- branch : nfb --- KREngine/kraken/KRAmbientZone.cpp | 1 + KREngine/kraken/KRAudioSource.cpp | 2 + KREngine/kraken/KRBone.cpp | 1 + KREngine/kraken/KRCamera.cpp | 9 ++- KREngine/kraken/KRCollider.cpp | 1 + KREngine/kraken/KRContext.cpp | 1 + KREngine/kraken/KRContext.h | 1 + KREngine/kraken/KRDirectionalLight.cpp | 2 + KREngine/kraken/KREngine.mm | 2 + KREngine/kraken/KRLODGroup.cpp | 25 ++++-- KREngine/kraken/KRLODGroup.h | 2 +- KREngine/kraken/KRLODSet.cpp | 80 ++++++++----------- KREngine/kraken/KRLODSet.h | 11 +-- KREngine/kraken/KRLight.cpp | 2 + KREngine/kraken/KRMaterial.cpp | 44 ++++++++-- KREngine/kraken/KRMaterial.h | 3 +- KREngine/kraken/KRMesh.cpp | 15 +++- KREngine/kraken/KRMesh.h | 3 +- KREngine/kraken/KRModel.cpp | 39 ++++++--- KREngine/kraken/KRModel.h | 4 +- KREngine/kraken/KRNode.cpp | 45 +++++------ KREngine/kraken/KRNode.h | 20 +++-- KREngine/kraken/KRParticleSystemNewtonian.cpp | 1 + KREngine/kraken/KRPointLight.cpp | 1 + KREngine/kraken/KRReverbZone.cpp | 1 + KREngine/kraken/KRScene.cpp | 6 +- KREngine/kraken/KRSprite.cpp | 2 + KREngine/kraken/KRTexture.cpp | 13 +-- KREngine/kraken/KRTexture.h | 4 +- 29 files changed, 202 insertions(+), 139 deletions(-) diff --git a/KREngine/kraken/KRAmbientZone.cpp b/KREngine/kraken/KRAmbientZone.cpp index 927caa5..a76142f 100644 --- a/KREngine/kraken/KRAmbientZone.cpp +++ b/KREngine/kraken/KRAmbientZone.cpp @@ -87,6 +87,7 @@ void KRAmbientZone::setZone(const std::string &zone) void KRAmbientZone::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRAudioSource.cpp b/KREngine/kraken/KRAudioSource.cpp index dd1668a..bce86a7 100644 --- a/KREngine/kraken/KRAudioSource.cpp +++ b/KREngine/kraken/KRAudioSource.cpp @@ -200,6 +200,8 @@ void KRAudioSource::queueBuffer() void KRAudioSource::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; + KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); bool bVisualize = false; diff --git a/KREngine/kraken/KRBone.cpp b/KREngine/kraken/KRBone.cpp index 18b4a87..974985b 100644 --- a/KREngine/kraken/KRBone.cpp +++ b/KREngine/kraken/KRBone.cpp @@ -41,6 +41,7 @@ KRAABB KRBone::getBounds() { void KRBone::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRCamera.cpp b/KREngine/kraken/KRCamera.cpp index b111908..915a873 100644 --- a/KREngine/kraken/KRCamera.cpp +++ b/KREngine/kraken/KRCamera.cpp @@ -115,11 +115,14 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende scene.updateOctree(m_viewport); + // ----====---- Pre-stream resources ----====---- + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_PRESTREAM, true); + // ----====---- Generate Shadowmaps for Lights ----====---- if(settings.m_cShadowBuffers > 0) { GL_PUSH_GROUP_MARKER("Generate Shadowmaps"); - scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, settings.bEnableDeferredLighting); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, false /*settings.bEnableDeferredLighting*/); GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y)); GL_POP_GROUP_MARKER; } @@ -158,7 +161,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende GLDEBUG(glDisable(GL_BLEND)); // Render the geometry - scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, true); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, false); GL_POP_GROUP_MARKER; @@ -280,7 +283,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende // Render the geometry - scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, true); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, false); GL_POP_GROUP_MARKER; } diff --git a/KREngine/kraken/KRCollider.cpp b/KREngine/kraken/KRCollider.cpp index df0f9a8..5b98e43 100644 --- a/KREngine/kraken/KRCollider.cpp +++ b/KREngine/kraken/KRCollider.cpp @@ -187,6 +187,7 @@ void KRCollider::setAudioOcclusion(float audio_occlusion) void KRCollider::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRContext.cpp b/KREngine/kraken/KRContext.cpp index 60a4dff..ca54490 100644 --- a/KREngine/kraken/KRContext.cpp +++ b/KREngine/kraken/KRContext.cpp @@ -20,6 +20,7 @@ int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX; int KRContext::KRENGINE_MAX_TEXTURE_DIM; int KRContext::KRENGINE_MIN_TEXTURE_DIM; int KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT; +int KRContext::KRENGINE_PRESTREAM_DISTANCE; const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = { "GL_EXT_texture_storage" diff --git a/KREngine/kraken/KRContext.h b/KREngine/kraken/KRContext.h index 06402e2..d311214 100644 --- a/KREngine/kraken/KRContext.h +++ b/KREngine/kraken/KRContext.h @@ -32,6 +32,7 @@ public: static int KRENGINE_MAX_TEXTURE_DIM; static int KRENGINE_MIN_TEXTURE_DIM; static int KRENGINE_MAX_TEXTURE_THROUGHPUT; + static int KRENGINE_PRESTREAM_DISTANCE; KRContext(); diff --git a/KREngine/kraken/KRDirectionalLight.cpp b/KREngine/kraken/KRDirectionalLight.cpp index 532e6d0..31245b8 100644 --- a/KREngine/kraken/KRDirectionalLight.cpp +++ b/KREngine/kraken/KRDirectionalLight.cpp @@ -89,6 +89,8 @@ int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewpor void KRDirectionalLight::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; + KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { diff --git a/KREngine/kraken/KREngine.mm b/KREngine/kraken/KREngine.mm index a45570c..d5949cc 100644 --- a/KREngine/kraken/KREngine.mm +++ b/KREngine/kraken/KREngine.mm @@ -94,6 +94,7 @@ void kraken::set_debug_text(const std::string &print_text) KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000; KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048; KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; + KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 4000000; @@ -139,6 +140,7 @@ void kraken::set_debug_text(const std::string &print_text) KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192; KRContext::KRENGINE_MIN_TEXTURE_DIM = 64; KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 128000000; + KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f; #endif _context = NULL; diff --git a/KREngine/kraken/KRLODGroup.cpp b/KREngine/kraken/KRLODGroup.cpp index 907427a..e3cbe52 100644 --- a/KREngine/kraken/KRLODGroup.cpp +++ b/KREngine/kraken/KRLODGroup.cpp @@ -102,15 +102,17 @@ void KRLODGroup::setReference(const KRAABB &reference) m_reference = reference; } -bool KRLODGroup::getLODVisibility(const KRViewport &viewport) +KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport) { if(m_min_distance == 0 && m_max_distance == 0) { - return true; + return LOD_VISIBILITY_VISIBLE; } else { float lod_bias = viewport.getLODBias(); lod_bias = pow(2.0f, -lod_bias); - float sqr_distance; // Compare using squared distances as sqrt is expensive + // Compare using squared distances as sqrt is expensive + float sqr_distance; + float sqr_prestream_distance; KRVector3 world_camera_position = viewport.getCameraPosition(); KRVector3 local_camera_position = worldToLocal(world_camera_position); @@ -119,13 +121,24 @@ bool KRLODGroup::getLODVisibility(const KRViewport &viewport) if(m_use_world_units) { KRVector3 world_reference_point = localToWorld(local_reference_point); sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias); + sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE; } else { sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias); + + KRVector3 world_reference_point = localToWorld(local_reference_point); + sqr_prestream_distance = worldToLocal(KRVector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc? + } - float sqr_min_distance = m_min_distance * m_min_distance; - float sqr_max_distance = m_max_distance * m_max_distance; - return ((sqr_distance >= sqr_min_distance || m_min_distance == 0) && (sqr_distance < sqr_max_distance || m_max_distance == 0)); + float sqr_min_visible_distance = m_min_distance * m_min_distance; + float sqr_max_visible_distance = m_max_distance * m_max_distance; + if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) { + return LOD_VISIBILITY_VISIBLE; + } else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) { + return LOD_VISIBILITY_PRESTREAM; + } else { + return LOD_VISIBILITY_HIDDEN; + } } } diff --git a/KREngine/kraken/KRLODGroup.h b/KREngine/kraken/KRLODGroup.h index e86a9c8..f16929a 100644 --- a/KREngine/kraken/KRLODGroup.h +++ b/KREngine/kraken/KRLODGroup.h @@ -30,7 +30,7 @@ public: void setUseWorldUnits(bool use_world_units); bool getUseWorldUnits() const; - bool getLODVisibility(const KRViewport &viewport); + LodVisibility calcLODVisibility(const KRViewport &viewport); private: float m_min_distance; diff --git a/KREngine/kraken/KRLODSet.cpp b/KREngine/kraken/KRLODSet.cpp index cc37fe0..bb1f144 100644 --- a/KREngine/kraken/KRLODSet.cpp +++ b/KREngine/kraken/KRLODSet.cpp @@ -12,7 +12,7 @@ KRLODSet::KRLODSet(KRScene &scene, std::string name) : KRNode(scene, name) { - m_activeLODGroup = NULL; + } KRLODSet::~KRLODSet() @@ -38,37 +38,38 @@ void KRLODSet::loadXML(tinyxml2::XMLElement *e) void KRLODSet::updateLODVisibility(const KRViewport &viewport) { - if(m_lod_visible) { + if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) { KRLODGroup *new_active_lod_group = NULL; // Upgrade and downgrade LOD groups as needed for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { KRLODGroup *lod_group = dynamic_cast(*itr); assert(lod_group != NULL); - if(lod_group->getLODVisibility(viewport)) { + LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); + if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) { new_active_lod_group = lod_group; } + lod_group->setLODVisibility(group_lod_visibility); } + /* + // FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues: + bool streamer_ready = false; if(new_active_lod_group == NULL) { - m_activeLODGroup = NULL; - } else if(m_activeLODGroup == NULL) { - m_activeLODGroup = new_active_lod_group; - } else if(new_active_lod_group != m_activeLODGroup) { - if(true || new_active_lod_group->getStreamLevel(true, viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) { // FINDME, HACK! Disabled due to performance issues. - // fprintf(stderr, "LOD %s -> %s\n", m_activeLODGroup->getName().c_str(), new_active_lod_group->getName().c_str()); - m_activeLODGroup = new_active_lod_group; - } else { - // fprintf(stderr, "LOD %s -> %s - waiting for streaming...\n", m_activeLODGroup->getName().c_str(), new_active_lod_group->getName().c_str()); - } + streamer_ready = true; + } else if(new_active_lod_group->getStreamLevel(viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) { + streamer_ready = true; } - - for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - KRNode *child = *itr; - if(child == m_activeLODGroup) { - child->showLOD(); - } else { - child->hideLOD(); + */ + bool streamer_ready = true; + + if(streamer_ready) { + // Upgrade and downgrade LOD groups as needed + for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { + KRLODGroup *lod_group = dynamic_cast(*itr); + assert(lod_group != NULL); + LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); + lod_group->setLODVisibility(group_lod_visibility); } } @@ -76,35 +77,20 @@ void KRLODSet::updateLODVisibility(const KRViewport &viewport) } } -KRLODGroup *KRLODSet::getActiveLODGroup() const +void KRLODSet::setLODVisibility(KRNode::LodVisibility lod_visibility) { - return m_activeLODGroup; -} - -void KRLODSet::childDeleted(KRNode *child_node) -{ - KRNode::childDeleted(child_node); - if(m_activeLODGroup == child_node) { - m_activeLODGroup = NULL; + if(lod_visibility == LOD_VISIBILITY_HIDDEN) { + KRNode::setLODVisibility(lod_visibility); + } else if(m_lod_visible != lod_visibility) { + // Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility + if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) { + getScene().notify_sceneGraphCreate(this); + } + m_lod_visible = lod_visibility; } } -void KRLODSet::hideLOD() -{ - KRNode::hideLOD(); - m_activeLODGroup = NULL; // Ensure that the streamer will wait for the group to load in next time -} - -void KRLODSet::showLOD() -{ - // Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility - if(!m_lod_visible) { - getScene().notify_sceneGraphCreate(this); - m_lod_visible = true; - } -} - -kraken_stream_level KRLODSet::getStreamLevel(bool prime, const KRViewport &viewport) +kraken_stream_level KRLODSet::getStreamLevel(const KRViewport &viewport) { KRLODGroup *new_active_lod_group = NULL; @@ -112,13 +98,13 @@ kraken_stream_level KRLODSet::getStreamLevel(bool prime, const KRViewport &viewp for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { KRLODGroup *lod_group = dynamic_cast(*itr); assert(lod_group != NULL); - if(lod_group->getLODVisibility(viewport)) { + if(lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) { new_active_lod_group = lod_group; } } if(new_active_lod_group) { - return new_active_lod_group->getStreamLevel(prime, viewport); + return new_active_lod_group->getStreamLevel(viewport); } else { return kraken_stream_level::STREAM_LEVEL_IN_HQ; } diff --git a/KREngine/kraken/KRLODSet.h b/KREngine/kraken/KRLODSet.h index 3e3c433..2e8034b 100644 --- a/KREngine/kraken/KRLODSet.h +++ b/KREngine/kraken/KRLODSet.h @@ -24,16 +24,9 @@ public: virtual void updateLODVisibility(const KRViewport &viewport); - KRLODGroup *getActiveLODGroup() const; + virtual void setLODVisibility(LodVisibility lod_visibility); - virtual void showLOD(); - virtual void hideLOD(); - virtual void childDeleted(KRNode *child_node); - - virtual kraken_stream_level getStreamLevel(bool prime, const KRViewport &viewport); - -private: - KRLODGroup *m_activeLODGroup; + virtual kraken_stream_level getStreamLevel(const KRViewport &viewport); }; diff --git a/KREngine/kraken/KRLight.cpp b/KREngine/kraken/KRLight.cpp index 6f44976..4d531ca 100644 --- a/KREngine/kraken/KRLight.cpp +++ b/KREngine/kraken/KRLight.cpp @@ -176,6 +176,8 @@ float KRLight::getDecayStart() { void KRLight::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; + KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) { diff --git a/KREngine/kraken/KRMaterial.cpp b/KREngine/kraken/KRMaterial.cpp index 9a33fd5..fa91451 100644 --- a/KREngine/kraken/KRMaterial.cpp +++ b/KREngine/kraken/KRMaterial.cpp @@ -217,34 +217,64 @@ bool KRMaterial::isTransparent() { return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE; } -kraken_stream_level KRMaterial::getStreamLevel(bool prime, float lodCoverage) +void KRMaterial::preStream(float lodCoverage) +{ + getTextures(); + + if(m_pAmbientMap) { + m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP); + } + + if(m_pDiffuseMap) { + m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); + } + + if(m_pNormalMap) { + m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); + } + + if(m_pSpecularMap) { + m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); + } + + if(m_pReflectionMap) { + m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP); + } + + if(m_pReflectionCube) { + m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); + } +} + + +kraken_stream_level KRMaterial::getStreamLevel() { kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; getTextures(); if(m_pAmbientMap) { - stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP)); + stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP)); } if(m_pDiffuseMap) { - stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP)); + stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP)); } if(m_pNormalMap) { - stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP)); + stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP)); } if(m_pSpecularMap) { - stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP)); + stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP)); } if(m_pReflectionMap) { - stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP)); + stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP)); } if(m_pReflectionCube) { - stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(prime, lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE)); + stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE)); } return stream_level; diff --git a/KREngine/kraken/KRMaterial.h b/KREngine/kraken/KRMaterial.h index 31a09a5..d15a2a6 100644 --- a/KREngine/kraken/KRMaterial.h +++ b/KREngine/kraken/KRMaterial.h @@ -88,7 +88,8 @@ public: bool needsVertexTangents(); - kraken_stream_level getStreamLevel(bool prime, float lodCoverage); + kraken_stream_level getStreamLevel(); + void preStream(float lodCoverage); private: std::string m_name; diff --git a/KREngine/kraken/KRMesh.cpp b/KREngine/kraken/KRMesh.cpp index c180b3c..8358bde 100644 --- a/KREngine/kraken/KRMesh.cpp +++ b/KREngine/kraken/KRMesh.cpp @@ -186,21 +186,30 @@ void KRMesh::getMaterials() } } -kraken_stream_level KRMesh::getStreamLevel(bool prime, float lodCoverage) +void KRMesh::preStream(float lodCoverage) +{ + getSubmeshes(); + getMaterials(); + + for(std::set::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) { + (*mat_itr)->preStream(lodCoverage); + } +} + +kraken_stream_level KRMesh::getStreamLevel() { kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; getSubmeshes(); getMaterials(); for(std::set::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) { - stream_level = KRMIN(stream_level, (*mat_itr)->getStreamLevel(prime, lodCoverage)); + stream_level = KRMIN(stream_level, (*mat_itr)->getStreamLevel()); } return stream_level; } void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector &bones, const KRVector3 &rim_color, float rim_power, float lod_coverage) { - //fprintf(stderr, "Rendering model: %s\n", m_name.c_str()); if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { diff --git a/KREngine/kraken/KRMesh.h b/KREngine/kraken/KRMesh.h index c2ab5ea..4e426d7 100644 --- a/KREngine/kraken/KRMesh.h +++ b/KREngine/kraken/KRMesh.h @@ -67,7 +67,8 @@ public: KRMesh(KRContext &context, std::string name); virtual ~KRMesh(); - kraken_stream_level getStreamLevel(bool prime, float lodCoverage); + kraken_stream_level getStreamLevel(); + void preStream(float lodCoverage); bool hasTransparency(); diff --git a/KREngine/kraken/KRModel.cpp b/KREngine/kraken/KRModel.cpp index 731baea..58b1cdb 100644 --- a/KREngine/kraken/KRModel.cpp +++ b/KREngine/kraken/KRModel.cpp @@ -149,10 +149,15 @@ void KRModel::loadModel() { void KRModel::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible == LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) { + preStream(viewport); + } + + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); - if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) { + if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) { loadModel(); if(m_models.size() > 0) { @@ -205,19 +210,33 @@ void KRModel::render(KRCamera *pCamera, std::vector &point_light } } - -kraken_stream_level KRModel::getStreamLevel(bool prime, const KRViewport &viewport) +void KRModel::preStream(const KRViewport &viewport) { - kraken_stream_level stream_level = KRNode::getStreamLevel(prime, viewport); - loadModel(); - float lod_coverage = 0.0f; - if(prime) { - lod_coverage = viewport.coverage(getBounds()); // This is only used when prime is true - } + float lod_coverage = viewport.coverage(getBounds()); for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { - stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(prime, lod_coverage)); + (*itr)->preStream(lod_coverage); + } + + if(m_pLightMap == NULL && m_lightMap.size()) { + m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); + } + + if(m_pLightMap) { + m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); + } +} + + +kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport) +{ + kraken_stream_level stream_level = KRNode::getStreamLevel(viewport); + + loadModel(); + + for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { + stream_level = KRMIN(stream_level, (*itr)->getStreamLevel()); } return stream_level; diff --git a/KREngine/kraken/KRModel.h b/KREngine/kraken/KRModel.h index f771a4b..95e1ee3 100644 --- a/KREngine/kraken/KRModel.h +++ b/KREngine/kraken/KRModel.h @@ -69,9 +69,11 @@ public: void setLightMap(const std::string &name); std::string getLightMap(); - virtual kraken_stream_level getStreamLevel(bool prime, const KRViewport &viewport); + virtual kraken_stream_level getStreamLevel(const KRViewport &viewport); private: + void preStream(const KRViewport &viewport); + std::vector m_models; unordered_map > m_bones; // Outer std::map connects model to set of bones KRTexture *m_pLightMap; diff --git a/KREngine/kraken/KRNode.cpp b/KREngine/kraken/KRNode.cpp index 4f5b07f..90b35de 100644 --- a/KREngine/kraken/KRNode.cpp +++ b/KREngine/kraken/KRNode.cpp @@ -63,7 +63,7 @@ KRNode::KRNode(KRScene &scene, std::string name) : KRContextObject(scene.getCont m_modelMatrix = KRMat4(); m_bindPoseMatrix = KRMat4(); m_activePoseMatrix = KRMat4(); - m_lod_visible = false; + m_lod_visible = LOD_VISIBILITY_HIDDEN; m_scale_compensation = false; m_boundsValid = false; @@ -117,10 +117,7 @@ void KRNode::addChild(KRNode *child) { assert(child->m_parentNode == NULL); child->m_parentNode = this; m_childNodes.insert(child); - if(m_lod_visible) { - // Child node inherits LOD visibility status from parent - child->showLOD(); - } + child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent } tinyxml2::XMLElement *KRNode::saveXML(tinyxml2::XMLNode *parent) { @@ -456,6 +453,8 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) { void KRNode::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; + m_lastRenderFrame = getContext().getCurrentFrame(); } @@ -887,37 +886,31 @@ void KRNode::addToOctreeNode(KROctreeNode *octree_node) void KRNode::updateLODVisibility(const KRViewport &viewport) { - if(m_lod_visible) { + if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) { for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { (*itr)->updateLODVisibility(viewport); } } } -void KRNode::hideLOD() +void KRNode::setLODVisibility(KRNode::LodVisibility lod_visibility) { - if(m_lod_visible) { - m_lod_visible = false; - getScene().notify_sceneGraphDelete(this); + if(m_lod_visible != lod_visibility) { + if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) { + getScene().notify_sceneGraphCreate(this); + } else if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && lod_visibility == LOD_VISIBILITY_HIDDEN) { + getScene().notify_sceneGraphDelete(this); + } + + m_lod_visible = lod_visibility; + for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - (*itr)->hideLOD(); + (*itr)->setLODVisibility(lod_visibility); } } } -void KRNode::showLOD() -{ - if(!m_lod_visible) { - getScene().notify_sceneGraphCreate(this); - m_lod_visible = true; - for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - (*itr)->showLOD(); - } - } -} - - -bool KRNode::lodIsVisible() +KRNode::LodVisibility KRNode::getLODVisibility() { return m_lod_visible; } @@ -944,12 +937,12 @@ std::set &KRNode::getBehaviors() return m_behaviors; } -kraken_stream_level KRNode::getStreamLevel(bool prime, const KRViewport &viewport) +kraken_stream_level KRNode::getStreamLevel(const KRViewport &viewport) { kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; for(std::set::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { - stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(prime, viewport)); + stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(viewport)); } return stream_level; diff --git a/KREngine/kraken/KRNode.h b/KREngine/kraken/KRNode.h index f542d1a..937f6bf 100644 --- a/KREngine/kraken/KRNode.h +++ b/KREngine/kraken/KRNode.h @@ -43,7 +43,14 @@ public: RENDER_PASS_ADDITIVE_PARTICLES, RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, RENDER_PASS_GENERATE_SHADOWMAPS, - RENDER_PASS_SHADOWMAP + RENDER_PASS_SHADOWMAP, + RENDER_PASS_PRESTREAM + }; + + enum LodVisibility { + LOD_VISIBILITY_HIDDEN, + LOD_VISIBILITY_PRESTREAM, + LOD_VISIBILITY_VISIBLE }; KRNode(KRScene &scene, std::string name); @@ -159,7 +166,7 @@ public: virtual bool hasPhysics(); virtual void updateLODVisibility(const KRViewport &viewport); - bool lodIsVisible(); + LodVisibility getLODVisibility(); void setScaleCompensation(bool scale_compensation); bool getScaleCompensation(); @@ -167,10 +174,9 @@ public: bool getAnimationEnabled(node_attribute_type attrib) const; - virtual kraken_stream_level getStreamLevel(bool prime, const KRViewport &viewport); + virtual kraken_stream_level getStreamLevel(const KRViewport &viewport); - virtual void hideLOD(); - virtual void showLOD(); + virtual void setLODVisibility(LodVisibility lod_visibility); protected: KRVector3 m_localTranslation; @@ -195,7 +201,7 @@ protected: KRVector3 m_initialPreRotation; KRVector3 m_initialPostRotation; - bool m_lod_visible; + LodVisibility m_lod_visible; KRNode *m_parentNode; std::set m_childNodes; @@ -246,7 +252,7 @@ public: } void removeFromOctreeNodes(); void addToOctreeNode(KROctreeNode *octree_node); - virtual void childDeleted(KRNode *child_node); + void childDeleted(KRNode *child_node); template T *find() { diff --git a/KREngine/kraken/KRParticleSystemNewtonian.cpp b/KREngine/kraken/KRParticleSystemNewtonian.cpp index 7431e75..8426600 100644 --- a/KREngine/kraken/KRParticleSystemNewtonian.cpp +++ b/KREngine/kraken/KRParticleSystemNewtonian.cpp @@ -56,6 +56,7 @@ bool KRParticleSystemNewtonian::hasPhysics() void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRPointLight.cpp b/KREngine/kraken/KRPointLight.cpp index 8ce2f07..bd9355a 100644 --- a/KREngine/kraken/KRPointLight.cpp +++ b/KREngine/kraken/KRPointLight.cpp @@ -43,6 +43,7 @@ KRAABB KRPointLight::getBounds() { void KRPointLight::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRReverbZone.cpp b/KREngine/kraken/KRReverbZone.cpp index 322dfea..577316e 100644 --- a/KREngine/kraken/KRReverbZone.cpp +++ b/KREngine/kraken/KRReverbZone.cpp @@ -86,6 +86,7 @@ void KRReverbZone::setZone(const std::string &zone) void KRReverbZone::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRScene.cpp b/KREngine/kraken/KRScene.cpp index 576d8a8..df92172 100644 --- a/KREngine/kraken/KRScene.cpp +++ b/KREngine/kraken/KRScene.cpp @@ -485,7 +485,7 @@ void KRScene::notify_sceneGraphDelete(KRNode *pNode) void KRScene::updateOctree(const KRViewport &viewport) { - m_pRootNode->showLOD(); + m_pRootNode->setLODVisibility(KRNode::LOD_VISIBILITY_VISIBLE); m_pRootNode->updateLODVisibility(viewport); std::set newNodes = std::move(m_newNodes); @@ -518,7 +518,7 @@ void KRScene::updateOctree(const KRViewport &viewport) } for(std::set::iterator itr=modifiedNodes.begin(); itr != modifiedNodes.end(); itr++) { KRNode *node = *itr; - if(node->lodIsVisible()) { + if(node->getLODVisibility() >= KRNode::LOD_VISIBILITY_PRESTREAM) { m_nodeTree.update(node); } if(node->hasPhysics()) { @@ -605,7 +605,7 @@ kraken_stream_level KRScene::getStreamLevel() if(m_pRootNode) { KRViewport viewport; // This isn't used when prime is false - stream_level = KRMIN(stream_level, m_pRootNode->getStreamLevel(false, viewport)); + stream_level = KRMIN(stream_level, m_pRootNode->getStreamLevel(viewport)); } return stream_level; diff --git a/KREngine/kraken/KRSprite.cpp b/KREngine/kraken/KRSprite.cpp index 62fbe5f..eebabcc 100644 --- a/KREngine/kraken/KRSprite.cpp +++ b/KREngine/kraken/KRSprite.cpp @@ -85,6 +85,8 @@ KRAABB KRSprite::getBounds() { void KRSprite::render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { + if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; + KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); diff --git a/KREngine/kraken/KRTexture.cpp b/KREngine/kraken/KRTexture.cpp index 062d52f..c6e1e6f 100644 --- a/KREngine/kraken/KRTexture.cpp +++ b/KREngine/kraken/KRTexture.cpp @@ -21,7 +21,6 @@ KRTexture::KRTexture(KRContext &context, std::string name) : KRResource(context, m_textureMemUsed = 0; m_newTextureMemUsed = 0; m_last_frame_used = 0; - m_last_frame_bound = 0; m_last_frame_max_lod_coverage = 0.0f; m_last_frame_usage = TEXTURE_USAGE_NONE; m_handle_lock.clear(); @@ -114,12 +113,8 @@ void KRTexture::resetPoolExpiry(float lodCoverage, KRTexture::texture_usage_t te m_last_frame_usage = static_cast(static_cast(m_last_frame_usage) | static_cast(textureUsage)); } -kraken_stream_level KRTexture::getStreamLevel(bool prime, float lodCoverage, KRTexture::texture_usage_t textureUsage) +kraken_stream_level KRTexture::getStreamLevel(KRTexture::texture_usage_t textureUsage) { - if(prime) { - resetPoolExpiry(lodCoverage, textureUsage); - } - if(m_current_lod_max_dim == 0) { return kraken_stream_level::STREAM_LEVEL_OUT; } else if(m_current_lod_max_dim == KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, m_max_lod_max_dim)) { @@ -198,11 +193,7 @@ bool KRTexture::hasMipmaps() { } void KRTexture::bind(GLuint texture_unit) { - m_last_frame_bound = getContext().getCurrentFrame(); -} - -bool KRTexture::canStreamOut() const { - return (m_last_frame_bound + 2 > getContext().getCurrentFrame()); + } void KRTexture::_swapHandles() diff --git a/KREngine/kraken/KRTexture.h b/KREngine/kraken/KRTexture.h index fa338b5..75284f6 100644 --- a/KREngine/kraken/KRTexture.h +++ b/KREngine/kraken/KRTexture.h @@ -85,8 +85,7 @@ public: int getMinMipMap(); bool hasMipmaps(); - bool canStreamOut() const; - kraken_stream_level getStreamLevel(bool prime, float lodCoverage, KRTexture::texture_usage_t textureUsage); + kraken_stream_level getStreamLevel(KRTexture::texture_usage_t textureUsage); float getLastFrameLodCoverage() const; void _swapHandles(); @@ -107,7 +106,6 @@ protected: uint32_t m_min_lod_max_dim; long m_last_frame_used; - long m_last_frame_bound; float m_last_frame_max_lod_coverage; texture_usage_t m_last_frame_usage;