Bindless texture buffer now working

This commit is contained in:
antopilo
2025-01-08 19:23:40 -05:00
parent e60c114acf
commit f0325e1ce9
15 changed files with 333 additions and 74 deletions

View File

@@ -4,11 +4,11 @@
using namespace Nuake;
void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type)
void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count)
{
VkDescriptorSetLayoutBinding newbind{};
newbind.binding = binding;
newbind.descriptorCount = 1;
newbind.descriptorCount = count;
newbind.descriptorType = type;
Bindings.push_back(newbind);

View File

@@ -10,7 +10,7 @@ namespace Nuake
{
std::vector<VkDescriptorSetLayoutBinding> Bindings;
void AddBinding(uint32_t binding, VkDescriptorType type);
void AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count = 1);
void Clear();
VkDescriptorSetLayout Build(VkDevice device, VkShaderStageFlags shaderStages, void* pNext = nullptr, VkDescriptorSetLayoutCreateFlags flags = 0);
};

View File

@@ -21,7 +21,8 @@ TextureAttachment::TextureAttachment(const std::string& name, ImageFormat format
}
RenderPass::RenderPass(const std::string& name) :
Name(name)
Name(name),
PushConstantSize(0)
{
}
@@ -45,7 +46,7 @@ void RenderPass::ClearAttachments(PassRenderContext& ctx)
// TODO: Queue deletion of old textures
}
if (DepthAttachment.Image->GetSize() != ctx.resolution)
if (DepthAttachment.Image && DepthAttachment.Image->GetSize() != ctx.resolution)
{
Ref<VulkanImage> newDepthAttachment = std::make_shared<VulkanImage>(DepthAttachment.Format, ctx.resolution, ImageUsage::Depth);
DepthAttachment.Image = newDepthAttachment;
@@ -74,7 +75,25 @@ void RenderPass::TransitionAttachments(PassRenderContext& ctx)
}
// Transition depth attachment
VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
if (DepthAttachment.Image)
{
VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
}
}
void RenderPass::UntransitionAttachments(PassRenderContext& ctx)
{
for (auto& attachment : Attachments)
{
// Transform from color attachment to transfer src for next pass
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
}
if (DepthAttachment.Image)
{
//VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
}
}
void RenderPass::Render(PassRenderContext& ctx)
@@ -96,9 +115,13 @@ void RenderPass::Render(PassRenderContext& ctx)
renderAttachmentInfos.push_back(attachmentInfo);
}
VkRenderingAttachmentInfo depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
VkRenderingAttachmentInfo depthAttachmentInfo = {};
if (DepthAttachment.Image)
{
depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
}
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, &depthAttachmentInfo);
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !DepthAttachment.Image ? nullptr : &depthAttachmentInfo);
renderInfo.colorAttachmentCount = std::size(renderAttachmentInfos);
renderInfo.pColorAttachments = renderAttachmentInfos.data();
@@ -132,12 +155,7 @@ void RenderPass::Render(PassRenderContext& ctx)
vkCmdEndRendering(ctx.commandBuffer);
// End rendering
for (auto& attachment : Attachments)
{
// Transform from color attachment to transfer src for next pass
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
}
if (PostRender)
{
@@ -172,9 +190,9 @@ TextureAttachment& RenderPass::GetAttachment(const std::string& name)
return Attachments[0];
}
std::vector<TextureAttachment&> RenderPass::GetAttachments()
std::vector<TextureAttachment> RenderPass::GetAttachments()
{
std::vector<TextureAttachment&> attachentRefs;
std::vector<TextureAttachment> attachentRefs;
attachentRefs.reserve(Attachments.size());
for (auto& attachment : Attachments)
{
@@ -188,12 +206,12 @@ void RenderPass::AddInput(const std::string& name)
InputNames.push_back(name);
}
std::vector<std::string> Nuake::RenderPass::GetInputs()
std::vector<std::string> RenderPass::GetInputs()
{
return InputNames;
}
void RenderPass::SetInput(const std::string& name, TextureAttachment& attachment)
void RenderPass::SetInput(const std::string& name, TextureAttachment attachment)
{
Inputs[name] = attachment;
}
@@ -207,10 +225,16 @@ void RenderPass::SetShaders(Ref<VulkanShader> vertShader, Ref<VulkanShader> frag
void RenderPass::Build()
{
// Push constant range
uint32_t pushRange = 0;
VkPushConstantRange bufferRange{};
bufferRange.offset = 0;
bufferRange.size = PushConstantSize;
bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
if (PushConstantSize > 0)
{
bufferRange.offset = 0;
bufferRange.size = PushConstantSize;
bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
pushRange = 1;
}
// TODO: Get the bindless descriptor layout
std::vector<VkDescriptorSetLayout> layouts = GPUResources::Get().GetBindlessLayout();
@@ -218,7 +242,7 @@ void RenderPass::Build()
// Create pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_info = VulkanInit::PipelineLayoutCreateInfo();
pipeline_layout_info.pPushConstantRanges = &bufferRange;
pipeline_layout_info.pushConstantRangeCount = 1;
pipeline_layout_info.pushConstantRangeCount = pushRange;
pipeline_layout_info.pSetLayouts = layouts.data();
pipeline_layout_info.setLayoutCount = layouts.size();
@@ -283,26 +307,43 @@ RenderPass& RenderPipeline::GetRenderPass(const std::string& name)
bool RenderPipeline::Build()
{
std::map<std::string, TextureAttachment&> attachments;
std::map<std::string, TextureAttachment> attachments;
for (auto& pass : RenderPasses)
{
pass.Build();
for (auto& input : pass.GetInputs())
{
bool alreadyFoundAttachment = false;
if (attachments.find(input) == attachments.end())
{
Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL);
return false;
if (pass.GetDepthAttachment().Image && pass.GetDepthAttachment().Name == input)
{
pass.SetInput(input, pass.GetDepthAttachment());
alreadyFoundAttachment = true;
}
else
{
Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL);
return false;
}
}
pass.SetInput(input, attachments[input]);
if (!alreadyFoundAttachment)
{
pass.SetInput(input, attachments[input]);
}
}
for (auto& attachment : pass.GetAttachments())
{
attachments[attachment.Name] = attachment;
}
if (pass.GetDepthAttachment().Image)
{
attachments[pass.GetDepthAttachment().Name] = pass.GetDepthAttachment();
}
}
for (auto& pass : RenderPasses)
@@ -325,6 +366,7 @@ void RenderPipeline::Execute(PassRenderContext& ctx)
pass.ClearAttachments(ctx);
pass.TransitionAttachments(ctx);
pass.Render(ctx);
pass.UntransitionAttachments(ctx);
}
}

View File

@@ -73,18 +73,20 @@ namespace Nuake
void ClearAttachments(PassRenderContext& ctx);
void TransitionAttachments(PassRenderContext& ctx);
void UntransitionAttachments(PassRenderContext& ctx);
void Render(PassRenderContext& ctx);
public:
std::string GetName() const { return Name; }
TextureAttachment& AddAttachment(const std::string& name, ImageFormat format, ImageUsage usage = ImageUsage::Default);
TextureAttachment& GetAttachment(const std::string& name);
std::vector<TextureAttachment&> GetAttachments();
std::vector<TextureAttachment> GetAttachments();
void AddInput(const std::string& name);
std::vector<std::string> GetInputs();
TextureAttachment& GetDepthAttachment() { return DepthAttachment; }
void SetInput(const std::string& name, TextureAttachment& attachment);
void SetInput(const std::string& name, TextureAttachment attachment);
void SetShaders(Ref<VulkanShader> vertShader, Ref<VulkanShader> fragShader);
template<typename T>
@@ -109,9 +111,7 @@ namespace Nuake
{
private:
bool Built;
std::vector<RenderPass> RenderPasses;
public:
RenderPipeline();

View File

@@ -30,11 +30,13 @@ namespace Nuake
VkDescriptorSetLayout ImageDescriptorLayout;
VkDescriptorSetLayout SamplerDescriptorLayout;
VkDescriptorSetLayout MaterialDescriptorLayout;
VkDescriptorSetLayout TexturesDescriptorLayout;
VkDescriptorSet CameraDescriptor;
VkDescriptorSet ModelDescriptor;
VkDescriptorSet SamplerDescriptor;
VkDescriptorSet MaterialDescriptor;
VkDescriptorSet TextureDescriptor;
public:
static GPUResources& Get()
@@ -60,6 +62,7 @@ namespace Nuake
bool AddTexture(Ref<VulkanImage> image);
Ref<VulkanImage> GetTexture(const UUID& id);
std::vector<Ref<VulkanImage>> GetAllTextures();
std::vector<VkDescriptorSetLayout> GetBindlessLayout();

View File

@@ -110,6 +110,7 @@ VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize, ImageUsage usage)
else if (usage == ImageUsage::Depth)
{
drawImageUsages |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
drawImageUsages |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
VkImageCreateInfo imgCreateInfo = VulkanInit::ImageCreateInfo(static_cast<VkFormat>(inFormat), drawImageUsages, vkExtent);

View File

@@ -514,7 +514,6 @@ void VkRenderer::InitTrianglePipeline()
void VkRenderer::DrawScene(RenderContext ctx)
{
SceneRenderer->BeginScene(ctx);
SceneRenderer->DrawScene();
SceneRenderer->EndScene();
}

View File

@@ -125,6 +125,7 @@ namespace Nuake
constexpr uint32_t FRAME_OVERLAP = 2;
constexpr uint32_t MAX_MODEL_MATRIX = 3000;
constexpr uint32_t MAX_MATERIAL = 1000;
constexpr uint32_t MAX_TEXTURES = 500;
class VkRenderer
{

View File

@@ -108,6 +108,17 @@ Ref<VulkanImage> GPUResources::GetTexture(const UUID& id)
return TextureManager::Get()->GetTexture2("missing_texture");
}
std::vector<Ref<VulkanImage>> GPUResources::GetAllTextures()
{
std::vector<Ref<VulkanImage>> allImages;
allImages.reserve(Images.size());
for (const auto& [id, image] : Images)
{
allImages.push_back(image);
}
return allImages;
}
void GPUResources::CreateBindlessLayout()
{
auto& vk = VkRenderer::Get();
@@ -153,6 +164,13 @@ void GPUResources::CreateBindlessLayout()
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
MaterialDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
}
// Textures
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES);
TexturesDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
}
std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
@@ -163,7 +181,8 @@ std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
TriangleBufferDescriptorLayout,
ImageDescriptorLayout,
SamplerDescriptorLayout,
MaterialDescriptorLayout
MaterialDescriptorLayout,
TexturesDescriptorLayout
};
return layouts;
}

View File

@@ -52,6 +52,8 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
BuildMatrixBuffer();
UpdateTransformBuffer();
auto& cmd = Context.CommandBuffer;
auto& scene = Context.CurrentScene;
auto& vk = VkRenderer::Get();
@@ -107,6 +109,8 @@ void VkSceneRenderer::LoadShaders()
ShaderCompiler& shaderCompiler = ShaderCompiler::Get();
Shaders["basic_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.frag");
Shaders["basic_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.vert");
Shaders["shading_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.frag");
Shaders["shading_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.vert");
}
void VkSceneRenderer::CreateSamplers()
@@ -170,12 +174,20 @@ void VkSceneRenderer::CreateDescriptors()
MaterialBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
}
//Bindless Textures
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES);
TextureBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
auto allocator = vk.GetDescriptorAllocator();
TriangleBufferDescriptors = allocator.Allocate(device, TriangleBufferDescriptorLayout);
CameraBufferDescriptors = allocator.Allocate(device, CameraBufferDescriptorLayout);
ModelBufferDescriptor = allocator.Allocate(device, ModelBufferDescriptorLayout);
SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
MaterialBufferDescriptor = allocator.Allocate(device, MaterialBufferDescriptorLayout);
TextureBufferDescriptor = allocator.Allocate(device, TextureBufferDescriptorLayout);
//SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
// Update descriptor set for camera
@@ -209,6 +221,9 @@ void VkSceneRenderer::CreateDescriptors()
samplerWrite.pImageInfo = &textureInfo; // Sampler info (same as texture)
vkUpdateDescriptorSets(device, 1, &samplerWrite, 0, nullptr);
// Textures
}
void VkSceneRenderer::CreatePipelines()
@@ -247,6 +262,17 @@ void VkSceneRenderer::CreatePipelines()
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
6, // firstSet
1, // descriptorSetCount
&TextureBufferDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
});
gBufferPass.SetRender([&](PassRenderContext& ctx){
@@ -321,10 +347,17 @@ void VkSceneRenderer::CreatePipelines()
});
auto& shadingPass = GBufferPipeline.AddPass("Shading");
shadingPass.SetShaders(Shaders["shading_vert"], Shaders["shading_frag"]);
shadingPass.SetPushConstant<ModelPushConstant>(modelPushConstant);
shadingPass.AddAttachment("Output", ImageFormat::RGBA16F);
shadingPass.AddAttachment("DepthShading", ImageFormat::D32F, ImageUsage::Depth);
shadingPass.AddInput("Albedo");
shadingPass.AddInput("Normal");
shadingPass.AddInput("Material");
shadingPass.AddInput("Depth");
shadingPass.SetPreRender([](PassRenderContext& ctx) {});
shadingPass.SetRender([](PassRenderContext& ctx) {});
GBufferPipeline.Build();
}
@@ -488,6 +521,25 @@ void VkSceneRenderer::UpdateTransformBuffer()
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);
}
auto allTextures = GPUResources::Get().GetAllTextures();
std::vector<VkDescriptorImageInfo> imageInfos(allTextures.size());
for (size_t i = 0; i < allTextures.size(); i++) {
imageInfos[i].imageView = allTextures[i]->GetImageView();
imageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
VkWriteDescriptorSet write{};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = TextureBufferDescriptor;
write.dstBinding = 0; // Binding 0
write.dstArrayElement = 0;
write.descriptorCount = static_cast<uint32_t>(imageInfos.size());
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
write.pImageInfo = imageInfos.data();
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &write, 0, nullptr);
}

View File

@@ -74,6 +74,10 @@ namespace Nuake
VkDescriptorSet MaterialBufferDescriptor;
VkDescriptorSetLayout MaterialBufferDescriptorLayout;
Ref<AllocatedBuffer> TextureBuffer;
VkDescriptorSet TextureBufferDescriptor;
VkDescriptorSetLayout TextureBufferDescriptorLayout;
ModelData ModelTransforms;
MaterialData MaterialDataContainer;

View File

@@ -0,0 +1,103 @@
[[vk::binding(0, 3)]]
Texture2D<float4> albedo : register(t1); // Texture binding at slot t0
[[vk::binding(0, 4)]]
SamplerState mySampler : register(s0); // Sampler binding at slot s0
struct Material
{
float hasAlbedo;
float3 albedo;
int hasNormal;
int hasMetalness;
int hasRoughness;
int hasAO;
float metalnessValue;
float roughnessValue;
float aoValue;
};
[[vk::binding(0, 5)]]
StructuredBuffer<Material> material;
struct PSInput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
float2 UV : TEXCOORD1;
float3 Normal : TEXCOORD2;
float3x3 TBN : TEXCOORD3;
};
struct PSOutput {
float4 oColor0 : SV_TARGET;
float4 oNormal : SV_TARGET1;
float4 oMaterial : SV_TARGET2;
};
struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
};
[[vk::push_constant]]
ModelPushConstant pushConstants;
PSOutput main(PSInput input)
{
PSOutput output;
Material inMaterial = material[pushConstants.materialIndex];
// NORMAL
// TODO use TBN matrix
float3 normal = float3(0.0, 0.0f, 1.0f);
if(inMaterial.hasNormal == 1)
{
// Sample from texture.
}
normal = mul(input.TBN, normal);
normal = normal / 2.0f + 0.5f;
output.oNormal = float4(normal, 1.0f);
// MATERIAL
// ALBEDO COLOR
float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f);
if(inMaterial.hasAlbedo == 1)
{
float4 albedoTextureSample = albedo.Sample(mySampler, input.UV);
// Alpha cutout?
if(albedoTextureSample.a < 0.001f)
{
discard;
}
albedoColor.xyz = albedoTextureSample.xyz;
}
output.oColor0 = albedoColor;
// MATERIAL PROPERTIES
float metalnessValue = inMaterial.metalnessValue;
if(inMaterial.hasMetalness == 1)
{
// TODO: Sample from metal texture
}
float aoValue = inMaterial.aoValue;
if(inMaterial.hasAO == 1)
{
// TODO: Sample from AO texture
}
float roughnessValue = inMaterial.roughnessValue;
if(inMaterial.hasRoughness == 1)
{
// TODO: Sample from roughness texture
}
float3 materialOuput = float3(inMaterial.metalnessValue, inMaterial.aoValue, inMaterial.roughnessValue);
output.oMaterial = float4(materialOuput, 1.0f);
return output;
}

View File

@@ -0,0 +1,70 @@
struct Camera
{
float4x4 view;
float4x4 proj;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
struct ModelData
{
float4x4 model;
};
[[vk::binding(0, 1)]]
StructuredBuffer<ModelData> model : register(t1);
struct Vertex
{
float3 position;
float uv_x;
float3 normal;
float uv_y;
float3 tangent;
float3 bitangent;
};
[[vk::binding(0, 2)]]
StructuredBuffer<Vertex> vertexBuffer : register(t2);
struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
};
[[vk::push_constant]]
ModelPushConstant pushConstants;
// Outputs
struct VSOutput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
float2 UV : TEXCOORD1;
float3 Normal : TEXCOORD2;
float3x3 TBN : TEXCOORD3;
};
// Main vertex shader
VSOutput main(uint vertexIndex : SV_VertexID)
{
VSOutput output;
Camera camData = camera[0];
ModelData modelData = model[pushConstants.modelIndex];
// Load vertex data from the buffer
Vertex v = vertexBuffer[vertexIndex];
// Output the position of each vertex
output.Position = mul(camData.proj, mul(camData.view, mul(modelData.model, float4(v.position, 1.0f))));
output.Color = normalize(float3(v.position.xyz));
output.UV = float2(v.uv_x, v.uv_y);
output.Normal = normalize(v.normal);
float3 T = normalize(mul((float3x3)modelData.model, normalize(v.tangent.xyz)));
float3 B = normalize(mul((float3x3)modelData.model, normalize(v.bitangent.xyz)));
float3 N = normalize(mul((float3x3)modelData.model, normalize(v.normal)).xyz);
output.TBN = transpose(float3x3(T, B, N));
return output;
}

View File

@@ -19,6 +19,9 @@ struct Material
[[vk::binding(0, 5)]]
StructuredBuffer<Material> material;
[[vk::binding(0, 6)]]
Texture2D textures[];
struct PSInput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
@@ -65,6 +68,7 @@ PSOutput main(PSInput input)
float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f);
if(inMaterial.hasAlbedo == 1)
{
float4 testTexture = textures[pushConstants.modelIndex].Sample(mySampler, input.UV);
float4 albedoTextureSample = albedo.Sample(mySampler, input.UV);
// Alpha cutout?
@@ -73,7 +77,7 @@ PSOutput main(PSInput input)
discard;
}
albedoColor.xyz = albedoTextureSample.xyz;
albedoColor.xyz = testTexture.xyz * albedoTextureSample.xyz;
}
output.oColor0 = albedoColor;

View File

@@ -1,39 +0,0 @@
struct Vertex
{
float3 position;
float uv_x;
float3 normal;
float uv_y;
float4 color;
};
// Define the structured buffer for vertices
StructuredBuffer<Vertex> vertexBuffer : register(t0); // Binding of vertex buffer (example: t0)
// Define push constants block
cbuffer PushConstants : register(b0) { // Push constants binding (example: b0)
float4x4 render_matrix; // Matrix for rendering
uint64_t vertexBufferAddress; // Buffer reference address (Vulkan-specific handling required)
};
// Outputs
struct VSOutput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
float2 UV : TEXCOORD1;
};
// Main vertex shader
VSOutput main(uint vertexIndex : SV_VertexID) {
VSOutput output;
// Load vertex data from the buffer
Vertex v = vertexBuffer[vertexIndex];
// Transform and output vertex data
output.Position = mul(render_matrix, float4(v.position, 1.0f));
output.Color = v.color.xyz;
output.UV = float2(v.uv_x, v.uv_y);
return output;
}