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