Trying to add prefiltered environment mapping

This commit is contained in:
2025-07-06 20:57:09 +02:00
parent bcdcc47eb3
commit eb07d0fdd1
7 changed files with 113 additions and 41 deletions
+3
View File
@@ -99,6 +99,9 @@ if(UNIX)
endif() endif()
add_executable(Editor "") add_executable(Editor "")
set_target_properties(Editor PROPERTIES
INSTALL_RPATH "$ORIGIN"
)
target_link_libraries(Editor PRIVATE Engine) target_link_libraries(Editor PRIVATE Engine)
target_include_directories(Editor PRIVATE src/Editor) target_include_directories(Editor PRIVATE src/Editor)
target_include_directories(Editor PRIVATE ${Stb_INCLUDE_DIR}) target_include_directories(Editor PRIVATE ${Stb_INCLUDE_DIR})
+2 -2
View File
@@ -96,8 +96,8 @@ static const float upperLimit = 0.1;
float4 fragmentMain( float4 fragmentMain(
VertexShaderOutput output) : SV_Target VertexShaderOutput output) : SV_Target
{ {
float4 texture1 = pSkyboxTextures.cubeMap.Sample(pSkyboxTextures.sampler, output.texCoords); float4 texture1 = pSkyboxTextures.cubeMap.SampleLevel(pSkyboxTextures.sampler, output.texCoords, 5);
float4 texture2 = pSkyboxTextures.cubeMap2.Sample(pSkyboxTextures.sampler, output.texCoords); float4 texture2 = pSkyboxTextures.cubeMap2.SampleLevel(pSkyboxTextures.sampler, output.texCoords, 5);
float4 finalColor = lerp(texture1, texture2, pSkyboxData.fogBlend.w); float4 finalColor = lerp(texture1, texture2, pSkyboxData.fogBlend.w);
float factor = (output.texCoords.y - lowerLimit) / (upperLimit - lowerLimit); float factor = (output.texCoords.y - lowerLimit) / (upperLimit - lowerLimit);
+83 -15
View File
@@ -26,6 +26,16 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
}, },
.fieldOfView = glm::radians(90.0f), .fieldOfView = glm::radians(90.0f),
}); });
for (uint32 i = 0; i < prefilterViewports.size(); ++i) {
prefilterViewports[i] = graphics->createViewport(nullptr, ViewportCreateInfo{
.dimensions =
{
.size = {128 * std::pow(0.5, i), 128 * std::pow(0.5, i)},
.offset = {0, 0},
},
.fieldOfView = glm::radians(90.0f),
});
}
cubeSampler = graphics->createSampler({ cubeSampler = graphics->createSampler({
.magFilter = Gfx::SE_FILTER_LINEAR, .magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR, .minFilter = Gfx::SE_FILTER_LINEAR,
@@ -61,16 +71,20 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
cubePipelineLayout = graphics->createPipelineLayout("CubeRenderLayout"); cubePipelineLayout = graphics->createPipelineLayout("CubeRenderLayout");
cubePipelineLayout->addDescriptorLayout(cubeRenderLayout); cubePipelineLayout->addDescriptorLayout(cubeRenderLayout);
cubePipelineLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
.offset = 0,
.size = sizeof(float),
.name = "pRoughness",
});
graphics->beginShaderCompilation(ShaderCompilationInfo{ graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "CubeRenderPipeline", .name = "CubeRenderPipeline",
.modules = {"EnvironmentMapping"}, .modules = {"EnvironmentMapping"},
.entryPoints = .entryPoints = {{"vertMain", "EnvironmentMapping"},
{
{"vertMain", "EnvironmentMapping"},
{"computeCubemap", "EnvironmentMapping"}, {"computeCubemap", "EnvironmentMapping"},
{"convolveCubemap", "EnvironmentMapping"}, {"convolveCubemap", "EnvironmentMapping"},
}, {"computePrefilteredCubemap", "EnvironmentMapping"}},
.rootSignature = cubePipelineLayout, .rootSignature = cubePipelineLayout,
}); });
cubePipelineLayout->create(); cubePipelineLayout->create();
@@ -78,6 +92,7 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
cubeRenderVertex = graphics->createVertexShader({0}); cubeRenderVertex = graphics->createVertexShader({0});
cubeRenderFrag = graphics->createFragmentShader({1}); cubeRenderFrag = graphics->createFragmentShader({1});
convolutionFrag = graphics->createFragmentShader({2}); convolutionFrag = graphics->createFragmentShader({2});
prefilterFrag = graphics->createFragmentShader({3});
} }
EnvironmentLoader::~EnvironmentLoader() {} EnvironmentLoader::~EnvironmentLoader() {}
@@ -143,8 +158,9 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout{
.colorAttachments = .colorAttachments =
{ {
Gfx::RenderTargetAttachment(cubeViews[i], Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::RenderTargetAttachment(cubeViews[i], Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE), Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE,
Gfx::SE_ATTACHMENT_STORE_OP_STORE),
}, },
}, },
{ {
@@ -162,7 +178,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
.offset = {0, 0}, .offset = {0, 0},
}, },
"EnvironmentRenderPass"); "EnvironmentRenderPass");
cubeRenderPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{ Gfx::PGraphicsPipeline cubeRenderPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = cubeRenderVertex, .vertexShader = cubeRenderVertex,
.fragmentShader = cubeRenderFrag, .fragmentShader = cubeRenderFrag,
.renderPass = cubeRenderPass, .renderPass = cubeRenderPass,
@@ -193,15 +209,15 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
.format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT,
.width = CONVOLUTED_RESOLUTION, .width = CONVOLUTED_RESOLUTION,
.height = CONVOLUTED_RESOLUTION, .height = CONVOLUTED_RESOLUTION,
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
}); });
Array<Gfx::OTextureView> convolutedViews; Array<Gfx::OTextureView> convolutedViews;
convolutedViews.add(cubeMap->createTextureView(0, 1, 0, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 0, 1));
convolutedViews.add(cubeMap->createTextureView(0, 1, 1, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 1, 1));
convolutedViews.add(cubeMap->createTextureView(0, 1, 2, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 2, 1));
convolutedViews.add(cubeMap->createTextureView(0, 1, 3, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 3, 1));
convolutedViews.add(cubeMap->createTextureView(0, 1, 4, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 4, 1));
convolutedViews.add(cubeMap->createTextureView(0, 1, 5, 1)); convolutedViews.add(convolutedMap->createTextureView(0, 1, 5, 1));
for (uint32 i = 0; i < 6; ++i) { for (uint32 i = 0; i < 6; ++i) {
Gfx::ORenderPass convolutionPass = graphics->createRenderPass( Gfx::ORenderPass convolutionPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout{
@@ -215,7 +231,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
.offset = {0, 0}, .offset = {0, 0},
}, },
"EnvironmentRenderPass"); "EnvironmentRenderPass");
convolutionPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{ Gfx::PGraphicsPipeline convolutionPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = cubeRenderVertex, .vertexShader = cubeRenderVertex,
.fragmentShader = convolutionFrag, .fragmentShader = convolutionFrag,
.renderPass = convolutionPass, .renderPass = convolutionPass,
@@ -234,10 +250,62 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
cmd->draw(6, 1, i * 6, 0); cmd->draw(6, 1, i * 6, 0);
graphics->executeCommands(std::move(cmd)); graphics->executeCommands(std::move(cmd));
graphics->endRenderPass(); graphics->endRenderPass();
}
Gfx::OTextureCube prefilteredCubeMap = graphics->createTextureCube(TextureCreateInfo{
.format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT,
.width = 128,
.height = 128,
.useMip = true,
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
});
for (uint32 mip = 0; mip < prefilteredCubeMap->getMipLevels(); ++mip) {
Array<Gfx::OTextureView> views;
views.add(prefilteredCubeMap->createTextureView(mip, 1, 0, 1));
views.add(prefilteredCubeMap->createTextureView(mip, 1, 1, 1));
views.add(prefilteredCubeMap->createTextureView(mip, 1, 2, 1));
views.add(prefilteredCubeMap->createTextureView(mip, 1, 3, 1));
views.add(prefilteredCubeMap->createTextureView(mip, 1, 4, 1));
views.add(prefilteredCubeMap->createTextureView(mip, 1, 5, 1));
for (uint32 i = 0; i < 6; ++i) {
Gfx::ORenderPass prefilterPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.colorAttachments = {Gfx::RenderTargetAttachment(
views[i], Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE)},
},
{},
{
.size = {prefilterViewports[mip]->getWidth(), prefilterViewports[mip]->getHeight()},
.offset = {0, 0},
},
"PrefilterPass");
Gfx::PGraphicsPipeline prefilterPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = cubeRenderVertex,
.fragmentShader = prefilterFrag,
.renderPass = prefilterPass,
.pipelineLayout = cubePipelineLayout,
.colorBlend =
{
.attachmentCount = 1,
},
});
graphics->beginRenderPass(prefilterPass);
Gfx::ORenderCommand cmd = graphics->createRenderCommand("PrefilterPass");
cmd->bindPipeline(prefilterPipeline);
cmd->bindDescriptor({set});
float roughness = (float)mip / (float)(prefilteredCubeMap->getMipLevels() - 1);
cmd->pushConstants(Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(float), &roughness);
cmd->setViewport(prefilterViewports[mip]);
cmd->draw(6, 1, i * 6, 0);
graphics->executeCommands(std::move(cmd));
graphics->endRenderPass();
}
} }
asset->skybox = std::move(cubeMap); asset->skybox = std::move(cubeMap);
asset->irradianceMap = std::move(convolutedMap); asset->irradianceMap = std::move(convolutedMap);
asset->prefilteredMap = std::move(prefilteredCubeMap);
graphics->waitDeviceIdle(); graphics->waitDeviceIdle();
} }
+3 -2
View File
@@ -24,11 +24,12 @@ class EnvironmentLoader {
Gfx::OFragmentShader cubeRenderFrag; Gfx::OFragmentShader cubeRenderFrag;
Gfx::ODescriptorLayout cubeRenderLayout; Gfx::ODescriptorLayout cubeRenderLayout;
Gfx::OPipelineLayout cubePipelineLayout; Gfx::OPipelineLayout cubePipelineLayout;
Gfx::PGraphicsPipeline cubeRenderPipeline;
Gfx::OFragmentShader convolutionFrag; Gfx::OFragmentShader convolutionFrag;
Gfx::PGraphicsPipeline convolutionPipeline; Gfx::OFragmentShader prefilterFrag;
Gfx::OViewport cubeRenderViewport; Gfx::OViewport cubeRenderViewport;
Gfx::OViewport convolutionViewport; Gfx::OViewport convolutionViewport;
// for now we hardcode 128x128 as mip 0, so we have 8 roughness levels
StaticArray<Gfx::OViewport, 8> prefilterViewports;
Gfx::OSampler cubeSampler; Gfx::OSampler cubeSampler;
}; };
} }
+2 -2
View File
@@ -26,8 +26,8 @@ static Gfx::OGraphics graphics;
int main() { int main() {
std::string gameName = "MeshShadingDemo"; std::string gameName = "MeshShadingDemo";
std::filesystem::path outputPath = fmt::format("../../../../{0}Game", gameName); std::filesystem::path outputPath = fmt::format("../../../../{0}Game/", gameName);
std::filesystem::path sourcePath = fmt::format("../../../../{0}", gameName); std::filesystem::path sourcePath = fmt::format("../../../../{0}/", gameName);
#ifdef WIN32 #ifdef WIN32
std::string libraryEnding = "dll"; std::string libraryEnding = "dll";
#elif __APPLE__ #elif __APPLE__
+2 -2
View File
@@ -13,11 +13,11 @@ class EnvironmentMapAsset : public Asset {
virtual void load(ArchiveBuffer& buffer) override; virtual void load(ArchiveBuffer& buffer) override;
Gfx::PTextureCube getSkybox() const { return skybox; } Gfx::PTextureCube getSkybox() const { return skybox; }
Gfx::PTextureCube getIrradianceMap() const { return irradianceMap; } Gfx::PTextureCube getIrradianceMap() const { return irradianceMap; }
Gfx::PTextureCube getSpecularMap() const { return specularMap; } Gfx::PTextureCube getPrefilteredMap() const { return prefilteredMap; }
private: private:
Gfx::OTextureCube skybox; Gfx::OTextureCube skybox;
Gfx::OTextureCube irradianceMap; Gfx::OTextureCube irradianceMap;
Gfx::OTextureCube specularMap; Gfx::OTextureCube prefilteredMap;
friend class EnvironmentLoader; friend class EnvironmentLoader;
}; };
} // namespace Seele } // namespace Seele
+6 -6
View File
@@ -79,8 +79,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
}); });
} }
skybox = Seele::Component::Skybox{ skybox = Seele::Component::Skybox{
.day = scene->getLightEnvironment()->getEnvironmentMap()->getSkybox(), .day = scene->getLightEnvironment()->getEnvironmentMap()->getPrefilteredMap(),
.night = scene->getLightEnvironment()->getEnvironmentMap()->getSkybox(), .night = scene->getLightEnvironment()->getEnvironmentMap()->getPrefilteredMap(),
.fogColor = Vector(0, 0, 0), .fogColor = Vector(0, 0, 0),
.blendFactor = 0, .blendFactor = 0,
}; };
@@ -179,7 +179,7 @@ void BasePass::render() {
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr); assert(collection != nullptr);
bool twoSided = materialData.material->isTwoSided(); //bool twoSided = materialData.material->isTwoSided();
if (graphics->supportMeshShading()) { if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = { Gfx::MeshPipelineCreateInfo pipelineInfo = {
@@ -283,7 +283,7 @@ void BasePass::render() {
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr); assert(collection != nullptr);
bool twoSided = t.matInst->getBaseMaterial()->isTwoSided(); //bool twoSided = t.matInst->getBaseMaterial()->isTwoSided();
if (graphics->supportMeshShading()) { if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = { Gfx::MeshPipelineCreateInfo pipelineInfo = {
@@ -298,7 +298,7 @@ void BasePass::render() {
}, },
.rasterizationState = .rasterizationState =
{ {
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), .cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
}, },
.colorBlend = .colorBlend =
{ {
@@ -325,7 +325,7 @@ void BasePass::render() {
}, },
.rasterizationState = .rasterizationState =
{ {
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), .cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
}, },
.depthStencilState = .depthStencilState =
{ {