diff --git a/aster/buffer.cpp b/aster/buffer.cpp index 2085cc5..d24b918 100644 --- a/aster/buffer.cpp +++ b/aster/buffer.cpp @@ -54,6 +54,13 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs device->SetName(m_Buffer, name); } +uptr +Buffer::GetDeviceAddress(const Device *device) +{ + vk::BufferDeviceAddressInfo addressInfo = {.buffer = m_Buffer}; + return device->m_Device.getBufferAddress(&addressInfo); +} + void Buffer::Write(const Device *device, usize offset, usize size, const void *data) { @@ -143,6 +150,24 @@ StorageIndexBuffer::Init(const Device *device, usize size, bool hostVisible, boo } } +void +IndirectBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name) +{ + vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer | vk::BufferUsageFlagBits::eShaderDeviceAddress; + if (hostVisible) + { + Allocate(device, size, usage, + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, + VMA_MEMORY_USAGE_AUTO, name); + } + else + { + usage |= vk::BufferUsageFlagBits::eTransferDst; + Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name); + } +} + void VertexBuffer::Init(const Device *device, usize size, cstr name) { diff --git a/aster/buffer.h b/aster/buffer.h index cee1edb..45075d3 100644 --- a/aster/buffer.h +++ b/aster/buffer.h @@ -31,6 +31,9 @@ struct Buffer void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage, VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name); + uptr + GetDeviceAddress(const Device *device); + // Buffer.size is used for bookkeeping // If the buffer is Invalid, the remaining data in Buffer is used intrusively by `GpuResourceManager`. usize m_Size_ = 0; @@ -54,6 +57,11 @@ struct StorageBuffer : Buffer void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr); }; +struct IndirectBuffer : Buffer +{ + void Init(const Device *device, usize size, bool hostVisible, cstr name = nullptr); +}; + struct StorageIndexBuffer : StorageBuffer { void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr); diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index 2296562..60830d8 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -157,6 +157,8 @@ main(int, char **) .descriptorBindingStorageBufferUpdateAfterBind = true, .descriptorBindingPartiallyBound = true, .runtimeDescriptorArray = true, + .bufferDeviceAddress = true, + .bufferDeviceAddressCaptureReplay = true, }, .m_Vulkan13Features = { diff --git a/samples/04_scenes/asset_loader.cpp b/samples/04_scenes/asset_loader.cpp index 4290083..d877329 100644 --- a/samples/04_scenes/asset_loader.cpp +++ b/samples/04_scenes/asset_loader.cpp @@ -879,6 +879,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) Entity modelRootEntity = m_Registry->create(); m_Registry->emplace(modelRootEntity); m_Registry->emplace(modelRootEntity); + m_Registry->emplace(modelRootEntity); entities.push_back(modelRootEntity); assert(model.defaultScene >= 0); diff --git a/samples/04_scenes/asset_loader.h b/samples/04_scenes/asset_loader.h index dc5ce9d..bd7564d 100644 --- a/samples/04_scenes/asset_loader.h +++ b/samples/04_scenes/asset_loader.h @@ -61,6 +61,8 @@ struct Model void Destroy(RenderResourceManager *resourceManager, EcsRegistry *registry); }; +struct CModel {}; + struct AssetLoader { RenderResourceManager *m_ResourceManager; diff --git a/samples/04_scenes/ecs_adapter.h b/samples/04_scenes/ecs_adapter.h index 3cc09bf..ced8d8d 100644 --- a/samples/04_scenes/ecs_adapter.h +++ b/samples/04_scenes/ecs_adapter.h @@ -12,6 +12,9 @@ using Entity = entt::entity; template using Without = entt::exclude_t; +template +using Get = entt::get_t; + [[nodiscard]] inline bool Exists(Entity entity) { diff --git a/samples/04_scenes/light_manager.cpp b/samples/04_scenes/light_manager.cpp index bbf9b0b..c2ff6f5 100644 --- a/samples/04_scenes/light_manager.cpp +++ b/samples/04_scenes/light_manager.cpp @@ -289,15 +289,15 @@ LightManager::RemoveLight(const LightHandle handle) } void -LightManager::SetEnvironment(Environment &&environment) +LightManager::SetEnvironment(Environment *environment) { m_ResourceManager->Release(m_MetaInfo.m_Skybox); m_ResourceManager->Release(m_MetaInfo.m_Diffuse); m_ResourceManager->Release(m_MetaInfo.m_Prefilter); m_ResourceManager->Release(m_MetaInfo.m_BrdfLut); - m_MetaInfo.m_Skybox = environment.m_Skybox; - m_MetaInfo.m_Diffuse = environment.m_Diffuse; - m_MetaInfo.m_Prefilter = environment.m_Prefilter; - m_MetaInfo.m_BrdfLut = environment.m_BrdfLut; + m_MetaInfo.m_Skybox = environment->m_Skybox; + m_MetaInfo.m_Diffuse = environment->m_Diffuse; + m_MetaInfo.m_Prefilter = environment->m_Prefilter; + m_MetaInfo.m_BrdfLut = environment->m_BrdfLut; } \ No newline at end of file diff --git a/samples/04_scenes/light_manager.h b/samples/04_scenes/light_manager.h index 8e83940..5a52e86 100644 --- a/samples/04_scenes/light_manager.h +++ b/samples/04_scenes/light_manager.h @@ -55,6 +55,7 @@ struct LightManager u16 m_PointLightOffset; // 02 24 u16 m_DirectionalLightMaxCount; // 02 26 u16 m_UnusedPadding0 = 0; // 02 28 + u32 m_UnusedPadding1 = 0; // 04 32 }; RenderResourceManager *m_ResourceManager; @@ -79,7 +80,7 @@ struct LightManager void Update(); void RemoveLight(LightHandle handle); - void SetEnvironment(Environment &&environment); + void SetEnvironment(Environment *environment); explicit LightManager(RenderResourceManager *resourceManager); ~LightManager(); diff --git a/samples/04_scenes/main.cpp b/samples/04_scenes/main.cpp index 16bde5e..f7ff544 100644 --- a/samples/04_scenes/main.cpp +++ b/samples/04_scenes/main.cpp @@ -11,10 +11,10 @@ #include "swapchain.h" #include "window.h" -#include "light_manager.h" #include "asset_loader.h" #include "camera.h" #include "core_components.h" +#include "light_manager.h" #include "ecs_adapter.h" #include "frame.h" @@ -43,12 +43,10 @@ main(int, char *[]) PhysicalDevices physicalDevices = {&window, &context}; PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); - usize physicalDeviceOffsetAlignment = deviceToUse.m_DeviceProperties.limits.minUniformBufferOffsetAlignment; - vk::Extent2D internalResolution = {1920, 1080}; internalResolution.width = (internalResolution.height * INIT_WIDTH) / INIT_HEIGHT; - CameraController cameraController = {vec3{0.0f, 0.0f, 2.0f}, vec3{0.0f}, 70_deg, + CameraController cameraController = {vec3{0.0f, 2.0f, 4.0f}, vec3{0.0f, 0.0f, 0.0f}, 70_deg, Cast(internalResolution.width) / Cast(internalResolution.height)}; INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data()); @@ -56,9 +54,14 @@ main(int, char *[]) Features enabledDeviceFeatures = { .m_Vulkan10Features = { + .multiDrawIndirect = true, .samplerAnisotropy = true, .shaderInt64 = true, }, + .m_Vulkan11Features = + { + .shaderDrawParameters = true, + }, .m_Vulkan12Features = { .descriptorIndexing = true, @@ -105,17 +108,25 @@ main(int, char *[]) resourceManager.Release(envHdriHandle); - lightManager.SetEnvironment(std::move(environment)); + lightManager.SetEnvironment(&environment); - Model model = assetLoader.LoadModelToGpu(MODEL_FILE, "Main Model"); - Model model2 = assetLoader.LoadModelToGpu(MODEL_FILE2, "Main Model 2"); - registry.get(model2.m_RootEntity).m_Position.x += 1.0f; + eastl::vector models; + for (int i = -1; i <= 1; ++i) + { + for (int j = -1; j <= 1; ++j) + { + INFO("{}, {}", i, j); + auto &model = models.emplace_back(std::move(assetLoader.LoadModelToGpu(MODEL_FILE, "Main Model"))); + registry.get(model.m_RootEntity).m_Position = vec3(2 * i, 0, 2 * j); + } + } UniformBuffer ubo; - constexpr usize uboTotalSize = sizeof cameraController.m_Camera + sizeof lightManager.m_MetaInfo; + constexpr usize uboLightManagerOffset = sizeof cameraController.m_Camera; + constexpr usize uboTotalSize = uboLightManagerOffset + sizeof lightManager.m_MetaInfo; ubo.Init(&device, uboTotalSize, "Desc1 UBO"); ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera); - ubo.Write(&device, sizeof cameraController.m_Camera, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo); + ubo.Write(&device, uboLightManagerOffset, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo); Pipeline pipeline = CreatePipeline(&device, attachmentFormat, &resourceManager); Pipeline backgroundPipeline = CreateBackgroundPipeline(&device, attachmentFormat, &resourceManager); @@ -287,19 +298,23 @@ main(int, char *[]) uptr m_VertexPositionPtr; uptr m_VertexDataPtr; uptr m_MaterialPtr; - - // TODO: Remove - u32 m_FirstIndex; - u32 m_IndexCount; + u8 m_Padding_[8]; }; - eastl::fixed_vector, MAX_FRAMES_IN_FLIGHT> perFrameNodeData(frameManager.m_FramesInFlight); - eastl::fixed_vector perFrameNodeBuffer(frameManager.m_FramesInFlight); - for (auto &bufferHandle : perFrameNodeBuffer) + eastl::vector nodeData; + eastl::vector nodeDrawInfo; + + eastl::fixed_vector nodeBuffers; + eastl::fixed_vector nodeIndirectBuffers; + eastl::fixed_vector perFrameNodeBufferPtr; + + for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i) { - StorageBuffer buffer; - buffer.Init(&device, sizeof(NodeData) * 100'000, true); - bufferHandle = resourceManager.Commit(&buffer); + auto *buffer = &nodeBuffers.push_back(); + buffer->Init(&device, sizeof(NodeData) * 100'000, true, true, "Node Buffer"); + auto *indirect = &nodeIndirectBuffers.push_back(); + indirect->Init(&device, sizeof(vk::DrawIndexedIndirectCommand) * 100'000, true); + perFrameNodeBufferPtr.push_back(buffer->GetDeviceAddress(&device)); } swapchain.RegisterResizeCallback( @@ -324,19 +339,28 @@ main(int, char *[]) auto rootNodeUpdateView = registry.view(Without>{}); + auto rootModel = registry.group(Get{}); + auto nodeWithParentsUpdateView = registry.view, CGlobalTransform>(); nodeWithParentsUpdateView.use>(); auto renderableObjectsGroup = registry.group(); + lightManager.Update(); + ubo.Write(&device, uboLightManagerOffset, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo); + resourceManager.Update(); while (window.Poll()) { Time::Update(); - auto *rot = ®istry.get(model.m_RootEntity).m_Rotation; - *rot = glm::rotate(*rot, Cast(30_deg * Time::m_Delta), vec3{0.0f, 1.0f, 0.0f}); + u32 index = 0; + for (auto [entity, dynTrans] : rootModel.each()) + { + dynTrans.m_Rotation = + glm::rotate(dynTrans.m_Rotation, Cast(30_deg * (++index) * Time::m_Delta), vec3{0.0f, 1.0f, 0.0f}); + } Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window); @@ -392,23 +416,31 @@ main(int, char *[]) registry.get(parent.m_ParentEntity).m_Transform * translation * rotation * scale; } - usize objectCount = renderableObjectsGroup.size(); - auto *nodeData = &perFrameNodeData[currentFrame->m_FrameIdx]; - nodeData->clear(); - nodeData->reserve(objectCount); + u32 objectCount = Cast(renderableObjectsGroup.size()); + nodeData.clear(); + nodeDrawInfo.clear(); + nodeData.reserve(objectCount); + nodeDrawInfo.reserve(objectCount); for (auto [entity, globalTransform, mesh, material] : renderableObjectsGroup.each()) { - nodeData->push_back({ + nodeData.push_back({ .m_Transform = globalTransform.m_Transform, .m_VertexPositionPtr = mesh.m_VertexPositionPtr, .m_VertexDataPtr = mesh.m_VertexDataPtr, .m_MaterialPtr = material.m_MaterialPtr, - .m_FirstIndex = mesh.m_FirstIndex, - .m_IndexCount = mesh.m_IndexCount, + }); + nodeDrawInfo.push_back({ + .indexCount = mesh.m_IndexCount, + .instanceCount = 1, + .firstIndex = mesh.m_FirstIndex, + .vertexOffset = 0, + .firstInstance = 0, }); } - resourceManager.Write(perFrameNodeBuffer[currentFrame->m_FrameIdx], 0, objectCount * sizeof(NodeData), - nodeData->data()); + + nodeBuffers[currentFrame->m_FrameIdx].Write(&device, 0, objectCount * sizeof(NodeData), nodeData.data()); + nodeIndirectBuffers[currentFrame->m_FrameIdx].Write(&device, 0, objectCount * sizeof nodeDrawInfo[0], + nodeDrawInfo.data()); vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit}; AbortIfFailed(cmd.begin(&beginInfo)); @@ -458,14 +490,12 @@ main(int, char *[]) cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline); - // TODO("Get the data to the GPU"); - // auto nodeHandle = perFrameNodeBuffer[currentFrame->m_FrameIdx]; - auto &nodeBuffer = perFrameNodeData[currentFrame->m_FrameIdx]; - for (auto &node : nodeBuffer) - { - cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof node, &node); - cmd.drawIndexed(node.m_IndexCount, 1, node.m_FirstIndex, 0, 0); - } + auto nodeBufferAddr = perFrameNodeBufferPtr[currentFrame->m_FrameIdx]; + + cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof nodeBufferAddr, &nodeBufferAddr); + + cmd.drawIndexedIndirect(nodeIndirectBuffers[currentFrame->m_FrameIdx].m_Buffer, 0, objectCount, + sizeof nodeDrawInfo[0]); cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, backgroundPipeline.m_Pipeline); @@ -527,9 +557,13 @@ main(int, char *[]) device.WaitIdle(); - for (auto bufferHandle : perFrameNodeBuffer) + for (auto buffer : nodeIndirectBuffers) { - resourceManager.Release(bufferHandle); + buffer.Destroy(&device); + } + for (auto buffer : nodeBuffers) + { + buffer.Destroy(&device); } for (auto depthImage : depthImages) { @@ -543,6 +577,8 @@ main(int, char *[]) device.m_Device.destroy(descriptorPool, nullptr); - model.Destroy(&resourceManager, ®istry); - model2.Destroy(&resourceManager, ®istry); + for (auto &model : models) + { + model.Destroy(&resourceManager, ®istry); + } } \ No newline at end of file diff --git a/samples/04_scenes/render_resource_manager.cpp b/samples/04_scenes/render_resource_manager.cpp index aa3bc41..76f22a8 100644 --- a/samples/04_scenes/render_resource_manager.cpp +++ b/samples/04_scenes/render_resource_manager.cpp @@ -641,9 +641,9 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u INFO("Max Texture Count: {}", texturesCount); INFO("Max Storage Texture Count: {}", storageTexturesCount); - m_Geometry.InitStorage(device, Megabyte(128u)); - m_Index.InitIndex(device, Megabyte(8u)); - m_Material.InitStorage(device, Kilobyte(560u)); + m_Geometry.InitStorage(device, Gigabyte(1u)); + m_Index.InitIndex(device, Megabyte(256u)); + m_Material.InitStorage(device, Gigabyte(1u)); m_BufferManager.Init(buffersCount); m_TextureManager.Init(texturesCount); m_StorageTextureManager.Init(storageTexturesCount); diff --git a/samples/04_scenes/shader/bindless_structs.glsl b/samples/04_scenes/shader/bindless_structs.glsl index ce0ee91..91e861e 100644 --- a/samples/04_scenes/shader/bindless_structs.glsl +++ b/samples/04_scenes/shader/bindless_structs.glsl @@ -20,13 +20,36 @@ struct Material // We might be able to go upto 64 without pains. }; +struct PointLight +{ + vec3 m_Position; + float m_Range; + uint m_Color; + float m_Intensity; +}; + +struct DirectionalLight +{ + vec3 m_Direction; + float m_Validity_; + uint m_Color; + float m_Intensity; +}; + // ---------- Bindless Bindings ---------- #define INVALID_HANDLE 0xFFFFFFFF +layout (std430, set = 0, binding = 0) readonly buffer PointLightBuffer { + PointLight lights[]; +} pointLightBuffers[]; + +layout (std430, set = 0, binding = 0) readonly buffer DirectionLightBuffer { + DirectionalLight lights[]; +} directionalLightBuffers[]; + layout (set = 0, binding = 1) uniform sampler2D textures[]; layout (set = 0, binding = 1) uniform samplerCube textureCubes[]; - // ---------- Buffer References ---------- layout(std430, buffer_reference, buffer_reference_align=16) readonly buffer VPositionRef { vec4 Positions[]; @@ -41,13 +64,20 @@ layout(std430, buffer_reference, buffer_reference_align=8) readonly buffer Mater }; layout(std430, buffer_reference, buffer_reference_align=8) readonly buffer MaterialRef { - vec4 m_AlbedoFactor; // 16 16 - vec3 m_EmissionFactor; // 12 28 - float m_MetalFactor; // 04 32 - float m_RoughFactor; // 04 36 - uint m_AlbedoTex; // 04 40 - uint m_NormalTex; // 04 44 - uint m_MetalRoughTex; // 04 48 - uint m_OcclusionTex; // 04 52 - uint m_EmissionTex; // 04 56 + Material material; +}; + +// Node + +struct Node +{ + mat4 globalTransform; // 64 64 + VPositionRef pVertexPosition; // 08 72 + VDataRef pVertexData; // 08 80 + MaterialRef pMaterial; // 08 88 + // pad // 08 96 +}; + +layout(std430, buffer_reference, buffer_reference_align=8) readonly buffer NodeRef { + Node nodes[]; }; \ No newline at end of file diff --git a/samples/04_scenes/shader/model.frag.glsl b/samples/04_scenes/shader/model.frag.glsl index 5df242e..8a12303 100644 --- a/samples/04_scenes/shader/model.frag.glsl +++ b/samples/04_scenes/shader/model.frag.glsl @@ -1,4 +1,4 @@ -#version 450 +#version 460 #pragma shader_stage(fragment) #extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable #extension GL_EXT_buffer_reference : require @@ -11,15 +11,12 @@ layout (location = 0) in vec4 in_Position; layout (location = 1) in vec4 in_Normal; layout (location = 2) in vec4 in_Color0; layout (location = 3) in vec2 in_TexCoord0; +layout (location = 4) in flat uint in_DrawID; layout (location = 0) out vec4 outColor; -layout(push_constant) uniform Constants -{ - mat4 globalTransform; - uint64_t vertexPos; - uint64_t vertexDat; - MaterialRef g_Material; +layout (push_constant) uniform Const { + NodeRef nodes; }; vec4 GetAlbedo(vec4 albedoFactor, uint texHandle, vec4 in_Color0, vec2 uv) @@ -159,99 +156,99 @@ vec3 GetPBRContrib(vec3 albedo, vec3 lightColor, vec3 viewDir, vec3 normal, floa return ndotl * radiance * (kDiffuse * albedo / PI + specular); } -// -//vec3 GetPointLightInfluence(vec3 albedo, vec2 MetalRough, vec3 Position, vec3 Normal) -//{ -// if (lights.LightHandle == INVALID_HANDLE) -// return 0.0f.xxx; -// -// uint Offset = IndexerOffset(lights.PointLightIndexer); -// uint Count = IndexerCount(lights.PointLightIndexer); -// -// vec3 ViewDir = normalize(Camera.Position.xyz - Position); -// -// float Metallic = MetalRough.r; -// float Roughness = MetalRough.g; -// -// // Dielectric F_0 based on LearnOpenGL. -// // TODO: Cite -// vec3 F_0 = 0.04f.xxx; -// F_0 = lerp(F_0, albedo, Metallic); -// -// vec3 Contrib = 0.0f; -// for (uint i = 0; i < Count; ++i) -// { -// PointLight Light = PointLightBuffer[lights.LightHandle][i + Offset]; -// -// if (Light.Range < 0.0f) -// continue; -// -// vec3 LightDir = vec3(Light.Position) - Position; -// float LightDistance = length(LightDir); -// -// if (LightDistance > Light.Range) -// continue; -// -// LightDir /= LightDistance; // Normalization -// -// // Color Unpack -// float R = (Light.Color & 0xFF000000) >> 24; -// float G = (Light.Color & 0x00FF0000) >> 16; -// float B = (Light.Color & 0x0000FF00) >> 8; -// -// vec3 LightColor = Light.Intensity * vec3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255 -// -// Contrib += GetPBRContrib(albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, LightDistance); -// } -// -// return Contrib; -//} -// -//vec3 GetDirectionalLightInfluence(vec3 albedo, float2 MetalRough, vec3 Position, vec3 Normal) -//{ -// if (lights.LightHandle == INVALID_HANDLE) -// return 0.0f.xxx; -// -// uint Count = IndexerCount(lights.DirectionalLightIndexer); -// -// vec3 ViewDir = normalize(Camera.Position.xyz - Position); -// -// float Metallic = MetalRough.r; -// float Roughness = MetalRough.g; -// -// // Dielectric F_0 based on LearnOpenGL. -// // TODO: Cite -// vec3 F_0 = 0.04f.xxx; -// F_0 = lerp(F_0, albedo, Metallic); -// -// vec3 Contrib = 0.0f; -// for (uint i = 0; i < Count; ++i) -// { -// DirectionalLight Light = DirectionalLightBuffer[lights.LightHandle][i]; -// -// if (Light.Validity_ < 0.0f) -// continue; -// -// vec3 LightDir = -normalize(vec3(Light.Direction)); -// -// // Color Unpack -// float R = (Light.Color & 0xFF000000) >> 24; -// float G = (Light.Color & 0x00FF0000) >> 16; -// float B = (Light.Color & 0x0000FF00) >> 8; -// -// vec3 LightColor = Light.Intensity * vec3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255 -// -// Contrib += GetPBRContrib(albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, 1.0f); -// } -// -// return Contrib; -//} -// + +vec3 GetPointLightInfluence(vec3 albedo, vec2 metalRough, vec3 position, vec3 normal) +{ + if (lights.m_LightHandle == INVALID_HANDLE) + return 0.0f.xxx; + + uint offset = IndexerOffset(lights.m_PointLightIndexer); + uint count = IndexerCount(lights.m_PointLightIndexer); + + vec3 viewDir = normalize(camera.m_Position.xyz - position); + + float metallic = metalRough.r; + float roughness = metalRough.g; + + // Dielectric F_0 based on LearnOpenGL. + // TODO: Cite + vec3 f0 = vec3(0.04f); + f0 = mix(f0, albedo, metallic); + + vec3 contrib = vec3(0.0f); + for (uint i = 0; i < count; ++i) + { + PointLight light = pointLightBuffers[lights.m_LightHandle].lights[i + offset]; + + if (light.m_Range < 0.0f) + continue; + + vec3 lightDir = vec3(light.m_Position) - position; + float lightDistance = length(lightDir); + + if (lightDistance > light.m_Range) + continue; + + lightDir /= lightDistance; // Normalization + + // Color Unpack + float r = (light.m_Color & 0xFF000000) >> 24; + float g = (light.m_Color & 0x00FF0000) >> 16; + float b = (light.m_Color & 0x0000FF00) >> 8; + + vec3 lightColor = light.m_Intensity * vec3(r, g, b) * 0.00392156862f; // 0.00392156862 = 1/255 + + contrib += GetPBRContrib(albedo, lightColor, viewDir, normal, metallic, roughness, f0, lightDir, lightDistance); + } + + return contrib; +} + +vec3 GetDirectionalLightInfluence(vec3 albedo, vec2 metalRough, vec3 position, vec3 normal) +{ + if (lights.m_LightHandle == INVALID_HANDLE) + return 0.0f.xxx; + + uint count = IndexerCount(lights.m_DirectionalLightIndexer); + + vec3 viewDir = normalize(camera.m_Position.xyz - position); + + float metallic = metalRough.r; + float roughness = metalRough.g; + + // Dielectric F_0 based on LearnOpenGL. + // TODO: Cite + vec3 f0 = vec3(0.04f); + f0 = mix(f0, albedo, metallic); + + vec3 contrib = vec3(0.0f); + for (uint i = 0; i < count; ++i) + { + DirectionalLight light = directionalLightBuffers[lights.m_LightHandle].lights[i]; + + if (light.m_Validity_ < 0.0f) + continue; + + vec3 lightDir = -normalize(light.m_Direction); + + // Color Unpack + float r = (light.m_Color & 0xFF000000) >> 24; + float g = (light.m_Color & 0x00FF0000) >> 16; + float b = (light.m_Color & 0x0000FF00) >> 8; + + vec3 lightColor = light.m_Intensity * vec3(r, g, b) * 0.00392156862f; // 0.00392156862 = 1/255 + + contrib += GetPBRContrib(albedo, lightColor, viewDir, normal, metallic, roughness, f0, lightDir, 1.0f); + } + + return contrib; +} + vec3 GetAmbientInfluence(vec3 albedo, float metal, float roughness, vec3 Position, vec3 Normal, float Occlusion) { vec3 ViewDir = normalize(camera.m_Position.xyz - Position); float CosineFactor = max(dot(Normal, ViewDir), 0.0f); // Normal instead of Halfway since there's no halfway in ambient. - + vec3 F_0 = 0.04f.xxx; F_0 = mix(F_0, albedo, metal); vec3 K_Specular = FresnelSchlickRoughness(CosineFactor, F_0, roughness); @@ -280,21 +277,24 @@ vec3 GetAmbientInfluence(vec3 albedo, float metal, float roughness, vec3 Positio } void main() { + + Material material = nodes.nodes[nonuniformEXT(in_DrawID)].pMaterial.material; - vec4 albedoA = GetAlbedo(g_Material.m_AlbedoFactor, g_Material.m_AlbedoTex, in_Color0, in_TexCoord0); + vec4 albedoA = GetAlbedo(material.m_AlbedoFactor, material.m_AlbedoTex, in_Color0, in_TexCoord0); vec3 albedo = albedoA.rgb; float alpha = albedoA.a; - vec3 normal = GetNormal(g_Material.m_NormalTex, in_Position.xyz, normalize(in_Normal.xyz), in_TexCoord0); + vec3 normal = GetNormal(material.m_NormalTex, in_Position.xyz, normalize(in_Normal.xyz), in_TexCoord0); - vec3 emission = GetEmissive(g_Material.m_EmissionFactor, g_Material.m_EmissionTex, in_TexCoord0); + vec3 emission = GetEmissive(material.m_EmissionFactor, material.m_EmissionTex, in_TexCoord0); - vec2 metalRough = GetMetalRough(g_Material.m_MetalFactor, g_Material.m_RoughFactor, g_Material.m_MetalRoughTex, in_TexCoord0); - float occlusion = GetOcclusion(g_Material.m_OcclusionTex, in_TexCoord0); + vec2 metalRough = GetMetalRough(material.m_MetalFactor, material.m_RoughFactor, material.m_MetalRoughTex, in_TexCoord0); + float occlusion = GetOcclusion(material.m_OcclusionTex, in_TexCoord0); + vec3 pointLumin = GetPointLightInfluence(albedo, metalRough, in_Position.xyz, normal); + vec3 directionalLumin = GetDirectionalLightInfluence(albedo, metalRough, in_Position.xyz, normal); vec3 ambientLumin = GetAmbientInfluence(albedo, metalRough.r, metalRough.g, in_Position.xyz, normal, occlusion); - - outColor = vec4(Uncharted2Tonemap(ambientLumin + emission), alpha); - -// outColor = vec4(0.5f + 0.5f * normal, 1.0f); -} \ No newline at end of file + + vec3 viewDir = normalize(camera.m_Position.xyz - in_Position.xyz); + outColor = vec4(Uncharted2Tonemap(pointLumin + directionalLumin + ambientLumin + emission), alpha); +} diff --git a/samples/04_scenes/shader/model.vert.glsl b/samples/04_scenes/shader/model.vert.glsl index 5283fe2..53cbe10 100644 --- a/samples/04_scenes/shader/model.vert.glsl +++ b/samples/04_scenes/shader/model.vert.glsl @@ -1,21 +1,27 @@ -#version 450 +#version 460 #pragma shader_stage(vertex) #extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable #extension GL_EXT_buffer_reference : require +#extension GL_EXT_nonuniform_qualifier : require #include "bindless_structs.glsl" #include "graphics_bindings.glsl" -layout(location=0) out vec4 outWorldNormal; -layout(location=1) out vec4 outWorldPosition; +layout(location=0) out vec4 outWorldPosition; +layout(location=1) out vec4 outWorldNormal; layout(location=2) out vec4 outColor; layout(location=3) out vec2 outUV0; +layout(location=4) out uint drawID; +// +//layout(push_constant) uniform Constants { +// mat4 globalTransform; +// VPositionRef pVertexPosition; +// VDataRef pVertexData; +// uint64_t materialIdx; +//}; -layout(push_constant) uniform Constants { - mat4 globalTransform; - VPositionRef pVertexPosition; - VDataRef pVertexData; - uint64_t materialIdx; +layout (push_constant) uniform Const { + NodeRef nodes; }; void main() { @@ -25,10 +31,14 @@ void main() { vec3( 0.0f, 0.0f, 1.0f ), }; - outWorldNormal = vec4(normalize(transpose(inverse(mat3(globalTransform))) * pVertexData.Data[gl_VertexIndex].Normal.xyz), 0.0f); + drawID = gl_DrawID; + Node n = nodes.nodes[gl_DrawID]; - outWorldPosition = globalTransform * vec4(pVertexPosition.Positions[gl_VertexIndex].xyz, 1.0f); + outWorldNormal = normalize(n.globalTransform * vec4(n.pVertexData.Data[gl_VertexIndex].Normal.xyz, 0.0f)); + + outWorldPosition = n.globalTransform * vec4(n.pVertexPosition.Positions[gl_VertexIndex].xyz, 1.0f); gl_Position = camera.m_Projection * camera.m_View * outWorldPosition; - outColor = vec4(pVertexData.Data[gl_VertexIndex].Color.rgb, 1.0f); //vec3(colors[gl_VertexIndex % 3]); - outUV0 = pVertexData.Data[gl_VertexIndex].TexCoord0; + outColor = vec4(n.pVertexData.Data[gl_VertexIndex].Color.rgb, 1.0f); +// outColor = vec4(colors[gl_VertexIndex % 3], 1.0f); + outUV0 = n.pVertexData.Data[gl_VertexIndex].TexCoord0; } \ No newline at end of file