From 24625c98df9f73aef3113089a1d7d7bed2508141 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 00:57:16 +0000 Subject: [PATCH 01/13] feat: cloud shadow for Lighting --- .../Shaders/CloudShadow/CloudShadow.hlsli | 51 +++ .../Shaders/Features/CloudShadow.ini | 2 + .../Shaders/DistantTree.hlsl | 20 ++ package/Shaders/Lighting.hlsl | 70 ++-- package/Shaders/Sky.hlsl | 7 + src/Feature.cpp | 4 +- src/Features/CloudShadow.cpp | 304 ++++++++++++++++++ src/Features/CloudShadow.h | 62 ++++ 8 files changed, 492 insertions(+), 28 deletions(-) create mode 100644 features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli create mode 100644 features/Cloud Shadow/Shaders/Features/CloudShadow.ini create mode 100644 src/Features/CloudShadow.cpp create mode 100644 src/Features/CloudShadow.h diff --git a/features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli b/features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli new file mode 100644 index 000000000..3acc18c2a --- /dev/null +++ b/features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli @@ -0,0 +1,51 @@ +struct PerPassCloudShadow +{ + uint EnableCloudShadow; + + float CloudHeight; + float PlanetRadius; + + float ShadowBlend; + float DiffuseLightBrightness; + float DiffuseLightSaturation; + + float RcpHPlusR; +}; + +StructuredBuffer perPassCloudShadow : register(t23); +TextureCube cloudShadows : register(t40); + +float3 getCloudShadowSampleDir(float3 rel_pos, float3 eye_to_sun) +{ + float r = perPassCloudShadow[0].PlanetRadius; + float3 p = (rel_pos + float3(0, 0, r)) * perPassCloudShadow[0].RcpHPlusR; + float dotprod = dot(p, eye_to_sun); + float lengthsqr = dot(p, p); + float t = -dotprod + sqrt(dotprod * dotprod - dot(p, p) + 1); + float3 v = (p + eye_to_sun * t) * (r + perPassCloudShadow[0].CloudHeight) - float3(0, 0, r); + v = normalize(v); + return v; +} + +float3 getCloudShadowSampleDirFlatEarth(float3 rel_pos, float3 eye_to_sun) +{ + float3 p = rel_pos / perPassCloudShadow[0].CloudHeight; + float dotprod = dot(p, eye_to_sun); + float t = -dotprod + sqrt(dotprod * dotprod - dot(p, p) + 1); + float3 v = p + eye_to_sun * t; + v = normalize(v); // optional + return v; +} + +float3 getCloudShadowMult(float3 rel_pos, float3 eye_to_sun, SamplerState samp) +{ + // float3 cloudSampleDir = getCloudShadowSampleDirFlatEarth(rel_pos, eye_to_sun).xyz; + float3 cloudSampleDir = getCloudShadowSampleDir(rel_pos, eye_to_sun).xyz; + + float4 cloudCubeSample = cloudShadows.Sample(samp, cloudSampleDir); + float3 cloudDiffuseLight = cloudCubeSample.xyz * perPassCloudShadow[0].DiffuseLightBrightness; + cloudDiffuseLight = saturate(lerp(length(cloudDiffuseLight), cloudDiffuseLight, perPassCloudShadow[0].DiffuseLightSaturation)); + float cloudShadowBlend = lerp(0, saturate(cloudCubeSample.w), perPassCloudShadow[0].ShadowBlend); + + return lerp(1.0, cloudDiffuseLight, cloudShadowBlend); +} \ No newline at end of file diff --git a/features/Cloud Shadow/Shaders/Features/CloudShadow.ini b/features/Cloud Shadow/Shaders/Features/CloudShadow.ini new file mode 100644 index 000000000..19f01444d --- /dev/null +++ b/features/Cloud Shadow/Shaders/Features/CloudShadow.ini @@ -0,0 +1,2 @@ +[Info] +Version = 1-0-0 \ No newline at end of file diff --git a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl index 5eaf8c1b9..feeb3e5e1 100644 --- a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl +++ b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl @@ -2,6 +2,14 @@ #include "Common/FrameBuffer.hlsl" #include "Common/MotionBlur.hlsl" +struct LightingData +{ + float WaterHeight[25]; + bool Reflections; +}; + +StructuredBuffer lightingData : register(t126); + cbuffer PerFrame : register(b3) { row_major float3x4 DirectionalAmbient; @@ -174,6 +182,10 @@ Texture2D TexShadowMaskSampler : register(t17); # include "ScreenSpaceShadows/ShadowsPS.hlsli" # endif +# if defined(CLOUD_SHADOW) +# include "CloudShadow/CloudShadow.hlsli" +# endif + PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { @@ -243,6 +255,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace dirLightColor *= DirLightScale; } +# if defined(CLOUD_SHADOW) + float3 cloudShadowMult = 1.0; + if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, DirLightDirection.xyz, SampDiffuse); + dirLightColor *= cloudShadowMult; + } +# endif + float3 nsDirLightColor = dirLightColor; # if defined(SCREEN_SPACE_SHADOWS) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 4eb95d558..904687959 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1005,6 +1005,10 @@ float2 ComputeTriplanarUV(float3 InputPosition) # include "WetnessEffects/WetnessEffects.hlsli" # endif +# if defined(CLOUD_SHADOW) +# include "CloudShadow/CloudShadow.hlsli" +# endif + PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { @@ -1441,6 +1445,41 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 dirLightColor = DirLightColor.xyz; float selfShadowFactor = 1.0f; + float3 screenSpaceNormal; + screenSpaceNormal.x = dot(input.ScreenNormalTransform0.xyz, normal.xyz); + screenSpaceNormal.y = dot(input.ScreenNormalTransform1.xyz, normal.xyz); + screenSpaceNormal.z = dot(input.ScreenNormalTransform2.xyz, normal.xyz); + screenSpaceNormal = normalize(screenSpaceNormal); + + float3 worldSpaceNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceNormal, 0))); + float3 normalizedDirLightDirectionWS = DirLightDirection; + +# if (defined(SKINNED) || !defined(MODELSPACENORMALS)) + float3 vertexNormal = tbnTr[2]; + +# if !defined(MODELSPACENORMALS) + float3 screenSpaceVertexNormal; + screenSpaceVertexNormal.x = dot(input.ScreenNormalTransform0.xyz, vertexNormal); + screenSpaceVertexNormal.y = dot(input.ScreenNormalTransform1.xyz, vertexNormal); + screenSpaceVertexNormal.z = dot(input.ScreenNormalTransform2.xyz, vertexNormal); + screenSpaceVertexNormal = normalize(screenSpaceVertexNormal); + + float3 worldSpaceVertexNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceVertexNormal, 0))); +# endif + +# if (!defined(DRAW_IN_WORLDSPACE)) + normalizedDirLightDirectionWS = lerp(normalize(mul(input.World[eyeIndex], float4(DirLightDirection, 0))), normalizedDirLightDirectionWS, input.WorldSpace); +# endif +# endif + +# if defined(CLOUD_SHADOW) + float3 cloudShadowMult = 1.0; + if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, normalizedDirLightDirectionWS, SampColorSampler); + dirLightColor *= cloudShadowMult; + } +# endif + float3 nsDirLightColor = dirLightColor; if ((shaderDescriptors[0].PixelShaderDescriptor & _DefShadow) && (shaderDescriptors[0].PixelShaderDescriptor & _ShadowDir)) @@ -1512,33 +1551,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace lightsDiffuseColor += dirDiffuseColor; - float3 screenSpaceNormal; - screenSpaceNormal.x = dot(input.ScreenNormalTransform0.xyz, normal.xyz); - screenSpaceNormal.y = dot(input.ScreenNormalTransform1.xyz, normal.xyz); - screenSpaceNormal.z = dot(input.ScreenNormalTransform2.xyz, normal.xyz); - screenSpaceNormal = normalize(screenSpaceNormal); - - float3 worldSpaceNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceNormal, 0))); - float3 normalizedDirLightDirectionWS = DirLightDirection; - -# if (defined(SKINNED) || !defined(MODELSPACENORMALS)) - float3 vertexNormal = tbnTr[2]; - -# if !defined(MODELSPACENORMALS) - float3 screenSpaceVertexNormal; - screenSpaceVertexNormal.x = dot(input.ScreenNormalTransform0.xyz, vertexNormal); - screenSpaceVertexNormal.y = dot(input.ScreenNormalTransform1.xyz, vertexNormal); - screenSpaceVertexNormal.z = dot(input.ScreenNormalTransform2.xyz, vertexNormal); - screenSpaceVertexNormal = normalize(screenSpaceVertexNormal); - - float3 worldSpaceVertexNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceVertexNormal, 0))); -# endif - -# if (!defined(DRAW_IN_WORLDSPACE)) - normalizedDirLightDirectionWS = lerp(normalize(mul(input.World[eyeIndex], float4(DirLightDirection, 0))), normalizedDirLightDirectionWS, input.WorldSpace); -# endif -# endif - float porosity = 1.0; # if defined(WATER_BLENDING) || defined(WETNESS_EFFECTS) @@ -1935,7 +1947,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif # if defined(CPM_AVAILABLE) && defined(ENVMAP) +# if defined(DYNAMIC_CUBEMAPS) vertexColor += envColor * lerp(complexSpecular, 1.0, dynamicCubemap) * diffuseColor; +# else + vertexColor += envColor * complexSpecular * diffuseColor; +# endif # else vertexColor += envColor * diffuseColor; # endif diff --git a/package/Shaders/Sky.hlsl b/package/Shaders/Sky.hlsl index 33dc7741d..bad321430 100644 --- a/package/Shaders/Sky.hlsl +++ b/package/Shaders/Sky.hlsl @@ -121,6 +121,7 @@ struct PS_OUTPUT float4 Color : SV_Target0; float2 MotionVectors : SV_Target1; float4 Normal : SV_Target2; + float4 CloudShadows : SV_Target3; }; #ifdef PSHADER @@ -205,6 +206,12 @@ PS_OUTPUT main(PS_INPUT input) psout.MotionVectors = screenMotionVector; psout.Normal = float4(0.5, 0.5, 0, 0); +# if defined(CLOUDS) + psout.CloudShadows = psout.Color; +# else + psout.CloudShadows = 0.0; +# endif + return psout; } #endif diff --git a/src/Feature.cpp b/src/Feature.cpp index f418cee33..aa915522e 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -1,5 +1,6 @@ #include "Feature.h" +#include "Features/CloudShadow.h" #include "Features/DistantTreeLighting.h" #include "Features/DynamicCubemaps.h" #include "Features/ExtendedMaterials.h" @@ -81,7 +82,8 @@ const std::vector& Feature::GetFeatureList() WaterBlending::GetSingleton(), WetnessEffects::GetSingleton(), LightLimitFix::GetSingleton(), - DynamicCubemaps::GetSingleton() + DynamicCubemaps::GetSingleton(), + CloudShadow::GetSingleton() }; static std::vector featuresVR = { diff --git a/src/Features/CloudShadow.cpp b/src/Features/CloudShadow.cpp new file mode 100644 index 000000000..5263f731a --- /dev/null +++ b/src/Features/CloudShadow.cpp @@ -0,0 +1,304 @@ +#include "CloudShadow.h" + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + CloudShadow::Settings, + EnableCloudShadow, + CloudHeight, + PlanetRadius, + DiffuseLightBrightness, + DiffuseLightSaturation) + +class FrameChecker +{ +private: + uint32_t last_frame = UINT32_MAX; + +public: + inline bool isNewFrame(uint32_t frame) + { + bool retval = last_frame != frame; + last_frame = frame; + return retval; + } + inline bool isNewFrame() { return isNewFrame(RE::BSGraphics::State::GetSingleton()->uiFrameCount); } +}; + +void CloudShadow::DrawSettings() +{ + if (ImGui::TreeNodeEx("Cloud Shadow", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("Enable Cloud Shadow", (bool*)&settings.EnableCloudShadow); + + if (ImGui::TreeNodeEx("Mixing", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); + + ImGui::SliderFloat("Diffuse Light Brightness", &settings.DiffuseLightBrightness, 0.0f, 1.0f, "%.2f"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::Text("Simulates diffuse light \"filtered\" by the cloud."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + ImGui::SliderFloat("Diffuse Light Saturation", &settings.DiffuseLightSaturation, 0.0f, 2.0f, "%.2f"); + + ImGui::TreePop(); + } + + if (ImGui::TreeNodeEx("Geometry")) { + ImGui::SliderFloat("Cloud Height", &settings.CloudHeight, 1e3f / 1.428e-2f, 10e3f / 1.428e-2f, "%.1f units"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::BulletText(std::format("approx: {:.2f} km / {:.2f} miles", settings.CloudHeight * 1.428e-5f, settings.CloudHeight * 8.877e-6f).data()); + ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts greater shadow."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + ImGui::SliderFloat("Planet Radius", &settings.PlanetRadius, 2000e3f / 1.428e-2f, 10000e3f / 1.428e-2f, "%.1f units"); + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::BulletText(std::format("approx: {:.1f} km / {:.1f} miles", settings.PlanetRadius * 1.428e-5f, settings.PlanetRadius * 8.877e-6f).data()); + ImGui::Text("This setting affects distortion of clouds near horizon."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + ImGui::TreePop(); + } + + ImGui::TreePop(); + } + + ImGui::Spacing(); + ImGui::Spacing(); + + if (ImGui::Button("Restore Defaults", { -1, 0 })) { + RestoreDefaultSettings(); + } + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::Text( + "Restores the feature's settings back to their default values. " + "You will still need to Save Settings to make these changes permanent. "); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } +} + +void CloudShadow::CheckResourcesSide(int side) +{ + static FrameChecker frame_checker[6]; + if (!frame_checker[side].isNewFrame()) + return; + + auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; + + float black[4] = { 0, 0, 0, 0 }; + context->ClearRenderTargetView(cubemapCloudOccRTVs[side], black); +} + +void CloudShadow::ModifySky(const RE::BSShader*, const uint32_t descriptor) +{ + auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton(); + auto cubeMapRenderTarget = !REL::Module::IsVR() ? shadowState->GetRuntimeData().cubeMapRenderTarget : shadowState->GetVRRuntimeData().cubeMapRenderTarget; + if (cubeMapRenderTarget != RE::RENDER_TARGETS_CUBEMAP::kREFLECTIONS) + return; + + enum class SkyShaderTechniques + { + SunOcclude = 0, + SunGlare = 1, + MoonAndStarsMask = 2, + Stars = 3, + Clouds = 4, + CloudsLerp = 5, + CloudsFade = 6, + Texture = 7, + Sky = 8, + }; + + auto tech_enum = static_cast(descriptor); + if (tech_enum == SkyShaderTechniques::Clouds || tech_enum == SkyShaderTechniques::CloudsLerp || tech_enum == SkyShaderTechniques::CloudsFade) { + auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; + auto renderer = RE::BSGraphics::Renderer::GetSingleton(); + auto device = renderer->GetRuntimeData().forwarder; + + { + ID3D11ShaderResourceView* srv = nullptr; + context->PSSetShaderResources(40, 1, &srv); + } + + auto reflections = renderer->GetRendererData().cubemapRenderTargets[RE::RENDER_TARGET_CUBEMAP::kREFLECTIONS]; + + // render targets + ID3D11RenderTargetView* rtvs[4]; + ID3D11DepthStencilView* depthStencil; + context->OMGetRenderTargets(3, rtvs, &depthStencil); + + int side = -1; + for (int i = 0; i < 6; ++i) + if (rtvs[0] == reflections.cubeSideRTV[i]) { + side = i; + break; + } + if (side == -1) + return; + + CheckResourcesSide(side); + + rtvs[3] = cubemapCloudOccRTVs[side]; + context->OMSetRenderTargets(4, rtvs, depthStencil); + + // blend states + ID3D11BlendState* blendState; + FLOAT blendFactor[4]; + UINT sampleMask; + + context->OMGetBlendState(&blendState, blendFactor, &sampleMask); + + if (!mappedBlendStates.contains(blendState)) { + if (!modifiedBlendStates.contains(blendState)) { + D3D11_BLEND_DESC blendDesc; + blendState->GetDesc(&blendDesc); + + blendDesc.RenderTarget[3] = blendDesc.RenderTarget[0]; + + ID3D11BlendState* modifiedBlendState; + DX::ThrowIfFailed(device->CreateBlendState(&blendDesc, &modifiedBlendState)); + + mappedBlendStates.insert(modifiedBlendState); + modifiedBlendStates.insert({ blendState, modifiedBlendState }); + } + blendState = modifiedBlendStates[blendState]; + context->OMSetBlendState(blendState, blendFactor, sampleMask); + } + + //auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); + //state->GetRuntimeData().stateUpdateFlags |= (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_ALPHA_BLEND; + } +} + +void CloudShadow::ModifyLighting() +{ + auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; + + auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton(); + auto cubeMapRenderTarget = !REL::Module::IsVR() ? shadowState->GetRuntimeData().cubeMapRenderTarget : shadowState->GetVRRuntimeData().cubeMapRenderTarget; + if (cubeMapRenderTarget != RE::RENDER_TARGETS_CUBEMAP::kREFLECTIONS) { + static FrameChecker frame_checker; + if (frame_checker.isNewFrame()) + context->GenerateMips(texCubemapCloudOcc->srv.get()); + + auto srv = texCubemapCloudOcc->srv.get(); + context->PSSetShaderResources(40, 1, &srv); + } else { + ID3D11ShaderResourceView* srv = nullptr; + context->PSSetShaderResources(40, 1, &srv); + } + + ID3D11ShaderResourceView* views[1]{}; + views[0] = perPass->srv.get(); + context->PSSetShaderResources(23, ARRAYSIZE(views), views); +} + +void CloudShadow::Draw(const RE::BSShader* shader, const uint32_t descriptor) +{ + static FrameChecker frame_checker; + if (frame_checker.isNewFrame()) { + // update settings buffer + auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; + + PerPass perPassData{}; + + perPassData.Settings = settings; + perPassData.RcpHPlusR = 1.f / (settings.CloudHeight + settings.PlanetRadius); + + D3D11_MAPPED_SUBRESOURCE mapped; + DX::ThrowIfFailed(context->Map(perPass->resource.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); + size_t bytes = sizeof(PerPass); + memcpy_s(mapped.pData, bytes, &perPassData, bytes); + context->Unmap(perPass->resource.get(), 0); + } + + switch (shader->shaderType.get()) { + case RE::BSShader::Type::Sky: + ModifySky(shader, descriptor); + break; + case RE::BSShader::Type::Lighting: + case RE::BSShader::Type::DistantTree: + ModifyLighting(); + break; + default: + break; + } +} + +void CloudShadow::Load(json& o_json) +{ + if (o_json[GetName()].is_object()) + settings = o_json[GetName()]; + + Feature::Load(o_json); +} + +void CloudShadow::Save(json& o_json) +{ + o_json[GetName()] = settings; +} + +void CloudShadow::SetupResources() +{ + auto renderer = RE::BSGraphics::Renderer::GetSingleton(); + auto device = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().forwarder; + + { + auto reflections = renderer->GetRendererData().cubemapRenderTargets[RE::RENDER_TARGET_CUBEMAP::kREFLECTIONS]; + + D3D11_TEXTURE2D_DESC texDesc{}; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc{}; + + reflections.texture->GetDesc(&texDesc); + reflections.SRV->GetDesc(&srvDesc); + + texDesc.Format = srvDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + texDesc.MipLevels = srvDesc.Texture2D.MipLevels = 5; + texDesc.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + + texCubemapCloudOcc = new Texture2D(texDesc); + texCubemapCloudOcc->CreateSRV(srvDesc); + + for (int i = 0; i < 6; ++i) { + reflections.cubeSideRTV[i]->GetDesc(&rtvDesc); + rtvDesc.Format = texDesc.Format; + DX::ThrowIfFailed(device->CreateRenderTargetView(texCubemapCloudOcc->resource.get(), &rtvDesc, cubemapCloudOccRTVs + i)); + } + } + + { + D3D11_BUFFER_DESC sbDesc{}; + sbDesc.Usage = D3D11_USAGE_DYNAMIC; + sbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + sbDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + sbDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + sbDesc.StructureByteStride = sizeof(PerPass); + sbDesc.ByteWidth = sizeof(PerPass); + perPass = std::make_unique(sbDesc); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = DXGI_FORMAT_UNKNOWN; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + srvDesc.Buffer.FirstElement = 0; + srvDesc.Buffer.NumElements = 1; + perPass->CreateSRV(srvDesc); + } +} + +void CloudShadow::RestoreDefaultSettings() +{ + settings = {}; +} \ No newline at end of file diff --git a/src/Features/CloudShadow.h b/src/Features/CloudShadow.h new file mode 100644 index 000000000..3d8151f36 --- /dev/null +++ b/src/Features/CloudShadow.h @@ -0,0 +1,62 @@ +#pragma once + +#include "Buffer.h" +#include "Feature.h" + +struct CloudShadow : Feature +{ + static CloudShadow* GetSingleton() + { + static CloudShadow singleton; + return &singleton; + } + + virtual inline std::string GetName() { return "Cloud Shadow"; } + virtual inline std::string GetShortName() { return "CloudShadow"; } + virtual inline std::string_view GetShaderDefineName() { return "CLOUD_SHADOW"; } + virtual inline bool HasShaderDefine(RE::BSShader::Type) { return true; } + + struct Settings + { + uint EnableCloudShadow = true; + + float CloudHeight = 2e3f / 1.428e-2f; + float PlanetRadius = 6371e3f / 1.428e-2f; + + float ShadowBlend = 1.f; + float DiffuseLightBrightness = 0.5f; + float DiffuseLightSaturation = 1.f; + } settings; + + struct alignas(16) PerPass + { + Settings Settings; + + float RcpHPlusR; + + float padding; + }; + std::unique_ptr perPass = nullptr; + + std::set mappedBlendStates; + std::map modifiedBlendStates; + + Texture2D* texCubemapCloudOcc = nullptr; + ID3D11RenderTargetView* cubemapCloudOccRTVs[6] = { nullptr }; + ID3D11ShaderResourceView* cubemapCloudOccDebugSRV = nullptr; + + virtual void SetupResources(); + virtual inline void Reset() {} + + virtual void DrawSettings(); + + void CheckResourcesSide(int side); + void ModifySky(const RE::BSShader* shader, const uint32_t descriptor); + void ModifyLighting(); + virtual void Draw(const RE::BSShader* shader, const uint32_t descriptor); + + virtual void Load(json& o_json); + virtual void Save(json& o_json); + + virtual void RestoreDefaultSettings(); +}; From e5ef581d1ac850648724185954c03f8ada211337 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 11:39:44 +0000 Subject: [PATCH 02/13] feat: Tree LOD cloud shadow --- .../Shaders/DistantTree.hlsl | 8 +++- src/Features/CloudShadow.cpp | 38 +++---------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl index feeb3e5e1..0f17e32f5 100644 --- a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl +++ b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl @@ -44,6 +44,8 @@ struct VS_OUTPUT float4 PreviousWorldPosition : POSITION2; #endif float3 SphereNormal : TEXCOORD4; + + row_major float3x4 World : POSITION3; }; #ifdef VSHADER @@ -90,6 +92,8 @@ VS_OUTPUT main(VS_INPUT input) vsout.SphereNormal.xyz = mul(World, normalize(adjustedModelPosition)); + vsout.World = World; + return vsout; } #endif @@ -256,9 +260,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } # if defined(CLOUD_SHADOW) + float3 normalizedDirLightDirectionWS = -normalize(mul(input.World, float4(DirLightDirection.xyz, 0))).xyz; + float3 cloudShadowMult = 1.0; if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { - cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, DirLightDirection.xyz, SampDiffuse); + cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, normalizedDirLightDirectionWS.xyz, SampDiffuse); dirLightColor *= cloudShadowMult; } # endif diff --git a/src/Features/CloudShadow.cpp b/src/Features/CloudShadow.cpp index 5263f731a..da2458de9 100644 --- a/src/Features/CloudShadow.cpp +++ b/src/Features/CloudShadow.cpp @@ -1,5 +1,7 @@ #include "CloudShadow.h" +#include "Util.h" + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( CloudShadow::Settings, EnableCloudShadow, @@ -32,12 +34,8 @@ void CloudShadow::DrawSettings() ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat("Diffuse Light Brightness", &settings.DiffuseLightBrightness, 0.0f, 1.0f, "%.2f"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::Text("Simulates diffuse light \"filtered\" by the cloud."); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); } ImGui::SliderFloat("Diffuse Light Saturation", &settings.DiffuseLightSaturation, 0.0f, 2.0f, "%.2f"); @@ -47,46 +45,22 @@ void CloudShadow::DrawSettings() if (ImGui::TreeNodeEx("Geometry")) { ImGui::SliderFloat("Cloud Height", &settings.CloudHeight, 1e3f / 1.428e-2f, 10e3f / 1.428e-2f, "%.1f units"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::BulletText(std::format("approx: {:.2f} km / {:.2f} miles", settings.CloudHeight * 1.428e-5f, settings.CloudHeight * 8.877e-6f).data()); - ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts greater shadow."); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); + ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts slightly greater shadow."); } ImGui::SliderFloat("Planet Radius", &settings.PlanetRadius, 2000e3f / 1.428e-2f, 10000e3f / 1.428e-2f, "%.1f units"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::BulletText(std::format("approx: {:.1f} km / {:.1f} miles", settings.PlanetRadius * 1.428e-5f, settings.PlanetRadius * 8.877e-6f).data()); ImGui::Text("This setting affects distortion of clouds near horizon."); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); } ImGui::TreePop(); } ImGui::TreePop(); } - - ImGui::Spacing(); - ImGui::Spacing(); - - if (ImGui::Button("Restore Defaults", { -1, 0 })) { - RestoreDefaultSettings(); - } - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::Text( - "Restores the feature's settings back to their default values. " - "You will still need to Save Settings to make these changes permanent. "); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } } void CloudShadow::CheckResourcesSide(int side) From a80fa8e14c8d5c94ef2616537ce3c015e638d11e Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 11:46:59 +0000 Subject: [PATCH 03/13] feat: grass lighting cloud shadow --- features/Grass Lighting/Shaders/RunGrass.hlsl | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index a4b4e10c5..439e89022 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -2,6 +2,14 @@ #include "Common/FrameBuffer.hlsl" #include "Common/MotionBlur.hlsl" +struct LightingData +{ + float WaterHeight[25]; + bool Reflections; +}; + +StructuredBuffer lightingData : register(t126); + #define GRASS struct VS_INPUT @@ -355,6 +363,10 @@ float3x3 CalculateTBN(float3 N, float3 p, float2 uv) # include "DynamicCubemaps/DynamicCubemaps.hlsli" # endif +# if defined(CLOUD_SHADOW) +# include "CloudShadow/CloudShadow.hlsli" +# endif + PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { @@ -435,6 +447,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace dirLightColor *= SunlightScale; } +# if defined(CLOUD_SHADOW) + float3 cloudShadowMult = 1.0; + if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, DirLightDirection.xyz, SampColorSampler); + dirLightColor *= cloudShadowMult; + } +# endif + dirLightColor *= shadowColor.x; # if defined(SCREEN_SPACE_SHADOWS) From 46ec8a90c8af6b1930a096cc747640275db3f993 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 12:32:28 +0000 Subject: [PATCH 04/13] feat: water cloud shadow --- package/Shaders/Water.hlsl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/package/Shaders/Water.hlsl b/package/Shaders/Water.hlsl index af6afd424..59361435c 100644 --- a/package/Shaders/Water.hlsl +++ b/package/Shaders/Water.hlsl @@ -2,6 +2,14 @@ #include "Common/MotionBlur.hlsl" #include "Common/Permutation.hlsl" +struct LightingData +{ + float WaterHeight[25]; + bool Reflections; +}; + +StructuredBuffer lightingData : register(t126); + #define WATER struct VS_INPUT @@ -507,6 +515,10 @@ float3 GetSunColor(float3 normal, float3 viewDirection) # include "LightLimitFix/LightLimitFix.hlsli" # endif +# if defined(CLOUD_SHADOW) +# include "CloudShadow/CloudShadow.hlsli" +# endif + PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; @@ -623,6 +635,15 @@ PS_OUTPUT main(PS_INPUT input) finalSpecularColor; # else float3 sunColor = GetSunColor(normal, viewDirection); + +# if defined(CLOUD_SHADOW) + float3 cloudShadowMult = 1.0; + if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + cloudShadowMult = getCloudShadowMult(input.WPosition.xyz, SunDir.xyz, CubeMapSampler); + sunColor *= cloudShadowMult; + } +# endif + float specularFraction = lerp(1, fresnel * depthControl.x, distanceFactor); float3 finalColorPreFog = lerp(diffuseColor, specularColor, specularFraction) + sunColor * depthControl.w; float3 finalColor = lerp(finalColorPreFog, input.FogParam.xyz, input.FogParam.w); From 1098879f14cce2fba634834a55ed707b83f166de Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 14:53:21 +0000 Subject: [PATCH 05/13] refactor: use plural form of "shadow" in names and titles --- .../Shaders/CloudShadows/CloudShadows.hlsli} | 2 +- .../Shaders/Features/CloudShadows.ini} | 0 features/Grass Lighting/Shaders/RunGrass.hlsl | 8 +++--- .../Shaders/DistantTree.hlsl | 8 +++--- package/Shaders/Lighting.hlsl | 8 +++--- package/Shaders/Water.hlsl | 8 +++--- src/Feature.cpp | 4 +-- .../{CloudShadow.cpp => CloudShadows.cpp} | 28 +++++++++---------- .../{CloudShadow.h => CloudShadows.h} | 14 +++++----- 9 files changed, 40 insertions(+), 40 deletions(-) rename features/{Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli => Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli} (98%) rename features/{Cloud Shadow/Shaders/Features/CloudShadow.ini => Cloud Shadows/Shaders/Features/CloudShadows.ini} (100%) rename src/Features/{CloudShadow.cpp => CloudShadows.cpp} (92%) rename src/Features/{CloudShadow.h => CloudShadows.h} (85%) diff --git a/features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli similarity index 98% rename from features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli rename to features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli index 3acc18c2a..abd49b0c2 100644 --- a/features/Cloud Shadow/Shaders/CloudShadow/CloudShadow.hlsli +++ b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli @@ -1,6 +1,6 @@ struct PerPassCloudShadow { - uint EnableCloudShadow; + uint EnableCloudShadows; float CloudHeight; float PlanetRadius; diff --git a/features/Cloud Shadow/Shaders/Features/CloudShadow.ini b/features/Cloud Shadows/Shaders/Features/CloudShadows.ini similarity index 100% rename from features/Cloud Shadow/Shaders/Features/CloudShadow.ini rename to features/Cloud Shadows/Shaders/Features/CloudShadows.ini diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 439e89022..6733429de 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -363,8 +363,8 @@ float3x3 CalculateTBN(float3 N, float3 p, float2 uv) # include "DynamicCubemaps/DynamicCubemaps.hlsli" # endif -# if defined(CLOUD_SHADOW) -# include "CloudShadow/CloudShadow.hlsli" +# if defined(CLOUD_SHADOWS) +# include "CloudShadows/CloudShadows.hlsli" # endif PS_OUTPUT main(PS_INPUT input, bool frontFace @@ -447,9 +447,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace dirLightColor *= SunlightScale; } -# if defined(CLOUD_SHADOW) +# if defined(CLOUD_SHADOWS) float3 cloudShadowMult = 1.0; - if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) { cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, DirLightDirection.xyz, SampColorSampler); dirLightColor *= cloudShadowMult; } diff --git a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl index 0f17e32f5..faeb5f539 100644 --- a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl +++ b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl @@ -186,8 +186,8 @@ Texture2D TexShadowMaskSampler : register(t17); # include "ScreenSpaceShadows/ShadowsPS.hlsli" # endif -# if defined(CLOUD_SHADOW) -# include "CloudShadow/CloudShadow.hlsli" +# if defined(CLOUD_SHADOWS) +# include "CloudShadows/CloudShadows.hlsli" # endif PS_OUTPUT main(PS_INPUT input, bool frontFace @@ -259,11 +259,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace dirLightColor *= DirLightScale; } -# if defined(CLOUD_SHADOW) +# if defined(CLOUD_SHADOWS) float3 normalizedDirLightDirectionWS = -normalize(mul(input.World, float4(DirLightDirection.xyz, 0))).xyz; float3 cloudShadowMult = 1.0; - if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) { cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, normalizedDirLightDirectionWS.xyz, SampDiffuse); dirLightColor *= cloudShadowMult; } diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 904687959..8407a67c2 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1005,8 +1005,8 @@ float2 ComputeTriplanarUV(float3 InputPosition) # include "WetnessEffects/WetnessEffects.hlsli" # endif -# if defined(CLOUD_SHADOW) -# include "CloudShadow/CloudShadow.hlsli" +# if defined(CLOUD_SHADOWS) +# include "CloudShadows/CloudShadows.hlsli" # endif PS_OUTPUT main(PS_INPUT input, bool frontFace @@ -1472,9 +1472,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif # endif -# if defined(CLOUD_SHADOW) +# if defined(CLOUD_SHADOWS) float3 cloudShadowMult = 1.0; - if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) { cloudShadowMult = getCloudShadowMult(input.WorldPosition.xyz, normalizedDirLightDirectionWS, SampColorSampler); dirLightColor *= cloudShadowMult; } diff --git a/package/Shaders/Water.hlsl b/package/Shaders/Water.hlsl index 59361435c..de26203bb 100644 --- a/package/Shaders/Water.hlsl +++ b/package/Shaders/Water.hlsl @@ -515,8 +515,8 @@ float3 GetSunColor(float3 normal, float3 viewDirection) # include "LightLimitFix/LightLimitFix.hlsli" # endif -# if defined(CLOUD_SHADOW) -# include "CloudShadow/CloudShadow.hlsli" +# if defined(CLOUD_SHADOWS) +# include "CloudShadows/CloudShadows.hlsli" # endif PS_OUTPUT main(PS_INPUT input) @@ -636,9 +636,9 @@ PS_OUTPUT main(PS_INPUT input) # else float3 sunColor = GetSunColor(normal, viewDirection); -# if defined(CLOUD_SHADOW) +# if defined(CLOUD_SHADOWS) float3 cloudShadowMult = 1.0; - if (perPassCloudShadow[0].EnableCloudShadow && !lightingData[0].Reflections) { + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) { cloudShadowMult = getCloudShadowMult(input.WPosition.xyz, SunDir.xyz, CubeMapSampler); sunColor *= cloudShadowMult; } diff --git a/src/Feature.cpp b/src/Feature.cpp index aa915522e..5b8663edf 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -1,6 +1,6 @@ #include "Feature.h" -#include "Features/CloudShadow.h" +#include "Features/CloudShadows.h" #include "Features/DistantTreeLighting.h" #include "Features/DynamicCubemaps.h" #include "Features/ExtendedMaterials.h" @@ -83,7 +83,7 @@ const std::vector& Feature::GetFeatureList() WetnessEffects::GetSingleton(), LightLimitFix::GetSingleton(), DynamicCubemaps::GetSingleton(), - CloudShadow::GetSingleton() + CloudShadows::GetSingleton() }; static std::vector featuresVR = { diff --git a/src/Features/CloudShadow.cpp b/src/Features/CloudShadows.cpp similarity index 92% rename from src/Features/CloudShadow.cpp rename to src/Features/CloudShadows.cpp index da2458de9..7cd2f65e4 100644 --- a/src/Features/CloudShadow.cpp +++ b/src/Features/CloudShadows.cpp @@ -1,10 +1,10 @@ -#include "CloudShadow.h" +#include "CloudShadows.h" #include "Util.h" NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( - CloudShadow::Settings, - EnableCloudShadow, + CloudShadows::Settings, + EnableCloudShadows, CloudHeight, PlanetRadius, DiffuseLightBrightness, @@ -25,10 +25,10 @@ class FrameChecker inline bool isNewFrame() { return isNewFrame(RE::BSGraphics::State::GetSingleton()->uiFrameCount); } }; -void CloudShadow::DrawSettings() +void CloudShadows::DrawSettings() { - if (ImGui::TreeNodeEx("Cloud Shadow", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Enable Cloud Shadow", (bool*)&settings.EnableCloudShadow); + if (ImGui::TreeNodeEx("Cloud Shadows", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("Enable Cloud Shadows", (bool*)&settings.EnableCloudShadows); if (ImGui::TreeNodeEx("Mixing", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); @@ -63,7 +63,7 @@ void CloudShadow::DrawSettings() } } -void CloudShadow::CheckResourcesSide(int side) +void CloudShadows::CheckResourcesSide(int side) { static FrameChecker frame_checker[6]; if (!frame_checker[side].isNewFrame()) @@ -75,7 +75,7 @@ void CloudShadow::CheckResourcesSide(int side) context->ClearRenderTargetView(cubemapCloudOccRTVs[side], black); } -void CloudShadow::ModifySky(const RE::BSShader*, const uint32_t descriptor) +void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor) { auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton(); auto cubeMapRenderTarget = !REL::Module::IsVR() ? shadowState->GetRuntimeData().cubeMapRenderTarget : shadowState->GetVRRuntimeData().cubeMapRenderTarget; @@ -156,7 +156,7 @@ void CloudShadow::ModifySky(const RE::BSShader*, const uint32_t descriptor) } } -void CloudShadow::ModifyLighting() +void CloudShadows::ModifyLighting() { auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; @@ -179,7 +179,7 @@ void CloudShadow::ModifyLighting() context->PSSetShaderResources(23, ARRAYSIZE(views), views); } -void CloudShadow::Draw(const RE::BSShader* shader, const uint32_t descriptor) +void CloudShadows::Draw(const RE::BSShader* shader, const uint32_t descriptor) { static FrameChecker frame_checker; if (frame_checker.isNewFrame()) { @@ -211,7 +211,7 @@ void CloudShadow::Draw(const RE::BSShader* shader, const uint32_t descriptor) } } -void CloudShadow::Load(json& o_json) +void CloudShadows::Load(json& o_json) { if (o_json[GetName()].is_object()) settings = o_json[GetName()]; @@ -219,12 +219,12 @@ void CloudShadow::Load(json& o_json) Feature::Load(o_json); } -void CloudShadow::Save(json& o_json) +void CloudShadows::Save(json& o_json) { o_json[GetName()] = settings; } -void CloudShadow::SetupResources() +void CloudShadows::SetupResources() { auto renderer = RE::BSGraphics::Renderer::GetSingleton(); auto device = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().forwarder; @@ -272,7 +272,7 @@ void CloudShadow::SetupResources() } } -void CloudShadow::RestoreDefaultSettings() +void CloudShadows::RestoreDefaultSettings() { settings = {}; } \ No newline at end of file diff --git a/src/Features/CloudShadow.h b/src/Features/CloudShadows.h similarity index 85% rename from src/Features/CloudShadow.h rename to src/Features/CloudShadows.h index 3d8151f36..65d01b974 100644 --- a/src/Features/CloudShadow.h +++ b/src/Features/CloudShadows.h @@ -3,22 +3,22 @@ #include "Buffer.h" #include "Feature.h" -struct CloudShadow : Feature +struct CloudShadows : Feature { - static CloudShadow* GetSingleton() + static CloudShadows* GetSingleton() { - static CloudShadow singleton; + static CloudShadows singleton; return &singleton; } - virtual inline std::string GetName() { return "Cloud Shadow"; } - virtual inline std::string GetShortName() { return "CloudShadow"; } - virtual inline std::string_view GetShaderDefineName() { return "CLOUD_SHADOW"; } + virtual inline std::string GetName() { return "Cloud Shadows"; } + virtual inline std::string GetShortName() { return "CloudShadows"; } + virtual inline std::string_view GetShaderDefineName() { return "CLOUD_SHADOWS"; } virtual inline bool HasShaderDefine(RE::BSShader::Type) { return true; } struct Settings { - uint EnableCloudShadow = true; + uint EnableCloudShadows = true; float CloudHeight = 2e3f / 1.428e-2f; float PlanetRadius = 6371e3f / 1.428e-2f; From 0402c36925b740022bc6b56d5a3bf7ea2863c8ba Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 15:34:40 +0000 Subject: [PATCH 06/13] fix: tree bark temporary fix --- package/Shaders/Lighting.hlsl | 48 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 8407a67c2..09fc3cd73 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1445,31 +1445,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 dirLightColor = DirLightColor.xyz; float selfShadowFactor = 1.0f; - float3 screenSpaceNormal; - screenSpaceNormal.x = dot(input.ScreenNormalTransform0.xyz, normal.xyz); - screenSpaceNormal.y = dot(input.ScreenNormalTransform1.xyz, normal.xyz); - screenSpaceNormal.z = dot(input.ScreenNormalTransform2.xyz, normal.xyz); - screenSpaceNormal = normalize(screenSpaceNormal); - - float3 worldSpaceNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceNormal, 0))); float3 normalizedDirLightDirectionWS = DirLightDirection; - -# if (defined(SKINNED) || !defined(MODELSPACENORMALS)) - float3 vertexNormal = tbnTr[2]; - -# if !defined(MODELSPACENORMALS) - float3 screenSpaceVertexNormal; - screenSpaceVertexNormal.x = dot(input.ScreenNormalTransform0.xyz, vertexNormal); - screenSpaceVertexNormal.y = dot(input.ScreenNormalTransform1.xyz, vertexNormal); - screenSpaceVertexNormal.z = dot(input.ScreenNormalTransform2.xyz, vertexNormal); - screenSpaceVertexNormal = normalize(screenSpaceVertexNormal); - - float3 worldSpaceVertexNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceVertexNormal, 0))); -# endif - -# if (!defined(DRAW_IN_WORLDSPACE)) +# if ((defined(SKINNED) || !defined(MODELSPACENORMALS)) && !defined(DRAW_IN_WORLDSPACE)) normalizedDirLightDirectionWS = lerp(normalize(mul(input.World[eyeIndex], float4(DirLightDirection, 0))), normalizedDirLightDirectionWS, input.WorldSpace); -# endif + // temp fix for tree barks + normalizedDirLightDirectionWS = any(isnan(normalizedDirLightDirectionWS)) ? DirLightDirection : normalizedDirLightDirectionWS; # endif # if defined(CLOUD_SHADOWS) @@ -1551,6 +1531,28 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace lightsDiffuseColor += dirDiffuseColor; + float3 screenSpaceNormal; + screenSpaceNormal.x = dot(input.ScreenNormalTransform0.xyz, normal.xyz); + screenSpaceNormal.y = dot(input.ScreenNormalTransform1.xyz, normal.xyz); + screenSpaceNormal.z = dot(input.ScreenNormalTransform2.xyz, normal.xyz); + screenSpaceNormal = normalize(screenSpaceNormal); + + float3 worldSpaceNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceNormal, 0))); + +# if (defined(SKINNED) || !defined(MODELSPACENORMALS)) + float3 vertexNormal = tbnTr[2]; + +# if !defined(MODELSPACENORMALS) + float3 screenSpaceVertexNormal; + screenSpaceVertexNormal.x = dot(input.ScreenNormalTransform0.xyz, vertexNormal); + screenSpaceVertexNormal.y = dot(input.ScreenNormalTransform1.xyz, vertexNormal); + screenSpaceVertexNormal.z = dot(input.ScreenNormalTransform2.xyz, vertexNormal); + screenSpaceVertexNormal = normalize(screenSpaceVertexNormal); + + float3 worldSpaceVertexNormal = normalize(mul(CameraViewInverse[eyeIndex], float4(screenSpaceVertexNormal, 0))); +# endif +# endif + float porosity = 1.0; # if defined(WATER_BLENDING) || defined(WETNESS_EFFECTS) From 5c41e5272e784dd11092a0c3e0b41ad716e82ade Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 18:24:50 +0000 Subject: [PATCH 07/13] chore: use luma for diffuse light saturation --- .../Shaders/CloudShadows/CloudShadows.hlsli | 2 +- src/Features/CloudShadows.cpp | 53 ++++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli index abd49b0c2..aa8530959 100644 --- a/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli +++ b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli @@ -44,7 +44,7 @@ float3 getCloudShadowMult(float3 rel_pos, float3 eye_to_sun, SamplerState samp) float4 cloudCubeSample = cloudShadows.Sample(samp, cloudSampleDir); float3 cloudDiffuseLight = cloudCubeSample.xyz * perPassCloudShadow[0].DiffuseLightBrightness; - cloudDiffuseLight = saturate(lerp(length(cloudDiffuseLight), cloudDiffuseLight, perPassCloudShadow[0].DiffuseLightSaturation)); + cloudDiffuseLight = saturate(lerp(dot(cloudDiffuseLight, float3(0.2125, 0.7154, 0.0721)), cloudDiffuseLight, perPassCloudShadow[0].DiffuseLightSaturation)); float cloudShadowBlend = lerp(0, saturate(cloudCubeSample.w), perPassCloudShadow[0].ShadowBlend); return lerp(1.0, cloudDiffuseLight, cloudShadowBlend); diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index 7cd2f65e4..f8007c4c1 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -2,6 +2,8 @@ #include "Util.h" +#include "magic_enum_flags.hpp" + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( CloudShadows::Settings, EnableCloudShadows, @@ -27,38 +29,34 @@ class FrameChecker void CloudShadows::DrawSettings() { - if (ImGui::TreeNodeEx("Cloud Shadows", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Enable Cloud Shadows", (bool*)&settings.EnableCloudShadows); - - if (ImGui::TreeNodeEx("Mixing", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); + ImGui::Checkbox("Enable Cloud Shadows", (bool*)&settings.EnableCloudShadows); - ImGui::SliderFloat("Diffuse Light Brightness", &settings.DiffuseLightBrightness, 0.0f, 1.0f, "%.2f"); - if (auto _tt = Util::HoverTooltipWrapper()) { - ImGui::Text("Simulates diffuse light \"filtered\" by the cloud."); - } + if (ImGui::TreeNodeEx("Mixing", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); - ImGui::SliderFloat("Diffuse Light Saturation", &settings.DiffuseLightSaturation, 0.0f, 2.0f, "%.2f"); - - ImGui::TreePop(); + ImGui::SliderFloat("Diffuse Light Brightness", &settings.DiffuseLightBrightness, 0.0f, 1.0f, "%.2f"); + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::Text("Simulates diffuse light \"filtered\" by the cloud."); } - if (ImGui::TreeNodeEx("Geometry")) { - ImGui::SliderFloat("Cloud Height", &settings.CloudHeight, 1e3f / 1.428e-2f, 10e3f / 1.428e-2f, "%.1f units"); - if (auto _tt = Util::HoverTooltipWrapper()) { - ImGui::BulletText(std::format("approx: {:.2f} km / {:.2f} miles", settings.CloudHeight * 1.428e-5f, settings.CloudHeight * 8.877e-6f).data()); - ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts slightly greater shadow."); - } + ImGui::SliderFloat("Diffuse Light Saturation", &settings.DiffuseLightSaturation, 0.0f, 2.0f, "%.2f"); - ImGui::SliderFloat("Planet Radius", &settings.PlanetRadius, 2000e3f / 1.428e-2f, 10000e3f / 1.428e-2f, "%.1f units"); + ImGui::TreePop(); + } - if (auto _tt = Util::HoverTooltipWrapper()) { - ImGui::BulletText(std::format("approx: {:.1f} km / {:.1f} miles", settings.PlanetRadius * 1.428e-5f, settings.PlanetRadius * 8.877e-6f).data()); - ImGui::Text("This setting affects distortion of clouds near horizon."); - } - ImGui::TreePop(); + if (ImGui::TreeNodeEx("Geometry")) { + ImGui::SliderFloat("Cloud Height", &settings.CloudHeight, 1e3f / 1.428e-2f, 10e3f / 1.428e-2f, "%.1f units"); + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::BulletText(std::format("approx: {:.2f} km / {:.2f} miles", settings.CloudHeight * 1.428e-5f, settings.CloudHeight * 8.877e-6f).data()); + ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts slightly greater shadow."); } + ImGui::SliderFloat("Planet Radius", &settings.PlanetRadius, 2000e3f / 1.428e-2f, 10000e3f / 1.428e-2f, "%.1f units"); + + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::BulletText(std::format("approx: {:.1f} km / {:.1f} miles", settings.PlanetRadius * 1.428e-5f, settings.PlanetRadius * 8.877e-6f).data()); + ImGui::Text("This setting affects distortion of clouds near horizon."); + } ImGui::TreePop(); } } @@ -151,8 +149,11 @@ void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor) context->OMSetBlendState(blendState, blendFactor, sampleMask); } - //auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); - //state->GetRuntimeData().stateUpdateFlags |= (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_ALPHA_BLEND; + // auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); + // state->GetRuntimeData().stateUpdateFlags = RE::BSGraphics::ShaderFlags( + // (uint32_t)state->GetRuntimeData().stateUpdateFlags | + // (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_ALPHA_BLEND | + // (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET); } } From eacae26a5a8ad5004bdb0dda0632e863826c6983 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 22:23:05 +0000 Subject: [PATCH 08/13] chores: disable water codes that have little effect --- package/Shaders/Water.hlsl | 11 ++++------- src/Features/CloudShadows.cpp | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package/Shaders/Water.hlsl b/package/Shaders/Water.hlsl index de26203bb..4952aceff 100644 --- a/package/Shaders/Water.hlsl +++ b/package/Shaders/Water.hlsl @@ -636,13 +636,10 @@ PS_OUTPUT main(PS_INPUT input) # else float3 sunColor = GetSunColor(normal, viewDirection); -# if defined(CLOUD_SHADOWS) - float3 cloudShadowMult = 1.0; - if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) { - cloudShadowMult = getCloudShadowMult(input.WPosition.xyz, SunDir.xyz, CubeMapSampler); - sunColor *= cloudShadowMult; - } -# endif + // # if defined(CLOUD_SHADOWS) + // if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) + // sunColor *= getCloudShadowMult(input.WPosition.xyz, SunDir.xyz, CubeMapSampler); + // # endif float specularFraction = lerp(1, fresnel * depthControl.x, distanceFactor); float3 finalColorPreFog = lerp(diffuseColor, specularColor, specularFraction) + sunColor * depthControl.w; diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index f8007c4c1..1b0214496 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -205,6 +205,8 @@ void CloudShadows::Draw(const RE::BSShader* shader, const uint32_t descriptor) break; case RE::BSShader::Type::Lighting: case RE::BSShader::Type::DistantTree: + case RE::BSShader::Type::Grass: + // case RE::BSShader::Type::Water: ModifyLighting(); break; default: From 1a8a254139e388bde6fe68ee88ef719fd455b722 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Thu, 1 Feb 2024 23:37:29 +0000 Subject: [PATCH 09/13] refactor: remove commented code --- src/Features/CloudShadows.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index 1b0214496..306874585 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -148,12 +148,6 @@ void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor) blendState = modifiedBlendStates[blendState]; context->OMSetBlendState(blendState, blendFactor, sampleMask); } - - // auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); - // state->GetRuntimeData().stateUpdateFlags = RE::BSGraphics::ShaderFlags( - // (uint32_t)state->GetRuntimeData().stateUpdateFlags | - // (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_ALPHA_BLEND | - // (uint32_t)RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET); } } From c700f2c0ba08cbb7ecaa49769721f483c14e5e60 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Fri, 2 Feb 2024 16:53:28 +0000 Subject: [PATCH 10/13] chore: ditch diffuse light, add ambient light options --- .../Shaders/CloudShadows/CloudShadows.hlsli | 13 +++++----- .../Shaders/Features/CloudShadows.ini | 2 +- features/Grass Lighting/Shaders/RunGrass.hlsl | 4 +++ .../Shaders/DistantTree.hlsl | 4 +++ package/Shaders/Lighting.hlsl | 4 +++ src/Features/CloudShadows.cpp | 26 ++++++++++++------- src/Features/CloudShadows.h | 7 ++--- 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli index aa8530959..c5229ae66 100644 --- a/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli +++ b/features/Cloud Shadows/Shaders/CloudShadows/CloudShadows.hlsli @@ -5,9 +5,10 @@ struct PerPassCloudShadow float CloudHeight; float PlanetRadius; - float ShadowBlend; - float DiffuseLightBrightness; - float DiffuseLightSaturation; + float EffectMix; + + float TransparencyPower; + float AbsorptionAmbient; float RcpHPlusR; }; @@ -43,9 +44,7 @@ float3 getCloudShadowMult(float3 rel_pos, float3 eye_to_sun, SamplerState samp) float3 cloudSampleDir = getCloudShadowSampleDir(rel_pos, eye_to_sun).xyz; float4 cloudCubeSample = cloudShadows.Sample(samp, cloudSampleDir); - float3 cloudDiffuseLight = cloudCubeSample.xyz * perPassCloudShadow[0].DiffuseLightBrightness; - cloudDiffuseLight = saturate(lerp(dot(cloudDiffuseLight, float3(0.2125, 0.7154, 0.0721)), cloudDiffuseLight, perPassCloudShadow[0].DiffuseLightSaturation)); - float cloudShadowBlend = lerp(0, saturate(cloudCubeSample.w), perPassCloudShadow[0].ShadowBlend); + float alpha = pow(saturate(cloudCubeSample.w), perPassCloudShadow[0].TransparencyPower); - return lerp(1.0, cloudDiffuseLight, cloudShadowBlend); + return lerp(1.0, 1.0 - alpha, perPassCloudShadow[0].EffectMix); } \ No newline at end of file diff --git a/features/Cloud Shadows/Shaders/Features/CloudShadows.ini b/features/Cloud Shadows/Shaders/Features/CloudShadows.ini index 19f01444d..312d7ff98 100644 --- a/features/Cloud Shadows/Shaders/Features/CloudShadows.ini +++ b/features/Cloud Shadows/Shaders/Features/CloudShadows.ini @@ -1,2 +1,2 @@ [Info] -Version = 1-0-0 \ No newline at end of file +Version = 1-1-0 \ No newline at end of file diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 6733429de..4aa36e5f6 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -538,6 +538,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif float3 directionalAmbientColor = mul(DirectionalAmbient, float4(worldNormal.xyz, 1)); +# if defined(CLOUD_SHADOWS) + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) + directionalAmbientColor *= lerp(1.0, cloudShadowMult, perPassCloudShadow[0].AbsorptionAmbient); +# endif lightsDiffuseColor += directionalAmbientColor; diffuseColor += lightsDiffuseColor; diff --git a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl index faeb5f539..cebc3fea7 100644 --- a/features/Tree LOD Lighting/Shaders/DistantTree.hlsl +++ b/features/Tree LOD Lighting/Shaders/DistantTree.hlsl @@ -294,6 +294,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace lightsDiffuseColor += subsurfaceColor * dirLightColor * saturate(-dirLightAngle) * SubsurfaceScatteringAmount; float3 directionalAmbientColor = mul(DirectionalAmbient, float4(worldNormal.xyz, 1)); +# if defined(CLOUD_SHADOWS) + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) + directionalAmbientColor *= lerp(1.0, cloudShadowMult, perPassCloudShadow[0].AbsorptionAmbient); +# endif lightsDiffuseColor += directionalAmbientColor; diffuseColor += lightsDiffuseColor; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 09fc3cd73..36d89eaa3 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1864,6 +1864,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif float3 directionalAmbientColor = mul(DirectionalAmbient, modelNormal); +# if defined(CLOUD_SHADOWS) + if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) + directionalAmbientColor *= lerp(1.0, cloudShadowMult, perPassCloudShadow[0].AbsorptionAmbient); +# endif diffuseColor = directionalAmbientColor + emitColor.xyz + diffuseColor; # if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index 306874585..3e5ce76d8 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -9,8 +9,9 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( EnableCloudShadows, CloudHeight, PlanetRadius, - DiffuseLightBrightness, - DiffuseLightSaturation) + EffectMix, + TransparencyPower, + AbsorptionAmbient) class FrameChecker { @@ -32,14 +33,20 @@ void CloudShadows::DrawSettings() ImGui::Checkbox("Enable Cloud Shadows", (bool*)&settings.EnableCloudShadows); if (ImGui::TreeNodeEx("Mixing", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::SliderFloat("Effect Mix", &settings.ShadowBlend, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("Effect Mix", &settings.EffectMix, 0.0f, 1.0f, "%.2f"); - ImGui::SliderFloat("Diffuse Light Brightness", &settings.DiffuseLightBrightness, 0.0f, 1.0f, "%.2f"); - if (auto _tt = Util::HoverTooltipWrapper()) { - ImGui::Text("Simulates diffuse light \"filtered\" by the cloud."); - } + ImGui::SliderFloat("Transparency Power", &settings.TransparencyPower, -2.f, 2.f, "%.1f"); + if (auto _tt = Util::HoverTooltipWrapper()) + ImGui::Text( + "The amount of light absorbed by the cloud is determined by the alpha of the cloud. " + "Negative value will result in more light absorbed, and more contrast between lit and occluded areas."); - ImGui::SliderFloat("Diffuse Light Saturation", &settings.DiffuseLightSaturation, 0.0f, 2.0f, "%.2f"); + ImGui::SliderFloat("Ambient Absorption", &settings.AbsorptionAmbient, 0.f, 1.f, "%.2f"); + if (auto _tt = Util::HoverTooltipWrapper()) + ImGui::Text( + "By default, ambient light is not affected by cloud, as it is an approximation of reflected light. " + "However, if you want darker ambient, you may turn it up a bit. " + "Not entirely physical, nonetheless helpful."); ImGui::TreePop(); } @@ -48,7 +55,7 @@ void CloudShadows::DrawSettings() ImGui::SliderFloat("Cloud Height", &settings.CloudHeight, 1e3f / 1.428e-2f, 10e3f / 1.428e-2f, "%.1f units"); if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::BulletText(std::format("approx: {:.2f} km / {:.2f} miles", settings.CloudHeight * 1.428e-5f, settings.CloudHeight * 8.877e-6f).data()); - ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts slightly greater shadow."); + ImGui::Text("This setting affects the scale of the cloud movement. Higher clouds casts greater shadow."); } ImGui::SliderFloat("Planet Radius", &settings.PlanetRadius, 2000e3f / 1.428e-2f, 10000e3f / 1.428e-2f, "%.1f units"); @@ -184,6 +191,7 @@ void CloudShadows::Draw(const RE::BSShader* shader, const uint32_t descriptor) PerPass perPassData{}; perPassData.Settings = settings; + perPassData.Settings.TransparencyPower = exp2(perPassData.Settings.TransparencyPower); perPassData.RcpHPlusR = 1.f / (settings.CloudHeight + settings.PlanetRadius); D3D11_MAPPED_SUBRESOURCE mapped; diff --git a/src/Features/CloudShadows.h b/src/Features/CloudShadows.h index 65d01b974..ab5e2ec1e 100644 --- a/src/Features/CloudShadows.h +++ b/src/Features/CloudShadows.h @@ -23,9 +23,10 @@ struct CloudShadows : Feature float CloudHeight = 2e3f / 1.428e-2f; float PlanetRadius = 6371e3f / 1.428e-2f; - float ShadowBlend = 1.f; - float DiffuseLightBrightness = 0.5f; - float DiffuseLightSaturation = 1.f; + float EffectMix = 1.f; + + float TransparencyPower = 0.1f; + float AbsorptionAmbient = 0.2f; } settings; struct alignas(16) PerPass From 72d637b4ba1091a722b991e0ba7dfb04dd58a321 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Fri, 2 Feb 2024 17:56:23 +0000 Subject: [PATCH 11/13] chore: remove water.hlsl edits --- package/Shaders/Water.hlsl | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/package/Shaders/Water.hlsl b/package/Shaders/Water.hlsl index 4952aceff..af6afd424 100644 --- a/package/Shaders/Water.hlsl +++ b/package/Shaders/Water.hlsl @@ -2,14 +2,6 @@ #include "Common/MotionBlur.hlsl" #include "Common/Permutation.hlsl" -struct LightingData -{ - float WaterHeight[25]; - bool Reflections; -}; - -StructuredBuffer lightingData : register(t126); - #define WATER struct VS_INPUT @@ -515,10 +507,6 @@ float3 GetSunColor(float3 normal, float3 viewDirection) # include "LightLimitFix/LightLimitFix.hlsli" # endif -# if defined(CLOUD_SHADOWS) -# include "CloudShadows/CloudShadows.hlsli" -# endif - PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; @@ -635,12 +623,6 @@ PS_OUTPUT main(PS_INPUT input) finalSpecularColor; # else float3 sunColor = GetSunColor(normal, viewDirection); - - // # if defined(CLOUD_SHADOWS) - // if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) - // sunColor *= getCloudShadowMult(input.WPosition.xyz, SunDir.xyz, CubeMapSampler); - // # endif - float specularFraction = lerp(1, fresnel * depthControl.x, distanceFactor); float3 finalColorPreFog = lerp(diffuseColor, specularColor, specularFraction) + sunColor * depthControl.w; float3 finalColor = lerp(finalColorPreFog, input.FogParam.xyz, input.FogParam.w); From c99d1a41ee162ddb6394899bf6160f7af0e2b9e7 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Fri, 2 Feb 2024 18:27:05 +0000 Subject: [PATCH 12/13] refactor: simplify context and device fetching --- src/Features/CloudShadows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index 3e5ce76d8..e7028fe42 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -102,8 +102,8 @@ void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor) auto tech_enum = static_cast(descriptor); if (tech_enum == SkyShaderTechniques::Clouds || tech_enum == SkyShaderTechniques::CloudsLerp || tech_enum == SkyShaderTechniques::CloudsFade) { - auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; auto renderer = RE::BSGraphics::Renderer::GetSingleton(); + auto context = renderer->GetRuntimeData().context; auto device = renderer->GetRuntimeData().forwarder; { @@ -232,7 +232,7 @@ void CloudShadows::Save(json& o_json) void CloudShadows::SetupResources() { auto renderer = RE::BSGraphics::Renderer::GetSingleton(); - auto device = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().forwarder; + auto device = renderer->GetRuntimeData().forwarder; { auto reflections = renderer->GetRendererData().cubemapRenderTargets[RE::RENDER_TARGET_CUBEMAP::kREFLECTIONS]; From accd8415267dd973d10b99b9eaa2def94d753346 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Fri, 2 Feb 2024 19:54:38 +0000 Subject: [PATCH 13/13] perf: Sky resources early return --- src/Features/CloudShadows.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index e7028fe42..83db3ca5b 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -82,6 +82,9 @@ void CloudShadows::CheckResourcesSide(int side) void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor) { + if (!settings.EnableCloudShadows) + return; + auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton(); auto cubeMapRenderTarget = !REL::Module::IsVR() ? shadowState->GetRuntimeData().cubeMapRenderTarget : shadowState->GetVRRuntimeData().cubeMapRenderTarget; if (cubeMapRenderTarget != RE::RENDER_TARGETS_CUBEMAP::kREFLECTIONS)