From d4eb502460a8e0c30a83d9e356401dd279c0c376 Mon Sep 17 00:00:00 2001 From: JC Date: Sun, 23 Jun 2024 03:49:30 -0700 Subject: [PATCH] uniform buffer for grass shader parameters --- application/lucre/models/assets | 2 +- .../lucre/sceneDescriptions/terrain.json | 2 +- .../terrainDescriptions/lucre island.json | 4 +- engine/platform/Vulkan/VKrenderer.cpp | 1 + .../platform/Vulkan/VKresourceDescriptor.cpp | 26 ++++++++++--- engine/platform/Vulkan/shaders/grass.vert | 24 ++++++------ engine/platform/Vulkan/shaders/pbrSA.vert | 2 +- engine/renderer/builder/terrainBuilder.cpp | 37 +++++++++++++------ engine/scene/resource.h | 1 + engine/scene/terrain.h | 10 +++++ engine/scene/terrainLoaderDeserializeJSON.cpp | 10 +++++ 11 files changed, 87 insertions(+), 32 deletions(-) diff --git a/application/lucre/models/assets b/application/lucre/models/assets index d3b5d315..a882290a 160000 --- a/application/lucre/models/assets +++ b/application/lucre/models/assets @@ -1 +1 @@ -Subproject commit d3b5d315fcfc99ea279240b8625bbf6b34ca77b7 +Subproject commit a882290a95be3c676938cc268ab38582b7573a52 diff --git a/application/lucre/sceneDescriptions/terrain.json b/application/lucre/sceneDescriptions/terrain.json index f359f390..4b50c905 100644 --- a/application/lucre/sceneDescriptions/terrain.json +++ b/application/lucre/sceneDescriptions/terrain.json @@ -343,7 +343,7 @@ ], "translation": [ - -0.745493, 2.37433, -0.536219 + -0.745493, 2.329, -0.536219 ] } } diff --git a/application/lucre/terrainDescriptions/lucre island.json b/application/lucre/terrainDescriptions/lucre island.json index a4480641..ce682ae8 100644 --- a/application/lucre/terrainDescriptions/lucre island.json +++ b/application/lucre/terrainDescriptions/lucre island.json @@ -27,6 +27,8 @@ [ 4.37885, -1.14346, 59.3405 ] - } + }, + "scaleXZ": 5.0, + "scaleY": 7.0 } } diff --git a/engine/platform/Vulkan/VKrenderer.cpp b/engine/platform/Vulkan/VKrenderer.cpp index eea76e9d..e7838d62 100644 --- a/engine/platform/Vulkan/VKrenderer.cpp +++ b/engine/platform/Vulkan/VKrenderer.cpp @@ -154,6 +154,7 @@ namespace GfxRenderEngine .AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT) // shader data for instances .AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT) // dummy .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT) // shader data for height map + .AddBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT) // shader parameters .Build(); std::unique_ptr instanceDescriptorSetLayout = diff --git a/engine/platform/Vulkan/VKresourceDescriptor.cpp b/engine/platform/Vulkan/VKresourceDescriptor.cpp index b73ab830..baf3ddc1 100644 --- a/engine/platform/Vulkan/VKresourceDescriptor.cpp +++ b/engine/platform/Vulkan/VKresourceDescriptor.cpp @@ -35,6 +35,7 @@ namespace GfxRenderEngine auto& instBuffer = buffers[Resources::INSTANCE_BUFFER_INDEX]; auto& skelBuffer = buffers[Resources::SKELETAL_ANIMATION_BUFFER_INDEX]; auto& hBuffer = buffers[Resources::HEIGHTMAP]; + auto& mPurposeBuffer = buffers[Resources::MULTI_PURPOSE_BUFFER]; // instance buffer std::shared_ptr& instanceUbo = instBuffer ? instBuffer : gDummyBuffer; @@ -51,35 +52,48 @@ namespace GfxRenderEngine VK_Buffer* heightmapBuffer = static_cast(heightmapUbo.get()); VkDescriptorBufferInfo heightmapBufferInfo = heightmapBuffer->DescriptorInfo(); + // multi purpose + std::shared_ptr& multiPurposeUbo = mPurposeBuffer ? mPurposeBuffer : gDummyBuffer; + VK_Buffer* multiPurposeBuffer = static_cast(multiPurposeUbo.get()); + VkDescriptorBufferInfo multiPurposeBufferInfo = multiPurposeBuffer->DescriptorInfo(); + { VK_DescriptorSetLayout::Builder builder{}; - if (instBuffer || skelBuffer || hBuffer) + if (instBuffer || skelBuffer || hBuffer || mPurposeBuffer) { builder.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); } - if (skelBuffer || hBuffer) + if (skelBuffer || hBuffer || mPurposeBuffer) { builder.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); } - if (hBuffer) + if (hBuffer || mPurposeBuffer) { builder.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); } + if (mPurposeBuffer) + { + builder.AddBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); + } std::unique_ptr localDescriptorSetLayout = builder.Build(); VK_DescriptorWriter descriptorWriter(*localDescriptorSetLayout, *VK_Renderer::m_DescriptorPool); - if (instBuffer || skelBuffer || hBuffer) + if (instBuffer || skelBuffer || hBuffer || mPurposeBuffer) { descriptorWriter.WriteBuffer(0, instanceBufferInfo); } - if (skelBuffer || hBuffer) + if (skelBuffer || hBuffer || mPurposeBuffer) { descriptorWriter.WriteBuffer(1, skeletalAnimationBufferInfo); } - if (hBuffer) + if (hBuffer || mPurposeBuffer) { descriptorWriter.WriteBuffer(2, heightmapBufferInfo); } + if (mPurposeBuffer) + { + descriptorWriter.WriteBuffer(3, multiPurposeBufferInfo); + } descriptorWriter.Build(m_DescriptorSet); } diff --git a/engine/platform/Vulkan/shaders/grass.vert b/engine/platform/Vulkan/shaders/grass.vert index 6f913c46..ce60ca90 100644 --- a/engine/platform/Vulkan/shaders/grass.vert +++ b/engine/platform/Vulkan/shaders/grass.vert @@ -61,19 +61,22 @@ layout(set = 0, binding = 0) uniform GlobalUniformBuffer int m_NumberOfActiveDirectionalLights; } ubo; +layout(set = 2, binding = 3) uniform ParameterBuffer +{ + int m_Width; + int m_Height; // not used, + float m_ScaleXZ; + float m_ScaleY; +} parameters; + layout(set = 2, binding = 0) uniform InstanceUniformBuffer { InstanceData m_InstanceData; } baseTransform; -#define WIDTH 512 // row -#define HEIGHT 375 // col -#define NUM_HEIGHT_VALUES WIDTH*HEIGHT // 192000 -#define INSTANCE_COUNT NUM_HEIGHT_VALUES - layout(set = 2, binding = 2) readonly buffer HeightMap { - int m_HeightMapData[INSTANCE_COUNT]; + int m_HeightMapData[1]; // actual array size is larger than 1 } heightMap; layout(location = 0) out vec3 fragPosition; @@ -89,14 +92,14 @@ void main() int index = gl_InstanceIndex; float hgt = heightMap.m_HeightMapData[index]; - float row = floor(index / WIDTH); - float col = floor((index - WIDTH * row)); + float row = floor(index / parameters.m_Width); + float col = floor((index - parameters.m_Width * row)); float theta = sin(hgt+gl_InstanceIndex); // random float s = sin(theta); // sine float c = cos(theta); // cosine - float sclXZ = 5.0; - float sclY = 5.0; + float sclXZ = parameters.m_ScaleXZ; + float sclY = parameters.m_ScaleY; mat4 translation = mat4 ( @@ -138,7 +141,6 @@ void main() 1.0 ) // fourth column ); - mat4 scale = mat4 ( vec4( sclXZ, diff --git a/engine/platform/Vulkan/shaders/pbrSA.vert b/engine/platform/Vulkan/shaders/pbrSA.vert index d5b232b8..5c74b3d7 100644 --- a/engine/platform/Vulkan/shaders/pbrSA.vert +++ b/engine/platform/Vulkan/shaders/pbrSA.vert @@ -111,7 +111,7 @@ void main() gl_Position = ubo.m_Projection * ubo.m_View * positionWorld; fragPosition = positionWorld.xyz; - mat3 normalMatrix = transpose(inverse(mat3(instanceNormalMatrix) * mat3(jointTransform))); + mat3 normalMatrix = transpose(inverse(mat3(modelMatrix) * mat3(jointTransform))); fragNormal = normalize(normalMatrix * normal); fragTangent = normalize(normalMatrix * tangent); diff --git a/engine/renderer/builder/terrainBuilder.cpp b/engine/renderer/builder/terrainBuilder.cpp index 728f1da4..4d6653da 100644 --- a/engine/renderer/builder/terrainBuilder.cpp +++ b/engine/renderer/builder/terrainBuilder.cpp @@ -293,19 +293,34 @@ namespace GfxRenderEngine uint heightMapSize = heightMap.Size(); Resources::ResourceBuffers resourceBuffers; { - // unforunately, need to copy one buffer into another (glsl does not support uint8_t by default) - std::vector bufferData(heightMapSize); - for (uint index = 0; index < heightMapSize; ++index) + { // unforunately, need to copy one buffer into another (glsl does not support uint8_t by default) + std::vector bufferData(heightMapSize); + for (uint index = 0; index < heightMapSize; ++index) + { + bufferData[index] = heightMap[index]; + } + int bufferSize = heightMapSize * sizeof(int); // in bytes + auto& ubo = resourceBuffers[Resources::HEIGHTMAP]; + ubo = Buffer::Create(bufferSize, Buffer::BufferUsage::STORAGE_BUFFER_VISIBLE_TO_CPU); + ubo->MapBuffer(); + // update ubo + ubo->WriteToBuffer(bufferData.data()); + ubo->Flush(); + } + { - bufferData[index] = heightMap[index]; + Terrain::GrassParameters grassParameters{.m_Width = heightMap.Width(), + .m_Height = heightMap.Height(), + .m_ScaleXZ = grassSpec.m_ScaleXZ, + .m_ScaleY = grassSpec.m_ScaleY}; + int bufferSize = sizeof(Terrain::GrassParameters); + auto& ubo = resourceBuffers[Resources::MULTI_PURPOSE_BUFFER]; + ubo = Buffer::Create(bufferSize, Buffer::BufferUsage::UNIFORM_BUFFER_VISIBLE_TO_CPU); + ubo->MapBuffer(); + // update ubo + ubo->WriteToBuffer(&grassParameters); + ubo->Flush(); } - int bufferSize = heightMapSize * sizeof(int); // in bytes - auto& ubo = resourceBuffers[Resources::HEIGHTMAP]; - ubo = Buffer::Create(bufferSize, Buffer::BufferUsage::STORAGE_BUFFER_VISIBLE_TO_CPU); - resourceBuffers[Resources::HEIGHTMAP]->MapBuffer(); - // update ubo - ubo->WriteToBuffer(bufferData.data()); - ubo->Flush(); FastgltfBuilder builder(grassSpec.m_FilepathGrassModel, scene, &resourceBuffers); builder.Load(1 /*1 instance in scene graph (grass has the instance count in the tag)*/); diff --git a/engine/scene/resource.h b/engine/scene/resource.h index aee48cdd..8c39b97e 100644 --- a/engine/scene/resource.h +++ b/engine/scene/resource.h @@ -39,6 +39,7 @@ namespace GfxRenderEngine INSTANCE_BUFFER_INDEX = 0, SKELETAL_ANIMATION_BUFFER_INDEX, HEIGHTMAP, + MULTI_PURPOSE_BUFFER, NUM_BUFFERS }; diff --git a/engine/scene/terrain.h b/engine/scene/terrain.h index a8a983aa..4d1445d4 100644 --- a/engine/scene/terrain.h +++ b/engine/scene/terrain.h @@ -39,6 +39,14 @@ namespace GfxRenderEngine Instance(entt::entity entity) : m_Entity{entity} {} }; + struct GrassParameters + { + int m_Width; + int m_Height; // not used, + float m_ScaleXZ; + float m_ScaleY; + }; + struct TerrainDescription { std::string m_Filename; @@ -54,6 +62,8 @@ namespace GfxRenderEngine glm::vec3 m_Translation{}; glm::vec3 m_Rotation{}; glm::vec3 m_Scale{}; + float m_ScaleXZ{1.0f}; + float m_ScaleY{1.0f}; }; struct TerrainSpec diff --git a/engine/scene/terrainLoaderDeserializeJSON.cpp b/engine/scene/terrainLoaderDeserializeJSON.cpp index 5296e03c..35d8af1b 100644 --- a/engine/scene/terrainLoaderDeserializeJSON.cpp +++ b/engine/scene/terrainLoaderDeserializeJSON.cpp @@ -182,6 +182,16 @@ namespace GfxRenderEngine ondemand::object transformJSON = grassAttribute.value().get_object(); ParseTransform(transformJSON); } + else if (grassAttributeKey == "scaleXZ") + { + CORE_ASSERT((grassAttribute.value().type() == ondemand::json_type::number), "type must be number"); + grassSpec.m_ScaleXZ = grassAttribute.value().get_double(); + } + else if (grassAttributeKey == "scaleY") + { + CORE_ASSERT((grassAttribute.value().type() == ondemand::json_type::number), "type must be number"); + grassSpec.m_ScaleY = grassAttribute.value().get_double(); + } else { LOG_CORE_CRITICAL("unrecognized grass attribute");