diff --git a/kraken/CMakeLists.txt b/kraken/CMakeLists.txt index 7183f3a..5e3db5e 100644 --- a/kraken/CMakeLists.txt +++ b/kraken/CMakeLists.txt @@ -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) diff --git a/kraken/nodes/KRCamera.cpp b/kraken/nodes/KRCamera.cpp index 76b655f..c85617c 100755 --- a/kraken/nodes/KRCamera.cpp +++ b/kraken/nodes/KRCamera.cpp @@ -146,12 +146,12 @@ const std::string KRCamera::getSkyBox() const return m_skyBox.getName(); } -void KRCamera::preStream(const KRViewport& viewport, std::list& resourceRequests) +void KRCamera::getResourceBindings(std::list& 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) diff --git a/kraken/nodes/KRCamera.h b/kraken/nodes/KRCamera.h index 500324c..8d53e70 100755 --- a/kraken/nodes/KRCamera.h +++ b/kraken/nodes/KRCamera.h @@ -61,7 +61,7 @@ public: void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface, KRRenderGraph& renderGraph); - void preStream(const KRViewport& viewport, std::list& resourceRequests) final; + void getResourceBindings(std::list& bindings) final; void render(KRNode::RenderInfo& ri) final; KRRenderSettings settings; diff --git a/kraken/nodes/KRLight.cpp b/kraken/nodes/KRLight.cpp index 3f85335..81bd9f0 100755 --- a/kraken/nodes/KRLight.cpp +++ b/kraken/nodes/KRLight.cpp @@ -223,12 +223,11 @@ float KRLight::getDecayStart() const return m_decayStart; } -void KRLight::preStream(const KRViewport& viewport, std::list& resourceRequests) +void KRLight::getResourceBindings(std::list& 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) diff --git a/kraken/nodes/KRLight.h b/kraken/nodes/KRLight.h index 61cd82f..406a7ea 100755 --- a/kraken/nodes/KRLight.h +++ b/kraken/nodes/KRLight.h @@ -65,7 +65,7 @@ public: void setFlareOcclusionSize(float occlusion_size); void deleteBuffers(); - virtual void preStream(const KRViewport& viewport, std::list& resourceRequests) override; + virtual void getResourceBindings(std::list& bindings) override; virtual void render(RenderInfo& ri) override; int getShadowBufferCount(); diff --git a/kraken/nodes/KRModel.cpp b/kraken/nodes/KRModel.cpp index 761ec3a..7a5a82d 100755 --- a/kraken/nodes/KRModel.cpp +++ b/kraken/nodes/KRModel.cpp @@ -306,20 +306,29 @@ void KRModel::render(KRNode::RenderInfo& ri) } } +void KRModel::getResourceBindings(std::list& 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& 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); diff --git a/kraken/nodes/KRModel.h b/kraken/nodes/KRModel.h index ff38bcc..6cf5a74 100755 --- a/kraken/nodes/KRModel.h +++ b/kraken/nodes/KRModel.h @@ -63,6 +63,7 @@ public: virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent); virtual void render(KRNode::RenderInfo& ri) override; + virtual void getResourceBindings(std::list& bindings) override; virtual void preStream(const KRViewport& viewport, std::list& resourceRequests) override; virtual hydra::AABB getBounds(); diff --git a/kraken/nodes/KRNode.cpp b/kraken/nodes/KRNode.cpp index bdc96dd..e66a01a 100755 --- a/kraken/nodes/KRNode.cpp +++ b/kraken/nodes/KRNode.cpp @@ -685,6 +685,28 @@ KRNode* KRNode::LoadXML(KRScene& scene, tinyxml2::XMLElement* e) } void KRNode::preStream(const KRViewport& viewport, std::list& 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 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& bindings) { } diff --git a/kraken/nodes/KRNode.h b/kraken/nodes/KRNode.h index 2ddc206..cdcb587 100755 --- a/kraken/nodes/KRNode.h +++ b/kraken/nodes/KRNode.h @@ -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& resourceRequests); + virtual void getResourceBindings(std::list& bindings); virtual void render(RenderInfo& ri); virtual void physicsUpdate(float deltaTime); diff --git a/kraken/nodes/KRSprite.cpp b/kraken/nodes/KRSprite.cpp index 0c4436d..a576946 100755 --- a/kraken/nodes/KRSprite.cpp +++ b/kraken/nodes/KRSprite.cpp @@ -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& resourceRequests) +void KRSprite::getResourceBindings(std::list& 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) diff --git a/kraken/nodes/KRSprite.h b/kraken/nodes/KRSprite.h index da3ed77..44290a1 100755 --- a/kraken/nodes/KRSprite.h +++ b/kraken/nodes/KRSprite.h @@ -52,7 +52,7 @@ public: void setSpriteAlpha(float alpha); float getSpriteAlpha() const; - virtual void preStream(const KRViewport& viewport, std::list& resourceRequests) override; + virtual void getResourceBindings(std::list& bindings) override; virtual void render(RenderInfo& ri) override; virtual hydra::AABB getBounds() override; diff --git a/kraken/resources/KRResource.cpp b/kraken/resources/KRResource.cpp index 185a303..2feeee2 100755 --- a/kraken/resources/KRResource.cpp +++ b/kraken/resources/KRResource.cpp @@ -76,3 +76,8 @@ void KRResource::requestResidency(uint32_t usage, float lodCoverage) { } + +void KRResource::getResourceBindings(std::list& bindings) +{ + +} diff --git a/kraken/resources/KRResource.h b/kraken/resources/KRResource.h index f228eeb..98e3ac1 100755 --- a/kraken/resources/KRResource.h +++ b/kraken/resources/KRResource.h @@ -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& bindings); + virtual ~KRResource(); static KRMesh* LoadObj(KRContext& context, const std::string& path); diff --git a/kraken/resources/material/KRMaterial.cpp b/kraken/resources/material/KRMaterial.cpp index 9bfffac..83117ae 100755 --- a/kraken/resources/material/KRMaterial.cpp +++ b/kraken/resources/material/KRMaterial.cpp @@ -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& resourceRequests, float lodCoverage) +void KRMaterial::getResourceBindings(std::list& 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() diff --git a/kraken/resources/material/KRMaterial.h b/kraken/resources/material/KRMaterial.h index f0fe566..6c995b6 100755 --- a/kraken/resources/material/KRMaterial.h +++ b/kraken/resources/material/KRMaterial.h @@ -96,7 +96,8 @@ public: bool needsVertexTangents(); kraken_stream_level getStreamLevel(); - void preStream(std::list& resourceRequests, float lodCoverage); + + virtual void getResourceBindings(std::list& bindings) override; private: std::string m_name; diff --git a/kraken/resources/material/KRMaterialBinding.cpp b/kraken/resources/material/KRMaterialBinding.cpp new file mode 100644 index 0000000..e059de9 --- /dev/null +++ b/kraken/resources/material/KRMaterialBinding.cpp @@ -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(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); +} diff --git a/kraken/resources/material/KRMaterialBinding.h b/kraken/resources/material/KRMaterialBinding.h new file mode 100644 index 0000000..d8547ef --- /dev/null +++ b/kraken/resources/material/KRMaterialBinding.h @@ -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: +}; \ No newline at end of file diff --git a/kraken/resources/mesh/KRMesh.cpp b/kraken/resources/mesh/KRMesh.cpp index bff72fa..b85ff0e 100755 --- a/kraken/resources/mesh/KRMesh.cpp +++ b/kraken/resources/mesh/KRMesh.cpp @@ -164,26 +164,7 @@ void KRMesh::getMaterials() for (std::vector::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::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& resourceRequests, float lodCoverage) +void KRMesh::preStream() { getSubmeshes(); getMaterials(); - for (std::set::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& 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::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::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 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 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; } } } diff --git a/kraken/resources/mesh/KRMesh.h b/kraken/resources/mesh/KRMesh.h index bc47766..5c03324 100755 --- a/kraken/resources/mesh/KRMesh.h +++ b/kraken/resources/mesh/KRMesh.h @@ -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& resourceRequests, float lodCoverage); + virtual void getResourceBindings(std::list& 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 m_materials; + vector m_materials; set m_uniqueMaterials; bool m_hasTransparency;