From 2dd7ad8eb2580482b43bedb77eb648a6162c4e32 Mon Sep 17 00:00:00 2001 From: RaveYard <29225776+MrRaveYard@users.noreply.github.com> Date: Thu, 20 Feb 2025 20:10:39 +0100 Subject: [PATCH] WIP multiple probes support --- .../rendering/hwrenderer/data/hw_lightprobe.h | 17 +++ src/common/rendering/v_video.h | 3 +- .../rendering/vulkan/textures/vk_texture.cpp | 2 +- .../rendering/vulkan/vk_renderdevice.cpp | 15 ++- src/common/rendering/vulkan/vk_renderdevice.h | 3 +- src/namedef_custom.h | 3 + src/p_setup.cpp | 1 + src/rendering/hwrenderer/hw_entrypoint.cpp | 102 +++++++++++++++++- .../static/shaders/scene/lightmodel_pbr.glsl | 2 +- wadsrc/static/zscript.txt | 1 + .../zscript/actors/shared/lightprobe.zs | 15 +++ 11 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 wadsrc/static/zscript/actors/shared/lightprobe.zs diff --git a/src/common/rendering/hwrenderer/data/hw_lightprobe.h b/src/common/rendering/hwrenderer/data/hw_lightprobe.h index fbfaa9937..38a7c989f 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightprobe.h +++ b/src/common/rendering/hwrenderer/data/hw_lightprobe.h @@ -12,3 +12,20 @@ struct LightProbeTarget { int index = 0; // parameter for renderstate.SetLightProbe }; + +class LightProbeIncrementalBuilder +{ + int lastIndex = 0; + + int collected; + + TArray irradianceMaps; + TArray prefilterMaps; + +public: + + void Step(const TArray& probes, std::function&, TArray&)> renderScene, std::function&&, TArray&&)> uploadEnv); + void Full(const TArray& probes, std::function&, TArray&)> renderScene, std::function&&, TArray&&)> uploadEnv); + + auto GetStep() const { return lastIndex; } +}; \ No newline at end of file diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index 594598cf2..6b987af8f 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -221,7 +221,8 @@ public: // Get the array index for the material in the textures array accessible from shaders virtual int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) { return -1; } - virtual void RenderEnvironmentMap(std::function renderFunc) {} + virtual void RenderEnvironmentMap(std::function renderFunc, TArray& irradianceMap, TArray& prefilterMap) {} + virtual void UploadEnvironmentMaps(int cubemapCount, TArray&& irradianceMaps, TArray&& prefilterMaps) {} // Screen wiping virtual FTexture *WipeStartScreen(); diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp index 24a333637..da30bd190 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.cpp +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -420,7 +420,7 @@ void VkTextureManager::CreatePrefiltermap(int size, int count, TArray& .Execute(cmdbuffer); int offset = 0; - for (int i = 0; i < 6; ++i) + for (int i = 0; i < count; ++i) { for (int level = 0; level < miplevels; level++) { diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 326718b5e..8b87354c0 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -321,13 +321,18 @@ void VulkanRenderDevice::RenderTextureView(FCanvasTexture* tex, std::functionSetUpdated(true); } -void VulkanRenderDevice::RenderEnvironmentMap(std::function renderFunc) +void VulkanRenderDevice::RenderEnvironmentMap(std::function renderFunc, TArray& irradianceMap, TArray& prefilterMap) { mLightprober->RenderEnvironmentMap(std::move(renderFunc)); - TArray irradianceMap = mLightprober->GenerateIrradianceMap(); - TArray prefilterMap = mLightprober->GeneratePrefilterMap(); - mTextureManager->CreateIrradiancemap(32, 6, std::move(irradianceMap)); - mTextureManager->CreatePrefiltermap(128, 6, std::move(prefilterMap)); + irradianceMap = mLightprober->GenerateIrradianceMap(); + prefilterMap = mLightprober->GeneratePrefilterMap(); + +} + +void VulkanRenderDevice::UploadEnvironmentMaps(int cubemapCount, TArray&& irradianceMaps, TArray&& prefilterMaps) +{ + mTextureManager->CreateIrradiancemap(32, 6 * cubemapCount, std::move(irradianceMaps)); + mTextureManager->CreatePrefiltermap(128, 6 * cubemapCount, std::move(prefilterMaps)); } void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index 350936d19..59392cf8a 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -104,7 +104,8 @@ public: private: void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; - void RenderEnvironmentMap(std::function renderFunc) override; + void RenderEnvironmentMap(std::function renderFunc, TArray& irradianceMap, TArray& prefilterMap) override; + void UploadEnvironmentMaps(int cubemapCount, TArray&& irradianceMaps, TArray&& prefilterMaps) override; void PrintStartupLog(); void CopyScreenToBuffer(int w, int h, uint8_t *data) override; diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 097a9d78c..abccd1cd8 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -881,6 +881,9 @@ xx(light_dontlightactors) xx(light_dontlightmap) xx(light_shadowminquality) +// Light probe +xx(LightProbe) + xx(skew_bottom_type) xx(skew_middle_type) xx(skew_top_type) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 275764767..d0b9fff15 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -379,6 +379,7 @@ void FLevelLocals::ClearLevelData(bool fullgc) if (levelMesh) delete levelMesh; aabbTree = nullptr; levelMesh = nullptr; + lightProbes.Clear(); if (screen) screen->SetLevelMesh(nullptr); if (screen && screen->mShadowMap) diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 6eaeb63ec..131059c5b 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -333,6 +333,7 @@ static void CheckTimer(FRenderState &state, uint64_t ShaderStartTime) state.firstFrame = screen->FrameTime - 1; } +LightProbeIncrementalBuilder lightProbeBuilder; sector_t* RenderView(player_t* player) { @@ -403,16 +404,56 @@ sector_t* RenderView(player_t* player) if (gl_lightprobe) { + // Render the light probes if not found in a lump // To do: we need light probe actors - AActor* lightprobe = player->camera; + + AActor* lightprobe = level.GetThinkerIterator(NAME_LightProbe, STAT_DEFAULT).Next(); if (lightprobe) { + /*TArray irradianceMap; + TArray prefilteredMap; + screen->RenderEnvironmentMap([=](IntRect& bounds, int side) { FRenderViewpoint probevp; RenderViewpoint(probevp, lightprobe, &bounds, 90.0, 1.0f, 1.0f, false, false, side); - }); + }, irradianceMap, prefilteredMap); + + screen->UploadEnvironmentMaps(1, std::move(irradianceMap), std::move(prefilteredMap));*/ + + auto renderEnvMap = [&](const LightProbe& probe, TArray& irradianceMap, TArray& prefilteredMap) + { + auto oldPos = lightprobe->Pos(); + + lightprobe->SetOrigin(DVector3(probe.position), false); // crime against nature + lightprobe->ClearInterpolation(); + + r_NoInterpolate = true; + + // Printf("%p | %f %f %f\n", &probe, probe.position.X, probe.position.Y, probe.position.Z); + + screen->RenderEnvironmentMap([&](IntRect& bounds, int side) + { + FRenderViewpoint probevp; + RenderViewpoint(probevp, lightprobe, &bounds, 90.0, 1.0f, 1.0f, false, false, side); + }, irradianceMap, prefilteredMap); + + r_NoInterpolate = false; + }; + + lightProbeBuilder.Step( + level.lightProbes, + renderEnvMap, + [&](TArray&& irradianceMaps, TArray&& prefilteredMaps) { + screen->UploadEnvironmentMaps(level.lightProbes.size(), std::move(irradianceMaps), std::move(prefilteredMaps)); + } + ); + } + else + { + Printf("Warning: spawning LightProbe\n"); + Spawn(&level, NAME_LightProbe); } } @@ -438,3 +479,60 @@ sector_t* RenderView(player_t* player) return retsec; } +void LightProbeIncrementalBuilder::Step(const TArray& probes, std::function&, TArray&)> renderScene, std::function&&, TArray&&)> uploadEnv) +{ + if (lastIndex >= probes.size()) + { + lastIndex = 0; + collected = 0; + + if (!probes.size()) + { + return; + } + } + + TArray irradianceMap; + TArray prefilterMap; + + renderScene(probes[lastIndex++], irradianceMap, prefilterMap); + ++collected; + + this->irradianceMaps.Append(irradianceMap); + this->prefilterMaps.Append(prefilterMap); + + if (lastIndex >= probes.size()) + { + if (collected == probes.size()) + { + uploadEnv(std::move(this->irradianceMaps), std::move(this->prefilterMaps)); + } + this->irradianceMaps.Clear(); + this->prefilterMaps.Clear(); + } +} + +void LightProbeIncrementalBuilder::Full(const TArray& probes, std::function&, TArray&)> renderScene, std::function&&, TArray&&)> uploadEnv) +{ + if (lastIndex >= probes.size()) + { + lastIndex = 0; + + if (!probes.size()) + { + return; + } + } + + while (lastIndex < probes.size()) + { + Step(probes, renderScene, uploadEnv); + } +} + +ADD_STAT(lightprobes) +{ + FString out; + out.Format("Rendering probe: %d / %d", lightProbeBuilder.GetStep(), level.lightProbes.Size()); + return out; +} \ No newline at end of file diff --git a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl index 433f18c84..20f1679bb 100644 --- a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl @@ -147,7 +147,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight) vec3 kS = F; vec3 kD = 1.0 - kS; - const float environmentScaleFactor = 0.1; + const float environmentScaleFactor = 1.0; vec3 irradiance = texture(IrradianceMap, vec4(N, uLightProbeIndex)).rgb * environmentScaleFactor; vec3 diffuse = irradiance * albedo; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8229680ca..8df987fd7 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -97,6 +97,7 @@ version "4.12" #include "zscript/actors/shared/dynlights.zs" #include "zscript/actors/shared/corona.zs" #include "zscript/actors/shared/fogball.zs" +#include "zscript/actors/shared/lightprobe.zs" #include "zscript/actors/doom/doomplayer.zs" #include "zscript/actors/doom/possessed.zs" diff --git a/wadsrc/static/zscript/actors/shared/lightprobe.zs b/wadsrc/static/zscript/actors/shared/lightprobe.zs new file mode 100644 index 000000000..e56a6a726 --- /dev/null +++ b/wadsrc/static/zscript/actors/shared/lightprobe.zs @@ -0,0 +1,15 @@ +/* + Light probe actor. +*/ + +class LightProbe : Actor +{ + Default + { + +NOINTERACTION + +NOBLOCKMAP + +NOGRAVITY + Height 2; + Radius 1; + } +}