General Cleanup.
This commit is contained in:
parent
3ca3beb1e4
commit
56dd76d16e
|
|
@ -31,9 +31,3 @@ function(add_shader TARGET SHADER)
|
||||||
set_source_files_properties(${current-output-path} PROPERTIES GENERATED TRUE)
|
set_source_files_properties(${current-output-path} PROPERTIES GENERATED TRUE)
|
||||||
target_sources(${TARGET} PRIVATE ${current-output-path})
|
target_sources(${TARGET} PRIVATE ${current-output-path})
|
||||||
endfunction(add_shader)
|
endfunction(add_shader)
|
||||||
|
|
||||||
function(add_shaders TARGET SHADERS)
|
|
||||||
foreach(shader IN ${SHADERS})
|
|
||||||
add_shader(TARGET ${shader})
|
|
||||||
endforeach()
|
|
||||||
endfunction(add_shaders)
|
|
||||||
|
|
@ -5,35 +5,25 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address")
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address")
|
||||||
find_path(TINYGLTF_INCLUDE_DIRS "tiny_gltf.h")
|
find_path(TINYGLTF_INCLUDE_DIRS "tiny_gltf.h")
|
||||||
|
|
||||||
add_executable(model_render "model_render.cpp"
|
add_executable(model_render
|
||||||
"pipeline_utils.cpp"
|
"model_render.cpp"
|
||||||
"pipeline_utils.h"
|
"asset_loader.cpp"
|
||||||
"asset_loader.cpp"
|
"asset_loader.h"
|
||||||
"asset_loader.h"
|
"light_manager.cpp"
|
||||||
"light_manager.cpp"
|
"light_manager.h"
|
||||||
"light_manager.h"
|
"nodes.cpp"
|
||||||
"nodes.cpp"
|
"nodes.h"
|
||||||
"nodes.h"
|
"ibl_helpers.cpp"
|
||||||
"ibl_helpers.cpp"
|
"ibl_helpers.h"
|
||||||
"ibl_helpers.h"
|
"tiny_gltf_setup.cpp")
|
||||||
"tiny_gltf_setup.cpp")
|
|
||||||
|
|
||||||
add_shader(model_render "shader/model.vs.hlsl")
|
add_shader(model_render "shader/background.slang")
|
||||||
add_shader(model_render "shader/model.ps.hlsl")
|
add_shader(model_render "shader/bindless.slang")
|
||||||
add_shader(model_render "shader/eqrect_to_cube.cs.hlsl")
|
add_shader(model_render "shader/common_structs.slang")
|
||||||
add_shader(model_render "shader/background.vs.hlsl")
|
add_shader(model_render "shader/environment.slang")
|
||||||
add_shader(model_render "shader/background.ps.hlsl")
|
add_shader(model_render "shader/eqrect_to_cube.slang")
|
||||||
add_shader(model_render "shader/diffuse_irradiance.cs.hlsl")
|
add_shader(model_render "shader/ibl_common.slang")
|
||||||
add_shader(model_render "shader/prefilter.cs.hlsl")
|
add_shader(model_render "shader/model.slang")
|
||||||
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")
|
|
||||||
|
|
||||||
target_link_libraries(model_render PRIVATE aster_core)
|
target_link_libraries(model_render PRIVATE aster_core)
|
||||||
target_link_libraries(model_render PRIVATE util_helper)
|
target_link_libraries(model_render PRIVATE util_helper)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
#include "asset_loader.h"
|
#include "asset_loader.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "pipeline_utils.h"
|
|
||||||
|
|
||||||
#include "aster/systems/commit_manager.h"
|
#include "aster/systems/commit_manager.h"
|
||||||
#include "aster/systems/device.h"
|
#include "aster/systems/device.h"
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,19 @@
|
||||||
#include "aster/core/pipeline.h"
|
#include "aster/core/pipeline.h"
|
||||||
#include "aster/core/swapchain.h"
|
#include "aster/core/swapchain.h"
|
||||||
#include "aster/core/window.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 "asset_loader.h"
|
||||||
#include "frame.h"
|
|
||||||
#include "helpers.h"
|
|
||||||
#include "light_manager.h"
|
#include "light_manager.h"
|
||||||
|
|
||||||
#include "aster/util/files.h"
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "ibl_helpers.h"
|
#include "ibl_helpers.h"
|
||||||
#include "pipeline_utils.h"
|
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
#include <aster/systems/commit_manager.h>
|
|
||||||
#include <aster/systems/device.h>
|
|
||||||
#include <tiny_gltf.h>
|
#include <tiny_gltf.h>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
constexpr auto PIPELINE_CACHE_FILE = "PipelineCacheData.bin";
|
constexpr auto PIPELINE_CACHE_FILE = "PipelineCacheData.bin";
|
||||||
constexpr auto MODEL_FILE = "model/DamagedHelmet.glb";
|
constexpr auto MODEL_FILE = "model/DamagedHelmet.glb";
|
||||||
|
|
@ -172,7 +169,7 @@ main(int, char **)
|
||||||
.m_AppName = "ModelRender",
|
.m_AppName = "ModelRender",
|
||||||
.m_AppVersion = VERSION,
|
.m_AppVersion = VERSION,
|
||||||
.m_PipelineCacheData = pipelineCacheData,
|
.m_PipelineCacheData = pipelineCacheData,
|
||||||
.m_ShaderSearchPaths = {"shader/slang/"},
|
.m_ShaderSearchPaths = {"shader/"},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
AssetLoader assetLoader{device};
|
AssetLoader assetLoader{device};
|
||||||
|
|
@ -321,13 +318,6 @@ main(int, char **)
|
||||||
.subresourceRange = subresourceRange,
|
.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> depthImages;
|
||||||
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> attachmentImages;
|
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> attachmentImages;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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[];
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue