Trying new meshlet gen approach
This commit is contained in:
Vendored
+1
-1
Submodule external/vcpkg updated: 53bef8994c...042c31edc6
@@ -31,5 +31,5 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
|
|||||||
uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
|
uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
|
||||||
result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf);
|
result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf);
|
||||||
}
|
}
|
||||||
return float4(result, 1.0f);
|
return float4(params.vertexColor, 1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ void cullLights(ComputeShaderInput in)
|
|||||||
{
|
{
|
||||||
PointLight light = pLightEnv.pointLights[i];
|
PointLight light = pLightEnv.pointLights[i];
|
||||||
float3 light_VS = mul(viewMatrix, float4(light.position_WS.xyz, 1.0f)).xyz;
|
float3 light_VS = mul(viewMatrix, float4(light.position_WS.xyz, 1.0f)).xyz;
|
||||||
//if(light.insideFrustum(groupFrustum, light_VS, nearClipVS, maxDepthVS))
|
if(light.insideFrustum(groupFrustum, light_VS, nearClipVS, maxDepthVS))
|
||||||
{
|
{
|
||||||
tAppendLight(i);
|
tAppendLight(i);
|
||||||
//if(!light.insidePlane(minPlane, light_VS))
|
if(!light.insidePlane(minPlane, light_VS))
|
||||||
{
|
{
|
||||||
oAppendLight(i);
|
oAppendLight(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ void taskMain(
|
|||||||
localToView = mul(pViewParams.viewMatrix, instance.transformMatrix);
|
localToView = mul(pViewParams.viewMatrix, instance.transformMatrix);
|
||||||
float3 origin = float3(0, 0, 0);
|
float3 origin = float3(0, 0, 0);
|
||||||
float3 corners[4] = {
|
float3 corners[4] = {
|
||||||
screenToView(float4(pViewParams.screenDimensions, -1.0f, 1.0f)).xyz,
|
screenToView(float4(100.0f, 100.0f, -1.0f, 1.0f)).xyz,
|
||||||
screenToView(float4(pViewParams.screenDimensions, -1.0f, 1.0f)).xyz,
|
screenToView(float4(pViewParams.screenDimensions.x - 100.0f, 100.0f, -1.0f, 1.0f)).xyz,
|
||||||
screenToView(float4(pViewParams.screenDimensions, -1.0f, 1.0f)).xyz,
|
screenToView(float4(100.0f, pViewParams.screenDimensions.y - 100.0f, -1.0f, 1.0f)).xyz,
|
||||||
screenToView(float4(pViewParams.screenDimensions, -1.0f, 1.0f)).xyz
|
screenToView(float4(pViewParams.screenDimensions - float2(100.0f, 100.0f), -1.0f, 1.0f)).xyz
|
||||||
};
|
};
|
||||||
viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]);
|
viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]);
|
||||||
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
||||||
@@ -47,7 +47,7 @@ void taskMain(
|
|||||||
{
|
{
|
||||||
uint m = mesh.meshletOffset + i;
|
uint m = mesh.meshletOffset + i;
|
||||||
MeshletDescription meshlet = pScene.meshletInfos[m];
|
MeshletDescription meshlet = pScene.meshletInfos[m];
|
||||||
//if(meshlet.bounding.insideFrustum(localToView, viewFrustum))
|
if(meshlet.bounding.insideFrustum(localToView, viewFrustum))
|
||||||
{
|
{
|
||||||
uint index;
|
uint index;
|
||||||
InterlockedAdd(head, 1, index);
|
InterlockedAdd(head, 1, index);
|
||||||
@@ -99,6 +99,7 @@ void meshMain(
|
|||||||
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
|
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
|
||||||
VertexAttributes attr = pVertexData.getAttributes(md.indicesOffset + vertexIndex);
|
VertexAttributes attr = pVertexData.getAttributes(md.indicesOffset + vertexIndex);
|
||||||
vertices[v] = attr.getParameter(inst.transformMatrix);
|
vertices[v] = attr.getParameter(inst.transformMatrix);
|
||||||
|
vertices[v].vertexColor = m.color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ struct BoundingSphere
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
for(int i = 0; i < 4 && result; ++i)
|
for(int i = 0; i < 4 && result; ++i)
|
||||||
{
|
{
|
||||||
if(dot(frustum.sides[i].n, transformed) - frustum.sides[i].d < scaledRange)
|
if(dot(frustum.sides[i].n, transformed) - frustum.sides[i].d < -scaledRange)
|
||||||
{
|
{
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ struct AABB
|
|||||||
for(int i = 0; i < 8; ++i)
|
for(int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
float3 adjusted = corners[i].xyz / corners[i].w;
|
float3 adjusted = corners[i].xyz / corners[i].w;
|
||||||
if(frustum.pointInside(corners[i].xyz))
|
if(frustum.pointInside(adjusted))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct Plane
|
|||||||
float d;
|
float d;
|
||||||
bool pointInside(float3 point)
|
bool pointInside(float3 point)
|
||||||
{
|
{
|
||||||
return dot(n, point) - d < 0.0f;
|
return dot(n, point) - d > 0.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ struct Frustum
|
|||||||
{
|
{
|
||||||
for(int p = 0; p < 4; ++p)
|
for(int p = 0; p < 4; ++p)
|
||||||
{
|
{
|
||||||
if(sides[p].pointInside(point))
|
if(!sides[p].pointInside(point))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,14 @@ using namespace Seele::Editor;
|
|||||||
SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
||||||
: View(graphics, owner, createInfo, "SceneView")
|
: View(graphics, owner, createInfo, "SceneView")
|
||||||
, scene(new Scene(graphics))
|
, scene(new Scene(graphics))
|
||||||
, renderGraph(RenderGraphBuilder::build(
|
|
||||||
DepthPrepass(graphics, scene),
|
|
||||||
LightCullingPass(graphics, scene),
|
|
||||||
BasePass(graphics, scene)
|
|
||||||
))
|
|
||||||
, cameraSystem(createInfo.dimensions, Vector(0, 0, 10))
|
, cameraSystem(createInfo.dimensions, Vector(0, 0, 10))
|
||||||
{
|
{
|
||||||
cameraSystem.update(viewportCamera, static_cast<float>(Gfx::getCurrentFrameDelta()));
|
cameraSystem.update(viewportCamera, static_cast<float>(Gfx::getCurrentFrameDelta()));
|
||||||
|
renderGraph.addPass(new DepthPrepass(graphics, scene));
|
||||||
renderGraph.updateViewport(viewport);
|
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||||
|
renderGraph.addPass(new BasePass(graphics, scene));
|
||||||
|
renderGraph.setViewport(viewport);
|
||||||
|
renderGraph.createRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneView::~SceneView()
|
SceneView::~SceneView()
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ private:
|
|||||||
OScene scene;
|
OScene scene;
|
||||||
Component::Camera viewportCamera;
|
Component::Camera viewportCamera;
|
||||||
|
|
||||||
RenderGraph<
|
RenderGraph renderGraph;
|
||||||
DepthPrepass,
|
|
||||||
LightCullingPass,
|
|
||||||
BasePass> renderGraph;
|
|
||||||
|
|
||||||
ThreadPool pool;
|
ThreadPool pool;
|
||||||
ViewportControl cameraSystem;
|
ViewportControl cameraSystem;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ private:
|
|||||||
Node(Node* prev, Node* next, const T& data)
|
Node(Node* prev, Node* next, const T& data)
|
||||||
: prev(prev)
|
: prev(prev)
|
||||||
, next(next)
|
, next(next)
|
||||||
, data(std::move(data))
|
, data(data)
|
||||||
{}
|
{}
|
||||||
Node(Node* prev, Node* next, T&& data)
|
Node(Node* prev, Node* next, T&& data)
|
||||||
: prev(prev)
|
: prev(prev)
|
||||||
@@ -133,7 +133,7 @@ public:
|
|||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
List()
|
constexpr List()
|
||||||
: root(nullptr)
|
: root(nullptr)
|
||||||
, tail(nullptr)
|
, tail(nullptr)
|
||||||
, beginIt(Iterator(root))
|
, beginIt(Iterator(root))
|
||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
, allocator(Allocator())
|
, allocator(Allocator())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit List(const Allocator& alloc)
|
constexpr explicit List(const Allocator& alloc)
|
||||||
: root(nullptr)
|
: root(nullptr)
|
||||||
, tail(nullptr)
|
, tail(nullptr)
|
||||||
, beginIt(Iterator(root))
|
, beginIt(Iterator(root))
|
||||||
@@ -151,7 +151,7 @@ public:
|
|||||||
, allocator(alloc)
|
, allocator(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
List(size_type count, const T& value = T(), const Allocator& alloc = Allocator())
|
constexpr List(size_type count, const T& value = T(), const Allocator& alloc = Allocator())
|
||||||
: List(alloc)
|
: List(alloc)
|
||||||
{
|
{
|
||||||
for(size_type i = 0; i < count; ++i)
|
for(size_type i = 0; i < count; ++i)
|
||||||
@@ -159,7 +159,7 @@ public:
|
|||||||
add(value);
|
add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List(size_type count, const Allocator& alloc = Allocator())
|
constexpr List(size_type count, const Allocator& alloc = Allocator())
|
||||||
: List(alloc)
|
: List(alloc)
|
||||||
{
|
{
|
||||||
for(size_type i = 0; i < count; ++i)
|
for(size_type i = 0; i < count; ++i)
|
||||||
@@ -167,7 +167,7 @@ public:
|
|||||||
add(T());
|
add(T());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List(const List& other)
|
constexpr List(const List& other)
|
||||||
: List(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
: List(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
||||||
{
|
{
|
||||||
//TODO: improve
|
//TODO: improve
|
||||||
@@ -177,7 +177,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List(const List& other, const Allocator& alloc)
|
constexpr List(const List& other, const Allocator& alloc)
|
||||||
: List(alloc)
|
: List(alloc)
|
||||||
{
|
{
|
||||||
//TODO: improve
|
//TODO: improve
|
||||||
@@ -186,7 +186,7 @@ public:
|
|||||||
add(it);
|
add(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List(List&& other)
|
constexpr List(List&& other)
|
||||||
: root(std::move(other.root))
|
: root(std::move(other.root))
|
||||||
, tail(std::move(other.tail))
|
, tail(std::move(other.tail))
|
||||||
, beginIt(std::move(other.beginIt))
|
, beginIt(std::move(other.beginIt))
|
||||||
@@ -196,7 +196,7 @@ public:
|
|||||||
{
|
{
|
||||||
other._size = 0;
|
other._size = 0;
|
||||||
}
|
}
|
||||||
List(List&& other, const Allocator& alloc)
|
constexpr List(List&& other, const Allocator& alloc)
|
||||||
: root(std::move(other.root))
|
: root(std::move(other.root))
|
||||||
, tail(std::move(other.tail))
|
, tail(std::move(other.tail))
|
||||||
, beginIt(std::move(other.beginIt))
|
, beginIt(std::move(other.beginIt))
|
||||||
@@ -206,11 +206,11 @@ public:
|
|||||||
{
|
{
|
||||||
other._size = 0;
|
other._size = 0;
|
||||||
}
|
}
|
||||||
~List()
|
constexpr ~List()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
List& operator=(const List& other)
|
constexpr List& operator=(const List& other)
|
||||||
{
|
{
|
||||||
if(this != &other)
|
if(this != &other)
|
||||||
{
|
{
|
||||||
@@ -232,7 +232,7 @@ public:
|
|||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
List& operator=(List&& other)
|
constexpr List& operator=(List&& other)
|
||||||
{
|
{
|
||||||
if(this != &other)
|
if(this != &other)
|
||||||
{
|
{
|
||||||
@@ -252,15 +252,15 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
reference front()
|
constexpr reference front()
|
||||||
{
|
{
|
||||||
return root->data;
|
return root->data;
|
||||||
}
|
}
|
||||||
reference back()
|
constexpr reference back()
|
||||||
{
|
{
|
||||||
return tail->prev->data;
|
return tail->prev->data;
|
||||||
}
|
}
|
||||||
void clear()
|
constexpr void clear()
|
||||||
{
|
{
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
@@ -279,17 +279,17 @@ public:
|
|||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
//Insert at the end
|
//Insert at the end
|
||||||
iterator add(const T &value)
|
constexpr iterator add(const T &value)
|
||||||
{
|
{
|
||||||
return addInternal(value);
|
return addInternal(value);
|
||||||
}
|
}
|
||||||
iterator add(T&& value)
|
constexpr iterator add(T&& value)
|
||||||
{
|
{
|
||||||
return addInternal(std::move(value));
|
return addInternal(std::move(value));
|
||||||
}
|
}
|
||||||
// takes all elements from other and move-inserts them into
|
// takes all elements from other and move-inserts them into
|
||||||
// this, clearing other in the process
|
// this, clearing other in the process
|
||||||
void moveElements(List&& other)
|
constexpr void moveElements(List&& other)
|
||||||
{
|
{
|
||||||
tail->prev->next = other.root;
|
tail->prev->next = other.root;
|
||||||
other.root->prev = tail->prev;
|
other.root->prev = tail->prev;
|
||||||
@@ -326,13 +326,13 @@ public:
|
|||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
// front + popFront
|
// front + popFront
|
||||||
value_type retrieve()
|
constexpr value_type retrieve()
|
||||||
{
|
{
|
||||||
value_type temp = std::move(root->data);
|
value_type temp = std::move(root->data);
|
||||||
popFront();
|
popFront();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
iterator remove(iterator pos)
|
constexpr iterator remove(iterator pos)
|
||||||
{
|
{
|
||||||
_size--;
|
_size--;
|
||||||
Node *prev = pos.node->prev;
|
Node *prev = pos.node->prev;
|
||||||
@@ -358,17 +358,27 @@ public:
|
|||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
return Iterator(next);
|
return Iterator(next);
|
||||||
}
|
}
|
||||||
void popBack()
|
constexpr void popBack()
|
||||||
{
|
{
|
||||||
assert(_size > 0);
|
assert(_size > 0);
|
||||||
remove(Iterator(tail->prev));
|
remove(Iterator(tail->prev));
|
||||||
}
|
}
|
||||||
void popFront()
|
constexpr void pop_back()
|
||||||
|
{
|
||||||
|
assert(_size > 0);
|
||||||
|
remove(Iterator(tail->prev));
|
||||||
|
}
|
||||||
|
constexpr void popFront()
|
||||||
{
|
{
|
||||||
assert(_size > 0);
|
assert(_size > 0);
|
||||||
remove(Iterator(root));
|
remove(Iterator(root));
|
||||||
}
|
}
|
||||||
iterator insert(iterator pos, const T &value)
|
constexpr void pop_front()
|
||||||
|
{
|
||||||
|
assert(_size > 0);
|
||||||
|
remove(Iterator(root));
|
||||||
|
}
|
||||||
|
constexpr iterator insert(iterator pos, const T &value)
|
||||||
{
|
{
|
||||||
_size++;
|
_size++;
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
@@ -393,7 +403,7 @@ public:
|
|||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
return Iterator(newNode);
|
return Iterator(newNode);
|
||||||
}
|
}
|
||||||
iterator find(const T &value)
|
constexpr iterator find(const T &value)
|
||||||
{
|
{
|
||||||
for (Node *i = root; i != tail; i = i->next)
|
for (Node *i = root; i != tail; i = i->next)
|
||||||
{
|
{
|
||||||
@@ -404,33 +414,33 @@ public:
|
|||||||
}
|
}
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
bool empty() const
|
constexpr bool empty() const
|
||||||
{
|
{
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
size_type size() const
|
constexpr size_type size() const
|
||||||
{
|
{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
iterator begin()
|
constexpr iterator begin()
|
||||||
{
|
{
|
||||||
return beginIt;
|
return beginIt;
|
||||||
}
|
}
|
||||||
const_iterator begin() const
|
constexpr const_iterator begin() const
|
||||||
{
|
{
|
||||||
return cbeginIt;
|
return cbeginIt;
|
||||||
}
|
}
|
||||||
iterator end()
|
constexpr iterator end()
|
||||||
{
|
{
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
const_iterator end() const
|
constexpr const_iterator end() const
|
||||||
{
|
{
|
||||||
return cendIt;
|
return cendIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Node* allocateNode()
|
constexpr Node* allocateNode()
|
||||||
{
|
{
|
||||||
Node* node = allocator.allocate(1);
|
Node* node = allocator.allocate(1);
|
||||||
assert(node != nullptr);
|
assert(node != nullptr);
|
||||||
@@ -439,7 +449,7 @@ private:
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void initializeNode(Node* node, Type&& data)
|
constexpr void initializeNode(Node* node, Type&& data)
|
||||||
{
|
{
|
||||||
std::allocator_traits<NodeAllocator>::construct(allocator,
|
std::allocator_traits<NodeAllocator>::construct(allocator,
|
||||||
node,
|
node,
|
||||||
@@ -447,16 +457,16 @@ private:
|
|||||||
node->next,
|
node->next,
|
||||||
std::forward<Type>(data));
|
std::forward<Type>(data));
|
||||||
}
|
}
|
||||||
void destroyNode(Node* node)
|
constexpr void destroyNode(Node* node)
|
||||||
{
|
{
|
||||||
std::allocator_traits<NodeAllocator>::destroy(allocator, node);
|
std::allocator_traits<NodeAllocator>::destroy(allocator, node);
|
||||||
}
|
}
|
||||||
void deallocateNode(Node* node)
|
constexpr void deallocateNode(Node* node)
|
||||||
{
|
{
|
||||||
allocator.deallocate(node, 1);
|
allocator.deallocate(node, 1);
|
||||||
}
|
}
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
iterator addInternal(ValueType&& value)
|
constexpr iterator addInternal(ValueType&& value)
|
||||||
{
|
{
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
{
|
{
|
||||||
@@ -474,7 +484,7 @@ private:
|
|||||||
_size++;
|
_size++;
|
||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
void markIteratorDirty()
|
constexpr void markIteratorDirty()
|
||||||
{
|
{
|
||||||
beginIt = Iterator(root);
|
beginIt = Iterator(root);
|
||||||
endIt = Iterator(tail);
|
endIt = Iterator(tail);
|
||||||
|
|||||||
@@ -5,62 +5,95 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
|
struct Triangle
|
||||||
|
{
|
||||||
|
StaticArray<uint32, 3> indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
int findIndex(Meshlet& current, uint32 index)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < current.numVertices; ++i)
|
||||||
|
{
|
||||||
|
if (current.uniqueVertices[i] == index)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current.numVertices == Gfx::numVerticesPerMeshlet)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
current.uniqueVertices[current.numVertices] = index;
|
||||||
|
|
||||||
|
return current.numVertices++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void completeMeshlet(Array<Meshlet>& meshlets, Meshlet& current)
|
||||||
|
{
|
||||||
|
meshlets.add(current);
|
||||||
|
current = {
|
||||||
|
.numVertices = 0,
|
||||||
|
.numPrimitives = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTriangle(Array<Meshlet>& meshlets, Meshlet& current, Triangle tri)
|
||||||
|
{
|
||||||
|
int f1 = findIndex(current, tri.indices[0]);
|
||||||
|
int f2 = findIndex(current, tri.indices[1]);
|
||||||
|
int f3 = findIndex(current, tri.indices[2]);
|
||||||
|
|
||||||
|
if (f1 == -1 || f2 == -1 || f3 == -1)
|
||||||
|
{
|
||||||
|
completeMeshlet(meshlets, current);
|
||||||
|
f1 = findIndex(current, tri.indices[0]);
|
||||||
|
f2 = findIndex(current, tri.indices[1]);
|
||||||
|
f3 = findIndex(current, tri.indices[2]);
|
||||||
|
}
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 0] = uint8(f1);
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 1] = uint8(f2);
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 2] = uint8(f3);
|
||||||
|
current.numPrimitives++;
|
||||||
|
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
|
||||||
|
{
|
||||||
|
completeMeshlet(meshlets, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Meshlet::build(const Array<Vector>& positions, const Array<uint32>& indices, Array<Meshlet>& meshlets)
|
void Meshlet::build(const Array<Vector>& positions, const Array<uint32>& indices, Array<Meshlet>& meshlets)
|
||||||
{
|
{
|
||||||
Meshlet current = {
|
Meshlet current = {
|
||||||
.numVertices = 0,
|
.numVertices = 0,
|
||||||
.numPrimitives = 0,
|
.numPrimitives = 0,
|
||||||
};
|
};
|
||||||
auto findIndex = [¤t](uint32 index) -> int {
|
Array<Triangle> triangles(indices.size() / 3);
|
||||||
for (uint32 i = 0; i < current.numVertices; ++i)
|
for (size_t i = 0; i < triangles.size(); ++i)
|
||||||
|
{
|
||||||
|
triangles[i].indices[0] = indices[i * 3 + 0];
|
||||||
|
triangles[i].indices[1] = indices[i * 3 + 1];
|
||||||
|
triangles[i].indices[2] = indices[i * 3 + 2];
|
||||||
|
}
|
||||||
|
while (!triangles.empty())
|
||||||
|
{
|
||||||
|
uint32 best = 0;
|
||||||
|
float lowestSurface = std::numeric_limits<float>::max();
|
||||||
|
AABB newAABB;
|
||||||
|
for (uint32 i = 0; i < triangles.size(); ++i)
|
||||||
{
|
{
|
||||||
if (current.uniqueVertices[i] == index)
|
AABB adjusted = current.boundingBox;
|
||||||
|
adjusted.adjust(positions[triangles[i].indices[0]]);
|
||||||
|
adjusted.adjust(positions[triangles[i].indices[1]]);
|
||||||
|
adjusted.adjust(positions[triangles[i].indices[2]]);
|
||||||
|
float surface = adjusted.surfaceArea();
|
||||||
|
if (surface < lowestSurface)
|
||||||
{
|
{
|
||||||
return i;
|
lowestSurface = surface;
|
||||||
|
best = i;
|
||||||
|
newAABB = adjusted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (current.numVertices == Gfx::numVerticesPerMeshlet)
|
current.boundingBox = newAABB;
|
||||||
{
|
addTriangle(meshlets, current, triangles[best]);
|
||||||
return -1;
|
triangles.removeAt(best);
|
||||||
}
|
|
||||||
current.uniqueVertices[current.numVertices] = index;
|
|
||||||
return current.numVertices++;
|
|
||||||
};
|
|
||||||
auto completeMeshlet = [&positions, &meshlets, ¤t]() {
|
|
||||||
for (uint32 i = 0; i < current.numVertices; ++i)
|
|
||||||
{
|
|
||||||
current.boundingBox.adjust(positions[current.uniqueVertices[i]]);
|
|
||||||
}
|
|
||||||
meshlets.add(current);
|
|
||||||
current = {
|
|
||||||
.numVertices = 0,
|
|
||||||
.numPrimitives = 0,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
for (size_t faceIndex = 0; faceIndex < indices.size() / 3; ++faceIndex)
|
|
||||||
{
|
|
||||||
int f1 = findIndex(indices[faceIndex * 3 + 0]);
|
|
||||||
int f2 = findIndex(indices[faceIndex * 3 + 1]);
|
|
||||||
int f3 = findIndex(indices[faceIndex * 3 + 2]);
|
|
||||||
|
|
||||||
if (f1 == -1 || f2 == -1 || f3 == -1)
|
|
||||||
{
|
|
||||||
completeMeshlet();
|
|
||||||
f1 = findIndex(indices[faceIndex * 3 + 0]);
|
|
||||||
f2 = findIndex(indices[faceIndex * 3 + 1]);
|
|
||||||
f3 = findIndex(indices[faceIndex * 3 + 2]);
|
|
||||||
}
|
|
||||||
current.primitiveLayout[current.numPrimitives * 3 + 0] = uint8(f1);
|
|
||||||
current.primitiveLayout[current.numPrimitives * 3 + 1] = uint8(f2);
|
|
||||||
current.primitiveLayout[current.numPrimitives * 3 + 2] = uint8(f3);
|
|
||||||
current.numPrimitives++;
|
|
||||||
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
|
|
||||||
{
|
|
||||||
completeMeshlet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (current.numVertices > 0)
|
|
||||||
{
|
|
||||||
completeMeshlet();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ void BasePass::publishOutputs()
|
|||||||
void BasePass::createRenderPass()
|
void BasePass::createRenderPass()
|
||||||
{
|
{
|
||||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
||||||
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||||
|
|||||||
@@ -177,6 +177,14 @@ void DepthPrepass::createRenderPass()
|
|||||||
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||||
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
|
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.srcSubpass = 0,
|
||||||
|
.dstSubpass = ~0U,
|
||||||
|
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||||
|
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||||
|
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport);
|
renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport);
|
||||||
|
|||||||
@@ -3,93 +3,54 @@
|
|||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
template<typename... RenderPasses>
|
class RenderGraph
|
||||||
class RenderGraph;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class RenderGraph<>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderGraph(PRenderGraphResources) {}
|
RenderGraph()
|
||||||
void updatePassData() {}
|
|
||||||
protected:
|
|
||||||
void setViewport(Gfx::PViewport) {}
|
|
||||||
void createRenderPass() {}
|
|
||||||
void beginFrame(const Component::Camera&) {}
|
|
||||||
void render() {}
|
|
||||||
void endFrame() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename This, typename... Rest>
|
|
||||||
class RenderGraph<This, Rest...> : private RenderGraph<Rest...>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RenderGraph(PRenderGraphResources resources, This pass, Rest... rest)
|
|
||||||
: RenderGraph<Rest...>(resources, std::move(rest)...)
|
|
||||||
, resources(resources)
|
|
||||||
, rp(std::move(pass))
|
|
||||||
{
|
{
|
||||||
rp.setResources(resources);
|
res = new RenderGraphResources();
|
||||||
}
|
}
|
||||||
template<typename PassData, typename... OtherData>
|
void addPass(ORenderPass pass)
|
||||||
void updatePassData(PassData passData, OtherData... otherData)
|
|
||||||
{
|
{
|
||||||
rp.updateViewFrame(std::move(passData));
|
pass->setResources(res);
|
||||||
RenderGraph<Rest...>::updatePassData(otherData...);
|
passes.add(std::move(pass));
|
||||||
}
|
}
|
||||||
void updateViewport(Gfx::PViewport viewport)
|
|
||||||
{
|
|
||||||
setViewport(viewport);
|
|
||||||
createRenderPass();
|
|
||||||
}
|
|
||||||
void render(const Component::Camera& cam)
|
|
||||||
{
|
|
||||||
beginFrame(cam);
|
|
||||||
render();
|
|
||||||
endFrame();
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
void setViewport(Gfx::PViewport viewport)
|
void setViewport(Gfx::PViewport viewport)
|
||||||
{
|
{
|
||||||
rp.setViewport(viewport);
|
for (auto& pass : passes)
|
||||||
RenderGraph<Rest...>::setViewport(viewport);
|
{
|
||||||
|
pass->setViewport(viewport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void createRenderPass()
|
void createRenderPass()
|
||||||
{
|
{
|
||||||
rp.createRenderPass();
|
for (auto& pass : passes)
|
||||||
RenderGraph<Rest...>::createRenderPass();
|
{
|
||||||
|
pass->publishOutputs();
|
||||||
|
}
|
||||||
|
for (auto& pass : passes)
|
||||||
|
{
|
||||||
|
pass->createRenderPass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void beginFrame(const Component::Camera& cam)
|
void render(const Component::Camera& cam)
|
||||||
{
|
{
|
||||||
rp.beginFrame(cam);
|
for (auto& pass : passes)
|
||||||
RenderGraph<Rest...>::beginFrame(cam);
|
{
|
||||||
}
|
pass->beginFrame(cam);
|
||||||
void render()
|
}
|
||||||
{
|
for (auto& pass : passes)
|
||||||
rp.render();
|
{
|
||||||
RenderGraph<Rest...>::render();
|
pass->render();
|
||||||
}
|
}
|
||||||
void endFrame()
|
for (auto& pass : passes)
|
||||||
{
|
{
|
||||||
rp.endFrame();
|
pass->endFrame();
|
||||||
RenderGraph<Rest...>::endFrame();
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
PRenderGraphResources resources;
|
PRenderGraphResources res;
|
||||||
This rp;
|
List<ORenderPass> passes;
|
||||||
};
|
|
||||||
|
|
||||||
class RenderGraphBuilder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
template<typename... RenderPasses>
|
|
||||||
static RenderGraph<RenderPasses...> build(RenderPasses... renderPasses)
|
|
||||||
{
|
|
||||||
PRenderGraphResources resources = new RenderGraphResources();
|
|
||||||
return RenderGraph<RenderPasses...>(resources, std::move(renderPasses)...);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
RenderGraphBuilder() = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ protected:
|
|||||||
Gfx::PViewport viewport;
|
Gfx::PViewport viewport;
|
||||||
PScene scene;
|
PScene scene;
|
||||||
};
|
};
|
||||||
|
DEFINE_REF(RenderPass)
|
||||||
template<typename RP>
|
template<typename RP>
|
||||||
concept RenderPassType = std::derived_from<RP, RenderPass>;
|
concept RenderPassType = std::derived_from<RP, RenderPass>;
|
||||||
|
|
||||||
|
|||||||
@@ -80,17 +80,17 @@ public:
|
|||||||
constexpr void setStencilStoreOp(SeAttachmentStoreOp val) { stencilStoreOp = val; }
|
constexpr void setStencilStoreOp(SeAttachmentStoreOp val) { stencilStoreOp = val; }
|
||||||
constexpr void setInitialLayout(SeImageLayout val) { initialLayout = val; }
|
constexpr void setInitialLayout(SeImageLayout val) { initialLayout = val; }
|
||||||
constexpr void setFinalLayout(SeImageLayout val) { finalLayout = val; }
|
constexpr void setFinalLayout(SeImageLayout val) { finalLayout = val; }
|
||||||
SeClearValue clear;
|
SeClearValue clear = { 0 };
|
||||||
SeColorComponentFlags componentFlags;
|
SeColorComponentFlags componentFlags = 0;
|
||||||
protected:
|
protected:
|
||||||
PTexture2D texture = nullptr;
|
PTexture2D texture = nullptr;
|
||||||
PViewport viewport = nullptr;
|
PViewport viewport = nullptr;
|
||||||
SeImageLayout initialLayout;
|
SeImageLayout initialLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE;
|
||||||
SeImageLayout finalLayout;
|
SeImageLayout finalLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE;
|
||||||
SeAttachmentLoadOp loadOp;
|
SeAttachmentLoadOp loadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE;
|
||||||
SeAttachmentStoreOp storeOp;
|
SeAttachmentStoreOp storeOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE;
|
||||||
SeAttachmentLoadOp stencilLoadOp;
|
SeAttachmentLoadOp stencilLoadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE;
|
||||||
SeAttachmentStoreOp stencilStoreOp;
|
SeAttachmentStoreOp stencilStoreOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderTargetLayout
|
struct RenderTargetLayout
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ DEFINE_REF(ShaderExpression)
|
|||||||
DECLARE_NAME_REF(Gfx, DescriptorSet)
|
DECLARE_NAME_REF(Gfx, DescriptorSet)
|
||||||
struct ShaderParameter : public ShaderExpression
|
struct ShaderParameter : public ShaderExpression
|
||||||
{
|
{
|
||||||
uint32 byteOffset;
|
uint32 byteOffset = 0;
|
||||||
uint32 binding;
|
uint32 binding = 0;
|
||||||
ShaderParameter() {}
|
ShaderParameter() {}
|
||||||
ShaderParameter(std::string name, uint32 byteOffset, uint32 binding);
|
ShaderParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~ShaderParameter();
|
virtual ~ShaderParameter();
|
||||||
@@ -67,7 +67,7 @@ DEFINE_REF(ShaderParameter)
|
|||||||
struct FloatParameter : public ShaderParameter
|
struct FloatParameter : public ShaderParameter
|
||||||
{
|
{
|
||||||
static constexpr uint64 IDENTIFIER = 0x01;
|
static constexpr uint64 IDENTIFIER = 0x01;
|
||||||
float data;
|
float data = 0.0f;
|
||||||
FloatParameter() {}
|
FloatParameter() {}
|
||||||
FloatParameter(std::string name, uint32 byteOffset, uint32 binding);
|
FloatParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~FloatParameter();
|
virtual ~FloatParameter();
|
||||||
@@ -81,7 +81,7 @@ DEFINE_REF(FloatParameter)
|
|||||||
struct VectorParameter : public ShaderParameter
|
struct VectorParameter : public ShaderParameter
|
||||||
{
|
{
|
||||||
static constexpr uint64 IDENTIFIER = 0x02;
|
static constexpr uint64 IDENTIFIER = 0x02;
|
||||||
Vector data;
|
Vector data = Vector();
|
||||||
VectorParameter() {}
|
VectorParameter() {}
|
||||||
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
|
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~VectorParameter();
|
virtual ~VectorParameter();
|
||||||
@@ -95,7 +95,7 @@ DEFINE_REF(VectorParameter)
|
|||||||
struct TextureParameter : public ShaderParameter
|
struct TextureParameter : public ShaderParameter
|
||||||
{
|
{
|
||||||
static constexpr uint64 IDENTIFIER = 0x04;
|
static constexpr uint64 IDENTIFIER = 0x04;
|
||||||
PTextureAsset data;
|
PTextureAsset data = nullptr;
|
||||||
TextureParameter() {}
|
TextureParameter() {}
|
||||||
TextureParameter(std::string name, uint32 byteOffset, uint32 binding);
|
TextureParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~TextureParameter();
|
virtual ~TextureParameter();
|
||||||
@@ -110,7 +110,7 @@ DECLARE_NAME_REF(Gfx, Sampler)
|
|||||||
struct SamplerParameter : public ShaderParameter
|
struct SamplerParameter : public ShaderParameter
|
||||||
{
|
{
|
||||||
static constexpr uint64 IDENTIFIER = 0x08;
|
static constexpr uint64 IDENTIFIER = 0x08;
|
||||||
Gfx::OSampler data;
|
Gfx::OSampler data = nullptr;
|
||||||
SamplerParameter() {}
|
SamplerParameter() {}
|
||||||
SamplerParameter(std::string name, uint32 byteOffset, uint32 binding);
|
SamplerParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~SamplerParameter();
|
virtual ~SamplerParameter();
|
||||||
@@ -124,8 +124,8 @@ DEFINE_REF(SamplerParameter)
|
|||||||
struct CombinedTextureParameter : public ShaderParameter
|
struct CombinedTextureParameter : public ShaderParameter
|
||||||
{
|
{
|
||||||
static constexpr uint64 IDENTIFIER = 0x10;
|
static constexpr uint64 IDENTIFIER = 0x10;
|
||||||
PTextureAsset data;
|
PTextureAsset data = nullptr;
|
||||||
Gfx::PSampler sampler;
|
Gfx::PSampler sampler = nullptr;
|
||||||
CombinedTextureParameter() {}
|
CombinedTextureParameter() {}
|
||||||
CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding);
|
CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||||
virtual ~CombinedTextureParameter();
|
virtual ~CombinedTextureParameter();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,15 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
|||||||
: View(graphics, window, createInfo, "Game")
|
: View(graphics, window, createInfo, "Game")
|
||||||
, scene(new Scene(graphics))
|
, scene(new Scene(graphics))
|
||||||
, gameInterface(dllPath)
|
, gameInterface(dllPath)
|
||||||
, renderGraph(RenderGraphBuilder::build(
|
|
||||||
DepthPrepass(graphics, scene),
|
|
||||||
LightCullingPass(graphics, scene),
|
|
||||||
BasePass(graphics, scene),
|
|
||||||
DebugPass(graphics, scene)
|
|
||||||
//SkyboxRenderPass(graphics, scene)
|
|
||||||
))
|
|
||||||
{
|
{
|
||||||
reloadGame();
|
reloadGame();
|
||||||
renderGraph.updateViewport(viewport);
|
renderGraph.addPass(new DepthPrepass(graphics, scene));
|
||||||
|
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||||
|
renderGraph.addPass(new BasePass(graphics, scene));
|
||||||
|
//renderGraph.addPass(new DebugPass(graphics, scene));
|
||||||
|
//renderGraph.addPass(new SkyboxRenderPass(graphics, scene));
|
||||||
|
renderGraph.setViewport(viewport);
|
||||||
|
renderGraph.createRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
GameView::~GameView()
|
GameView::~GameView()
|
||||||
@@ -77,7 +76,7 @@ void GameView::render()
|
|||||||
|
|
||||||
void GameView::applyArea(URect)
|
void GameView::applyArea(URect)
|
||||||
{
|
{
|
||||||
renderGraph.updateViewport(viewport);
|
renderGraph.setViewport(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameView::reloadGame()
|
void GameView::reloadGame()
|
||||||
|
|||||||
@@ -32,13 +32,7 @@ protected:
|
|||||||
virtual void applyArea(URect rect) override;
|
virtual void applyArea(URect rect) override;
|
||||||
OScene scene;
|
OScene scene;
|
||||||
GameInterface gameInterface;
|
GameInterface gameInterface;
|
||||||
RenderGraph<
|
RenderGraph renderGraph;
|
||||||
DepthPrepass,
|
|
||||||
LightCullingPass,
|
|
||||||
BasePass,
|
|
||||||
DebugPass
|
|
||||||
//SkyboxRenderPass
|
|
||||||
> renderGraph;
|
|
||||||
|
|
||||||
PSystemGraph systemGraph;
|
PSystemGraph systemGraph;
|
||||||
System::PKeyboardInput keyboardSystem;
|
System::PKeyboardInput keyboardSystem;
|
||||||
|
|||||||
Reference in New Issue
Block a user