diff --git a/code/Mesh/Instance/InstanceMesh.cpp b/code/Mesh/Instance/InstanceMesh.cpp
index 315c74ff01..a465894c11 100644
--- a/code/Mesh/Instance/InstanceMesh.cpp
+++ b/code/Mesh/Instance/InstanceMesh.cpp
@@ -64,7 +64,7 @@ void InstanceMesh::getTechniques(SmallSet< render::handle_t >& outHandles) const
outHandles.insert(part.first);
}
-void InstanceMesh::cullableBuild(
+void InstanceMesh::build(
const world::WorldBuildContext& context,
const world::WorldRenderView& worldRenderView,
const world::IWorldRenderPass& worldRenderPass,
@@ -84,6 +84,7 @@ void InstanceMesh::cullableBuild(
const auto& meshParts = m_renderMesh->getParts();
// Lazy create the buffers.
+ const uint32_t bufferItemCount = (uint32_t)alignUp(count, 16);
if (count > m_allocatedCount)
{
m_drawBuffers.resize(0);
@@ -95,11 +96,13 @@ void InstanceMesh::cullableBuild(
for (uint32_t i = dbSize; i < (peakCascade + 1) * parts.size(); ++i)
m_drawBuffers.push_back(m_renderSystem->createBuffer(
render::BufferUsage::BuStructured | render::BufferUsage::BuIndirect,
- count * sizeof(render::IndexedIndirectDraw),
+ bufferItemCount * sizeof(render::IndexedIndirectDraw),
false
));
// Create draw buffers from visibility buffer.
+ // Compute blocks are executed before render pass, so draws for shadow map rendering all cascades
+ // are dispatched at the same time.
for (uint32_t i = 0; i < parts.size(); ++i)
{
const auto& part = parts[i];
diff --git a/code/Mesh/Instance/InstanceMesh.h b/code/Mesh/Instance/InstanceMesh.h
index 96ceed5829..375854c04a 100644
--- a/code/Mesh/Instance/InstanceMesh.h
+++ b/code/Mesh/Instance/InstanceMesh.h
@@ -17,7 +17,6 @@
#include "Mesh/IMesh.h"
#include "Render/Shader.h"
#include "Resource/Proxy.h"
-#include "World/Entity/CullingComponent.h"
// import/export mechanism.
#undef T_DLLCLASS
@@ -30,22 +29,22 @@
namespace traktor::render
{
-//class Buffer;
+class Buffer;
class IRenderSystem;
class ProgramParameters;
-//class RenderContext;
class Mesh;
class Shader;
}
-//namespace traktor::world
-//{
-//
-//class IWorldRenderPass;
-//class WorldRenderView;
-//
-//}
+namespace traktor::world
+{
+
+class IWorldRenderPass;
+class WorldBuildContext;
+class WorldRenderView;
+
+}
namespace traktor::mesh
{
@@ -57,9 +56,7 @@ namespace traktor::mesh
* automatically by the GPU in any number of instances
* using hardware instancing in a single draw call.
*/
-class T_DLLCLASS InstanceMesh
-: public IMesh
-, public world::CullingComponent::ICullable
+class T_DLLCLASS InstanceMesh : public IMesh
{
T_RTTI_CLASS;
@@ -81,11 +78,7 @@ class T_DLLCLASS InstanceMesh
void getTechniques(SmallSet< render::handle_t >& outHandles) const;
- /* world::CullingComponent::ICullable */
-
- virtual const Aabb3& cullableGetBoundingBox() const override final { return getBoundingBox(); }
-
- virtual void cullableBuild(
+ void build(
const world::WorldBuildContext& context,
const world::WorldRenderView& worldRenderView,
const world::IWorldRenderPass& worldRenderPass,
@@ -93,7 +86,7 @@ class T_DLLCLASS InstanceMesh
render::Buffer* visibilityBuffer,
uint32_t start,
uint32_t count
- ) override final;
+ );
private:
friend class InstanceMeshResource;
diff --git a/code/Mesh/Instance/InstanceMeshComponent.cpp b/code/Mesh/Instance/InstanceMeshComponent.cpp
index 26b5a62b83..172ee920e2 100644
--- a/code/Mesh/Instance/InstanceMeshComponent.cpp
+++ b/code/Mesh/Instance/InstanceMeshComponent.cpp
@@ -22,7 +22,6 @@ T_IMPLEMENT_RTTI_CLASS(L"traktor.mesh.InstanceMeshComponent", InstanceMeshCompon
InstanceMeshComponent::InstanceMeshComponent(const resource::Proxy< InstanceMesh >& mesh)
: m_mesh(mesh)
{
- //m_cullingInstance = m_mesh->allocateInstance();
m_mesh.consume();
}
@@ -35,44 +34,36 @@ InstanceMeshComponent::~InstanceMeshComponent()
void InstanceMeshComponent::destroy()
{
- //// Only release instance if resource hasn't been replaced.
- //if (!m_mesh.changed())
- //{
- // if (m_mesh && m_meshInstance != nullptr)
- // m_mesh->releaseInstance(m_meshInstance);
- //}
-
- if (m_owner != nullptr && m_cullingInstance != nullptr)
- {
- world::CullingComponent* culling = m_owner->getWorld()->getComponent< world::CullingComponent >();
- culling->releaseInstance(m_cullingInstance);
- }
-
+ T_FATAL_ASSERT(m_cullingInstance == nullptr);
m_mesh.clear();
MeshComponent::destroy();
}
void InstanceMeshComponent::setWorld(world::World* world)
{
- T_FATAL_ASSERT(m_cullingInstance == nullptr);
+ // Remove from last world.
+ if (m_world != nullptr)
+ {
+ T_FATAL_ASSERT(m_cullingInstance != nullptr);
+ world::CullingComponent* culling = m_world->getComponent< world::CullingComponent >();
+ culling->releaseInstance(m_cullingInstance);
+ }
+
+ // Add to new world.
if (world != nullptr)
{
+ T_FATAL_ASSERT(m_cullingInstance == nullptr);
world::CullingComponent* culling = world->getComponent< world::CullingComponent >();
- m_cullingInstance = culling->allocateInstance(m_mesh);
+ m_cullingInstance = culling->allocateInstance(this, (intptr_t)m_mesh.getResource());
}
+
+ m_world = world;
}
void InstanceMeshComponent::setTransform(const Transform& transform)
{
MeshComponent::setTransform(transform);
- // Re-allocate instance if mesh resource has been replaced.
- //if (m_mesh.changed())
- //{
- // m_meshInstance = m_mesh->allocateInstance();
- // m_mesh.consume();
- //}
-
if (m_cullingInstance)
m_cullingInstance->setTransform(transform);
}
@@ -82,22 +73,37 @@ Aabb3 InstanceMeshComponent::getBoundingBox() const
return m_mesh->getBoundingBox();
}
-void InstanceMeshComponent::update(const world::UpdateParams& update)
+void InstanceMeshComponent::build(
+ const world::WorldBuildContext& context,
+ const world::WorldRenderView& worldRenderView,
+ const world::IWorldRenderPass& worldRenderPass
+)
{
- MeshComponent::update(update);
-
- // Re-allocate instance if mesh resource has been replaced.
- //if (m_mesh.changed())
- //{
- // m_meshInstance = m_mesh->allocateInstance();
- // m_meshInstance->setTransform(getTransform().get0());
- // m_mesh.consume();
- //}
+ // Not used since we're getting called by the culling component when we should build.
}
-void InstanceMeshComponent::build(const world::WorldBuildContext& context, const world::WorldRenderView& worldRenderView, const world::IWorldRenderPass& worldRenderPass)
+void InstanceMeshComponent::cullableBuild(
+ const world::WorldBuildContext& context,
+ const world::WorldRenderView& worldRenderView,
+ const world::IWorldRenderPass& worldRenderPass,
+ render::Buffer* instanceBuffer,
+ render::Buffer* visibilityBuffer,
+ uint32_t start,
+ uint32_t count
+)
{
- //T_ASSERT_M(0, L"Forgot to register InstanceMeshComponentRenderer?");
+ // Draw mesh instances; this method is called for the "first" InstanceMeshComponent using the same ordinal number
+ // assuming all other components reference the same mesh.
+ if (m_mesh)
+ m_mesh->build(
+ context,
+ worldRenderView,
+ worldRenderPass,
+ instanceBuffer,
+ visibilityBuffer,
+ start,
+ count
+ );
}
}
diff --git a/code/Mesh/Instance/InstanceMeshComponent.h b/code/Mesh/Instance/InstanceMeshComponent.h
index 12220a2ead..8b75c2c4e8 100644
--- a/code/Mesh/Instance/InstanceMeshComponent.h
+++ b/code/Mesh/Instance/InstanceMeshComponent.h
@@ -28,7 +28,9 @@ class InstanceMesh;
/*! Instancing mesh component.
* \ingroup Mesh
*/
-class T_DLLCLASS InstanceMeshComponent : public MeshComponent
+class T_DLLCLASS InstanceMeshComponent
+: public MeshComponent
+, public world::CullingComponent::ICullable
{
T_RTTI_CLASS;
@@ -45,14 +47,31 @@ class T_DLLCLASS InstanceMeshComponent : public MeshComponent
virtual Aabb3 getBoundingBox() const override final;
- virtual void update(const world::UpdateParams& update) override final;
-
- virtual void build(const world::WorldBuildContext& context, const world::WorldRenderView& worldRenderView, const world::IWorldRenderPass& worldRenderPass) override final;
+ virtual void build(
+ const world::WorldBuildContext& context,
+ const world::WorldRenderView& worldRenderView,
+ const world::IWorldRenderPass& worldRenderPass
+ ) override final;
inline resource::Proxy< InstanceMesh >& getMesh() { return m_mesh; }
+ /* world::CullingComponent::ICullable */
+
+ virtual Aabb3 cullableGetBoundingBox() const override final { return getBoundingBox(); }
+
+ virtual void cullableBuild(
+ const world::WorldBuildContext& context,
+ const world::WorldRenderView& worldRenderView,
+ const world::IWorldRenderPass& worldRenderPass,
+ render::Buffer* instanceBuffer,
+ render::Buffer* visibilityBuffer,
+ uint32_t start,
+ uint32_t count
+ ) override final;
+
private:
resource::Proxy< InstanceMesh > m_mesh;
+ world::World* m_world = nullptr;
world::CullingComponent::Instance* m_cullingInstance = nullptr;
};
diff --git a/code/World/Entity/CullingComponent.cpp b/code/World/Entity/CullingComponent.cpp
index b9c7b81984..785b05a327 100644
--- a/code/World/Entity/CullingComponent.cpp
+++ b/code/World/Entity/CullingComponent.cpp
@@ -47,8 +47,12 @@ void CullingComponent::destroy()
T_FATAL_ASSERT_M(m_instances.empty(), L"Culling instances not empty.");
safeDestroy(m_instanceBuffer);
for (auto visibilityBuffer : m_visibilityBuffers)
- safeDestroy(visibilityBuffer);
+ {
+ if (visibilityBuffer)
+ visibilityBuffer->destroy();
+ }
m_visibilityBuffers.resize(0);
+ m_renderSystem = nullptr;
}
void CullingComponent::update(World* world, const UpdateParams& update)
@@ -76,6 +80,7 @@ void CullingComponent::build(
m_instanceBufferDirty = true;
}
+ // Ensure we have visibility buffers for all cascades.
const uint32_t peakCascade = worldRenderView.getCascade();
const uint32_t vbSize = (uint32_t)m_visibilityBuffers.size();
for (uint32_t i = vbSize; i < peakCascade + 1; ++i)
@@ -100,7 +105,7 @@ void CullingComponent::build(
render::Buffer* visibilityBuffer = m_visibilityBuffers[worldRenderView.getCascade()];
// Cull instances, output are visibility buffer.
- // #todo Compute blocks are executed before render pass, so for shadow map rendering all cascades
+ // Compute blocks are executed before render pass, so for shadow map rendering all cascades
// are culled before being rendered.
{
Vector4 cullFrustum[12];
@@ -115,19 +120,19 @@ void CullingComponent::build(
const Vector2 viewSize = worldRenderView.getViewSize();
auto renderBlock = renderContext->allocNamed< render::ComputeRenderBlock >(
- str(L"Mesh cull %d", worldRenderView.getCascade())
+ str(L"Cull %d", worldRenderView.getCascade())
);
render::Shader::Permutation perm;
if (worldRenderPass.getTechnique() == s_techniqueDeferredGBufferWrite)
{
// Deferred g-buffer pass has access to HiZ texture.
- m_shaderCull->setCombination(render::getParameterHandle(L"InstanceMesh_HiZ"), true, perm);
+ m_shaderCull->setCombination(s_handleCullingHiZ, true, perm);
}
else
{
// All other paths use simple frustum culling only.
- m_shaderCull->setCombination(render::getParameterHandle(L"InstanceMesh_HiZ"), false, perm);
+ m_shaderCull->setCombination(s_handleCullingHiZ, false, perm);
}
renderBlock->program = m_shaderCull->getProgram(perm).program;
@@ -150,13 +155,13 @@ void CullingComponent::build(
renderContext->compute< render::BarrierRenderBlock >(render::Stage::Compute, render::Stage::Compute, nullptr, 0);
}
- // Batch draw instances; assumes m_instances are sorted by "cullable".
+ // Batch draw instances; assumes m_instances are sorted by "ordinal" so we can scan for run length.
for (uint32_t i = 0; i < (uint32_t)m_instances.size(); )
{
uint32_t j = i + 1;
for (; j < (uint32_t)m_instances.size(); ++j)
{
- if (m_instances[i]->cullable != m_instances[j]->cullable)
+ if (m_instances[i]->ordinal != m_instances[j]->ordinal)
break;
}
@@ -174,17 +179,18 @@ void CullingComponent::build(
}
}
-CullingComponent::Instance* CullingComponent::allocateInstance(ICullable* cullable)
+CullingComponent::Instance* CullingComponent::allocateInstance(ICullable* cullable, intptr_t ordinal)
{
Instance* instance = new Instance();
instance->owner = this;
instance->cullable = cullable;
+ instance->ordinal = ordinal;
instance->transform = Transform::identity();
instance->boundingBox = cullable->cullableGetBoundingBox();
- // Insert instance sorted by cullable so we can calculate run length when building.
+ // Insert instance sorted by ordinal so we can calculate run length when building.
auto it = std::upper_bound(m_instances.begin(), m_instances.end(), instance, [=](Instance* lh, Instance* rh) {
- return lh->cullable < rh->cullable;
+ return lh->ordinal < rh->ordinal;
});
m_instances.insert(it, instance);
return instance;
diff --git a/code/World/Entity/CullingComponent.h b/code/World/Entity/CullingComponent.h
index ed32d1dccb..e7f4fa2c6c 100644
--- a/code/World/Entity/CullingComponent.h
+++ b/code/World/Entity/CullingComponent.h
@@ -65,7 +65,7 @@ class T_DLLCLASS CullingComponent : public IWorldComponent
struct T_DLLCLASS ICullable
{
- virtual const Aabb3& cullableGetBoundingBox() const = 0;
+ virtual Aabb3 cullableGetBoundingBox() const = 0;
virtual void cullableBuild(
const WorldBuildContext& context,
@@ -82,6 +82,7 @@ class T_DLLCLASS CullingComponent : public IWorldComponent
{
CullingComponent* owner;
ICullable* cullable;
+ intptr_t ordinal;
Transform transform;
Aabb3 boundingBox;
@@ -100,7 +101,7 @@ class T_DLLCLASS CullingComponent : public IWorldComponent
const IWorldRenderPass& worldRenderPass
);
- Instance* allocateInstance(ICullable* cullable);
+ Instance* allocateInstance(ICullable* cullable, intptr_t ordinal);
void releaseInstance(Instance*& instance);
diff --git a/code/World/World.cpp b/code/World/World.cpp
index 8064d83d6a..f9cee43cf4 100644
--- a/code/World/World.cpp
+++ b/code/World/World.cpp
@@ -26,16 +26,16 @@ void World::destroy()
T_FATAL_ASSERT(m_deferredAdd.empty());
T_FATAL_ASSERT(m_deferredRemove.empty());
- for (auto component : m_components)
- component->destroy();
- m_components.clear();
-
for (auto entity : m_entities)
{
entity->setWorld(nullptr);
entity->destroy();
}
m_entities.clear();
+
+ for (auto component : m_components)
+ component->destroy();
+ m_components.clear();
}
void World::setComponent(IWorldComponent* component)
diff --git a/code/World/WorldHandles.cpp b/code/World/WorldHandles.cpp
index 88dbef3826..2cda87c370 100644
--- a/code/World/WorldHandles.cpp
+++ b/code/World/WorldHandles.cpp
@@ -1,6 +1,6 @@
/*
* TRAKTOR
- * Copyright (c) 2022-2023 Anders Pistol.
+ * Copyright (c) 2022-2024 Anders Pistol.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -99,6 +99,9 @@ const render::Handle s_handleFogVolumeMediumDensity(L"World_FogVolumeMediumDensi
// Contact shadows.
const render::Handle s_handleContactLightDirection(L"World_ContactLightDirection");
+// Occlusion culling.
+const render::Handle s_handleCullingHiZ(L"World_CullingHiZ");
+
// ImageGraph inputs.
const render::Handle s_handleInputColor(L"InputColor");
const render::Handle s_handleInputColorLast(L"InputColorLast");
diff --git a/code/World/WorldHandles.h b/code/World/WorldHandles.h
index bbe59142e9..01d00fbaa6 100644
--- a/code/World/WorldHandles.h
+++ b/code/World/WorldHandles.h
@@ -109,6 +109,9 @@ extern const render::Handle T_DLLCLASS s_handleFogVolumeMediumDensity;
// Contact shadows.
extern const render::Handle T_DLLCLASS s_handleContactLightDirection;
+// Occlusion culling.
+extern const render::Handle T_DLLCLASS s_handleCullingHiZ;
+
// ImageGraph inputs.
extern const render::Handle T_DLLCLASS s_handleInputColor;
extern const render::Handle T_DLLCLASS s_handleInputColorLast;
diff --git a/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi b/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi
index e750a73628..51efed462d 100644
--- a/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi
+++ b/data/Source/System/Mesh/Shaders/Instance/Cull/Cull.xdi
@@ -5,8 +5,8 @@
{4BAA3A0D-D779-C141-B519-197EEA8640D6}
- -398
- 135
+ -554
+ 108
Global
@@ -14,8 +14,8 @@
{B63DBBD3-72C0-C645-8A24-4893BBF22E30}
- -169
- 144
+ -325
+ 117
x
@@ -178,13 +178,13 @@ $Buffer[index].visible = $Input;
1212
579
- InstanceMesh_HiZ
+ World_CullingHiZ
-
{6FAE432D-36E8-D046-96BA-65165BB9DCCC}
- 425
+ 460
805
World_HiZTexture
@@ -281,7 +281,7 @@ $Output = visible ? 1.0f : 0.0f;
{7B83C271-F045-4343-9666-B5DC8E2A479D}
- 443
+ 478
847
FtPoint
@@ -307,7 +307,7 @@ $Output = visible ? 1.0f : 0.0f;
{2095B07F-6B63-D845-B825-6F4B49DCE4DA}
- 377
+ 412
889
InstanceMesh_TargetSize
@@ -469,7 +469,7 @@ else
{099F295D-79C3-9847-A2B5-E3BE5904F79D}
- 359
+ 412
1145
InstanceMesh_TargetSize
@@ -480,7 +480,7 @@ else
{68311C48-A517-3146-87E8-D82A66146355}
- 425
+ 478
1103
FtPoint
@@ -498,7 +498,7 @@ else
{51312172-C4B7-D843-A00A-5C13B2736AC2}
- 407
+ 460
1061
World_HiZTexture
@@ -516,6 +516,25 @@ else
Matrix
Frame
+ -
+ {0E5A6909-38D1-494B-A702-B69D3892E0A1}
+
+
+ -487
+ 194
+
+ InstanceMesh_InstanceOffset
+ Scalar
+ Draw
+
+ -
+ {CE7F05B8-293A-4D41-B1EC-4682AEE6504A}
+
+
+ -186
+ 137
+
+
-
@@ -758,11 +777,31 @@ else
{D2D716D6-C4A1-471F-894A-D718515F6281}
+ -
+
+
+
+ {9F45B2C3-B513-4646-B0C1-663748FD169C}
+
+
-
+
+
+ {3DE04294-4DEA-4A13-A460-2274647357EA}
+
+
+ -
+
{0FF6511C-0293-41A8-840E-81978BD01F7F}
@@ -770,8 +809,8 @@ else
-
diff --git a/data/Source/System/Mesh/Shaders/Instance/Cull/Draw.xdi b/data/Source/System/Mesh/Shaders/Instance/Cull/Draw.xdi
index 448a2245e7..10ad0d3ece 100644
--- a/data/Source/System/Mesh/Shaders/Instance/Cull/Draw.xdi
+++ b/data/Source/System/Mesh/Shaders/Instance/Cull/Draw.xdi
@@ -5,8 +5,8 @@
{AA20BF80-C68A-D649-9BF9-23BC5F6257F8}
- -305
- 333
+ 119
+ 320
x
@@ -14,8 +14,8 @@
{0C63324D-D49B-7C44-BE53-17ECD5DBE92E}
- -542
- 319
+ -106
+ 330
Global
@@ -23,8 +23,8 @@
{9772F569-3912-1B46-AB4B-157B8CC99284}
- -27
- 269
+ -23
+ 273
InstanceMesh_Visibility
@@ -38,7 +38,7 @@
{B6ABD193-2075-0442-A1B6-92D4C05F99CB}
- -17
+ -7
226
InstanceMesh_Draw
@@ -69,8 +69,8 @@
{EF3C22BB-6DAD-ED47-B381-BF0850063421}
- 355
- 250
+ 358
+ 270
WriteOut
Default
@@ -101,19 +101,25 @@
{618C459F-DE31-4E4D-A0ED-6D01AF8C87AF}
PrimFirstIndex
+ -
+ {7BC3CE94-B279-F442-A983-DD2FA6DFBDD4}
+ InstanceOffset
+
@@ -121,8 +127,8 @@ $DrawBuffer[index].firstInstance = 0;
{3491574B-839F-B74B-8747-0C4A10BECB57}
- 7
- 434
+ 15
+ 367
InstanceMesh_IndexCount
Scalar
@@ -133,31 +139,23 @@ $DrawBuffer[index].firstInstance = 0;
31
- 471
+ 414
InstanceMesh_FirstIndex
Scalar
Frame
-
- {63F715EF-F327-F04D-8827-705805B04479}
+ {2FB4EA3D-40CC-3548-B4A5-D965E96D6C05}
- -438
- 398
+ -1
+ 461
InstanceMesh_InstanceOffset
Scalar
Draw
- -
- {EBB7D461-F10E-FD4E-B98F-27018D533692}
-
-
- -137
- 341
-
-
-
@@ -210,34 +208,24 @@ $DrawBuffer[index].firstInstance = 0;
{788C47C3-E973-CF48-9A12-5A2751107996}
- -
-
-
-
- {9F45B2C3-B513-4646-B0C1-663748FD169C}
-
-
-
-
- {3DE04294-4DEA-4A13-A460-2274647357EA}
+
+ {89D6EAF6-DAAD-C647-B640-7F86B233A509}
-
- {89D6EAF6-DAAD-C647-B640-7F86B233A509}
+ {7BC3CE94-B279-F442-A983-DD2FA6DFBDD4}
diff --git a/data/Source/System/Mesh/Shaders/Instance/UnpackInstanceData.xdi b/data/Source/System/Mesh/Shaders/Instance/UnpackInstanceData.xdi
index d6d040025f..05b56d1318 100644
--- a/data/Source/System/Mesh/Shaders/Instance/UnpackInstanceData.xdi
+++ b/data/Source/System/Mesh/Shaders/Instance/UnpackInstanceData.xdi
@@ -59,8 +59,8 @@
{BD8029D8-D20D-AE40-9895-EA83610D8339}
- 431
- 773
+ 425
+ 759
InstanceWorld
@@ -86,8 +86,8 @@
{5193F279-0901-F345-97E6-238E9D406009}
- 415
- 846
+ 409
+ 832
InstanceWorldLast
@@ -173,8 +173,8 @@
{8A459FBA-5749-254B-9853-127DB9AF95F8}
- 491
- 919
+ 238
+ 886
gl_DrawID
@@ -232,6 +232,25 @@ $Output = gl_DrawID;
BoundingBoxMax
+ -
+ {24C3ACAD-6FB5-2143-9B61-CD34A943D39E}
+
+
+ 453
+ 905
+
+
+ -
+ {ECE608D7-5F60-4A4F-A5D9-17256271FD77}
+
+
+ 152
+ 962
+
+ InstanceMesh_InstanceOffset
+ Scalar
+ Draw
+
-
@@ -354,26 +373,6 @@ $Output = gl_DrawID;
{F2E22CA6-DFF3-4B20-A70A-0D7A44EACD8C}
- -
-
-
-
- {0FF6511C-0293-41A8-840E-81978BD01F7F}
-
-
- -
-
-
-
- {0FF6511C-0293-41A8-840E-81978BD01F7F}
-
-
-
+ -
+
+
+
+ {9F45B2C3-B513-4646-B0C1-663748FD169C}
+
+
+ -
+
+
+
+ {3DE04294-4DEA-4A13-A460-2274647357EA}
+
+
+ -
+
+
+
+ {0FF6511C-0293-41A8-840E-81978BD01F7F}
+
+
+ -
+
+
+
+ {0FF6511C-0293-41A8-840E-81978BD01F7F}
+
+