Compute and visualize Diffuse Irradiance.
This commit is contained in:
parent
f735b63d7e
commit
ba2e21f52e
|
|
@ -22,7 +22,7 @@ TextureManager::Init(const u32 maxCapacity)
|
||||||
TextureHandle
|
TextureHandle
|
||||||
TextureManager::Commit(Texture *texture)
|
TextureManager::Commit(Texture *texture)
|
||||||
{
|
{
|
||||||
ERROR_IF(!texture || !texture->IsValid() || !texture->IsOwned(), "Texture must be valid and owned for commital")
|
ERROR_IF(!texture || !texture->IsValid(), "Texture must be valid for commital")
|
||||||
THEN_ABORT(-1);
|
THEN_ABORT(-1);
|
||||||
|
|
||||||
if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE)
|
if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE)
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ add_executable(model_render model_render.cpp
|
||||||
|
|
||||||
add_shader(model_render shader/model.vs.hlsl)
|
add_shader(model_render shader/model.vs.hlsl)
|
||||||
add_shader(model_render shader/model.ps.hlsl)
|
add_shader(model_render shader/model.ps.hlsl)
|
||||||
add_shader(model_render shader/eqrectToCube.cs.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.vs.hlsl)
|
||||||
add_shader(model_render shader/background.ps.hlsl)
|
add_shader(model_render shader/background.ps.hlsl)
|
||||||
|
add_shader(model_render shader/diffuse_irradiance.cs.hlsl)
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -5,27 +5,41 @@
|
||||||
|
|
||||||
#include "ibl_helpers.h"
|
#include "ibl_helpers.h"
|
||||||
|
|
||||||
|
#include "EASTL/fixed_vector.h"
|
||||||
|
#include "EASTL/tuple.h"
|
||||||
#include "asset_loader.h"
|
#include "asset_loader.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "gpu_resource_manager.h"
|
#include "gpu_resource_manager.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "pipeline_utils.h"
|
#include "pipeline_utils.h"
|
||||||
#include "EASTL/tuple.h"
|
|
||||||
|
|
||||||
constexpr cstr EQUIRECT_TO_CUBE_SHADER_FILE = "shader/eqrectToCube.cs.hlsl.spv";
|
constexpr cstr EQUIRECT_TO_CUBE_SHADER_FILE = "shader/eqrect_to_cube.cs.hlsl.spv";
|
||||||
|
constexpr cstr DIFFUSE_IRRADIANCE_SHADER_FILE = "shader/diffuse_irradiance.cs.hlsl.spv";
|
||||||
|
|
||||||
TextureHandle
|
eastl::tuple<TextureHandle, TextureHandle>
|
||||||
CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide, TextureHandle hdrEnv,
|
CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide, TextureHandle hdrEnv,
|
||||||
const cstr name)
|
const cstr name)
|
||||||
{
|
{
|
||||||
GpuResourceManager *resMan = assetLoader->m_ResourceManager;
|
GpuResourceManager *resMan = assetLoader->m_ResourceManager;
|
||||||
const Device *pDevice = resMan->m_Device;
|
const Device *pDevice = resMan->m_Device;
|
||||||
|
|
||||||
StorageTextureCube cubeMap;
|
StackString<64> skyboxName = "Skybox: ";
|
||||||
cubeMap.Init(pDevice, cubeSide, vk::Format::eR16G16B16A16Sfloat, true, false, name ? name : "Env CubeMap");
|
StackString<64> diffuseIrradianceName = "DiffIrr: ";
|
||||||
StorageTextureHandle envStagingHandle = resMan->CommitStorageTexture(&cubeMap);
|
skyboxName += name ? name : "";
|
||||||
|
diffuseIrradianceName += name ? name : "";
|
||||||
|
|
||||||
|
StorageTextureCube skybox;
|
||||||
|
skybox.Init(pDevice, cubeSide, vk::Format::eR16G16B16A16Sfloat, true, false, skyboxName.c_str());
|
||||||
|
TextureHandle skyboxHandle = resMan->CommitTexture(&skybox);
|
||||||
|
StorageTextureHandle skyboxStorageHandle = resMan->CommitStorageTexture(&skybox);
|
||||||
|
|
||||||
|
StorageTextureCube diffuseIrradiance;
|
||||||
|
diffuseIrradiance.Init(pDevice, 64, vk::Format::eR16G16B16A16Sfloat, true, false, diffuseIrradianceName.c_str());
|
||||||
|
TextureHandle diffuseIrradianceHandle = resMan->CommitTexture(&diffuseIrradiance);
|
||||||
|
StorageTextureHandle diffuseIrradianceStorageHandle = resMan->CommitStorageTexture(&diffuseIrradiance);
|
||||||
|
|
||||||
|
#pragma region Dependencies and Copies
|
||||||
vk::ImageSubresourceRange cubeSubresRange = {
|
vk::ImageSubresourceRange cubeSubresRange = {
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
|
|
@ -34,7 +48,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
.layerCount = 6,
|
.layerCount = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::ImageMemoryBarrier2 readyToWriteBarrier = {
|
vk::ImageMemoryBarrier2 readyToWriteBarrierTemplate = {
|
||||||
.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe,
|
.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe,
|
||||||
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
.dstStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
.dstStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
||||||
|
|
@ -43,50 +57,73 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
.newLayout = vk::ImageLayout::eGeneral,
|
.newLayout = vk::ImageLayout::eGeneral,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = cubeMap.m_Image,
|
|
||||||
.subresourceRange = cubeSubresRange,
|
.subresourceRange = cubeSubresRange,
|
||||||
};
|
};
|
||||||
|
eastl::fixed_vector<vk::ImageMemoryBarrier2, 3> readyToWriteBarriers(2, readyToWriteBarrierTemplate);
|
||||||
|
readyToWriteBarriers[0].image = skybox.m_Image;
|
||||||
|
readyToWriteBarriers[1].image = diffuseIrradiance.m_Image;
|
||||||
|
|
||||||
vk::DependencyInfo readyToWriteDependency = {
|
vk::DependencyInfo readyToWriteDependency = {
|
||||||
.imageMemoryBarrierCount = 1,
|
.imageMemoryBarrierCount = Cast<u32>(readyToWriteBarriers.size()),
|
||||||
.pImageMemoryBarriers = &readyToWriteBarrier,
|
.pImageMemoryBarriers = readyToWriteBarriers.data(),
|
||||||
};
|
};
|
||||||
vk::ImageMemoryBarrier2 cubemapToRead = {
|
|
||||||
|
vk::ImageMemoryBarrier2 skyboxWriteToReadBarrier = {
|
||||||
.srcStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
.srcStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
||||||
.srcAccessMask = vk::AccessFlagBits2::eShaderStorageWrite,
|
.srcAccessMask = vk::AccessFlagBits2::eShaderStorageWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eShaderStorageRead,
|
||||||
|
.oldLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.newLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = skybox.m_Image,
|
||||||
|
.subresourceRange = cubeSubresRange,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::DependencyInfo skyboxWriteToReadDependency = {
|
||||||
|
.imageMemoryBarrierCount = 1,
|
||||||
|
.pImageMemoryBarriers = &skyboxWriteToReadBarrier,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::ImageMemoryBarrier2 skyboxToSampleBarrier = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eComputeShader,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eShaderStorageWrite | vk::AccessFlagBits2::eShaderStorageRead,
|
||||||
.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader,
|
.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader,
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eShaderSampledRead,
|
.dstAccessMask = vk::AccessFlagBits2::eShaderSampledRead,
|
||||||
.oldLayout = vk::ImageLayout::eGeneral,
|
.oldLayout = vk::ImageLayout::eGeneral,
|
||||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = cubeMap.m_Image,
|
.image = skybox.m_Image,
|
||||||
.subresourceRange = cubeSubresRange,
|
.subresourceRange = cubeSubresRange,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo cubemapToReadDependency = {
|
vk::DependencyInfo skyboxToSampleDependency = {
|
||||||
.imageMemoryBarrierCount = 1,
|
.imageMemoryBarrierCount = 1,
|
||||||
.pImageMemoryBarriers = &cubemapToRead,
|
.pImageMemoryBarriers = &skyboxToSampleBarrier,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorkloadPushConstants
|
#pragma endregion
|
||||||
|
|
||||||
|
struct SkyboxPushConstants
|
||||||
{
|
{
|
||||||
TextureHandle m_HdrEnvHandle;
|
TextureHandle m_HdrEnvHandle;
|
||||||
StorageTextureHandle m_OutputTexture;
|
StorageTextureHandle m_OutputTexture;
|
||||||
u32 m_CubeSide;
|
u32 m_CubeSide;
|
||||||
};
|
};
|
||||||
|
struct DiffuseIrradiancePushConstants
|
||||||
|
{
|
||||||
|
TextureHandle m_SkyboxHandle;
|
||||||
|
StorageTextureHandle m_OutputTexture;
|
||||||
|
u32 m_CubeSide;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma region Pipeline Creation etc
|
#pragma region Pipeline Creation etc
|
||||||
const auto shaderModule = CreateShader(pDevice, EQUIRECT_TO_CUBE_SHADER_FILE);
|
|
||||||
|
|
||||||
const vk::PipelineShaderStageCreateInfo shaderStageCreateInfo = {
|
|
||||||
.stage = vk::ShaderStageFlagBits::eCompute,
|
|
||||||
.module = shaderModule,
|
|
||||||
.pName = "main",
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::PushConstantRange pcr = {
|
vk::PushConstantRange pcr = {
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(WorkloadPushConstants),
|
.size = eastl::max(sizeof(SkyboxPushConstants), sizeof(DiffuseIrradiancePushConstants)),
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayout pipelineLayout;
|
vk::PipelineLayout pipelineLayout;
|
||||||
|
|
@ -98,21 +135,55 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
};
|
};
|
||||||
AbortIfFailed(pDevice->m_Device.createPipelineLayout(&layoutCreateInfo, nullptr, &pipelineLayout));
|
AbortIfFailed(pDevice->m_Device.createPipelineLayout(&layoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
|
|
||||||
const vk::ComputePipelineCreateInfo computePipelineCreateInfo = {
|
const auto eqRectToCubeShader = CreateShader(pDevice, EQUIRECT_TO_CUBE_SHADER_FILE);
|
||||||
.stage = shaderStageCreateInfo,
|
const auto diffuseRadianceShader = CreateShader(pDevice, DIFFUSE_IRRADIANCE_SHADER_FILE);
|
||||||
.layout = pipelineLayout,
|
eastl::array computePipelineCreateInfo = {
|
||||||
|
vk::ComputePipelineCreateInfo{
|
||||||
|
.stage =
|
||||||
|
{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.module = eqRectToCubeShader,
|
||||||
|
.pName = "main",
|
||||||
|
},
|
||||||
|
.layout = pipelineLayout,
|
||||||
|
},
|
||||||
|
vk::ComputePipelineCreateInfo{
|
||||||
|
.stage =
|
||||||
|
{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.module = diffuseRadianceShader,
|
||||||
|
.pName = "main",
|
||||||
|
},
|
||||||
|
.layout = pipelineLayout,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::Pipeline pipeline;
|
eastl::array<vk::Pipeline, 2> pipelines;
|
||||||
AbortIfFailed(pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, 1, &computePipelineCreateInfo,
|
static_assert(pipelines.size() == computePipelineCreateInfo.size());
|
||||||
nullptr, &pipeline));
|
AbortIfFailed(pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, computePipelineCreateInfo.size(),
|
||||||
|
computePipelineCreateInfo.data(), nullptr,
|
||||||
|
pipelines.data()));
|
||||||
|
|
||||||
pDevice->m_Device.destroy(shaderModule, nullptr);
|
vk::Pipeline eqRectToCubePipeline = pipelines[0];
|
||||||
|
vk::Pipeline diffuseIrradiancePipeline = pipelines[1];
|
||||||
|
|
||||||
|
for (auto &createInfos : computePipelineCreateInfo)
|
||||||
|
{
|
||||||
|
pDevice->m_Device.destroy(createInfos.stage.module, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
WorkloadPushConstants pushConstants = {
|
SkyboxPushConstants skyboxPushConstant = {
|
||||||
.m_HdrEnvHandle = hdrEnv, .m_OutputTexture = envStagingHandle, .m_CubeSide = cubeSide};
|
.m_HdrEnvHandle = hdrEnv,
|
||||||
|
.m_OutputTexture = skyboxStorageHandle,
|
||||||
|
.m_CubeSide = cubeSide,
|
||||||
|
};
|
||||||
|
DiffuseIrradiancePushConstants diffuseIrradiancePushConstants = {
|
||||||
|
.m_SkyboxHandle = skyboxHandle,
|
||||||
|
.m_OutputTexture = diffuseIrradianceStorageHandle,
|
||||||
|
.m_CubeSide = diffuseIrradiance.m_Extent.width,
|
||||||
|
};
|
||||||
|
|
||||||
resMan->Update();
|
resMan->Update();
|
||||||
|
|
||||||
|
|
@ -133,11 +204,19 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
cmd.pipelineBarrier2(&readyToWriteDependency);
|
cmd.pipelineBarrier2(&readyToWriteDependency);
|
||||||
|
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipelineLayout, 0, 1, &resMan->m_DescriptorSet, 0, nullptr);
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipelineLayout, 0, 1, &resMan->m_DescriptorSet, 0, nullptr);
|
||||||
cmd.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline);
|
cmd.bindPipeline(vk::PipelineBindPoint::eCompute, eqRectToCubePipeline);
|
||||||
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof pushConstants, &pushConstants);
|
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof skyboxPushConstant,
|
||||||
|
&skyboxPushConstant);
|
||||||
cmd.dispatch(cubeSide / 16, cubeSide / 16, 6);
|
cmd.dispatch(cubeSide / 16, cubeSide / 16, 6);
|
||||||
|
|
||||||
cmd.pipelineBarrier2(&cubemapToReadDependency);
|
cmd.pipelineBarrier2(&skyboxWriteToReadDependency);
|
||||||
|
|
||||||
|
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof skyboxPushConstant,
|
||||||
|
&diffuseIrradiancePushConstants);
|
||||||
|
cmd.bindPipeline(vk::PipelineBindPoint::eCompute, diffuseIrradiancePipeline);
|
||||||
|
cmd.dispatch(cubeSide / 16, cubeSide / 16, 6);
|
||||||
|
|
||||||
|
cmd.pipelineBarrier2(&skyboxToSampleDependency);
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
cmd.endDebugUtilsLabelEXT();
|
cmd.endDebugUtilsLabelEXT();
|
||||||
|
|
@ -161,10 +240,14 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
|
|
||||||
AbortIfFailed(pDevice->m_Device.resetCommandPool(assetLoader->m_CommandPool, {}));
|
AbortIfFailed(pDevice->m_Device.resetCommandPool(assetLoader->m_CommandPool, {}));
|
||||||
|
|
||||||
cubeMap = {};
|
skybox = {};
|
||||||
resMan->Release(&cubeMap, envStagingHandle);
|
resMan->Release(skyboxStorageHandle);
|
||||||
pDevice->m_Device.destroy(pipeline, nullptr);
|
resMan->Release(diffuseIrradianceStorageHandle);
|
||||||
|
for (auto &pipeline : pipelines)
|
||||||
|
{
|
||||||
|
pDevice->m_Device.destroy(pipeline, nullptr);
|
||||||
|
}
|
||||||
pDevice->m_Device.destroy(pipelineLayout, nullptr);
|
pDevice->m_Device.destroy(pipelineLayout, nullptr);
|
||||||
|
|
||||||
return resMan->CommitTexture(&cubeMap);
|
return {skyboxHandle, diffuseIrradianceHandle};
|
||||||
}
|
}
|
||||||
|
|
@ -8,10 +8,13 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "gpu_resource_manager.h"
|
#include "gpu_resource_manager.h"
|
||||||
|
|
||||||
|
#include <EASTL/tuple.h>
|
||||||
|
|
||||||
struct Pipeline;
|
struct Pipeline;
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct TextureCube;
|
struct TextureCube;
|
||||||
struct AssetLoader;
|
struct AssetLoader;
|
||||||
|
|
||||||
TextureHandle CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, TextureHandle hdrEnv,
|
eastl::tuple<TextureHandle, TextureHandle>
|
||||||
|
CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, TextureHandle hdrEnv,
|
||||||
cstr name = nullptr);
|
cstr name = nullptr);
|
||||||
|
|
@ -18,10 +18,10 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "light_manager.h"
|
#include "light_manager.h"
|
||||||
|
|
||||||
|
#include "asset_loader.h"
|
||||||
#include "gpu_resource_manager.h"
|
#include "gpu_resource_manager.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "ibl_helpers.h"
|
#include "ibl_helpers.h"
|
||||||
#include "asset_loader.h"
|
|
||||||
#include "pipeline_utils.h"
|
#include "pipeline_utils.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
|
|
@ -180,7 +180,7 @@ main(int, char **)
|
||||||
assetLoader.LoadHdrImage(&environment, BACKDROP_FILE);
|
assetLoader.LoadHdrImage(&environment, BACKDROP_FILE);
|
||||||
auto envHandle = resourceManager.CommitTexture(&environment);
|
auto envHandle = resourceManager.CommitTexture(&environment);
|
||||||
|
|
||||||
TextureHandle texCube = CreateCubeFromHdrEnv(&assetLoader, graphicsQueue, 1024, envHandle, "Cube Env");
|
auto [texCube, diffuseIrr] = CreateCubeFromHdrEnv(&assetLoader, graphicsQueue, 1024, envHandle, "Cube Env");
|
||||||
|
|
||||||
resourceManager.Release(envHandle);
|
resourceManager.Release(envHandle);
|
||||||
|
|
||||||
|
|
@ -371,6 +371,7 @@ main(int, char **)
|
||||||
queueAllocation.m_Family, graphicsQueue);
|
queueAllocation.m_Family, graphicsQueue);
|
||||||
bool rotating = false;
|
bool rotating = false;
|
||||||
bool lockToScreen = true;
|
bool lockToScreen = true;
|
||||||
|
bool showDiffuse = false;
|
||||||
i32 height = Cast<i32>(internalResolution.height);
|
i32 height = Cast<i32>(internalResolution.height);
|
||||||
f32 camPitch = glm::degrees(cameraController.m_Pitch);
|
f32 camPitch = glm::degrees(cameraController.m_Pitch);
|
||||||
f32 camYaw = glm::degrees(cameraController.m_Yaw);
|
f32 camYaw = glm::degrees(cameraController.m_Yaw);
|
||||||
|
|
@ -445,6 +446,7 @@ main(int, char **)
|
||||||
{
|
{
|
||||||
cameraController.SetPosition(camPosition);
|
cameraController.SetPosition(camPosition);
|
||||||
}
|
}
|
||||||
|
gui::Checkbox("Show DiffIrr", &showDiffuse);
|
||||||
gui::Checkbox("Rotate", &rotating);
|
gui::Checkbox("Rotate", &rotating);
|
||||||
gui::PopItemWidth();
|
gui::PopItemWidth();
|
||||||
if (gui::Button("Exit"))
|
if (gui::Button("Exit"))
|
||||||
|
|
@ -546,8 +548,18 @@ main(int, char **)
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof model.m_Handles,
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof model.m_Handles,
|
||||||
&model.m_Handles);
|
&model.m_Handles);
|
||||||
pcbOffset += sizeof model.m_Handles;
|
pcbOffset += sizeof model.m_Handles;
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof texCube, &texCube);
|
if (showDiffuse)
|
||||||
pcbOffset += sizeof texCube;
|
{
|
||||||
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof diffuseIrr,
|
||||||
|
&diffuseIrr);
|
||||||
|
pcbOffset += sizeof diffuseIrr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof texCube, &texCube);
|
||||||
|
pcbOffset += sizeof texCube;
|
||||||
|
}
|
||||||
|
static_assert(sizeof texCube == sizeof diffuseIrr);
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof lightManager.m_MetaInfo,
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof lightManager.m_MetaInfo,
|
||||||
&lightManager.m_MetaInfo);
|
&lightManager.m_MetaInfo);
|
||||||
pcbOffset += sizeof lightManager.m_MetaInfo;
|
pcbOffset += sizeof lightManager.m_MetaInfo;
|
||||||
|
|
@ -626,6 +638,7 @@ main(int, char **)
|
||||||
AbortIfFailed(device.m_Device.waitIdle());
|
AbortIfFailed(device.m_Device.waitIdle());
|
||||||
|
|
||||||
resourceManager.Release(texCube);
|
resourceManager.Release(texCube);
|
||||||
|
resourceManager.Release(diffuseIrr);
|
||||||
|
|
||||||
pipelineCacheData = device.DumpPipelineCache();
|
pipelineCacheData = device.DumpPipelineCache();
|
||||||
ERROR_IF(!WriteFileBytes(PIPELINE_CACHE_FILE, pipelineCacheData), "Pipeline Cache incorrectly written");
|
ERROR_IF(!WriteFileBytes(PIPELINE_CACHE_FILE, pipelineCacheData), "Pipeline Cache incorrectly written");
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,9 @@ struct DirectionalLight
|
||||||
|
|
||||||
#define INVALID_HANDLE 0xFFFFFFFF
|
#define INVALID_HANDLE 0xFFFFFFFF
|
||||||
|
|
||||||
|
static const float HALF_PI = 1.57079633f;
|
||||||
static const float PI = 3.14159265f;
|
static const float PI = 3.14159265f;
|
||||||
|
static const float TAU = 6.28318530f;
|
||||||
|
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<float4> VertexBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<float4> VertexBuffer[];
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<VertexData> VertexDataBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<VertexData> VertexDataBuffer[];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#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 = GetLocalDir(pcb.CubeSide, GlobalInvocationID);
|
||||||
|
Up = float3(0.0f, 1.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.025f;
|
||||||
|
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,10 +1,10 @@
|
||||||
#include "bindless_structs.hlsli"
|
#include "ibl_common.hlsli"
|
||||||
|
|
||||||
struct Block
|
struct Block
|
||||||
{
|
{
|
||||||
uint HdrEnvHandle;
|
uint HdrEnvHandle;
|
||||||
uint OutputTextureHandle;
|
uint OutputTextureHandle;
|
||||||
int CubeSize;
|
int CubeSide;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[vk::push_constant]]
|
[[vk::push_constant]]
|
||||||
|
|
@ -33,23 +33,8 @@ float2 SampleSphericalMap(float3 v)
|
||||||
[numthreads(16, 16, 1)]
|
[numthreads(16, 16, 1)]
|
||||||
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
void main(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||||
{
|
{
|
||||||
float3 LocalDir;
|
float3 LocalDir = GetLocalDir(pcb.CubeSide, GlobalInvocationID);
|
||||||
float HalfSide = pcb.CubeSize / 2;
|
|
||||||
float AxisSign = 2.0f * (0.5f - (GlobalInvocationID.z % 2));
|
|
||||||
|
|
||||||
if (GlobalInvocationID.z < 2)
|
float2 UV = SampleSphericalMap(LocalDir);
|
||||||
{
|
|
||||||
LocalDir = float3(AxisSign * HalfSide, HalfSide - GlobalInvocationID.y, (HalfSide - GlobalInvocationID.x) * AxisSign);
|
|
||||||
}
|
|
||||||
else if (GlobalInvocationID.z < 4)
|
|
||||||
{
|
|
||||||
LocalDir = float3(GlobalInvocationID.x - HalfSide, AxisSign * HalfSide, AxisSign * (GlobalInvocationID.y - HalfSide));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LocalDir = float3((GlobalInvocationID.x - HalfSide) * AxisSign, HalfSide - GlobalInvocationID.y, HalfSide * AxisSign);
|
|
||||||
}
|
|
||||||
|
|
||||||
float2 UV = SampleSphericalMap(normalize(LocalDir));
|
|
||||||
StorageTextureArrays[pcb.OutputTextureHandle][GlobalInvocationID.xyz] = Textures[pcb.HdrEnvHandle].SampleLevel(ImmutableSamplers[pcb.HdrEnvHandle], UV, 0);
|
StorageTextureArrays[pcb.OutputTextureHandle][GlobalInvocationID.xyz] = Textures[pcb.HdrEnvHandle].SampleLevel(ImmutableSamplers[pcb.HdrEnvHandle], UV, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "bindless_structs.hlsli"
|
||||||
|
|
||||||
|
float3 GetLocalDir(float Side, float3 GlobalInvocationID)
|
||||||
|
{
|
||||||
|
float HalfSide = Side / 2;
|
||||||
|
float AxisSign = 2.0f * (0.5f - (GlobalInvocationID.z % 2));
|
||||||
|
|
||||||
|
float3 LocalDir;
|
||||||
|
if (GlobalInvocationID.z < 2)
|
||||||
|
{
|
||||||
|
LocalDir = float3(AxisSign * HalfSide, HalfSide - GlobalInvocationID.y, (HalfSide - GlobalInvocationID.x) * AxisSign);
|
||||||
|
}
|
||||||
|
else if (GlobalInvocationID.z < 4)
|
||||||
|
{
|
||||||
|
LocalDir = float3(GlobalInvocationID.x - HalfSide, AxisSign * HalfSide, AxisSign * (GlobalInvocationID.y - HalfSide));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LocalDir = float3((GlobalInvocationID.x - HalfSide) * AxisSign, HalfSide - GlobalInvocationID.y, HalfSide * AxisSign);
|
||||||
|
}
|
||||||
|
return normalize(LocalDir);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue