Basic meshlet generation algorithm
This commit is contained in:
@@ -82,6 +82,7 @@ void meshMain(
|
|||||||
out Indices<uint3, MAX_PRIMITIVES> indices
|
out Indices<uint3, MAX_PRIMITIVES> indices
|
||||||
){
|
){
|
||||||
InstanceData inst = scene.instances[meshPayload.instanceId[groupID]];
|
InstanceData inst = scene.instances[meshPayload.instanceId[groupID]];
|
||||||
|
MeshData md = scene.meshData[meshPayload.instanceId[groupID]];
|
||||||
MeshletDescription m = meshlets.meshletInfos[meshPayload.meshletId[groupID]];
|
MeshletDescription m = meshlets.meshletInfos[meshPayload.meshletId[groupID]];
|
||||||
const uint vertexLoops = (MAX_VERTICES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE;
|
const uint vertexLoops = (MAX_VERTICES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE;
|
||||||
for(uint loop = 0; loop < vertexLoops; ++loop)
|
for(uint loop = 0; loop < vertexLoops; ++loop)
|
||||||
@@ -91,7 +92,7 @@ void meshMain(
|
|||||||
InterlockedMax(gs_numVertices, v + 1);
|
InterlockedMax(gs_numVertices, v + 1);
|
||||||
{
|
{
|
||||||
int vertexIndex = meshlets.vertexIndices[m.vertexOffset + v];
|
int vertexIndex = meshlets.vertexIndices[m.vertexOffset + v];
|
||||||
gs_vertices[v] = vertexData.getAttributes(vertexIndex, inst);
|
gs_vertices[v] = vertexData.getAttributes(md.indexOffset + vertexIndex, inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,11 @@ struct MeshletDescription
|
|||||||
uint32_t primitiveOffset;
|
uint32_t primitiveOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshletData
|
|
||||||
{
|
|
||||||
StructuredBuffer<MeshletDescription> meshletInfos;
|
|
||||||
StructuredBuffer<uint8_t> primitiveIndices;
|
|
||||||
|
|
||||||
StructuredBuffer<uint32_t> vertexIndices;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MeshData
|
struct MeshData
|
||||||
{
|
{
|
||||||
uint numMeshlets;
|
uint numMeshlets;
|
||||||
uint meshletOffset;
|
uint meshletOffset;
|
||||||
|
uint indicesOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint MAX_VERTICES = 64;
|
static const uint MAX_VERTICES = 64;
|
||||||
@@ -38,7 +31,10 @@ struct Scene
|
|||||||
{
|
{
|
||||||
StructuredBuffer<InstanceData> instances;
|
StructuredBuffer<InstanceData> instances;
|
||||||
StructuredBuffer<MeshData> meshData;
|
StructuredBuffer<MeshData> meshData;
|
||||||
StructuredBuffer<MeshletData> meshlets;
|
StructuredBuffer<MeshletDescription> meshletInfos;
|
||||||
|
StructuredBuffer<uint8_t> primitiveIndices;
|
||||||
|
|
||||||
|
StructuredBuffer<uint32_t> vertexIndices;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = INDEX_SCENE_DATA)
|
layout(set = INDEX_SCENE_DATA)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "MeshLoader.h"
|
#include "MeshLoader.h"
|
||||||
#include "Graphics/GraphicsResources.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Asset/MeshAsset.h"
|
#include "Asset/MeshAsset.h"
|
||||||
#include "Graphics/Mesh.h"
|
#include "Graphics/Mesh.h"
|
||||||
#include "Graphics/StaticMeshVertexInput.h"
|
#include "Graphics/StaticMeshVertexData.h"
|
||||||
#include "Asset/AssetImporter.h"
|
#include "Asset/AssetImporter.h"
|
||||||
#include "Asset/MaterialAsset.h"
|
#include "Asset/MaterialAsset.h"
|
||||||
|
#include <set>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@@ -120,7 +120,6 @@ void MeshLoader::loadMaterials(const aiScene* scene, const std::string& baseName
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
||||||
{
|
{
|
||||||
if (node->mNumMeshes > 0)
|
if (node->mNumMeshes > 0)
|
||||||
@@ -133,57 +132,7 @@ void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
|||||||
findMeshRoots(node->mChildren[i], meshNodes);
|
findMeshRoots(node->mChildren[i], meshNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
|
|
||||||
{
|
|
||||||
Array<Vector> buffer(size);
|
|
||||||
for(uint32 i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
|
||||||
}
|
|
||||||
VertexBufferCreateInfo vbInfo;
|
|
||||||
vbInfo.numVertices = size;
|
|
||||||
vbInfo.vertexSize = sizeof(Vector);
|
|
||||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
|
||||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
|
||||||
vbInfo.resourceData.size = sizeof(Vector) * buffer.size();
|
|
||||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
|
||||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
|
||||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
|
|
||||||
}
|
|
||||||
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
|
||||||
{
|
|
||||||
Array<Vector2> buffer(size);
|
|
||||||
for(uint32 i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
buffer[i] = Vector2(sourceData[i].x, sourceData[i].y);
|
|
||||||
}
|
|
||||||
VertexBufferCreateInfo vbInfo;
|
|
||||||
vbInfo.numVertices = size;
|
|
||||||
vbInfo.vertexSize = sizeof(Vector2);
|
|
||||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
|
||||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
|
||||||
vbInfo.resourceData.size = sizeof(Vector2) * buffer.size();
|
|
||||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
|
||||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
|
||||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
|
||||||
}
|
|
||||||
VertexStreamComponent createVertexStream(uint32 size, aiColor4D* sourceData, Gfx::PGraphics graphics)
|
|
||||||
{
|
|
||||||
Array<Vector4> buffer(size);
|
|
||||||
for(uint32 i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
buffer[i] = Vector4(sourceData[i].r, sourceData[i].g, sourceData[i].b, sourceData[i].a);
|
|
||||||
}
|
|
||||||
VertexBufferCreateInfo vbInfo;
|
|
||||||
vbInfo.numVertices = size;
|
|
||||||
vbInfo.vertexSize = sizeof(Vector4);
|
|
||||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
|
||||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
|
||||||
vbInfo.resourceData.size = sizeof(Vector4) * buffer.size();
|
|
||||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
|
||||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
|
||||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT);
|
|
||||||
}
|
|
||||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialAsset>& materials, Array<PMesh>& globalMeshes, Component::Collider& collider)
|
void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialAsset>& materials, Array<PMesh>& globalMeshes, Component::Collider& collider)
|
||||||
{
|
{
|
||||||
for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||||
@@ -192,50 +141,106 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialAss
|
|||||||
collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z));
|
collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z));
|
||||||
collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z));
|
collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z));
|
||||||
|
|
||||||
//! \todo duplicate from createVertexStream, clean up
|
// assume static mesh for now
|
||||||
Array<Vector> vertices(mesh->mNumVertices);
|
Array<Vector> positions(mesh->mNumVertices);
|
||||||
|
Array<Vector2> texCoords(mesh->mNumVertices);
|
||||||
|
Array<Vector> normals(mesh->mNumVertices);
|
||||||
|
Array<Vector> tangents(mesh->mNumVertices);
|
||||||
|
Array<Vector> biTangents(mesh->mNumVertices);
|
||||||
|
|
||||||
|
StaticMeshVertexData* vertexData = StaticMeshVertexData::getInstance();
|
||||||
|
|
||||||
for(uint32 i = 0; i < mesh->mNumVertices; ++i)
|
for(uint32 i = 0; i < mesh->mNumVertices; ++i)
|
||||||
{
|
{
|
||||||
vertices[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
positions[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
||||||
|
texCoords[i] = Vector2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].x);
|
||||||
|
normals[i] = Vector(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
|
||||||
|
tangents[i] = Vector(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z);
|
||||||
|
biTangents[i] = Vector(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z);
|
||||||
}
|
}
|
||||||
|
|
||||||
PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str()));
|
MeshId id = vertexData->allocateVertexData(mesh->mNumVertices);
|
||||||
StaticMeshDataType data;
|
vertexData->loadPositions(id, positions);
|
||||||
data.positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics);
|
vertexData->loadTexCoords(id, texCoords);
|
||||||
|
vertexData->loadNormals(id, normals);
|
||||||
for(uint32 i = 0; i < MAX_TEXCOORDS; ++i)
|
vertexData->loadTangents(id, tangents);
|
||||||
{
|
vertexData->loadBiTangents(id, biTangents);
|
||||||
if(mesh->HasTextureCoords(i))
|
|
||||||
{
|
|
||||||
data.textureCoordinates[i] = createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(mesh->HasNormals())
|
|
||||||
{
|
|
||||||
data.tangentBasisComponents[0] = createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics);
|
|
||||||
}
|
|
||||||
if(mesh->HasTangentsAndBitangents())
|
|
||||||
{
|
|
||||||
//TODO: use bitangent to calculate sign for 4th coordinate of tangentstream
|
|
||||||
data.tangentBasisComponents[1] = createVertexStream(mesh->mNumVertices, mesh->mTangents, graphics);
|
|
||||||
data.tangentBasisComponents[2] = createVertexStream(mesh->mNumVertices, mesh->mBitangents, graphics);
|
|
||||||
}
|
|
||||||
if(mesh->HasVertexColors(0))
|
|
||||||
{
|
|
||||||
data.colorComponent = createVertexStream(mesh->mNumVertices, mesh->mColors[0], graphics);
|
|
||||||
}
|
|
||||||
vertexShaderInput->setData(std::move(data));
|
|
||||||
vertexShaderInput->init(graphics);
|
|
||||||
|
|
||||||
Array<uint32> indices(mesh->mNumFaces * 3);
|
Array<uint32> indices(mesh->mNumFaces * 3);
|
||||||
for (uint32 faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex)
|
for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex)
|
||||||
{
|
{
|
||||||
indices[faceIndex * 3 + 0] = mesh->mFaces[faceIndex].mIndices[0];
|
indices[faceIndex * 3 + 0] = mesh->mFaces[faceIndex].mIndices[0];
|
||||||
indices[faceIndex * 3 + 1] = mesh->mFaces[faceIndex].mIndices[1];
|
indices[faceIndex * 3 + 1] = mesh->mFaces[faceIndex].mIndices[1];
|
||||||
indices[faceIndex * 3 + 2] = mesh->mFaces[faceIndex].mIndices[2];
|
indices[faceIndex * 3 + 2] = mesh->mFaces[faceIndex].mIndices[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
collider.physicsMesh.addCollider(vertices, indices, Matrix4(1.0f));
|
if (Gfx::useMeshShading)
|
||||||
|
{
|
||||||
|
Array<Meshlet> meshlets;
|
||||||
|
meshlets.reserve(indices.size() / (3ull * Gfx::numPrimitivesPerMeshlet));
|
||||||
|
std::set<uint32> uniqueVertices;
|
||||||
|
Meshlet current = {
|
||||||
|
.numVertices = 0,
|
||||||
|
.numPrimitives = 0,
|
||||||
|
};
|
||||||
|
auto insertAndGetIndex = [&uniqueVertices, ¤t](uint32 index) -> int8_t
|
||||||
|
{
|
||||||
|
auto [it, inserted] = uniqueVertices.insert(index);
|
||||||
|
if (inserted)
|
||||||
|
{
|
||||||
|
if (current.numVertices == Gfx::numVerticesPerMeshlet)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
current.uniqueVertices[current.numVertices] = index;
|
||||||
|
return current.numVertices++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < current.numVertices; ++i)
|
||||||
|
{
|
||||||
|
if (current.uniqueVertices[i] == index)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto completeMeshlet = [&meshlets, ¤t, &uniqueVertices]() {
|
||||||
|
meshlets.add(current);
|
||||||
|
current = {
|
||||||
|
.numVertices = 0,
|
||||||
|
.numPrimitives = 0,
|
||||||
|
};
|
||||||
|
uniqueVertices.clear();
|
||||||
|
};
|
||||||
|
for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex)
|
||||||
|
{
|
||||||
|
auto i1 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[0]);
|
||||||
|
auto i2 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[1]);
|
||||||
|
auto i3 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[2]);
|
||||||
|
if (i1 == -1 || i2 == -1 || i3 == -1)
|
||||||
|
{
|
||||||
|
completeMeshlet();
|
||||||
|
}
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 0] = i1;
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 1] = i2;
|
||||||
|
current.primitiveLayout[current.numPrimitives * 3 + 2] = i3;
|
||||||
|
current.numPrimitives++;
|
||||||
|
if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet)
|
||||||
|
{
|
||||||
|
completeMeshlet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// \! todo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f));
|
||||||
|
|
||||||
IndexBufferCreateInfo idxInfo;
|
IndexBufferCreateInfo idxInfo;
|
||||||
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
|
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "Containers/List.h"
|
#include "Containers/List.h"
|
||||||
#include "Graphics/GraphicsEnums.h"
|
#include "Graphics/Enums.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ static constexpr bool useAsyncCompute = true;
|
|||||||
static constexpr bool waitIdleOnSubmit = true;
|
static constexpr bool waitIdleOnSubmit = true;
|
||||||
static constexpr bool useMeshShading = true;
|
static constexpr bool useMeshShading = true;
|
||||||
static constexpr uint32 numFramesBuffered = 8;
|
static constexpr uint32 numFramesBuffered = 8;
|
||||||
|
|
||||||
|
// meshlet dimensions curated by NVIDIA
|
||||||
|
static constexpr uint32 numVerticesPerMeshlet = 64;
|
||||||
|
static constexpr uint32 numPrimitivesPerMeshlet = 126;
|
||||||
double getCurrentFrameDelta();
|
double getCurrentFrameDelta();
|
||||||
|
|
||||||
enum class RenderPassType : uint8
|
enum class RenderPassType : uint8
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "Containers/Array.h"
|
#include "Containers/Array.h"
|
||||||
#include "Containers/List.h"
|
#include "Containers/List.h"
|
||||||
#include "Initializer.h"
|
#include "Initializer.h"
|
||||||
#include "Buffer.h"
|
|
||||||
#include "CRC.h"
|
#include "CRC.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,4 @@ ShaderCompiler::~ShaderCompiler()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCompiler::registerMaterial(PMaterial material)
|
|
||||||
{
|
|
||||||
for(auto& type : VertexInputType::getTypeList())
|
|
||||||
{
|
|
||||||
material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, type);
|
|
||||||
material->createShaders(graphics, Gfx::RenderPassType::BasePass, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ class ShaderCompiler
|
|||||||
public:
|
public:
|
||||||
ShaderCompiler(PGraphics graphics);
|
ShaderCompiler(PGraphics graphics);
|
||||||
~ShaderCompiler();
|
~ShaderCompiler();
|
||||||
void registerMaterial(PMaterial material);
|
|
||||||
private:
|
private:
|
||||||
Array<PMaterial> pendingCompiles;
|
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
};
|
};
|
||||||
DEFINE_REF(ShaderCompiler)
|
DEFINE_REF(ShaderCompiler)
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#include "StaticMeshVertexData.h"
|
#include "StaticMeshVertexData.h"
|
||||||
|
#include "Graphics.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
extern List<VertexData*> vertexDataList;
|
extern List<VertexData*> vertexDataList;
|
||||||
|
|
||||||
StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics)
|
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024;
|
||||||
: VertexData(graphics)
|
|
||||||
, head(0)
|
StaticMeshVertexData::StaticMeshVertexData()
|
||||||
|
: head(0)
|
||||||
|
, verticesAllocated(NUM_DEFAULT_ELEMENTS)
|
||||||
{
|
{
|
||||||
vertexDataList.add(this);
|
vertexDataList.add(this);
|
||||||
}
|
}
|
||||||
@@ -14,10 +17,120 @@ StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics)
|
|||||||
StaticMeshVertexData::~StaticMeshVertexData()
|
StaticMeshVertexData::~StaticMeshVertexData()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
StaticMeshVertexData* Seele::StaticMeshVertexData::getInstance()
|
||||||
|
{
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
MeshId StaticMeshVertexData::allocateVertexData(uint64 numVertices)
|
MeshId StaticMeshVertexData::allocateVertexData(uint64 numVertices)
|
||||||
{
|
{
|
||||||
MeshId res{ idCounter++ };
|
MeshId res{ idCounter++ };
|
||||||
meshOffsets[res] = head;
|
meshOffsets[res] = head;
|
||||||
head += numVertices;
|
head += numVertices;
|
||||||
|
if (head > verticesAllocated)
|
||||||
|
{
|
||||||
|
ShaderBufferCreateInfo createInfo = {
|
||||||
|
.resourceData = {
|
||||||
|
.size = head * sizeof(Vector),
|
||||||
|
},
|
||||||
|
.stride = sizeof(Vector),
|
||||||
|
.bDynamic = true,
|
||||||
|
};
|
||||||
|
positions = graphics->createShaderBuffer(createInfo);
|
||||||
|
normals = graphics->createShaderBuffer(createInfo);
|
||||||
|
tangents = graphics->createShaderBuffer(createInfo);
|
||||||
|
biTangents = graphics->createShaderBuffer(createInfo);
|
||||||
|
createInfo.resourceData.size = head * sizeof(Vector2);
|
||||||
|
createInfo.stride = sizeof(Vector2);
|
||||||
|
texCoords = graphics->createShaderBuffer(createInfo);
|
||||||
|
}
|
||||||
|
positionData.resize(head);
|
||||||
|
texCoordsData.resize(head);
|
||||||
|
normalData.resize(head);
|
||||||
|
tangentData.resize(head);
|
||||||
|
biTangentData.resize(head);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::loadPositions(MeshId id, const Array<Vector>& data)
|
||||||
|
{
|
||||||
|
uint64 offset = meshOffsets[id];
|
||||||
|
assert(offset + data.size() < head);
|
||||||
|
std::memcpy(positionData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::loadTexCoords(MeshId id, const Array<Vector2>& data)
|
||||||
|
{
|
||||||
|
uint64 offset = meshOffsets[id];
|
||||||
|
assert(offset + data.size() < head);
|
||||||
|
std::memcpy(texCoordsData.data() + offset, data.data(), data.size() * sizeof(Vector2));
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::loadNormals(MeshId id, const Array<Vector>& data)
|
||||||
|
{
|
||||||
|
uint64 offset = meshOffsets[id];
|
||||||
|
assert(offset + data.size() < head);
|
||||||
|
std::memcpy(normalData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::loadTangents(MeshId id, const Array<Vector>& data)
|
||||||
|
{
|
||||||
|
uint64 offset = meshOffsets[id];
|
||||||
|
assert(offset + data.size() < head);
|
||||||
|
std::memcpy(tangentData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::loadBiTangents(MeshId id, const Array<Vector>& data)
|
||||||
|
{
|
||||||
|
uint64 offset = meshOffsets[id];
|
||||||
|
assert(offset + data.size() < head);
|
||||||
|
std::memcpy(biTangentData.data() + offset, data.data(), data.size() * sizeof(Vector));
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::init(Gfx::PGraphics graphics)
|
||||||
|
{
|
||||||
|
VertexData::init(graphics);
|
||||||
|
ShaderBufferCreateInfo createInfo = {
|
||||||
|
.resourceData = {
|
||||||
|
.size = NUM_DEFAULT_ELEMENTS * sizeof(Vector),
|
||||||
|
},
|
||||||
|
.stride = sizeof(Vector),
|
||||||
|
.bDynamic = true,
|
||||||
|
};
|
||||||
|
positions = graphics->createShaderBuffer(createInfo);
|
||||||
|
normals = graphics->createShaderBuffer(createInfo);
|
||||||
|
tangents = graphics->createShaderBuffer(createInfo);
|
||||||
|
biTangents = graphics->createShaderBuffer(createInfo);
|
||||||
|
createInfo.resourceData.size = NUM_DEFAULT_ELEMENTS * sizeof(Vector2);
|
||||||
|
createInfo.stride = sizeof(Vector2);
|
||||||
|
texCoords = graphics->createShaderBuffer(createInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticMeshVertexData::updateBuffers()
|
||||||
|
{
|
||||||
|
positions->updateContents(BulkResourceData{
|
||||||
|
.size = positionData.size() * sizeof(Vector),
|
||||||
|
.data = (uint8*)positionData.data(),
|
||||||
|
});
|
||||||
|
texCoords->updateContents(BulkResourceData{
|
||||||
|
.size = texCoordsData.size() * sizeof(Vector2),
|
||||||
|
.data = (uint8*)texCoordsData.data(),
|
||||||
|
});
|
||||||
|
normals->updateContents(BulkResourceData{
|
||||||
|
.size = normalData.size() * sizeof(Vector),
|
||||||
|
.data = (uint8*)normalData.data(),
|
||||||
|
});
|
||||||
|
tangents->updateContents(BulkResourceData{
|
||||||
|
.size = tangentData.size() * sizeof(Vector),
|
||||||
|
.data = (uint8*)tangentData.data(),
|
||||||
|
});
|
||||||
|
biTangents->updateContents(BulkResourceData{
|
||||||
|
.size = biTangentData.size() * sizeof(Vector),
|
||||||
|
.data = (uint8*)biTangentData.data(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ namespace Seele
|
|||||||
class StaticMeshVertexData : public VertexData
|
class StaticMeshVertexData : public VertexData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StaticMeshVertexData(Gfx::PGraphics graphics);
|
StaticMeshVertexData();
|
||||||
virtual ~StaticMeshVertexData();
|
virtual ~StaticMeshVertexData();
|
||||||
|
static StaticMeshVertexData* getInstance();
|
||||||
virtual MeshId allocateVertexData(uint64 numVertices) override;
|
virtual MeshId allocateVertexData(uint64 numVertices) override;
|
||||||
void loadPositions(MeshId id, const Array<Vector>& data);
|
void loadPositions(MeshId id, const Array<Vector>& data);
|
||||||
void loadTexCoords(MeshId id, const Array<Vector2>& data);
|
void loadTexCoords(MeshId id, const Array<Vector2>& data);
|
||||||
void loadNormals(MeshId id, const Array<Vector>& data);
|
void loadNormals(MeshId id, const Array<Vector>& data);
|
||||||
void loadTangents(MeshId id, const Array<Vector>& data);
|
void loadTangents(MeshId id, const Array<Vector>& data);
|
||||||
void loadBiTangents(MeshId id, const Array<Vector>& data);
|
void loadBiTangents(MeshId id, const Array<Vector>& data);
|
||||||
|
virtual void init(Gfx::PGraphics graphics) override;
|
||||||
private:
|
private:
|
||||||
|
virtual void updateBuffers() override;
|
||||||
Gfx::PShaderBuffer positions;
|
Gfx::PShaderBuffer positions;
|
||||||
Array<Vector> positionData;
|
Array<Vector> positionData;
|
||||||
Gfx::PShaderBuffer texCoords;
|
Gfx::PShaderBuffer texCoords;
|
||||||
@@ -27,5 +30,6 @@ private:
|
|||||||
Array<Vector> biTangentData;
|
Array<Vector> biTangentData;
|
||||||
Map<MeshId, uint64_t> meshOffsets;
|
Map<MeshId, uint64_t> meshOffsets;
|
||||||
uint64 head;
|
uint64 head;
|
||||||
|
uint64 verticesAllocated;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ using namespace Seele;
|
|||||||
void VertexData::resetMeshData()
|
void VertexData::resetMeshData()
|
||||||
{
|
{
|
||||||
materialData.clear();
|
materialData.clear();
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
|
updateBuffers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexData::updateMesh(const Component::Transform& transform, const Component::Mesh& mesh)
|
void VertexData::updateMesh(const Component::Transform& transform, const Component::Mesh& mesh)
|
||||||
@@ -24,6 +28,30 @@ void VertexData::updateMesh(const Component::Transform& transform, const Compone
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VertexData::loadMesh(MeshId id, Array<Meshlet> meshlets)
|
||||||
|
{
|
||||||
|
meshData[id].clear();
|
||||||
|
uint32 head = 0;
|
||||||
|
while (head < meshlets.size())
|
||||||
|
{
|
||||||
|
uint32 numMeshlets = std::min<uint32>(512, meshlets.size() - head);
|
||||||
|
Array<MeshletDescription> desc(numMeshlets);
|
||||||
|
for (uint32 i = 0; i < numMeshlets; ++i)
|
||||||
|
{
|
||||||
|
Meshlet& m = meshlets[head + i];
|
||||||
|
|
||||||
|
vertexIndices.resize()
|
||||||
|
desc.add(MeshletDescription{
|
||||||
|
.boundingBox = MeshletAABB(),
|
||||||
|
.vertexCount = m.numVertices,
|
||||||
|
.primitiveCount = m.numPrimitives,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
meshData[id].add();
|
||||||
|
head += numMeshlets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VertexData::createDescriptors()
|
void VertexData::createDescriptors()
|
||||||
{
|
{
|
||||||
for (const auto& [_, mat] : materialData)
|
for (const auto& [_, mat] : materialData)
|
||||||
@@ -74,10 +102,9 @@ List<VertexData*> VertexData::getList()
|
|||||||
return vertexDataList;
|
return vertexDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexData::VertexData(Gfx::PGraphics graphics)
|
void Seele::VertexData::init(Gfx::PGraphics graphics)
|
||||||
: graphics(graphics)
|
|
||||||
, idCounter(0)
|
|
||||||
{
|
{
|
||||||
|
this->graphics = graphics;
|
||||||
instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout");
|
instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout");
|
||||||
instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||||
if (Gfx::useMeshShading)
|
if (Gfx::useMeshShading)
|
||||||
@@ -96,3 +123,9 @@ VertexData::VertexData(Gfx::PGraphics graphics)
|
|||||||
}
|
}
|
||||||
instanceDataLayout->create();
|
instanceDataLayout->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexData::VertexData()
|
||||||
|
: idCounter(0)
|
||||||
|
, dirty(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,17 @@ namespace Component
|
|||||||
struct MeshId
|
struct MeshId
|
||||||
{
|
{
|
||||||
uint64 id;
|
uint64 id;
|
||||||
|
std::strong_ordering operator<=>(const MeshId& other) const
|
||||||
|
{
|
||||||
|
return id <=> other.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct Meshlet
|
||||||
|
{
|
||||||
|
uint32 uniqueVertices[Gfx::numVerticesPerMeshlet]; // unique vertiex indices in the vertex data
|
||||||
|
uint8 primitiveLayout[Gfx::numPrimitivesPerMeshlet * 3]; // indices into the uniqueVertices array, only uint8 needed
|
||||||
|
uint32 numVertices;
|
||||||
|
uint32 numPrimitives;
|
||||||
};
|
};
|
||||||
class VertexData
|
class VertexData
|
||||||
{
|
{
|
||||||
@@ -44,9 +55,11 @@ public:
|
|||||||
{
|
{
|
||||||
uint32 numMeshlets;
|
uint32 numMeshlets;
|
||||||
uint32 meshletOffset;
|
uint32 meshletOffset;
|
||||||
|
uint32 vertexOffset;
|
||||||
};
|
};
|
||||||
void resetMeshData();
|
void resetMeshData();
|
||||||
void updateMesh(const Component::Transform& transform, const Component::Mesh& mesh);
|
void updateMesh(const Component::Transform& transform, const Component::Mesh& mesh);
|
||||||
|
void loadMesh(MeshId id, Array<Meshlet> meshlets);
|
||||||
void createDescriptors();
|
void createDescriptors();
|
||||||
virtual MeshId allocateVertexData(uint64 numVertices) = 0;
|
virtual MeshId allocateVertexData(uint64 numVertices) = 0;
|
||||||
virtual void bindBuffers(Gfx::PRenderCommand command) = 0;
|
virtual void bindBuffers(Gfx::PRenderCommand command) = 0;
|
||||||
@@ -57,7 +70,10 @@ public:
|
|||||||
const Map<std::string, MaterialData>& getMaterialData() const { return materialData; }
|
const Map<std::string, MaterialData>& getMaterialData() const { return materialData; }
|
||||||
const Array<MeshData>& getMeshData(MeshId id) { return meshData[id]; }
|
const Array<MeshData>& getMeshData(MeshId id) { return meshData[id]; }
|
||||||
static List<VertexData*> getList();
|
static List<VertexData*> getList();
|
||||||
|
virtual void init(Gfx::PGraphics graphics);
|
||||||
protected:
|
protected:
|
||||||
|
virtual void updateBuffers() = 0;
|
||||||
|
VertexData();
|
||||||
struct MeshletAABB
|
struct MeshletAABB
|
||||||
{
|
{
|
||||||
Vector min;
|
Vector min;
|
||||||
@@ -65,24 +81,26 @@ protected:
|
|||||||
Vector max;
|
Vector max;
|
||||||
float pad1;
|
float pad1;
|
||||||
};
|
};
|
||||||
struct MeshletData
|
struct MeshletDescription
|
||||||
{
|
{
|
||||||
MeshletAABB boundingBox;
|
MeshletAABB boundingBox;
|
||||||
uint32_t vertexCount;
|
uint32_t vertexCount;
|
||||||
uint32_t primiticeCount;
|
uint32_t primitiveCount;
|
||||||
uint32_t vertexOffset;
|
uint32_t vertexOffset;
|
||||||
uint32_t primitiveOffset;
|
uint32_t primitiveOffset;
|
||||||
};
|
};
|
||||||
Map<std::string, MaterialData> materialData;
|
Map<std::string, MaterialData> materialData;
|
||||||
Map<MeshId, Array<MeshData>> meshData;
|
Map<MeshId, Array<MeshData>> meshData;
|
||||||
Array<MeshletData> meshlets;
|
Array<MeshletDescription> meshlets;
|
||||||
Gfx::PDescriptorLayout instanceDataLayout;
|
Array<uint8> primitiveIndices;
|
||||||
|
Array<uint32> vertexIndices;
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
|
Gfx::PDescriptorLayout instanceDataLayout;
|
||||||
// for mesh shading
|
// for mesh shading
|
||||||
Gfx::PShaderBuffer meshletBuffer;
|
Gfx::PShaderBuffer meshletBuffer;
|
||||||
// for legacy pipeline
|
// for legacy pipeline
|
||||||
Gfx::PIndexBuffer indexBuffer;
|
Gfx::PIndexBuffer indexBuffer;
|
||||||
VertexData(Gfx::PGraphics graphics);
|
|
||||||
uint64 idCounter;
|
uint64 idCounter;
|
||||||
|
bool dirty;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,33 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics)
|
|||||||
: graphics(graphics)
|
: graphics(graphics)
|
||||||
{
|
{
|
||||||
layout = graphics->createDescriptorLayout("LightEnvironment");
|
layout = graphics->createDescriptorLayout("LightEnvironment");
|
||||||
layout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
layout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||||
layout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
layout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||||
layout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
layout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||||
layout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
layout->create();
|
||||||
|
lightEnvBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
||||||
|
.resourceData = {
|
||||||
|
.size = sizeof(LightEnv),
|
||||||
|
.data = (uint8*) &lightEnv,
|
||||||
|
},
|
||||||
|
.bDynamic = true,
|
||||||
|
});
|
||||||
|
directionalLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.resourceData = {
|
||||||
|
.size = sizeof(Component::DirectionalLight) * MAX_DIRECTIONAL_LIGHTS,
|
||||||
|
.data = (uint8*)dirs.data(),
|
||||||
|
},
|
||||||
|
.stride = sizeof(Component::DirectionalLight),
|
||||||
|
.bDynamic = true,
|
||||||
|
});
|
||||||
|
pointLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.resourceData = {
|
||||||
|
.size = sizeof(Component::PointLight) * MAX_POINT_LIGHTS,
|
||||||
|
.data = (uint8*)dirs.data(),
|
||||||
|
},
|
||||||
|
.stride = sizeof(Component::PointLight),
|
||||||
|
.bDynamic = true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LightEnvironment::~LightEnvironment()
|
LightEnvironment::~LightEnvironment()
|
||||||
@@ -19,17 +42,39 @@ LightEnvironment::~LightEnvironment()
|
|||||||
|
|
||||||
void LightEnvironment::reset()
|
void LightEnvironment::reset()
|
||||||
{
|
{
|
||||||
|
layout->reset();
|
||||||
|
set = layout->allocateDescriptorSet();
|
||||||
|
dirs.clear();
|
||||||
|
points.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEnvironment::addDirectionalLight(Component::DirectionalLight dirLight)
|
void LightEnvironment::addDirectionalLight(Component::DirectionalLight dirLight)
|
||||||
{
|
{
|
||||||
|
dirs.add(dirLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEnvironment::addPointLight(Component::PointLight pointLight)
|
void LightEnvironment::addPointLight(Component::PointLight pointLight)
|
||||||
{
|
{
|
||||||
|
points.add(pointLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEnvironment::commit()
|
void LightEnvironment::commit()
|
||||||
{
|
{
|
||||||
|
lightEnv.numDirectionalLights = dirs.size();
|
||||||
|
lightEnv.numPointLights = points.size();
|
||||||
|
lightEnvBuffer->updateContents(BulkResourceData{
|
||||||
|
.size = sizeof(LightEnv),
|
||||||
|
.data = (uint8*) & lightEnv,
|
||||||
|
});
|
||||||
|
directionalLights->updateContents(BulkResourceData{
|
||||||
|
.size = sizeof(Component::DirectionalLight) * dirs.size(),
|
||||||
|
.data = (uint8*)dirs.data(),
|
||||||
|
});
|
||||||
|
pointLights->updateContents(BulkResourceData{
|
||||||
|
.size = sizeof(Component::PointLight) * points.size(),
|
||||||
|
.data = (uint8*)points.data(),
|
||||||
|
});
|
||||||
|
set->updateBuffer(0, lightEnvBuffer);
|
||||||
|
set->updateBuffer(1, directionalLights);
|
||||||
|
set->updateBuffer(2, pointLights);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
#define MAX_DIRECTIONAL_LIGHTS 4
|
#define MAX_DIRECTIONAL_LIGHTS 4
|
||||||
#define MAX_POINT_LIGHTS 256
|
#define MAX_POINT_LIGHTS 256
|
||||||
|
struct LightEnv
|
||||||
|
{
|
||||||
|
uint32 numDirectionalLights;
|
||||||
|
uint32 numPointLights;
|
||||||
|
} lightEnv;
|
||||||
Gfx::PShaderBuffer directionalLights;
|
Gfx::PShaderBuffer directionalLights;
|
||||||
Gfx::PUniformBuffer numDirectional;
|
Gfx::PUniformBuffer lightEnvBuffer;
|
||||||
Gfx::PShaderBuffer pointLights;
|
Gfx::PShaderBuffer pointLights;
|
||||||
Gfx::PUniformBuffer numPoints;;
|
|
||||||
Array<Component::DirectionalLight> dirs;
|
Array<Component::DirectionalLight> dirs;
|
||||||
Array<Component::PointLight> points;
|
Array<Component::PointLight> points;
|
||||||
Gfx::PDescriptorLayout layout;
|
Gfx::PDescriptorLayout layout;
|
||||||
|
|||||||
@@ -15,29 +15,8 @@ using namespace Seele;
|
|||||||
Scene::Scene(Gfx::PGraphics graphics)
|
Scene::Scene(Gfx::PGraphics graphics)
|
||||||
: graphics(graphics)
|
: graphics(graphics)
|
||||||
, physics(registry)
|
, physics(registry)
|
||||||
|
, lightEnv(new LightEnvironment(graphics))
|
||||||
{
|
{
|
||||||
ShaderBufferCreateInfo structInfo = {
|
|
||||||
.resourceData = {
|
|
||||||
.size = sizeof(Component::DirectionalLight) * MAX_DIRECTIONAL_LIGHTS,
|
|
||||||
.data = nullptr,
|
|
||||||
},
|
|
||||||
.stride = sizeof(Component::DirectionalLight),
|
|
||||||
.bDynamic = true,
|
|
||||||
};
|
|
||||||
lightEnv.directionalLights = graphics->createShaderBuffer(structInfo);
|
|
||||||
structInfo.resourceData.size = sizeof(Component::PointLight) * MAX_POINT_LIGHTS;
|
|
||||||
structInfo.stride = sizeof(Component::PointLight);
|
|
||||||
lightEnv.pointLights = graphics->createShaderBuffer(structInfo);
|
|
||||||
|
|
||||||
UniformBufferCreateInfo uniformInfo = {
|
|
||||||
.resourceData = {
|
|
||||||
.size = sizeof(uint32),
|
|
||||||
.data = nullptr
|
|
||||||
},
|
|
||||||
.bDynamic = true
|
|
||||||
};
|
|
||||||
lightEnv.numDirectional = graphics->createUniformBuffer(uniformInfo);
|
|
||||||
lightEnv.numPoints = graphics->createUniformBuffer(uniformInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene()
|
Scene::~Scene()
|
||||||
@@ -49,35 +28,3 @@ void Scene::update(float deltaTime)
|
|||||||
physics.update(deltaTime);
|
physics.update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
LightEnv Scene::getLightBuffer()
|
|
||||||
{
|
|
||||||
StaticArray<Component::DirectionalLight, MAX_DIRECTIONAL_LIGHTS> dirLights;
|
|
||||||
uint32 numDirLights = 0;
|
|
||||||
for(auto&& [entity, light] : registry.view<Component::DirectionalLight>().each())
|
|
||||||
{
|
|
||||||
dirLights[numDirLights++] = light;
|
|
||||||
}
|
|
||||||
lightEnv.directionalLights->updateContents({
|
|
||||||
.size = sizeof(Component::DirectionalLight) * numDirLights,
|
|
||||||
.data = (uint8*)dirLights.data(),
|
|
||||||
});
|
|
||||||
lightEnv.numDirectional->updateContents({
|
|
||||||
.size = sizeof(uint32),
|
|
||||||
.data = (uint8*)&numDirLights,
|
|
||||||
});
|
|
||||||
StaticArray<Component::PointLight, MAX_POINT_LIGHTS> pointLights;
|
|
||||||
uint32 numPointLights = 0;
|
|
||||||
for(auto&& [entity, light] : registry.view<Component::PointLight>().each())
|
|
||||||
{
|
|
||||||
pointLights[numPointLights++] = light;
|
|
||||||
}
|
|
||||||
lightEnv.pointLights->updateContents({
|
|
||||||
.size = sizeof(Component::PointLight) * numPointLights,
|
|
||||||
.data = (uint8*)pointLights.data(),
|
|
||||||
});
|
|
||||||
lightEnv.numPoints->updateContents({
|
|
||||||
.size = sizeof(uint32),
|
|
||||||
.data = (uint8*)&numPointLights,
|
|
||||||
});
|
|
||||||
return lightEnv;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user