General Cleanup.

This commit is contained in:
Anish Bhobe 2025-05-25 21:42:56 +02:00
parent 3ca3beb1e4
commit 56dd76d16e
24 changed files with 24 additions and 1337 deletions

View File

@ -30,10 +30,4 @@ function(add_shader TARGET SHADER)
# Make sure our build depends on this output.
set_source_files_properties(${current-output-path} PROPERTIES GENERATED TRUE)
target_sources(${TARGET} PRIVATE ${current-output-path})
endfunction(add_shader)
function(add_shaders TARGET SHADERS)
foreach(shader IN ${SHADERS})
add_shader(TARGET ${shader})
endforeach()
endfunction(add_shaders)
endfunction(add_shader)

View File

@ -5,35 +5,25 @@ cmake_minimum_required(VERSION 3.13)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address")
find_path(TINYGLTF_INCLUDE_DIRS "tiny_gltf.h")
add_executable(model_render "model_render.cpp"
"pipeline_utils.cpp"
"pipeline_utils.h"
"asset_loader.cpp"
"asset_loader.h"
"light_manager.cpp"
"light_manager.h"
"nodes.cpp"
"nodes.h"
"ibl_helpers.cpp"
"ibl_helpers.h"
"tiny_gltf_setup.cpp")
add_executable(model_render
"model_render.cpp"
"asset_loader.cpp"
"asset_loader.h"
"light_manager.cpp"
"light_manager.h"
"nodes.cpp"
"nodes.h"
"ibl_helpers.cpp"
"ibl_helpers.h"
"tiny_gltf_setup.cpp")
add_shader(model_render "shader/model.vs.hlsl")
add_shader(model_render "shader/model.ps.hlsl")
add_shader(model_render "shader/eqrect_to_cube.cs.hlsl")
add_shader(model_render "shader/background.vs.hlsl")
add_shader(model_render "shader/background.ps.hlsl")
add_shader(model_render "shader/diffuse_irradiance.cs.hlsl")
add_shader(model_render "shader/prefilter.cs.hlsl")
add_shader(model_render "shader/brdf_lut.cs.hlsl")
add_shader(model_render "shader/slang/background.slang")
add_shader(model_render "shader/slang/bindless.slang")
add_shader(model_render "shader/slang/common_structs.slang")
add_shader(model_render "shader/slang/environment.slang")
add_shader(model_render "shader/slang/eqrect_to_cube.slang")
add_shader(model_render "shader/slang/ibl_common.slang")
add_shader(model_render "shader/slang/model.slang")
add_shader(model_render "shader/background.slang")
add_shader(model_render "shader/bindless.slang")
add_shader(model_render "shader/common_structs.slang")
add_shader(model_render "shader/environment.slang")
add_shader(model_render "shader/eqrect_to_cube.slang")
add_shader(model_render "shader/ibl_common.slang")
add_shader(model_render "shader/model.slang")
target_link_libraries(model_render PRIVATE aster_core)
target_link_libraries(model_render PRIVATE util_helper)

View File

@ -10,7 +10,6 @@
#include "asset_loader.h"
#include "helpers.h"
#include "pipeline_utils.h"
#include "aster/systems/commit_manager.h"
#include "aster/systems/device.h"

View File

@ -14,22 +14,19 @@
#include "aster/core/pipeline.h"
#include "aster/core/swapchain.h"
#include "aster/core/window.h"
#include "aster/util/files.h"
#include "aster/systems/commit_manager.h"
#include "aster/systems/device.h"
#include "asset_loader.h"
#include "frame.h"
#include "helpers.h"
#include "light_manager.h"
#include "aster/util/files.h"
#include "gui.h"
#include "ibl_helpers.h"
#include "pipeline_utils.h"
#include <EASTL/array.h>
#include <aster/systems/commit_manager.h>
#include <aster/systems/device.h>
#include <tiny_gltf.h>
#include <filesystem>
constexpr auto PIPELINE_CACHE_FILE = "PipelineCacheData.bin";
constexpr auto MODEL_FILE = "model/DamagedHelmet.glb";
@ -172,7 +169,7 @@ main(int, char **)
.m_AppName = "ModelRender",
.m_AppVersion = VERSION,
.m_PipelineCacheData = pipelineCacheData,
.m_ShaderSearchPaths = {"shader/slang/"},
.m_ShaderSearchPaths = {"shader/"},
}};
AssetLoader assetLoader{device};
@ -321,13 +318,6 @@ main(int, char **)
.subresourceRange = subresourceRange,
};
auto primeBarriers = [](const eastl::span<vk::ImageMemoryBarrier2> &barriers, const vk::Image image) {
for (auto &bar : barriers)
{
bar.image = image;
}
};
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> attachmentImages;

View File

@ -1,354 +0,0 @@
// =============================================
// Aster: pipeline_utils.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "pipeline_utils.h"
#include "aster/core/device.h"
#include "aster/core/pipeline.h"
#include "helpers.h"
#include "aster/systems/commit_manager.h"
#include "aster/util/files.h"
#include <EASTL/array.h>
Pipeline
CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *commitManager)
{
// Pipeline Setup
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
eastl::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
descriptorSetLayouts.push_back(commitManager->GetDescriptorSetLayout());
{
eastl::array descriptorSetLayoutBindings = {
vk::DescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
AbortIfFailed(
device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout));
descriptorSetLayouts.push_back(descriptorSetLayout);
}
vk::PushConstantRange pushConstantRange = {
.stageFlags = vk::ShaderStageFlagBits::eAll,
.offset = 0,
.size = 32,
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
};
vk::PipelineLayout pipelineLayout;
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
device->SetName(pipelineLayout, "Box Layout");
descriptorSetLayouts[0] = nullptr; // Not owned.
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = false,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eBack,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = true,
.depthWriteEnable = true,
.depthCompareOp = vk::CompareOp::eLess,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = false,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &attachmentFormat,
.depthAttachmentFormat = vk::Format::eD24UnormS8Uint,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
AbortIfFailed(
device->m_Device.createGraphicsPipelines(device->m_PipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
device->SetName(pipeline, "Box Pipeline");
device->m_Device.destroy(vertexShaderModule, nullptr);
device->m_Device.destroy(fragmentShaderModule, nullptr);
return {device, pipelineLayout, pipeline, std::move(descriptorSetLayouts), Pipeline::Kind::eGraphics};
}
Pipeline
CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *commitManager)
{
// Pipeline Setup
auto vertexShaderModule = CreateShader(device, BACKGROUND_VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, BACKGROUND_FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
eastl::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
descriptorSetLayouts.push_back(commitManager->GetDescriptorSetLayout());
{
eastl::array descriptorSetLayoutBindings = {
vk::DescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eUniformBuffer,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
AbortIfFailed(
device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout));
descriptorSetLayouts.push_back(descriptorSetLayout);
}
vk::PushConstantRange pushConstantRange = {
.stageFlags = vk::ShaderStageFlagBits::eAll,
.offset = 0,
.size = 32,
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
};
vk::PipelineLayout pipelineLayout;
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
device->SetName(pipelineLayout, "Box Layout");
descriptorSetLayouts[0] = nullptr; // Not owned.
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = false,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eBack,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = true,
.depthWriteEnable = true,
.depthCompareOp = vk::CompareOp::eLessOrEqual,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = false,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &attachmentFormat,
.depthAttachmentFormat = vk::Format::eD24UnormS8Uint,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
AbortIfFailed(
device->m_Device.createGraphicsPipelines(device->m_PipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
device->SetName(pipeline, "BG Pipeline");
device->m_Device.destroy(vertexShaderModule, nullptr);
device->m_Device.destroy(fragmentShaderModule, nullptr);
return {device, pipelineLayout, pipeline, std::move(descriptorSetLayouts), Pipeline::Kind::eGraphics};
}
vk::ShaderModule
CreateShader(const Device *device, cstr shaderFile)
{
eastl::vector<u32> shaderCode = ReadFile(shaderFile);
const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {
.codeSize = shaderCode.size() * sizeof(u32),
.pCode = shaderCode.data(),
};
vk::ShaderModule shaderModule;
AbortIfFailedMV(device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule),
"Shader {} could not be created.", shaderFile);
return shaderModule;
}

View File

@ -1,30 +0,0 @@
// =============================================
// Aster: pipeline_utils.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
namespace systems
{
class CommitManager;
}
struct GpuResourceManager;
struct Swapchain;
struct Device;
struct Pipeline;
constexpr auto VERTEX_SHADER_FILE = "shader/model.vs.hlsl.spv";
constexpr auto FRAGMENT_SHADER_FILE = "shader/model.ps.hlsl.spv";
constexpr auto BACKGROUND_VERTEX_SHADER_FILE = "shader/background.vs.hlsl.spv";
constexpr auto BACKGROUND_FRAGMENT_SHADER_FILE = "shader/background.ps.hlsl.spv";
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
Pipeline
CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *resourceManager);
Pipeline CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat,
const systems::CommitManager *resourceManager);

View File

@ -1,38 +0,0 @@
#include "graphics_structs.hlsli"
struct PS_Input
{
float3 WorldPosition : POSITION;
};
struct PS_Output
{
float4 Color : SV_Target0;
};
PS_Output main(PS_Input StageInput)
{
PS_Output StageOutput;
float3 Direction = normalize(StageInput.WorldPosition - Camera.Position.xyz);
#ifndef _DEBUG
float4 Color = TextureCubes[Lights.EnvCubeHandle].Sample(ImmutableSamplers[Lights.EnvCubeHandle], Direction);
#else
float4 Color;
if ((PushConstant.DebugFlags & SHOW_DIFFUSE_BIT) > 0)
{
Color = TextureCubes[Lights.DiffuseIrradianceHandle].Sample(ImmutableSamplers[Lights.DiffuseIrradianceHandle], Direction);
}
else if ((PushConstant.DebugFlags & SHOW_PREFILTER_BIT) > 0)
{
Color = TextureCubes[Lights.PrefilterHandle].Sample(ImmutableSamplers[Lights.PrefilterHandle], Direction);
}
else
{
Color = TextureCubes[Lights.EnvCubeHandle].Sample(ImmutableSamplers[Lights.EnvCubeHandle], Direction);
}
#endif
StageOutput.Color = float4(Uncharted2Tonemap(Color.rgb), Color.a);
return StageOutput;
}

View File

@ -1,32 +0,0 @@
#include "graphics_structs.hlsli"
struct VS_Input
{
uint VertexIndex : SV_VertexID;
};
struct VS_Output
{
float4 VertexPosition : SV_Position;
float3 WorldPosition : POSITION;
};
VS_Output main(VS_Input StageInput)
{
float3 Points[] =
{
float3(-1.0f, -1.0f, 1.0f),
float3(3.0f, -1.0f, 1.0f),
float3(-1.0f, 3.0f, 1.0f),
};
VS_Output StageOutput;
StageOutput.VertexPosition = float4(Points[StageInput.VertexIndex], 1.0f);
float4 ClipSpace = mul(Camera.InvProjection, float4(Points[StageInput.VertexIndex], 1.0f));
float4 WorldSpace = mul(Camera.InvView, ClipSpace / ClipSpace.wwww);
StageOutput.WorldPosition = WorldSpace.xyz;
return StageOutput;
}

View File

@ -1,69 +0,0 @@
struct VertexData
{
float4 Normal;
float2 TexCoord0;
float2 TexCoord1;
float4 Color0;
};
struct TransformData
{
float4x4 Transform;
float4x4 NormalTransform;
};
struct MaterialData
{
float AlbedoFactor[4];
float EmissionFactor[3];
float MetalFactor;
float RoughFactor;
uint AlbedoTex;
uint NormalTex;
uint MetalRoughTex;
uint OcclusionTex;
uint EmissionTex;
};
struct PointLight
{
float Position[3];
float Range;
uint Color;
float Intensity;
};
struct DirectionalLight
{
float Direction[3];
float Validity_;
uint Color;
float Intensity;
};
// Little Endian storage. First short is least significant.
#define IndexerCount(Indexer) (Indexer & 0xFFFF)
#define IndexerOffset(Indexer) ((Indexer & 0xFFFF0000) >> 16);
#define INVALID_HANDLE 0xFFFFFFFF
static const float HALF_PI = 1.57079633f;
static const float PI = 3.14159265f;
static const float TAU = 6.28318530f;
[[vk::binding(0, 0)]] StructuredBuffer<float4> VertexBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<VertexData> VertexDataBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<MaterialData> MaterialsBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<TransformData> NodeBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<PointLight> PointLightBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<DirectionalLight> DirectionalLightBuffer[];
[[vk::binding(1, 0)]] Texture2D<float4> Textures[];
[[vk::binding(1, 0)]] Texture2D<float2> TexturesRG[];
[[vk::binding(1, 0)]] TextureCube<float4> TextureCubes[];
[[vk::binding(1, 0)]] SamplerState ImmutableSamplers[];
[[vk::binding(2, 0)]] RWTexture2D<float4> StorageTextures[];
[[vk::binding(2, 0)]] RWTexture2D<float2> StorageTexturesRG[];
[[vk::binding(2, 0)]] RWTexture2DArray<float4> StorageTextureArrays[];

View File

@ -1,82 +0,0 @@
#include "ibl_common.hlsli"
struct Block
{
uint OutputTextureHandle;
};
[[vk::push_constant]]
Block Pcb;
float GeometrySchlickGGX(float NdotV, float Roughness)
{
float R = Roughness;
// (Rough + 1)^2 / 8 for Punctual Lights
// Rough^2 / 2 for IBL
float K = (R * R) / 2.0;
float Numerator = NdotV;
float Denominator = NdotV * (1.0f - K) + K;
return Numerator / Denominator;
}
float GeometrySmith(float NdotV, float NdotL, float Roughness)
{
float GGX1 = GeometrySchlickGGX(NdotV, Roughness);
float GGX2 = GeometrySchlickGGX(NdotL, Roughness);
return GGX1 * GGX2;
}
float2 IntegrateBRDF(float NdotV, float Roughness)
{
float3 ViewDir;
ViewDir.x = sqrt(1.0f - NdotV * NdotV);
ViewDir.y = 0.0f;
ViewDir.z = NdotV;
float A = 0.0f;
float B = 0.0f;
float3 Normal = float3(0.0f, 0.0f, 1.0f);
const uint SAMPLE_COUNT = 1024u;
for (uint i = 0u; i < SAMPLE_COUNT; ++i)
{
float2 Xi = Hammersley(i, SAMPLE_COUNT);
float3 Halfway = ImportanceSampleGGX(Xi, Normal, Roughness);
float3 LightDir = normalize(2.0f * dot(ViewDir, Halfway) * Halfway - ViewDir);
float NdotL = max(LightDir.z, 0.0f);
float NdotH = max(Halfway.z, 0.0f);
float VdotH = max(dot(ViewDir, Halfway), 0.0f);
if (NdotL > 0.0f)
{
float G = GeometrySmith(NdotV, NdotL, Roughness);
float G_Vis = (G * VdotH) / max((NdotH * NdotV), 0.0001f);
float Fc = pow(1.0f - VdotH, 5.0f);
A += (1.0f - Fc) * G_Vis;
B += Fc * G_Vis;
}
}
A /= float(SAMPLE_COUNT);
B /= float(SAMPLE_COUNT);
return float2(A, B);
}
[numthreads(16, 16, 1)]
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
{
float Width, Height;
StorageTexturesRG[Pcb.OutputTextureHandle].GetDimensions(Width, Height);
float2 UV = GlobalInvocationID.xy / float2(Width, Height);
float2 IntegratedBRDF = IntegrateBRDF(UV.x, UV.y);
StorageTexturesRG[Pcb.OutputTextureHandle][GlobalInvocationID.xy] = IntegratedBRDF;
}

View File

@ -1,52 +0,0 @@
#include "ibl_common.hlsli"
struct Block
{
uint SkyboxHandle;
uint OutputTextureHandle;
int CubeSide;
};
[[vk::push_constant]]
Block pcb;
/*
| Axis | Layer | Up |
|:----:|:-----:|:--:|
| +x | 0 | -y |
| -x | 1 | -y |
| +y | 2 | +z |
| -y | 3 | -z |
| -z | 4 | -y |
| +z | 5 | -y |
*/
[numthreads(16, 16, 1)]
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
{
float3 Forward, Up, Right;
Forward = GetCubeDir(GlobalInvocationID, pcb.CubeSide);
Up = abs(Forward.y) < 1.0f ? float3(0.0f, 1.0f, 0.0f) : float3(1.0f, 0.0f, 0.0f); // 0.01f offset to
Right = normalize(cross(Up, Forward));
Up = normalize(cross(Forward, Right));
float3 Irradiance = 0.0f.xxx;
float3 IrrDirr = 0.0f.xxx;
float SampleStep = 0.005f;
float SampleCount = 0.0f;
for (float Azimuth = 0.0f; Azimuth < TAU; Azimuth += SampleStep)
{
for (float Zenith = 0.0f; Zenith < HALF_PI; Zenith += SampleStep)
{
float3 DirectionTanSpace = float3(sin(Zenith) * cos(Azimuth), sin(Zenith) * sin(Azimuth), cos(Zenith));
float3 DirectionWorld = DirectionTanSpace.x * Right + DirectionTanSpace.y * Up + DirectionTanSpace.z * Forward;
Irradiance += TextureCubes[pcb.SkyboxHandle].SampleLevel(ImmutableSamplers[pcb.SkyboxHandle], DirectionWorld, 0).xyz * (cos(Zenith) * sin(Zenith));
SampleCount++;
}
}
StorageTextureArrays[pcb.OutputTextureHandle][GlobalInvocationID.xyz] = PI * float4(Irradiance * (1.0f / SampleCount), 1.0f);
}

View File

@ -1,29 +0,0 @@
#include "ibl_common.hlsli"
struct Block
{
uint HdrEnvHandle;
uint OutputTextureHandle;
int CubeSide;
};
[[vk::push_constant]]
Block pcb;
float2 SampleSphericalMap(float3 v)
{
const float2 InvTan = float2(0.1591f, 0.3183f); // (1/2PI, 1/PI)
float2 UV = float2(atan2(-v.x, v.z), asin(-v.y)); // (-PI, -PI/2) to (PI, PI/2)
UV *= InvTan; // (-1/2, -1/2) to (1/2, 1/2)
UV += 0.5f.xx; // (0, 0) to (1, 1)
return UV;
}
[numthreads(16, 16, 1)]
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
{
float3 LocalDir = GetCubeDir(GlobalInvocationID, pcb.CubeSide);
float2 UV = SampleSphericalMap(LocalDir);
StorageTextureArrays[pcb.OutputTextureHandle][GlobalInvocationID.xyz] = Textures[pcb.HdrEnvHandle].SampleLevel(ImmutableSamplers[pcb.HdrEnvHandle], UV, 0);
}

View File

@ -1,66 +0,0 @@
#include "bindless_structs.hlsli"
struct CameraData
{
float4x4 View; // 64
float4x4 Projection; // 128
float4x4 InvView; // 192
float4x4 InvProjection; // 256
float4 Position; // 272
};
struct Lighting
{
uint EnvCubeHandle; // 4
uint DiffuseIrradianceHandle; // 8
uint PrefilterHandle; // 12
uint BrdfLutHandle; // 16
uint LightHandle; // 20
uint PointLightIndexer; // 24
uint DirectionalLightIndexer; // 28
};
struct ModelHandles
{
uint VertexBufferHandle; // 4
uint VertexDataHandle; // 8
uint MaterialBufferHandle; // 12
uint NodeBufferHandle; // 16
};
struct Block
{
uint VertexBufferHandle; // 4
uint VertexDataHandle; // 8
uint MaterialBufferHandle; // 12
uint NodeBufferHandle; // 16
uint DebugFlags; // 20
int MaterialIdx; // 24
uint NodeIdx; // 28
};
static const uint USE_DIFFUSE_BIT = 1;
static const uint USE_SPECULAR_BIT = 2;
static const uint SHOW_DIFFUSE_BIT = 4;
static const uint SHOW_PREFILTER_BIT = 8;
[[vk::binding(0, 1)]] ConstantBuffer<CameraData> Camera;
[[vk::binding(1, 1)]] ConstantBuffer<Lighting> Lights;
[[vk::binding(2, 1)]] ConstantBuffer<ModelHandles> Model;
[[vk::push_constant]]
Block PushConstant;
float3 Uncharted2Tonemap(float3 color)
{
float A = 0.15f;
float B = 0.50f;
float C = 0.10f;
float D = 0.20f;
float E = 0.02f;
float F = 0.30f;
float W = 11.2f;
return ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
}

View File

@ -1,77 +0,0 @@
#include "bindless_structs.hlsli"
/*
The Goal is simply to convert from a (0,0,0) to (CubeSide, CubeSide, FaceCount) Invocation ID space to a
(-1,-1,-1) to (1, 1, 1) space.
| Axis | Layer | Up |
|:----:|:-----:|:--:|
| +x | 0 | -y |
| -x | 1 | -y |
| +y | 2 | +z |
| -y | 3 | -z |
| -z | 4 | -y |
| +z | 5 | -y |
*/
float3 GetCubeDir(uint3 GlobalInvocationID, float SideLength)
{
float2 FaceUV = float2(GlobalInvocationID.xy) / SideLength; // (0, SideLength) -> (0, 1)
FaceUV = 2.0f * FaceUV - 1.0f; // (0, 1) -> (-1, 1)
switch (GlobalInvocationID.z)
{
case 0:
return normalize(float3(1.0f, -FaceUV.y, -FaceUV.x)); // Face +X; x = 1, y = -v, z = -u
case 1:
return normalize(float3(-1.0f, -FaceUV.y, FaceUV.x)); // Face -X; x = -1, y = -v, z = u
case 2:
return normalize(float3(FaceUV.x, 1.0f, FaceUV.y)); // Face +Y; x = u, y = 1, z = v
case 3:
return normalize(float3(FaceUV.x, -1.0f, -FaceUV.y)); // Face -Y; x=u, y=-1, z=-v
case 4:
return normalize(float3(FaceUV.x, -FaceUV.y, 1.0f)); // Face +Z; x=u,y=-v, z=1
case 5:
return normalize(float3(-FaceUV.x, -FaceUV.y, -1.0f)); // Face -Z; x=u,y=-v, z=-1
default:
// Never reach here.
return 0.0f.xxx;
}
}
float RadicalInverse_VdC(uint Bits)
{
Bits = (Bits << 16u) | (Bits >> 16u);
Bits = ((Bits & 0x55555555u) << 1u) | ((Bits & 0xAAAAAAAAu) >> 1u);
Bits = ((Bits & 0x33333333u) << 2u) | ((Bits & 0xCCCCCCCCu) >> 2u);
Bits = ((Bits & 0x0F0F0F0Fu) << 4u) | ((Bits & 0xF0F0F0F0u) >> 4u);
Bits = ((Bits & 0x00FF00FFu) << 8u) | ((Bits & 0xFF00FF00u) >> 8u);
return float(Bits) * 2.3283064365386963e-10; // / 0x100000000
}
float2 Hammersley(uint SampleIndex, uint SampleCount)
{
return float2(float(SampleIndex) / float(SampleCount), RadicalInverse_VdC(SampleIndex));
}
float3 ImportanceSampleGGX(float2 Xi, float3 Normal, float Roughness)
{
float A = Roughness * Roughness;
float Phi = 2.0f * PI * Xi.x;
float CosTheta = sqrt((1.0f - Xi.y) / (1.0f + (A * A - 1.0f) * Xi.y));
float SinTheta = sqrt(1.0f - CosTheta * CosTheta);
// from spherical coordinates to cartesian coordinates
float3 H;
H.x = cos(Phi) * SinTheta;
H.y = sin(Phi) * SinTheta;
H.z = CosTheta;
// from tangent-space vector to world-space sample vector
float3 Up = abs(Normal.z) < 0.999f ? float3(0.0f, 0.0f, 1.0f) : float3(1.0f, 0.0f, 0.0f);
float3 Tangent = normalize(cross(Up, Normal));
float3 Bitangent = cross(Normal, Tangent);
float3 SampleVec = Tangent * H.x + Bitangent * H.y + Normal * H.z;
return normalize(SampleVec);
}

View File

@ -1,322 +0,0 @@
#include "graphics_structs.hlsli"
struct FS_Input
{
float4 InPosition : POSITION;
float4 InNormal : NORMAL;
float4 InColor : COLOR0;
float2 InUV0 : TEXCOORD0;
};
struct FS_Output
{
float4 ColorTarget : SV_Target0;
};
float4 GetAlbedo(float2 UV, float4 InColor)
{
float4 AlbedoFactor = (float4) MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].AlbedoFactor;
uint AlbedoTexId = MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].AlbedoTex;
return AlbedoFactor * InColor * (AlbedoTexId != INVALID_HANDLE ? Textures[NonUniformResourceIndex(AlbedoTexId)].Sample(ImmutableSamplers[NonUniformResourceIndex(AlbedoTexId)], UV) : 1.0f.xxxx);
}
float GetOcclusion(float2 UV)
{
uint OcclusionTexId = MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].OcclusionTex;
return OcclusionTexId != INVALID_HANDLE ? Textures[NonUniformResourceIndex(OcclusionTexId)].Sample(ImmutableSamplers[NonUniformResourceIndex(OcclusionTexId)], UV).r : 1.0f;
}
float3 GetEmissive(float2 UV)
{
float3 EmissionFactor = (float3) MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].EmissionFactor;
uint EmissionTexId = MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].EmissionTex;
return EmissionFactor * (EmissionTexId != INVALID_HANDLE ? Textures[NonUniformResourceIndex(EmissionTexId)].Sample(ImmutableSamplers[NonUniformResourceIndex(EmissionTexId)], UV).rgb : 1.0f.xxx);
}
float3 GetNormal(float3 Position, float3 Normal, float2 UV)
{
float3 N = normalize(Normal);
uint NormalTexId = MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].NormalTex;
if (NormalTexId == INVALID_HANDLE)
{
return N;
}
float3 TangentSpaceNormal = Textures[NonUniformResourceIndex(NormalTexId)].Sample(ImmutableSamplers[NonUniformResourceIndex(NormalTexId)], UV).xyz * 2.0f - 1.0f;
float3 q1 = ddx(Position);
float3 q2 = ddy(Position);
float2 st1 = ddx(UV);
float2 st2 = ddy(UV);
float3 T = normalize(q1 * st2.y - q2 * st1.y).xyz;
float3 B = -normalize(cross(N, T));
float3x3 TBN = float3x3(T, B, N); // Construction is Row by Row.
return normalize(mul(TangentSpaceNormal, TBN)); // Post multiple to avoid transpose.
}
float2 GetMetalRough(float2 UV)
{
float2 MetalRoughFactors = float2(MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].MetalFactor, MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].RoughFactor);
uint MetalRoughTexId = MaterialsBuffer[PushConstant.MaterialBufferHandle][NonUniformResourceIndex(PushConstant.MaterialIdx)].MetalRoughTex;
return MetalRoughFactors * (MetalRoughTexId != INVALID_HANDLE ? Textures[NonUniformResourceIndex(MetalRoughTexId)].Sample(ImmutableSamplers[NonUniformResourceIndex(MetalRoughTexId)], UV).bg : 1.0f.xx); // Metal is B, Rough is G.
}
float3 SampleIrradiance(float3 Direction)
{
if (Lights.DiffuseIrradianceHandle != INVALID_HANDLE)
{
return TextureCubes[Lights.DiffuseIrradianceHandle].Sample(ImmutableSamplers[Lights.DiffuseIrradianceHandle], Direction).rgb;
}
return 0.04f.xxx;
}
float3 SamplePrefiltered(float3 Direction, float Roughness)
{
const float MAX_MIP_LEVEL = 5.0f;
float Mip = MAX_MIP_LEVEL * Roughness;
if (Lights.PrefilterHandle != INVALID_HANDLE)
{
return TextureCubes[Lights.PrefilterHandle].SampleLevel(ImmutableSamplers[Lights.PrefilterHandle], Direction, Mip).rgb;
}
return 0.0f.xxx;
}
float2 SampleBrdfLut(float NdotV, float Roughness)
{
if (Lights.BrdfLutHandle != INVALID_HANDLE)
{
return TexturesRG[Lights.BrdfLutHandle].Sample(ImmutableSamplers[Lights.BrdfLutHandle], float2(NdotV, Roughness));
}
return 0.0f.xx;
}
float TrowbridgeReitzGGX(float3 Normal, float3 Halfway, float Roughness)
{
float Coeff = Roughness * Roughness;
float Alpha2 = Coeff * Coeff;
float NdotH = max(dot(Normal, Halfway), 0.0f);
float NdotH2 = NdotH * NdotH;
float Numerator = Alpha2;
float Denominator = NdotH2 * (Alpha2 - 1.0f) + 1.0f;
Denominator = PI * Denominator * Denominator;
return Numerator / Denominator;
}
float GeometrySchlickGGX(float NdotV, float Roughness)
{
float R = Roughness + 1.0f;
float K = (R * R) / 8.0f;
float Numerator = NdotV;
float Denominator = NdotV * (1.0f - K) + K;
return Numerator / Denominator;
}
float GeometrySmith(float NdotV, float NdotL, float Roughness)
{
float GGX1 = GeometrySchlickGGX(NdotV, Roughness);
float GGX2 = GeometrySchlickGGX(NdotL, Roughness);
return GGX1 * GGX2;
}
// https://en.wikipedia.org/wiki/Schlick%27s_approximation
float3 FresnelSchlick(float cosine, float3 F_0)
{
return F_0 + (1.0f - F_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
}
// Sebastian Lagarde
float3 FresnelSchlickRoughness(float cosine, float3 F_0, float Roughness)
{
return F_0 + (max((1.0f - Roughness).xxx, F_0) - F_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
}
float3 GetPBRContrib(float3 Albedo, float3 LightColor, float3 ViewDir, float3 Normal, float Metallic, float Roughness, float3 F_0, float3 LightDir, float LightDistance)
{
float Attenuation = 1.0f / (LightDistance * LightDistance); // TODO: Controlled Attenuation
float3 Halfway = normalize(ViewDir + LightDir);
float CosineFactor = max(dot(Halfway, ViewDir), 0.0f);
float NdotV = max(dot(Normal, ViewDir), 0.0f);
float NdotL = max(dot(Normal, LightDir), 0.0f);
float3 Radiance = LightColor * Attenuation;
float NormalDistribution = TrowbridgeReitzGGX(Normal, Halfway, Roughness);
float Geometry = GeometrySmith(NdotV, NdotL, Roughness);
float3 Fresnel = FresnelSchlickRoughness(CosineFactor, F_0, Roughness);
float3 Numerator = (NormalDistribution * Geometry) * Fresnel;
float Denominator = 4.0f * NdotV * NdotL;
float3 Specular = Numerator / (Denominator + 0.00001f);
float3 K_Specular = Fresnel;
float3 K_Diffuse = 1.0f.xxx - K_Specular;
K_Diffuse *= 1.0f - Metallic;
return NdotL * Radiance * (K_Diffuse * Albedo / PI + Specular);
}
float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
{
if (Lights.LightHandle == INVALID_HANDLE)
return 0.0f.xxx;
uint Offset = IndexerOffset(Lights.PointLightIndexer);
uint Count = IndexerCount(Lights.PointLightIndexer);
float3 ViewDir = normalize(Camera.Position.xyz - Position);
float Metallic = MetalRough.r;
float Roughness = MetalRough.g;
// Dielectric F_0 based on LearnOpenGL.
// TODO: Cite
float3 F_0 = 0.04f.xxx;
F_0 = lerp(F_0, Albedo, Metallic);
float3 Contrib = 0.0f;
for (uint i = 0; i < Count; ++i)
{
PointLight Light = PointLightBuffer[Lights.LightHandle][i + Offset];
if (Light.Range < 0.0f)
continue;
float3 LightDir = float3(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;
float3 LightColor = Light.Intensity * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255
Contrib += GetPBRContrib(Albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, LightDistance);
}
return Contrib;
}
float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
{
if (Lights.LightHandle == INVALID_HANDLE)
return 0.0f.xxx;
uint Count = IndexerCount(Lights.DirectionalLightIndexer);
float3 ViewDir = normalize(Camera.Position.xyz - Position);
float Metallic = MetalRough.r;
float Roughness = MetalRough.g;
// Dielectric F_0 based on LearnOpenGL.
// TODO: Cite
float3 F_0 = 0.04f.xxx;
F_0 = lerp(F_0, Albedo, Metallic);
float3 Contrib = 0.0f;
for (uint i = 0; i < Count; ++i)
{
DirectionalLight Light = DirectionalLightBuffer[Lights.LightHandle][i];
if (Light.Validity_ < 0.0f)
continue;
float3 LightDir = -normalize(float3(Light.Direction));
// Color Unpack
float R = (Light.Color & 0xFF000000) >> 24;
float G = (Light.Color & 0x00FF0000) >> 16;
float B = (Light.Color & 0x0000FF00) >> 8;
float3 LightColor = Light.Intensity * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255
Contrib += GetPBRContrib(Albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, 1.0f);
}
return Contrib;
}
float3 GetAmbientInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal, float Occlusion)
{
float3 ViewDir = normalize(Camera.Position.xyz - Position);
float CosineFactor = max(dot(Normal, ViewDir), 0.0f); // Normal instead of Halfway since there's no halfway in ambient.
float Metal = MetalRough.r;
float Roughness = MetalRough.g;
float3 F_0 = 0.04f.xxx;
F_0 = lerp(F_0, Albedo, MetalRough.r);
float3 K_Specular = FresnelSchlickRoughness(CosineFactor, F_0, Roughness);
float3 K_Diffuse = 1.0f.xxx - K_Specular;
K_Diffuse *= 1.0f - Metal; // Metals don't have diffuse/refractions.
float3 ReflectionDir = reflect(-ViewDir, Normal);
float NdotV = max(dot(Normal, ViewDir), 0.0f);
float3 PrefilteredColor = SamplePrefiltered(ReflectionDir, Roughness).rgb;
float2 EnvBRDF = SampleBrdfLut(NdotV, Roughness);
float3 Specular = PrefilteredColor * (K_Specular * EnvBRDF.x + EnvBRDF.y);
float3 DiffuseIrradiance = Albedo * SampleIrradiance(Normal);
#ifdef _DEBUG
if ((PushConstant.DebugFlags & USE_DIFFUSE_BIT) == 0) {
DiffuseIrradiance = 0.0f.xxx;
}
if ((PushConstant.DebugFlags & USE_SPECULAR_BIT) == 0) {
Specular = 0.0f.xxx;
}
#endif
return (K_Diffuse * DiffuseIrradiance + Specular) * Occlusion;
}
FS_Output main(FS_Input StageInput)
{
FS_Output Output;
// TODO: This should be invalid on the CPU side.
if (PushConstant.MaterialIdx < 0)
{
Output.ColorTarget = float4(1.0f, 0.0f, 1.0f, 1.0f);
return Output;
}
float3 Position = StageInput.InPosition.xyz;
float3 Normal = GetNormal(Position, StageInput.InNormal.xyz, StageInput.InUV0);
float4 AlbedoAlpha = GetAlbedo(StageInput.InUV0, StageInput.InColor);
float3 Albedo = AlbedoAlpha.rgb;
float Alpha = AlbedoAlpha.a;
float2 MetalRough = GetMetalRough(StageInput.InUV0);
float3 Emission = GetEmissive(StageInput.InUV0);
float Occlusion = GetOcclusion(StageInput.InUV0);
float3 DirectionalLightLum = GetDirectionalLightInfluence(Albedo, MetalRough, Position, Normal);
float3 PointLighLum = GetPointLightInfluence(Albedo, MetalRough, Position, Normal);
float3 AmbientLum = GetAmbientInfluence(Albedo, MetalRough, Position, Normal, Occlusion);
float3 Color = DirectionalLightLum + PointLighLum + AmbientLum;
Output.ColorTarget = float4(Uncharted2Tonemap(Color + Emission), Alpha);
return Output;
}

View File

@ -1,67 +0,0 @@
#include "graphics_structs.hlsli"
struct VS_Input
{
uint VertexIndex : SV_VertexID;
};
struct VS_Output
{
float4 WorldPosition : POSITION;
float4 WorldNormal : NORMAL;
float4 VertexColor : COLOR0;
float2 UV0 : TEXCOORD0;
float4 VertexPosition : SV_Position;
};
float2 GetUV(uint VertexIdx)
{
uint BufferId = PushConstant.VertexDataHandle;
return VertexDataBuffer[BufferId][VertexIdx].TexCoord0.xy;
}
float4 GetPosition(uint VertexIdx)
{
uint BufferId = PushConstant.VertexBufferHandle;
return float4(VertexBuffer[BufferId][VertexIdx].xyz, 1.0f);
}
float4 GetNormal(uint VertexIdx)
{
uint BufferId = PushConstant.VertexDataHandle;
return VertexDataBuffer[BufferId][VertexIdx].Normal;
}
float4 GetColor(uint VertexIdx)
{
uint BufferId = PushConstant.VertexDataHandle;
return VertexDataBuffer[BufferId][VertexIdx].Color0;
}
float4x4 GetNodeTransform(uint NodeIndex)
{
uint BufferId = PushConstant.NodeBufferHandle;
return NodeBuffer[BufferId][NodeIndex].Transform;
}
float4x4 GetNormalTransform(uint NodeIndex)
{
uint BufferId = PushConstant.NodeBufferHandle;
return NodeBuffer[BufferId][NodeIndex].NormalTransform;
}
VS_Output main(VS_Input StageInput)
{
VS_Output Output;
float4 GlobalPosition = mul(GetNodeTransform(PushConstant.NodeIdx), GetPosition(StageInput.VertexIndex));
float4 ClipSpace = mul(Camera.View, GlobalPosition);
Output.VertexPosition = mul(Camera.Projection, ClipSpace);
Output.WorldPosition = GlobalPosition;
Output.UV0 = GetUV(StageInput.VertexIndex);
Output.VertexColor = GetColor(StageInput.VertexIndex);
Output.WorldNormal = mul(GetNormalTransform(PushConstant.NodeIdx), GetNormal(StageInput.VertexIndex));
return Output;
}

View File

@ -1,68 +0,0 @@
#include "ibl_common.hlsli"
struct Block
{
uint SkyboxHandle;
uint OutputTextureHandle;
int CubeSide;
float Roughness;
uint EnvRes;
};
[[vk::push_constant]]
Block Pcb;
float TrowbridgeReitzGGX(float NdotH, float Roughness)
{
float Coeff = Roughness * Roughness;
float Alpha2 = Coeff * Coeff;
float NdotH2 = NdotH * NdotH;
float Numerator = Alpha2;
float Denominator = NdotH2 * (Alpha2 - 1.0f) + 1.0f;
Denominator = PI * Denominator * Denominator;
return Numerator / Denominator;
}
float GetSampleMipLevel(float NdotH, float HdotV, float SampleCount)
{
float D = TrowbridgeReitzGGX(NdotH, Pcb.Roughness);
float Pdf = (D * NdotH / (4.0f * HdotV)) + 0.0001f;
float SurfAreaTexel = 4.0f * PI / (6.0f * Pcb.EnvRes * Pcb.EnvRes);
float SurfAreaSample = 1.0f / (SampleCount * Pdf + 0.0001f);
return Pcb.Roughness == 0.0f ? 0.0f : 0.5f * log2(SurfAreaSample / SurfAreaTexel);
}
[numthreads(16, 16, 1)]
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
{
float3 Normal = GetCubeDir(GlobalInvocationID, Pcb.CubeSide);
float3 ViewDir = Normal;
const uint SAMPLE_COUNT = 2048u;
float TotalWeight = 0.0f;
float3 PrefilterColor = 0.0f.xxx;
for (uint i = 0u; i < SAMPLE_COUNT; ++i)
{
float2 Xi = Hammersley(i, SAMPLE_COUNT);
float3 Halfway = ImportanceSampleGGX(Xi, Normal, Pcb.Roughness);
float3 LightDir = normalize(2.0 * dot(ViewDir, Halfway) * Halfway - ViewDir);
float NdotH = max(dot(Normal, Halfway), 0.0f);
float MipLevel = GetSampleMipLevel(NdotH, NdotH /* N = V :: NdotH = HdotV */, SAMPLE_COUNT);
float NdotL = max(dot(Normal, LightDir), 0.0);
if (NdotL > 0.0)
{
PrefilterColor += TextureCubes[Pcb.SkyboxHandle].SampleLevel(ImmutableSamplers[Pcb.SkyboxHandle], LightDir, MipLevel).rgb * NdotL;
TotalWeight += NdotL;
}
}
PrefilterColor = PrefilterColor / TotalWeight;
StorageTextureArrays[Pcb.OutputTextureHandle][GlobalInvocationID] = float4(PrefilterColor, 1.0f);
}