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:
@@ -8,48 +8,36 @@ add_sources(kraken.cpp)
|
||||
add_private_headers(KREngine-common.h)
|
||||
add_sources(resources/KRResource+blend.cpp)
|
||||
# add_source(resources/KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
|
||||
add_sources(resources/KRResource+obj.cpp)
|
||||
add_private_headers(resources/KRResource.h)
|
||||
add_source_and_header(resources/KRResource)
|
||||
add_source_and_header(resources/KRResourceBinding)
|
||||
add_source_and_header(resources/KRResourceManager)
|
||||
add_source_and_header(resources/animation/KRAnimation)
|
||||
add_source_and_header(resources/animation/KRAnimationAttribute)
|
||||
add_source_and_header(resources/animation/KRAnimationLayer)
|
||||
add_source_and_header(resources/animation/KRAnimationManager)
|
||||
add_source_and_header(resources/animation_curve/KRAnimationCurve)
|
||||
add_source_and_header(resources/animation_curve/KRAnimationCurveManager)
|
||||
add_source_and_header(resources/audio/KRAudioManager)
|
||||
add_source_and_header(resources/audio/KRAudioSample)
|
||||
add_source_and_header(resources/audio/KRAudioSampleBinding)
|
||||
add_source_and_header(resources/bundle/KRBundle)
|
||||
add_source_and_header(resources/bundle/KRBundleManager)
|
||||
add_source_and_header(resources/material/KRMaterial)
|
||||
add_source_and_header(resources/material/KRMaterialManager)
|
||||
add_source_and_header(resources/mesh/KRMesh)
|
||||
add_source_and_header(resources/mesh/KRMeshBinding)
|
||||
add_source_and_header(resources/mesh/KRMeshCube)
|
||||
add_source_and_header(resources/mesh/KRMeshManager)
|
||||
add_source_and_header(resources/mesh/KRMeshQuad)
|
||||
add_source_and_header(resources/mesh/KRMeshSphere)
|
||||
add_source_and_header(resources/scene/KRScene)
|
||||
add_source_and_header(resources/scene/KRSceneManager)
|
||||
add_source_and_header(resources/shader/KRShader)
|
||||
add_source_and_header(resources/shader/KRShaderManager)
|
||||
add_source_and_header(resources/source/KRSource)
|
||||
add_source_and_header(resources/source/KRSourceManager)
|
||||
add_source_and_header(resources/texture/KRTextureBinding)
|
||||
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(KRAudioBuffer)
|
||||
add_source_and_header(KRBehavior)
|
||||
add_source_and_header(KRContext)
|
||||
add_source_and_header(KRContextObject)
|
||||
add_source_and_header(KRDevice)
|
||||
add_source_and_header(KRDeviceManager)
|
||||
add_source_and_header(KRHelpers)
|
||||
add_source_and_header(KRModelView)
|
||||
add_source_and_header(KROctree)
|
||||
add_source_and_header(KROctreeNode)
|
||||
add_source_and_header(KRPipeline)
|
||||
add_source_and_header(KRPipelineManager)
|
||||
add_source_and_header(KRPresentationThread)
|
||||
add_source_and_header(KRRenderGraph)
|
||||
add_source_and_header(KRRenderGraphBlackFrame)
|
||||
add_source_and_header(KRRenderGraphDeferred)
|
||||
add_source_and_header(KRRenderGraphForward)
|
||||
add_source_and_header(KRRenderPass)
|
||||
add_source_and_header(KRRenderSettings)
|
||||
add_source_and_header(KRSampler)
|
||||
add_source_and_header(KRSamplerManager)
|
||||
add_source_and_header(KRShaderReflection)
|
||||
add_source_and_header(KRStreamerThread)
|
||||
add_source_and_header(KRSurface)
|
||||
add_source_and_header(KRSurfaceManager)
|
||||
add_source_and_header(KRSwapchain)
|
||||
add_source_and_header(KRUniformBuffer)
|
||||
add_source_and_header(KRUniformBufferManager)
|
||||
add_source_and_header(KRViewport)
|
||||
add_source_and_header(nodes/KRAmbientZone)
|
||||
add_source_and_header(nodes/KRAudioSource)
|
||||
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/KRSpotLight)
|
||||
add_source_and_header(nodes/KRSprite)
|
||||
add_source_and_header(KRAudioBuffer)
|
||||
add_source_and_header(KRBehavior)
|
||||
add_source_and_header(KRContext)
|
||||
add_source_and_header(KRUniformBuffer)
|
||||
add_source_and_header(KRUniformBufferManager)
|
||||
add_source_and_header(KRDevice)
|
||||
add_source_and_header(KRDeviceManager)
|
||||
add_source_and_header(KRRenderPass)
|
||||
add_source_and_header(KRSurface)
|
||||
add_source_and_header(KRSurfaceManager)
|
||||
add_source_and_header(KRStreamerThread)
|
||||
add_source_and_header(KRSwapchain)
|
||||
add_source_and_header(KRContextObject)
|
||||
add_source_and_header(KRHelpers)
|
||||
add_source_and_header(KRModelView)
|
||||
add_source_and_header(KROctree)
|
||||
add_source_and_header(KROctreeNode)
|
||||
add_source_and_header(KRPresentationThread)
|
||||
add_source_and_header(KRRenderGraph)
|
||||
add_source_and_header(KRRenderGraphBlackFrame)
|
||||
add_source_and_header(KRRenderGraphDeferred)
|
||||
add_source_and_header(KRRenderGraphForward)
|
||||
add_source_and_header(KRRenderSettings)
|
||||
add_source_and_header(KRPipeline)
|
||||
add_source_and_header(KRPipelineManager)
|
||||
add_source_and_header(KRSampler)
|
||||
add_source_and_header(KRSamplerManager)
|
||||
add_source_and_header(KRShaderReflection)
|
||||
add_source_and_header(KRViewport)
|
||||
add_source_and_header(resources/animation/KRAnimation)
|
||||
add_source_and_header(resources/animation/KRAnimationAttribute)
|
||||
add_source_and_header(resources/animation/KRAnimationLayer)
|
||||
add_source_and_header(resources/animation/KRAnimationManager)
|
||||
add_source_and_header(resources/animation_curve/KRAnimationCurve)
|
||||
add_source_and_header(resources/animation_curve/KRAnimationCurveManager)
|
||||
add_source_and_header(resources/audio/KRAudioManager)
|
||||
add_source_and_header(resources/audio/KRAudioSample)
|
||||
add_source_and_header(resources/audio/KRAudioSampleBinding)
|
||||
add_source_and_header(resources/bundle/KRBundle)
|
||||
add_source_and_header(resources/bundle/KRBundleManager)
|
||||
add_source_and_header(resources/KRResource)
|
||||
add_source_and_header(resources/KRResourceBinding)
|
||||
add_source_and_header(resources/KRResourceManager)
|
||||
add_source_and_header(resources/material/KRMaterial)
|
||||
add_source_and_header(resources/material/KRMaterialBinding)
|
||||
add_source_and_header(resources/material/KRMaterialManager)
|
||||
add_source_and_header(resources/mesh/KRMesh)
|
||||
add_source_and_header(resources/mesh/KRMeshBinding)
|
||||
add_source_and_header(resources/mesh/KRMeshCube)
|
||||
add_source_and_header(resources/mesh/KRMeshManager)
|
||||
add_source_and_header(resources/mesh/KRMeshQuad)
|
||||
add_source_and_header(resources/mesh/KRMeshSphere)
|
||||
add_source_and_header(resources/scene/KRScene)
|
||||
add_source_and_header(resources/scene/KRSceneManager)
|
||||
add_source_and_header(resources/shader/KRShader)
|
||||
add_source_and_header(resources/shader/KRShaderManager)
|
||||
add_source_and_header(resources/source/KRSource)
|
||||
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)
|
||||
|
||||
@@ -146,12 +146,12 @@ const std::string KRCamera::getSkyBox() const
|
||||
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);
|
||||
m_fontTexture.submitRequest(&getContext(), resourceRequests);
|
||||
bindings.push_back(&m_skyBox);
|
||||
bindings.push_back(&m_fontTexture);
|
||||
}
|
||||
|
||||
void KRCamera::render(KRNode::RenderInfo& ri)
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
KRRenderSettings settings;
|
||||
|
||||
@@ -223,12 +223,11 @@ float KRLight::getDecayStart() const
|
||||
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
|
||||
m_flareTexture.submitRequest(&getContext(), resourceRequests);
|
||||
bindings.push_back(&m_flareTexture);
|
||||
}
|
||||
|
||||
void KRLight::render(RenderInfo& ri)
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
void setFlareOcclusionSize(float occlusion_size);
|
||||
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;
|
||||
|
||||
int getShadowBufferCount();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
KRNode::preStream(viewport, resourceRequests);
|
||||
loadModel();
|
||||
float lod_coverage = viewport.coverage(getBounds());
|
||||
|
||||
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 stream_level = KRNode::getStreamLevel(viewport);
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
|
||||
|
||||
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 hydra::AABB getBounds();
|
||||
|
||||
@@ -685,6 +685,28 @@ KRNode* KRNode::LoadXML(KRScene& scene, tinyxml2::XMLElement* e)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ class KRTextureManager;
|
||||
class KRContext;
|
||||
class KRScene;
|
||||
class KRSurface;
|
||||
class KRResourceBinding;
|
||||
|
||||
class KRNode;
|
||||
class KRPointLight;
|
||||
@@ -218,6 +219,7 @@ public:
|
||||
KRScene& getScene();
|
||||
|
||||
virtual void preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests);
|
||||
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings);
|
||||
virtual void render(RenderInfo& ri);
|
||||
|
||||
virtual void physicsUpdate(float deltaTime);
|
||||
|
||||
@@ -113,13 +113,11 @@ AABB KRSprite::getBounds()
|
||||
return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
|
||||
}
|
||||
|
||||
|
||||
void KRSprite::preStream(const KRViewport& viewport, std::list<KRResourceRequest>& resourceRequests)
|
||||
void KRSprite::getResourceBindings(std::list<KRResourceBinding*>& bindings)
|
||||
{
|
||||
KRNode::preStream(viewport, resourceRequests);
|
||||
KRNode::getResourceBindings(bindings);
|
||||
|
||||
// Pre-stream sprites, even if the alpha is zero
|
||||
m_spriteTexture.submitRequest(&getContext(), resourceRequests);
|
||||
bindings.push_back(&m_spriteTexture);
|
||||
}
|
||||
|
||||
void KRSprite::render(RenderInfo& ri)
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
void setSpriteAlpha(float alpha);
|
||||
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 hydra::AABB getBounds() override;
|
||||
|
||||
@@ -76,3 +76,8 @@ void KRResource::requestResidency(uint32_t usage, float lodCoverage)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KRResource::getResourceBindings(std::list<KRResourceBinding*>& bindings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
class KRBundle;
|
||||
class KRScene;
|
||||
class KRMesh;
|
||||
class KRResourceBinding;
|
||||
class KRResource : public KRContextObject
|
||||
{
|
||||
public:
|
||||
@@ -52,6 +53,8 @@ public:
|
||||
// to directly balance memory from KRResourceRequest's
|
||||
virtual void requestResidency(uint32_t usage, float lodCoverage);
|
||||
|
||||
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings);
|
||||
|
||||
virtual ~KRResource();
|
||||
|
||||
static KRMesh* LoadObj(KRContext& context, const std::string& path);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
void KRMaterial::preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage)
|
||||
void KRMaterial::getResourceBindings(std::list<KRResourceBinding*>& bindings)
|
||||
{
|
||||
m_ambientMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
m_diffuseMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
m_normalMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
m_specularMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
m_reflectionMap.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
m_reflectionCube.submitRequest(&getContext(), resourceRequests, lodCoverage);
|
||||
KRResource::getResourceBindings(bindings);
|
||||
|
||||
bindings.push_back(&m_ambientMap);
|
||||
bindings.push_back(&m_diffuseMap);
|
||||
bindings.push_back(&m_normalMap);
|
||||
bindings.push_back(&m_specularMap);
|
||||
bindings.push_back(&m_reflectionMap);
|
||||
bindings.push_back(&m_reflectionCube);
|
||||
}
|
||||
|
||||
kraken_stream_level KRMaterial::getStreamLevel()
|
||||
|
||||
@@ -96,7 +96,8 @@ public:
|
||||
bool needsVertexTangents();
|
||||
|
||||
kraken_stream_level getStreamLevel();
|
||||
void preStream(std::list<KRResourceRequest>& resourceRequests, float lodCoverage);
|
||||
|
||||
virtual void getResourceBindings(std::list<KRResourceBinding*>& bindings) override;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
65
kraken/resources/material/KRMaterialBinding.cpp
Normal file
65
kraken/resources/material/KRMaterialBinding.cpp
Normal 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);
|
||||
}
|
||||
48
kraken/resources/material/KRMaterialBinding.h
Normal file
48
kraken/resources/material/KRMaterialBinding.h
Normal 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:
|
||||
};
|
||||
@@ -164,26 +164,7 @@ void KRMesh::getMaterials()
|
||||
|
||||
for (std::vector<KRMesh::Submesh>::iterator itr = m_submeshes.begin(); itr != m_submeshes.end(); itr++) {
|
||||
const char* szMaterialName = (*itr).szMaterialName;
|
||||
KRMaterial* pMaterial = nullptr;
|
||||
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;
|
||||
}
|
||||
m_materials.push_back(KRMaterialBinding(szMaterialName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
getMaterials();
|
||||
|
||||
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
|
||||
(*mat_itr)->preStream(resourceRequests, lodCoverage);
|
||||
m_hasTransparency = false;
|
||||
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();
|
||||
getMaterials();
|
||||
|
||||
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
|
||||
stream_level = KRMIN(stream_level, (*mat_itr)->getStreamLevel());
|
||||
for (KRMaterialBinding& material : m_materials) {
|
||||
if (material.isBound()) {
|
||||
stream_level = KRMIN(stream_level, material.get()->getStreamLevel());
|
||||
}
|
||||
}
|
||||
bool all_vbo_data_loaded = true;
|
||||
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();
|
||||
if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_SHADOWMAP) {
|
||||
for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
|
||||
KRMaterial* pMaterial = m_materials[iSubmesh];
|
||||
KRMaterial* pMaterial = m_materials[iSubmesh].get();
|
||||
if (pMaterial && !pMaterial->isTransparent()) {
|
||||
// Exclude transparent and semi-transparent meshes from shadow maps
|
||||
renderSubmesh(ri.commandBuffer, iSubmesh, ri.renderPass, object_name, pMaterial->getName(), lod_coverage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Apply submeshes in per-material batches to reduce number of state changes
|
||||
for (std::set<KRMaterial*>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
|
||||
for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
|
||||
KRMaterial* pMaterial = m_materials[iSubmesh];
|
||||
for (int iSubmesh = 0; iSubmesh < cSubmeshes; iSubmesh++) {
|
||||
KRMaterial* pMaterial = m_materials[iSubmesh].get();
|
||||
|
||||
if (pMaterial != NULL && pMaterial == (*mat_itr)) {
|
||||
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;
|
||||
for (int i = 0; i < (int)bones.size(); i++) {
|
||||
bone_bind_poses.push_back(getBoneBindPose(i));
|
||||
}
|
||||
if (pMaterial) {
|
||||
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;
|
||||
for (int i = 0; i < (int)bones.size(); 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()) {
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "KRContext.h"
|
||||
#include "nodes/KRBone.h"
|
||||
#include "KRMeshManager.h"
|
||||
#include "resources/material/KRMaterialBinding.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
@@ -75,7 +76,8 @@ public:
|
||||
virtual ~KRMesh();
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
bool m_hasTransparency;
|
||||
|
||||
Reference in New Issue
Block a user