Now PBR directional

This commit is contained in:
antopilo
2025-01-09 22:40:16 -05:00
parent 194b81e114
commit 5a0686bd17
12 changed files with 254 additions and 37 deletions

View File

@@ -21,7 +21,7 @@ namespace Nuake
LightComponent light;
};
struct LightData
struct LightDatas
{
int ShadowMapsIDs[4];
float CascadeDepth[4];

View File

@@ -18,6 +18,11 @@
namespace Nuake
{
struct LightResource
{
};
class GPUResources
{
private:
@@ -25,6 +30,7 @@ namespace Nuake
std::map<UUID, Ref<AllocatedBuffer>> Buffers;
std::map<UUID, Ref<VkMesh>> Meshes;
std::map<UUID, Ref<VulkanImage>> Images;
std::map<UUID, Ref<VulkanImage>> Light;
// Bindless buffer layouts
VkDescriptorSetLayout CameraDescriptorLayout;
@@ -34,11 +40,13 @@ namespace Nuake
VkDescriptorSetLayout SamplerDescriptorLayout;
VkDescriptorSetLayout MaterialDescriptorLayout;
VkDescriptorSetLayout TexturesDescriptorLayout;
VkDescriptorSetLayout LightsDescriptorLayout;
VkDescriptorSet CameraDescriptor;
VkDescriptorSet ModelDescriptor;
VkDescriptorSet SamplerDescriptor;
VkDescriptorSet MaterialDescriptor;
VkDescriptorSet LightsDescriptor;
std::map<UUID, uint32_t> BindlessTextureMapping;

View File

@@ -310,6 +310,7 @@ void VkRenderer::InitCommands()
Frames[i].CameraStagingBuffer = resources.CreateBuffer(sizeof(CameraData), BufferUsage::TRANSFER_SRC, MemoryUsage::CPU_ONLY, "CameraStaging" + std::to_string(i) );
Frames[i].ModelStagingBuffer = resources.CreateBuffer(sizeof(Matrix4) * MAX_MODEL_MATRIX, BufferUsage::TRANSFER_SRC, MemoryUsage::CPU_ONLY, "TransformStaging" + std::to_string(i));
Frames[i].MaterialStagingBuffer = resources.CreateBuffer(sizeof(MaterialBufferStruct) * MAX_MATERIAL, BufferUsage::TRANSFER_SRC, MemoryUsage::CPU_ONLY, "MaterialStaging" + std::to_string(i));
Frames[i].LightStagingBuffer = resources.CreateBuffer(sizeof(LightData) * MAX_LIGHTS, BufferUsage::TRANSFER_SRC, MemoryUsage::CPU_ONLY, "LightStaging" + std::to_string(i));
}
VK_CALL(vkCreateCommandPool(Device, &cmdPoolInfo, nullptr, &ImguiCommandPool));
@@ -904,6 +905,7 @@ void VkRenderer::UploadCameraData(const CameraData& data)
adjustedData.View = Matrix4(1.0f); //data.View;
adjustedData.View = data.View;
adjustedData.Projection = glm::perspective(glm::radians(70.f), (float)DrawExtent.width / (float)DrawExtent.height, 0.0001f, 10000.0f);
adjustedData.Position = data.View[3];
//adjustedData.Projection[1][1] *= -1;
void* mappedData;

View File

@@ -86,6 +86,7 @@ namespace Nuake
Ref<AllocatedBuffer> CameraStagingBuffer; // Current camera
Ref<AllocatedBuffer> ModelStagingBuffer; // Matrices
Ref<AllocatedBuffer> MaterialStagingBuffer; // Materials
Ref<AllocatedBuffer> LightStagingBuffer; // Lights
// Semaphore are for GPU -> GPU sync
// Fence are for CPU -> GPU
@@ -121,6 +122,7 @@ namespace Nuake
Matrix4 Projection;
Matrix4 InvView;
Matrix4 InvProjection;
Vector3 Position;
};
// Renderer configuration
@@ -128,7 +130,7 @@ namespace Nuake
constexpr uint32_t MAX_MODEL_MATRIX = 3000;
constexpr uint32_t MAX_MATERIAL = 1000;
constexpr uint32_t MAX_TEXTURES = 500;
constexpr uint32_t MAX_LIGHTS = 100;
class VkRenderer
{
private:

View File

@@ -172,6 +172,13 @@ void GPUResources::CreateBindlessLayout()
TexturesDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
// bindless lights
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
LightsDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
TextureDescriptor = VkRenderer::Get().GetDescriptorAllocator().Allocate(VkRenderer::Get().GetDevice(), TexturesDescriptorLayout);
}
@@ -211,7 +218,8 @@ std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
TriangleBufferDescriptorLayout,
SamplerDescriptorLayout,
MaterialDescriptorLayout,
TexturesDescriptorLayout
TexturesDescriptorLayout,
LightsDescriptorLayout
};
return layouts;
}

View File

@@ -114,7 +114,6 @@ void VkSceneRenderer::CreateBuffers()
camData.Projection = Matrix4(1.0f);
camData.InvView = Matrix4(1.0f);
camData.InvProjection = Matrix4(1.0f);
// init camera buffer
GPUResources& resources = GPUResources::Get();
CameraBuffer = resources.CreateBuffer(sizeof(CameraData), BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::GPU_ONLY, "CameraBuffer");
@@ -122,6 +121,7 @@ void VkSceneRenderer::CreateBuffers()
ModelBuffer = resources.CreateBuffer(sizeof(Matrix4) * MAX_MODEL_MATRIX, BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::GPU_ONLY, "TransformBuffer");
MaterialBuffer = resources.CreateBuffer(sizeof(MaterialBufferStruct) * MAX_MATERIAL, BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::GPU_ONLY, "MaterialBuffer");
LightBuffer = resources.CreateBuffer(sizeof(LightData) * MAX_LIGHTS, BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::GPU_ONLY, "LightBuffer");
}
void VkSceneRenderer::LoadShaders()
@@ -201,6 +201,13 @@ void VkSceneRenderer::CreateDescriptors()
TextureBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
// bindless lights
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
LightBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
auto allocator = vk.GetDescriptorAllocator();
TriangleBufferDescriptors = allocator.Allocate(device, TriangleBufferDescriptorLayout);
CameraBufferDescriptors = allocator.Allocate(device, CameraBufferDescriptorLayout);
@@ -208,6 +215,7 @@ void VkSceneRenderer::CreateDescriptors()
SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
MaterialBufferDescriptor = allocator.Allocate(device, MaterialBufferDescriptorLayout);
TextureBufferDescriptor = allocator.Allocate(device, TextureBufferDescriptorLayout);
LightBufferDescriptor = allocator.Allocate(device, LightBufferDescriptorLayout);
//SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
// Update descriptor set for camera
@@ -292,6 +300,17 @@ void VkSceneRenderer::CreatePipelines()
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
6, // firstSet
1, // descriptorSetCount
&LightBufferDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, &SamplerDescriptor, 0, nullptr);
});
gBufferPass.SetRender([&](PassRenderContext& ctx){
@@ -401,13 +420,23 @@ void VkSceneRenderer::CreatePipelines()
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
6, // firstSet
1, // descriptorSetCount
&LightBufferDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
auto& gpu = GPUResources::Get();
auto& gbufferPass = GBufferPipeline.GetRenderPass("GBuffer");
shadingPushConstant.AlbedoTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Albedo").Image->GetID());
shadingPushConstant.DepthTextureID = gpu.GetBindlessTextureID(gbufferPass.GetDepthAttachment().Image->GetID());
shadingPushConstant.NormalTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Normal").Image->GetID());
shadingPushConstant.MaterialTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Material").Image->GetID());
});
shadingPass.SetRender([](PassRenderContext& ctx) {
vkCmdPushConstants(
@@ -450,6 +479,7 @@ void VkSceneRenderer::UpdateCameraData(const CameraData& data)
adjustedData.Projection = data.Projection;
adjustedData.InvView = data.InvView;
adjustedData.InvProjection = data.InvProjection;
adjustedData.Position = data.InvView[3];
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().CameraStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &adjustedData, sizeof(CameraData));
@@ -534,8 +564,44 @@ void VkSceneRenderer::BuildMatrixBuffer()
currentIndex++;
}
currentIndex = 0;
LightData directionalLight = {};
directionalLight.castShadow = false;
directionalLight.color = Vector4(2.0f, 2.0f, 2.0f, 1.0f);
directionalLight.position = Vector3(0.0f, 0.0f, 0.0f);
directionalLight.type = LightType::Directional;
std::array<LightData, MAX_LIGHTS> allLights;
auto lightView = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : lightView)
{
// Check if we've reached the maximum capacity of the array
if (currentIndex >= MAX_LIGHTS)
{
assert(false);
break;
}
auto [transform, lightComp] = lightView.get<TransformComponent, LightComponent>(e);
Vector3 direction = transform.GetGlobalRotation() * Vector3(0, 0, -1);
LightData light = {};
light.position = Vector3(transform.GetGlobalTransform()[3]);
light.direction = direction;
light.outerConeAngle = glm::cos(Rad(lightComp.OuterCutoff));
light.innerConeAngle = glm::cos(Rad(lightComp.Cutoff));
light.type = lightComp.Type;
light.color = Vector4(lightComp.Color * lightComp.Strength, 1.0);
light.castShadow = lightComp.CastShadows;
allLights[currentIndex] = light;
currentIndex++;
}
ModelTransforms = ModelData{ allTransforms };
MaterialDataContainer = MaterialData{ allMaterials };
LightDataContainerArray = LightDataContainer{ allLights };
shadingPushConstant.LightCount = currentIndex;
}
void VkSceneRenderer::UpdateTransformBuffer()
@@ -608,5 +674,39 @@ void VkSceneRenderer::UpdateTransformBuffer()
bufferWrite.pImageInfo = VK_NULL_HANDLE;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWrite, 0, nullptr);
}
{
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &LightDataContainerArray, sizeof(LightDataContainer));
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd) {
VkBufferCopy copy{ 0 };
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = sizeof(LightDataContainer);
vkCmdCopyBuffer(cmd, VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetBuffer(), LightBuffer->GetBuffer(), 1, &copy);
});
vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetAllocation());
// Update descriptor set for camera
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = LightBuffer->GetBuffer();
bufferInfo.offset = 0;
bufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet bufferWrite = {};
bufferWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferWrite.pNext = nullptr;
bufferWrite.dstBinding = 0;
bufferWrite.dstSet = LightBufferDescriptor;
bufferWrite.descriptorCount = 1;
bufferWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWrite.pBufferInfo = &bufferInfo;
bufferWrite.pImageInfo = VK_NULL_HANDLE;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWrite, 0, nullptr);
}
}

View File

@@ -31,6 +31,7 @@ namespace Nuake
int DepthTextureID;
int NormalTextureID;
int MaterialTextureID;
int LightCount;
};
struct ModelData
@@ -63,6 +64,24 @@ namespace Nuake
std::array<MaterialBufferStruct, 1000> Data;
};
struct LightData
{
Vector3 position;
int type;
Vector4 color;
Vector3 direction;
float outerConeAngle;
float innerConeAngle;
bool castShadow;
int shadowMapTextureId;
int transformId;
};
struct LightDataContainer
{
std::array<LightData, 100> Data;
};
class VkSceneRenderer
{
private:
@@ -93,9 +112,15 @@ namespace Nuake
ModelData ModelTransforms;
MaterialData MaterialDataContainer;
LightDataContainer LightDataContainerArray;
std::map<UUID, uint32_t> ModelMatrixMapping; // Holds mapping between model entity and transform index
std::map<UUID, uint32_t> MeshMaterialMapping; // Holds mapping between mesh and material index
Ref<AllocatedBuffer> LightBuffer;
VkDescriptorSet LightBufferDescriptor;
VkDescriptorSetLayout LightBufferDescriptorLayout;
VkSampler SamplerLinear;
VkSampler SamplerNearest;
VkDescriptorSet SamplerDescriptor;

View File

@@ -9,7 +9,6 @@
#include "src/Rendering/Buffers/Framebuffer.h"
#include "VisibilityComponent.h"
#include "../Resource/Serializable.h"
#include <glm/ext/matrix_clip_space.hpp>
namespace Nuake

View File

@@ -4,6 +4,7 @@ struct Camera
float4x4 proj;
float4x4 invView;
float4x4 invProj;
float3 position;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -29,6 +30,22 @@ StructuredBuffer<Material> material;
[[vk::binding(0, 5)]]
Texture2D textures[]; // Array de 500 textures
struct Light
{
float3 position;
int type;
float4 color;
float3 direction;
float outerConeAngle;
float innerConeAngle;
bool castShadow;
int shadowMapTextureId;
int transformId;
};
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct PSInput {
float4 Position : SV_Position;
float2 UV : TEXCOORD0;
@@ -44,6 +61,7 @@ struct ShadingPushConstant
int DepthInputTextureId;
int NormalInputTextureId;
int MaterialInputTextureId;
int LightCount;
};
[[vk::push_constant]]
@@ -124,54 +142,57 @@ PSOutput main(PSInput input)
int depthTexture = pushConstants.DepthInputTextureId;
float depth = textures[depthTexture].Sample(mySampler, input.UV).r;
float3 worldPosition = WorldPosFromDepth(depth, input.UV, camData.invProj, camData.invView);
float3 worldPos = WorldPosFromDepth(depth, input.UV, camData.invProj, camData.invView);
int albedoTextureId = pushConstants.AlbedoInputTextureId;
float3 albedo = textures[albedoTextureId].Sample(mySampler, input.UV).xyz;
float3 normal = textures[pushConstants.NormalInputTextureId].Sample(mySampler, input.UV).rgb;
//output.oColor0 = float4(normal, 1);
//return output//;
//
normal = normal * 2.0f - 1.0f;
float4 materialSample = textures[pushConstants.MaterialInputTextureId].Sample(mySampler, input.UV);
float metallic = materialSample.r;
float ao = materialSample.g;
float roughness = materialSample.b;
float3 eyePosition = camData.view[3].xyz;
float3 N = normal;
float3 V = normalize(eyePosition - worldPosition);
float3 V = normalize(camData.position - worldPos);
float3 R = reflect(-V, N);
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);
const float PI = 3.141592653589793f;
float3 Lo = float3(0.0, 0.0, 0.0);
// Directional light
float3 dir = normalize(float3(0.1, 1.0, 0.1f));
float attenuation = 1.0f;
// Directional
{
Light light = lights[0];
float3 L = normalize(light.direction);
float attenuation = 1.0f;
float3 L = dir;
float3 radiance = float3(1, 1, 1) * attenuation;
float3 H = normalize(V + L);
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
float3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
float3 nominator = NDF * G * F;
float denominator = 4 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; // 0.001 to prevent divide by zero.
float3 specular = nominator / denominator;
// TODO: Shadow
float3 radiance = light.color.rgb * attenuation;
float3 H = normalize(V + L);
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
float3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
float3 nominator = NDF * G * F;
float denominator = 4 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; // 0.001 to prevent divide by zero.
float3 specular = nominator / denominator;
float3 kS = F;
float3 kD = float3(1.0, 1.0, 1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
}
float3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);
float3 kS = F;
float3 kD = float3(3.0, 3.0, 3.0) - kS;
float3 kD = 1.0 - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
const float PI = 3.141592653589793f;
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
float3 ambient = (albedo) * ao * 0.5f;
float3 ambient = (albedo) * ao * 0.5f;
float3 color = (ambient) + Lo;
output.oColor0 = float4(color, 1);

View File

@@ -4,6 +4,7 @@ struct Camera
float4x4 proj;
float4x4 invView;
float4x4 invProj;
float3 position;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -28,12 +29,29 @@ struct Vertex
[[vk::binding(0, 2)]]
StructuredBuffer<Vertex> vertexBuffer : register(t2);
struct Light
{
float3 position;
int type;
float4 color;
float3 direction;
float outerConeAngle;
float innerConeAngle;
bool castShadow;
int shadowMapTextureId;
int transformId;
};
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct ShadingPushConstant
{
int AlbedoInputTextureId;
int DepthInputTextureId;
int NormalInputTextureId;
int MaterialInputTextureId;
int LightCount;
};
[[vk::push_constant]]

View File

@@ -4,6 +4,7 @@ struct Camera
float4x4 proj;
float4x4 invView;
float4x4 invProj;
float3 position;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -35,6 +36,22 @@ StructuredBuffer<Material> material; // array de 2000 materials
[[vk::binding(0, 5)]]
Texture2D textures[]; // Array de 500 textures
struct Light
{
float3 position;
int type;
float4 color;
float3 direction;
float outerConeAngle;
float innerConeAngle;
bool castShadow;
int shadowMapTextureId;
int transformId;
};
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct PSInput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
@@ -65,14 +82,14 @@ PSOutput main(PSInput input)
Material inMaterial = material[pushConstants.materialIndex];
// NORMAL
// TODO use TBN matrix
float3 normal = float3(0.0, 0.0f, 1.0f);
float3 normal = float3(0.5, 0.5, 1.0);
if(inMaterial.hasNormal == 1)
{
// Sample from texture.
}
normal = mul(input.TBN, normal);
normal = normal / 2.0f + 0.5f;
normal = input.Normal / 2.0f + 0.5f;
output.oNormal = float4(normal, 1.0f);
// MATERIAL

View File

@@ -4,6 +4,7 @@ struct Camera
float4x4 proj;
float4x4 invView;
float4x4 invProj;
float3 position;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -34,6 +35,22 @@ struct ModelPushConstant
int materialIndex;
};
struct Light
{
float3 position;
int type;
float4 color;
float3 direction;
float outerConeAngle;
float innerConeAngle;
bool castShadow;
int shadowMapTextureId;
int transformId;
};
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
[[vk::push_constant]]
ModelPushConstant pushConstants;