Implemented getResourceBindings methods to recursively collect resource bindings from nodes and resource-to-resource connections. Replaced many KRNode::preStream() overrides with a generic handler in KRNode::preStream() that walks the resource binding tree.

This commit is contained in:
2025-11-17 19:40:51 -08:00
parent b146886691
commit 9b20d1ef1d
19 changed files with 307 additions and 157 deletions

View File

@@ -8,48 +8,36 @@ add_sources(kraken.cpp)
add_private_headers(KREngine-common.h) add_private_headers(KREngine-common.h)
add_sources(resources/KRResource+blend.cpp) add_sources(resources/KRResource+blend.cpp)
# add_source(resources/KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies # add_source(resources/KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
add_sources(resources/KRResource+obj.cpp)
add_private_headers(resources/KRResource.h) add_private_headers(resources/KRResource.h)
add_source_and_header(resources/KRResource) add_source_and_header(KRAudioBuffer)
add_source_and_header(resources/KRResourceBinding) add_source_and_header(KRBehavior)
add_source_and_header(resources/KRResourceManager) add_source_and_header(KRContext)
add_source_and_header(resources/animation/KRAnimation) add_source_and_header(KRContextObject)
add_source_and_header(resources/animation/KRAnimationAttribute) add_source_and_header(KRDevice)
add_source_and_header(resources/animation/KRAnimationLayer) add_source_and_header(KRDeviceManager)
add_source_and_header(resources/animation/KRAnimationManager) add_source_and_header(KRHelpers)
add_source_and_header(resources/animation_curve/KRAnimationCurve) add_source_and_header(KRModelView)
add_source_and_header(resources/animation_curve/KRAnimationCurveManager) add_source_and_header(KROctree)
add_source_and_header(resources/audio/KRAudioManager) add_source_and_header(KROctreeNode)
add_source_and_header(resources/audio/KRAudioSample) add_source_and_header(KRPipeline)
add_source_and_header(resources/audio/KRAudioSampleBinding) add_source_and_header(KRPipelineManager)
add_source_and_header(resources/bundle/KRBundle) add_source_and_header(KRPresentationThread)
add_source_and_header(resources/bundle/KRBundleManager) add_source_and_header(KRRenderGraph)
add_source_and_header(resources/material/KRMaterial) add_source_and_header(KRRenderGraphBlackFrame)
add_source_and_header(resources/material/KRMaterialManager) add_source_and_header(KRRenderGraphDeferred)
add_source_and_header(resources/mesh/KRMesh) add_source_and_header(KRRenderGraphForward)
add_source_and_header(resources/mesh/KRMeshBinding) add_source_and_header(KRRenderPass)
add_source_and_header(resources/mesh/KRMeshCube) add_source_and_header(KRRenderSettings)
add_source_and_header(resources/mesh/KRMeshManager) add_source_and_header(KRSampler)
add_source_and_header(resources/mesh/KRMeshQuad) add_source_and_header(KRSamplerManager)
add_source_and_header(resources/mesh/KRMeshSphere) add_source_and_header(KRShaderReflection)
add_source_and_header(resources/scene/KRScene) add_source_and_header(KRStreamerThread)
add_source_and_header(resources/scene/KRSceneManager) add_source_and_header(KRSurface)
add_source_and_header(resources/shader/KRShader) add_source_and_header(KRSurfaceManager)
add_source_and_header(resources/shader/KRShaderManager) add_source_and_header(KRSwapchain)
add_source_and_header(resources/source/KRSource) add_source_and_header(KRUniformBuffer)
add_source_and_header(resources/source/KRSourceManager) add_source_and_header(KRUniformBufferManager)
add_source_and_header(resources/texture/KRTextureBinding) add_source_and_header(KRViewport)
add_source_and_header(resources/texture/KRTexture)
add_source_and_header(resources/texture/KRTexture2D)
add_source_and_header(resources/texture/KRTextureAnimated)
add_source_and_header(resources/texture/KRTextureCube)
add_source_and_header(resources/texture/KRTextureKTX)
add_source_and_header(resources/texture/KRTextureKTX2)
add_source_and_header(resources/texture/KRTextureManager)
add_source_and_header(resources/texture/KRTexturePVR)
add_source_and_header(resources/texture/KRTextureTGA)
add_source_and_header(resources/unknown/KRUnknown)
add_source_and_header(resources/unknown/KRUnknownManager)
add_source_and_header(nodes/KRAmbientZone) add_source_and_header(nodes/KRAmbientZone)
add_source_and_header(nodes/KRAudioSource) add_source_and_header(nodes/KRAudioSource)
add_source_and_header(nodes/KRBone) add_source_and_header(nodes/KRBone)
@@ -68,32 +56,45 @@ add_source_and_header(nodes/KRPointLight)
add_source_and_header(nodes/KRReverbZone) add_source_and_header(nodes/KRReverbZone)
add_source_and_header(nodes/KRSpotLight) add_source_and_header(nodes/KRSpotLight)
add_source_and_header(nodes/KRSprite) add_source_and_header(nodes/KRSprite)
add_source_and_header(KRAudioBuffer) add_source_and_header(resources/animation/KRAnimation)
add_source_and_header(KRBehavior) add_source_and_header(resources/animation/KRAnimationAttribute)
add_source_and_header(KRContext) add_source_and_header(resources/animation/KRAnimationLayer)
add_source_and_header(KRUniformBuffer) add_source_and_header(resources/animation/KRAnimationManager)
add_source_and_header(KRUniformBufferManager) add_source_and_header(resources/animation_curve/KRAnimationCurve)
add_source_and_header(KRDevice) add_source_and_header(resources/animation_curve/KRAnimationCurveManager)
add_source_and_header(KRDeviceManager) add_source_and_header(resources/audio/KRAudioManager)
add_source_and_header(KRRenderPass) add_source_and_header(resources/audio/KRAudioSample)
add_source_and_header(KRSurface) add_source_and_header(resources/audio/KRAudioSampleBinding)
add_source_and_header(KRSurfaceManager) add_source_and_header(resources/bundle/KRBundle)
add_source_and_header(KRStreamerThread) add_source_and_header(resources/bundle/KRBundleManager)
add_source_and_header(KRSwapchain) add_source_and_header(resources/KRResource)
add_source_and_header(KRContextObject) add_source_and_header(resources/KRResourceBinding)
add_source_and_header(KRHelpers) add_source_and_header(resources/KRResourceManager)
add_source_and_header(KRModelView) add_source_and_header(resources/material/KRMaterial)
add_source_and_header(KROctree) add_source_and_header(resources/material/KRMaterialBinding)
add_source_and_header(KROctreeNode) add_source_and_header(resources/material/KRMaterialManager)
add_source_and_header(KRPresentationThread) add_source_and_header(resources/mesh/KRMesh)
add_source_and_header(KRRenderGraph) add_source_and_header(resources/mesh/KRMeshBinding)
add_source_and_header(KRRenderGraphBlackFrame) add_source_and_header(resources/mesh/KRMeshCube)
add_source_and_header(KRRenderGraphDeferred) add_source_and_header(resources/mesh/KRMeshManager)
add_source_and_header(KRRenderGraphForward) add_source_and_header(resources/mesh/KRMeshQuad)
add_source_and_header(KRRenderSettings) add_source_and_header(resources/mesh/KRMeshSphere)
add_source_and_header(KRPipeline) add_source_and_header(resources/scene/KRScene)
add_source_and_header(KRPipelineManager) add_source_and_header(resources/scene/KRSceneManager)
add_source_and_header(KRSampler) add_source_and_header(resources/shader/KRShader)
add_source_and_header(KRSamplerManager) add_source_and_header(resources/shader/KRShaderManager)
add_source_and_header(KRShaderReflection) add_source_and_header(resources/source/KRSource)
add_source_and_header(KRViewport) add_source_and_header(resources/source/KRSourceManager)
add_source_and_header(resources/texture/KRTexture)
add_source_and_header(resources/texture/KRTexture2D)
add_source_and_header(resources/texture/KRTextureAnimated)
add_source_and_header(resources/texture/KRTextureBinding)
add_source_and_header(resources/texture/KRTextureCube)
add_source_and_header(resources/texture/KRTextureKTX)
add_source_and_header(resources/texture/KRTextureKTX2)
add_source_and_header(resources/texture/KRTextureManager)
add_source_and_header(resources/texture/KRTexturePVR)
add_source_and_header(resources/texture/KRTextureTGA)
add_source_and_header(resources/unknown/KRUnknown)
add_source_and_header(resources/unknown/KRUnknownManager)
add_sources(resources/KRResource+obj.cpp)

View File

@@ -146,12 +146,12 @@ const std::string KRCamera::getSkyBox() const
return m_skyBox.getName(); return m_skyBox.getName();
} }
void KRCamera::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) void KRCamera::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{ {
KRNode::preStream(viewport, resourceRequests); KRNode::getResourceBindings(bindings);
m_skyBox.submitRequest(&getContext(), resourceRequests); bindings.push_back(&m_skyBox);
m_fontTexture.submitRequest(&getContext(), resourceRequests); bindings.push_back(&m_fontTexture);
} }
void KRCamera::render(KRNode::RenderInfo& ri) void KRCamera::render(KRNode::RenderInfo& ri)

View File

@@ -61,7 +61,7 @@ public:
void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface, KRRenderGraph& renderGraph); void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface, KRRenderGraph& renderGraph);
void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) final; void getResourceBindings(std::list<KRResourceBinding*>& bindings) final;
void render(KRNode::RenderInfo& ri) final; void render(KRNode::RenderInfo& ri) final;
KRRenderSettings settings; KRRenderSettings settings;

View File

@@ -223,12 +223,11 @@ float KRLight::getDecayStart() const
return m_decayStart; return m_decayStart;
} }
void KRLight::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) void KRLight::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{ {
KRNode::preStream(viewport, resourceRequests); KRNode::getResourceBindings(bindings);
// Pre-stream sprites, even if the alpha is zero bindings.push_back(&m_flareTexture);
m_flareTexture.submitRequest(&getContext(), resourceRequests);
} }
void KRLight::render(RenderInfo& ri) void KRLight::render(RenderInfo& ri)

View File

@@ -65,7 +65,7 @@ public:
void setFlareOcclusionSize(float occlusion_size); void setFlareOcclusionSize(float occlusion_size);
void deleteBuffers(); void deleteBuffers();
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) override; virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
virtual void render(RenderInfo& ri) override; virtual void render(RenderInfo& ri) override;
int getShadowBufferCount(); int getShadowBufferCount();

View File

@@ -306,20 +306,29 @@ void KRModel::render(KRNode::RenderInfo& ri)
} }
} }
void KRModel::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{
KRNode::getResourceBindings(bindings);
for (int i = 0; i < kMeshLODCount; i++) {
bindings.push_back(&m_meshes[i]);
}
bindings.push_back(&m_lightMap);
}
void KRModel::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) void KRModel::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests)
{ {
KRNode::preStream(viewport, resourceRequests); KRNode::preStream(viewport, resourceRequests);
loadModel(); loadModel();
float lod_coverage = viewport.coverage(getBounds());
for (int i = 0; i < kMeshLODCount; i++) { for (int i = 0; i < kMeshLODCount; i++) {
m_meshes[i].submitRequest(&getContext(), resourceRequests, lod_coverage); if (m_meshes[i].isBound()) {
m_meshes[i].get()->preStream();
}
} }
m_lightMap.submitRequest(&getContext(), resourceRequests);
} }
kraken_stream_level KRModel::getStreamLevel(const KRViewport& viewport) kraken_stream_level KRModel::getStreamLevel(const KRViewport& viewport)
{ {
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport); kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);

View File

@@ -63,6 +63,7 @@ public:
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void render(KRNode::RenderInfo& ri) override; virtual void render(KRNode::RenderInfo& ri) override;
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) override; virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) override;
virtual hydra::AABB getBounds(); virtual hydra::AABB getBounds();

View File

@@ -685,6 +685,28 @@ KRNode* KRNode::LoadXML(KRScene& scene, tinyxml2::XMLElement* e)
} }
void KRNode::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) void KRNode::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests)
{
float lod_coverage = viewport.coverage(getBounds());
// Walk through the resource tree recursively, submitting a resource request for each
// resource that is bound
std::list<KRResourceBinding*> bindings[2];
getResourceBindings(bindings[0]);
int bufferRead = 0;
while (!bindings[bufferRead].empty()) {
int bufferWrite = bufferRead ? 0 : 1;
for (KRResourceBinding* binding : bindings[bufferRead]) {
binding->submitRequest(&getContext(), resourceRequests, lod_coverage);
if (binding->isBound()) {
binding->get()->getResourceBindings(bindings[bufferWrite]);
}
}
bindings[bufferRead].clear();
bufferRead = bufferWrite;
}
}
void KRNode::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{ {
} }

View File

@@ -52,6 +52,7 @@ class KRTextureManager;
class KRContext; class KRContext;
class KRScene; class KRScene;
class KRSurface; class KRSurface;
class KRResourceBinding;
class KRNode; class KRNode;
class KRPointLight; class KRPointLight;
@@ -218,6 +219,7 @@ public:
KRScene& getScene(); KRScene& getScene();
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests); virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests);
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings);
virtual void render(RenderInfo& ri); virtual void render(RenderInfo& ri);
virtual void physicsUpdate(float deltaTime); virtual void physicsUpdate(float deltaTime);

View File

@@ -113,13 +113,11 @@ AABB KRSprite::getBounds()
return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix()); return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
} }
void KRSprite::getResourceBindings(std::list<KRResourceBinding*>& bindings)
void KRSprite::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests)
{ {
KRNode::preStream(viewport, resourceRequests); KRNode::getResourceBindings(bindings);
// Pre-stream sprites, even if the alpha is zero bindings.push_back(&m_spriteTexture);
m_spriteTexture.submitRequest(&getContext(), resourceRequests);
} }
void KRSprite::render(RenderInfo& ri) void KRSprite::render(RenderInfo& ri)

View File

@@ -52,7 +52,7 @@ public:
void setSpriteAlpha(float alpha); void setSpriteAlpha(float alpha);
float getSpriteAlpha() const; float getSpriteAlpha() const;
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests) override; virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
virtual void render(RenderInfo& ri) override; virtual void render(RenderInfo& ri) override;
virtual hydra::AABB getBounds() override; virtual hydra::AABB getBounds() override;

View File

@@ -76,3 +76,8 @@ void KRResource::requestResidency(uint32_t usage, float lodCoverage)
{ {
} }
void KRResource::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{
}

View File

@@ -38,6 +38,7 @@
class KRBundle; class KRBundle;
class KRScene; class KRScene;
class KRMesh; class KRMesh;
class KRResourceBinding;
class KRResource : public KRContextObject class KRResource : public KRContextObject
{ {
public: public:
@@ -52,6 +53,8 @@ public:
// to directly balance memory from KRResourceRequest's // to directly balance memory from KRResourceRequest's
virtual void requestResidency(uint32_t usage, float lodCoverage); virtual void requestResidency(uint32_t usage, float lodCoverage);
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings);
virtual ~KRResource(); virtual ~KRResource();
static KRMesh* LoadObj(KRContext& context, const std::string& path); static KRMesh* LoadObj(KRContext& context, const std::string& path);

View File

@@ -235,14 +235,16 @@ bool KRMaterial::isTransparent()
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE; return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
} }
void KRMaterial::preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage) void KRMaterial::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{ {
m_ambientMap.submitRequest(&getContext(), resourceRequests, lodCoverage); KRResource::getResourceBindings(bindings);
m_diffuseMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
m_normalMap.submitRequest(&getContext(), resourceRequests, lodCoverage); bindings.push_back(&m_ambientMap);
m_specularMap.submitRequest(&getContext(), resourceRequests, lodCoverage); bindings.push_back(&m_diffuseMap);
m_reflectionMap.submitRequest(&getContext(), resourceRequests, lodCoverage); bindings.push_back(&m_normalMap);
m_reflectionCube.submitRequest(&getContext(), resourceRequests, lodCoverage); bindings.push_back(&m_specularMap);
bindings.push_back(&m_reflectionMap);
bindings.push_back(&m_reflectionCube);
} }
kraken_stream_level KRMaterial::getStreamLevel() kraken_stream_level KRMaterial::getStreamLevel()

View File

@@ -96,7 +96,8 @@ public:
bool needsVertexTangents(); bool needsVertexTangents();
kraken_stream_level getStreamLevel(); kraken_stream_level getStreamLevel();
void preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage);
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
private: private:
std::string m_name; std::string m_name;

View File

@@ -0,0 +1,65 @@
//
// KRMaterialBinding.cpp
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRContext.h"
#include "KRMaterial.h"
#include "KRMaterialBinding.h"
KRMaterialBinding::KRMaterialBinding()
: KRResourceBinding(0)
{
}
KRMaterialBinding::KRMaterialBinding(const std::string& name)
: KRResourceBinding(name, 0)
{
}
KRMaterial* KRMaterialBinding::get()
{
return static_cast<KRMaterial*>(m_resource);
}
bool KRMaterialBinding::bind(KRContext* context)
{
if (m_name.size() == 0) {
return true;
}
if (m_resource != nullptr) {
return true;
}
m_resource = context->getMaterialManager()->getMaterial(m_name.c_str());
return (m_resource != nullptr);
}

View File

@@ -0,0 +1,48 @@
//
// KRMaterialBinding.h
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResourceBinding.h"
class KRMaterial;
class KRMaterialBinding : public KRResourceBinding
{
public:
KRMaterialBinding();
KRMaterialBinding(const std::string& name);
KRMaterial* get();
bool bind(KRContext* context) override final;
private:
};

View File

@@ -164,26 +164,7 @@ void KRMesh::getMaterials()
for (std::vector<KRMesh::Submesh>::iterator itr = m_submeshes.begin(); itr != m_submeshes.end(); itr++) { for (std::vector<KRMesh::Submesh>::iterator itr = m_submeshes.begin(); itr != m_submeshes.end(); itr++) {
const char* szMaterialName = (*itr).szMaterialName; const char* szMaterialName = (*itr).szMaterialName;
KRMaterial* pMaterial = nullptr; m_materials.push_back(KRMaterialBinding(szMaterialName));
if (*szMaterialName != '\0') {
pMaterial = getContext().getMaterialManager()->getMaterial(szMaterialName);
}
m_materials.push_back(pMaterial);
if (pMaterial) {
m_uniqueMaterials.insert(pMaterial);
} else if (*szMaterialName != '\0') {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Missing material: %s", szMaterialName);
m_materials.clear();
return;
}
}
m_hasTransparency = false;
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
if ((*mat_itr)->isTransparent()) {
m_hasTransparency = true;
break;
}
} }
} }
@@ -198,13 +179,26 @@ void KRMesh::requestResidency(uint32_t usage, float lodCoverage)
} }
} }
void KRMesh::preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage) void KRMesh::preStream()
{ {
getSubmeshes(); getSubmeshes();
getMaterials(); getMaterials();
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) { m_hasTransparency = false;
(*mat_itr)->preStream(resourceRequests, lodCoverage); for(KRMaterialBinding& material : m_materials) {
if (material.isBound() && material.get()->isTransparent()) {
m_hasTransparency = true;
break;
}
}
}
void KRMesh::getResourceBindings(std::list<KRResourceBinding*>& bindings)
{
KRResource::getResourceBindings(bindings);
for (KRResourceBinding& binding : m_materials) {
bindings.push_back(&binding);
} }
} }
@@ -214,8 +208,10 @@ kraken_stream_level KRMesh::getStreamLevel()
getSubmeshes(); getSubmeshes();
getMaterials(); getMaterials();
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) { for (KRMaterialBinding& material : m_materials) {
stream_level = KRMIN(stream_level, (*mat_itr)->getStreamLevel()); if (material.isBound()) {
stream_level = KRMIN(stream_level, material.get()->getStreamLevel());
}
} }
bool all_vbo_data_loaded = true; bool all_vbo_data_loaded = true;
bool vbo_data_loaded = false; bool vbo_data_loaded = false;
@@ -251,46 +247,42 @@ void KRMesh::render(KRNode::RenderInfo& ri, const std::string& object_name, cons
int cSubmeshes = (int)m_submeshes.size(); int cSubmeshes = (int)m_submeshes.size();
if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_SHADOWMAP) { if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_SHADOWMAP) {
for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) { for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
KRMaterial* pMaterial = m_materials[iSubmesh]; KRMaterial* pMaterial = m_materials[iSubmesh].get();
if (pMaterial && !pMaterial->isTransparent()) { if (pMaterial && !pMaterial->isTransparent()) {
// Exclude transparent and semi-transparent meshes from shadow maps // Exclude transparent and semi-transparent meshes from shadow maps
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage); renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
} }
} }
} else { } else {
// Apply submeshes in per-material batches to reduce number of state changes for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) { KRMaterial* pMaterial = m_materials[iSubmesh].get();
for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
KRMaterial* pMaterial = m_materials[iSubmesh];
if (pMaterial != NULL && pMaterial == (*mat_itr)) { if (pMaterial) {
if ((!pMaterial->isTransparent() && ri.renderPass->getType() != RenderPassType::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && ri.renderPass->getType() == RenderPassType::RENDER_PASS_FORWARD_TRANSPARENT)) { if ((!pMaterial->isTransparent() && ri.renderPass->getType() != RenderPassType::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && ri.renderPass->getType() == RenderPassType::RENDER_PASS_FORWARD_TRANSPARENT)) {
std::vector<Matrix4> bone_bind_poses; std::vector<Matrix4> bone_bind_poses;
for (int i = 0; i < (int)bones.size(); i++) { for (int i = 0; i < (int)bones.size(); i++) {
bone_bind_poses.push_back(getBoneBindPose(i)); bone_bind_poses.push_back(getBoneBindPose(i));
} }
switch (pMaterial->getAlphaMode()) {
case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials
case KRMaterial::KRMATERIAL_ALPHA_MODE_TEST: // Alpha in diffuse texture is interpreted as punch-through when < 0.5
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE: // Blended alpha with backface culling
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
// Render back faces first
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullFront, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
switch (pMaterial->getAlphaMode()) { // Render front faces second
case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
case KRMaterial::KRMATERIAL_ALPHA_MODE_TEST: // Alpha in diffuse texture is interpreted as punch-through when < 0.5 renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage); break;
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE: // Blended alpha with backface culling
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
// Render back faces first
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullFront, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
// Render front faces second
pMaterial->bind(ri, getModelFormat(), getVertexAttributes(), CullMode::kCullBack, bones, bone_bind_poses, matModel, pLightMap, lod_coverage);
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
}
} }
} }
} }

View File

@@ -36,6 +36,7 @@
#include "KRContext.h" #include "KRContext.h"
#include "nodes/KRBone.h" #include "nodes/KRBone.h"
#include "KRMeshManager.h" #include "KRMeshManager.h"
#include "resources/material/KRMaterialBinding.h"
#include "KREngine-common.h" #include "KREngine-common.h"
@@ -75,7 +76,8 @@ public:
virtual ~KRMesh(); virtual ~KRMesh();
kraken_stream_level getStreamLevel(); kraken_stream_level getStreamLevel();
void preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage); virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
void preStream();
void requestResidency(uint32_t usage, float lodCoverage) final; void requestResidency(uint32_t usage, float lodCoverage) final;
bool hasTransparency(); bool hasTransparency();
@@ -251,7 +253,7 @@ private:
static bool sphereCast(const hydra::Matrix4& model_to_world, const hydra::Vector3& v0, const hydra::Vector3& v1, float radius, const hydra::Triangle3& tri, hydra::HitInfo& hitinfo); static bool sphereCast(const hydra::Matrix4& model_to_world, const hydra::Vector3& v0, const hydra::Vector3& v1, float radius, const hydra::Triangle3& tri, hydra::HitInfo& hitinfo);
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model) int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
vector<KRMaterial*> m_materials; vector<KRMaterialBinding> m_materials;
set<KRMaterial*> m_uniqueMaterials; set<KRMaterial*> m_uniqueMaterials;
bool m_hasTransparency; bool m_hasTransparency;