From bf8a2f9642c63f813d0e1f038309562cc35d8b1a Mon Sep 17 00:00:00 2001 From: JC Date: Sat, 8 Jun 2024 17:43:59 -0700 Subject: [PATCH] instancing for terrain --- .../lucre/sceneDescriptions/terrain.json | 35 +++++- .../lucre/terrainDescriptions/heightmap.json | 6 + engine/renderer/builder/terrainBuilder.cpp | 118 ++++++++++-------- engine/scene/sceneLoaderDeserializeJSON.cpp | 14 +-- 4 files changed, 108 insertions(+), 65 deletions(-) create mode 100644 application/lucre/terrainDescriptions/heightmap.json diff --git a/application/lucre/sceneDescriptions/terrain.json b/application/lucre/sceneDescriptions/terrain.json index f93a048f..01840d91 100644 --- a/application/lucre/sceneDescriptions/terrain.json +++ b/application/lucre/sceneDescriptions/terrain.json @@ -13,15 +13,15 @@ { "scale": [ - 0.141, 0.141, 0.141 + 0.054, 0.054, 0.054 ], "rotation": [ - 3.14159, 1.07215, 3.14159 + 0, 0, 0 ], "translation": [ - -0.779968, 2.25822, -4 + -0.576, 2.33, -0.117 ] } }, @@ -30,15 +30,38 @@ { "scale": [ - 0.140998, 0.140998, 0.140998 + 0.219, 0.392, 0.219 ], "rotation": [ - 3.01614, 1.00771, 2.99355 + 0, 0, 0 ], "translation": [ - -0.494322, 2.28222, -3.408 + -4.807, 0.942, -11.044 + ] + } + } + ] + }, + { + "filename": "application/lucre/terrainDescriptions/heightmap.json", + "instances": + [ + { + "transform": + { + "scale": + [ + 0.219, 0.392, 0.219 + ], + "rotation": + [ + 0, 0.523, 0 + ], + "translation": + [ + -10.523, 0.942, -2.375 ] } } diff --git a/application/lucre/terrainDescriptions/heightmap.json b/application/lucre/terrainDescriptions/heightmap.json new file mode 100644 index 00000000..b729884a --- /dev/null +++ b/application/lucre/terrainDescriptions/heightmap.json @@ -0,0 +1,6 @@ +{ + "file format identifier": 1.2, + "description": "height map 2", + "author": "Copyright (c) 2024 Engine Development Team", + "terrainPngPath": "application/lucre/models/assets/terrain/heightmap.png" +} diff --git a/engine/renderer/builder/terrainBuilder.cpp b/engine/renderer/builder/terrainBuilder.cpp index 91e4c09f..91b553d4 100644 --- a/engine/renderer/builder/terrainBuilder.cpp +++ b/engine/renderer/builder/terrainBuilder.cpp @@ -23,6 +23,7 @@ #include "core.h" #include "renderer/builder/terrainBuilder.h" +#include "auxiliary/file.h" #include "scene/scene.h" #include "stb_image.h" @@ -121,7 +122,9 @@ namespace GfxRenderEngine { m_Vertices.clear(); m_Indices.clear(); + m_Submeshes.clear(); int width, height, bytesPerPixel; + stbi_set_flip_vertically_on_load(false); uchar* localBuffer = stbi_load(filepath.c_str(), &width, &height, &bytesPerPixel, 0); if (localBuffer) { @@ -137,67 +140,78 @@ namespace GfxRenderEngine PopulateTerrainData(terrainData); - // create game object - entt::entity entity; - std::shared_ptr instanceBuffer; + // create game objects for all instances { auto& registry = scene.GetRegistry(); auto& sceneGraph = scene.GetSceneGraph(); auto& dictionary = scene.GetDictionary(); - // create game object - entity = registry.create(); - TransformComponent transform{}; - PbrMaterialTag pbrMaterialTag{}; + auto name = EngineCore::GetFilenameWithoutPath(filepath); + name = EngineCore::GetFilenameWithoutExtension(name); InstanceTag instanceTag; - // create instance buffer - instanceTag.m_Instances.push_back(entity); - const uint numberOfInstances = instanceCount; - const uint indexOfFirstInstance = 0; - instanceBuffer = InstanceBuffer::Create(numberOfInstances); - instanceTag.m_InstanceBuffer = instanceBuffer; - instanceTag.m_InstanceBuffer->SetInstanceData(indexOfFirstInstance, transform.GetMat4Global(), - transform.GetNormalMatrix()); - transform.SetInstance(instanceTag.m_InstanceBuffer, indexOfFirstInstance); - - // push into ECS - registry.emplace(entity, transform); - registry.emplace(entity, pbrMaterialTag); - registry.emplace(entity, instanceTag); - - // add to scene graph - uint newNode = sceneGraph.CreateNode(entity, "terrain", "terrain", dictionary); - sceneGraph.GetRoot().AddChild(newNode); - - Submesh submesh{}; - submesh.m_FirstIndex = 0; - submesh.m_FirstVertex = 0; - submesh.m_IndexCount = m_Indices.size(); - submesh.m_VertexCount = m_Vertices.size(); - submesh.m_InstanceCount = 1; - - submesh.m_Material.m_PbrMaterial.m_Roughness = 0.1f; - submesh.m_Material.m_PbrMaterial.m_Metallic = 0.9f; - submesh.m_Material.m_PbrMaterial.m_NormalMapIntensity = 1.0f; - - { // create material descriptor - Material::MaterialTextures materialTextures; - - auto materialDescriptor = MaterialDescriptor::Create(MaterialDescriptor::MtPbr, materialTextures); - submesh.m_Material.m_MaterialDescriptor = materialDescriptor; - } - { // create resource descriptor - Resources::ResourceBuffers resourceBuffers; + for (int instanceIndex = 0; instanceIndex < instanceCount; ++instanceIndex) + { + // create game object + entt::entity entity = registry.create(); + std::shared_ptr model; + TransformComponent transform{}; + instanceTag.m_Instances.push_back(entity); + + // add to scene graph + auto instanceStr = std::to_string(instanceIndex); + auto shortName = name + "::" + instanceStr; + auto longName = filepath + "::" + instanceStr; + uint newNode = sceneGraph.CreateNode(entity, shortName, longName, dictionary); + sceneGraph.GetRoot().AddChild(newNode); + + // only for the 1st instance + if (!instanceIndex) + { + // create instance buffer + instanceTag.m_InstanceBuffer = InstanceBuffer::Create(instanceCount); + registry.emplace(entity, instanceTag); + + Submesh submesh{}; + submesh.m_FirstIndex = 0; + submesh.m_FirstVertex = 0; + submesh.m_IndexCount = m_Indices.size(); + submesh.m_VertexCount = m_Vertices.size(); + submesh.m_InstanceCount = instanceCount; + + submesh.m_Material.m_PbrMaterial.m_Roughness = 0.1f; + submesh.m_Material.m_PbrMaterial.m_Metallic = 0.9f; + submesh.m_Material.m_PbrMaterial.m_NormalMapIntensity = 1.0f; + + { // create material descriptor + Material::MaterialTextures materialTextures; + + auto materialDescriptor = + MaterialDescriptor::Create(MaterialDescriptor::MtPbr, materialTextures); + submesh.m_Material.m_MaterialDescriptor = materialDescriptor; + } + { // create resource descriptor + Resources::ResourceBuffers resourceBuffers; + + resourceBuffers[Resources::INSTANCE_BUFFER_INDEX] = instanceTag.m_InstanceBuffer->GetBuffer(); + auto resourceDescriptor = ResourceDescriptor::Create(resourceBuffers); + submesh.m_Resources.m_ResourceDescriptor = resourceDescriptor; + } + m_Submeshes.push_back(submesh); + model = Engine::m_Engine->LoadModel(*this); + + PbrMaterialTag pbrMaterialTag{}; + registry.emplace(entity, pbrMaterialTag); + } + + instanceTag.m_InstanceBuffer->SetInstanceData(instanceIndex, transform.GetMat4Global(), + transform.GetNormalMatrix()); + transform.SetInstance(instanceTag.m_InstanceBuffer, instanceIndex); + registry.emplace(entity, transform); - resourceBuffers[Resources::INSTANCE_BUFFER_INDEX] = instanceBuffer->GetBuffer(); - auto resourceDescriptor = ResourceDescriptor::Create(resourceBuffers); - submesh.m_Resources.m_ResourceDescriptor = resourceDescriptor; + MeshComponent mesh{shortName, model}; + registry.emplace(entity, mesh); } - m_Submeshes.push_back(submesh); - auto model = Engine::m_Engine->LoadModel(*this); - MeshComponent mesh{"terrain", model}; - registry.emplace(entity, mesh); } return true; diff --git a/engine/scene/sceneLoaderDeserializeJSON.cpp b/engine/scene/sceneLoaderDeserializeJSON.cpp index dc851b6c..bc8ddb9f 100644 --- a/engine/scene/sceneLoaderDeserializeJSON.cpp +++ b/engine/scene/sceneLoaderDeserializeJSON.cpp @@ -586,25 +586,25 @@ namespace GfxRenderEngine bool loadSuccessful = terrainLoaderJSON.Deserialize(filename, instanceCount); if (!loadSuccessful) - { - Terrain::TerrainDescription terrainDescriptionScene(filename); - terrainDescriptions.push_back(terrainDescriptionScene); - } - else { LOG_CORE_CRITICAL("terrain description did not load properly: {0}", filename); return; } + Terrain::TerrainDescription terrainDescriptionScene(filename); + terrainDescriptions.push_back(terrainDescriptionScene); + std::vector& terrainInstances = terrainDescriptions.back().m_Instances; terrainInstances.resize(instanceCount); { + auto name = EngineCore::GetFilenameWithoutPath(filename); + name = EngineCore::GetFilenameWithoutExtension(name); uint instanceIndex = 0; for (auto instance : instances) { - std::string fullEntityName = filename + std::string("::" + std::to_string(instanceIndex)); - entt::entity entity = m_Scene.m_Dictionary.Retrieve(fullEntityName); + std::string entityName = name + std::string("::" + std::to_string(instanceIndex)); + entt::entity entity = m_Scene.m_Dictionary.Retrieve(entityName); Terrain::Instance& terrainInstance = terrainInstances[instanceIndex]; terrainInstance.m_Entity = entity; ondemand::object instanceObjects = instance.value();