diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl index 2db55111b..08bb82698 100644 --- a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -145,7 +145,7 @@ void PS_Forward( #if USE_FOG // Calculate exponential height fog - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0); + float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z); // Apply fog to the output color #if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE diff --git a/Content/Editor/Particles/Smoke Material.flax b/Content/Editor/Particles/Smoke Material.flax index bd8c1c0e9..d5b8cb872 100644 --- a/Content/Editor/Particles/Smoke Material.flax +++ b/Content/Editor/Particles/Smoke Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6097a8ca31dbe7a985b5c512d2049d2d22c73175551965c75d6b360323505491 -size 38427 +oid sha256:a16a3fa5bed3bc8030c40fbe0e946f2bdec28745542bf08db1d7b4a43180f785 +size 38900 diff --git a/Content/Shaders/Fog.flax b/Content/Shaders/Fog.flax index 75590f84d..3f934412c 100644 --- a/Content/Shaders/Fog.flax +++ b/Content/Shaders/Fog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7735a770a87483d4df5e4e653373067c26469de8088f071ca092ed3e797bf461 -size 2785 +oid sha256:e83f9dbbcf84550de09e7c63bbdd3acc6591cf6ba1bcce2a2699772122ae07f4 +size 2633 diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp index d62aecac4..efb5351e7 100644 --- a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp +++ b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp @@ -41,11 +41,10 @@ void ExponentialHeightFog::Draw(RenderContext& renderContext) && _shader->IsLoaded() && renderContext.View.IsPerspectiveProjection()) { - // Prepare if (_psFog.States[0] == nullptr) - { - // Create pipeline states _psFog.CreatePipelineStates(); + if (!_psFog.States[0]->IsValid()) + { GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle; psDesc.DepthWriteEnable = false; psDesc.BlendMode.BlendEnable = true; @@ -59,6 +58,7 @@ void ExponentialHeightFog::Draw(RenderContext& renderContext) if (_psFog.Create(psDesc, _shader->GetShader(), "PS_Fog")) { LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString()); + return; } } @@ -160,7 +160,7 @@ void ExponentialHeightFog::GetExponentialHeightFogData(const RenderView& view, S result.FogAtViewPosition = density * Math::Pow(2.0f, Math::Clamp(-heightFalloff * (viewHeight - height), -125.f, 126.f)); result.StartDistance = StartDistance; result.FogMinOpacity = 1.0f - FogMaxOpacity; - result.FogCutoffDistance = FogCutoffDistance; + result.FogCutoffDistance = FogCutoffDistance >= 0 ? FogCutoffDistance : view.Far + FogCutoffDistance; if (useDirectionalLightInscattering) { result.InscatteringLightDirection = -DirectionalInscatteringLight->GetDirection(); diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.h b/Source/Engine/Level/Actors/ExponentialHeightFog.h index 0b442ba9f..c0e5407d2 100644 --- a/Source/Engine/Level/Actors/ExponentialHeightFog.h +++ b/Source/Engine/Level/Actors/ExponentialHeightFog.h @@ -55,9 +55,9 @@ public: float StartDistance = 0.0f; /// - /// Scene elements past this distance will not have fog applied. This is useful for excluding skyboxes which already have fog baked in. Setting this value to 0 disables it. + /// Scene elements past this distance will not have fog applied. This is useful for excluding skyboxes which already have fog baked in. Setting this value to 0 disables it. Negative value sets the cutoff distance relative to the far plane of the camera. /// - API_FIELD(Attributes="EditorOrder(60), DefaultValue(0.0f), Limit(0), EditorDisplay(\"Exponential Height Fog\")") + API_FIELD(Attributes="EditorOrder(60), DefaultValue(0.0f), EditorDisplay(\"Exponential Height Fog\")") float FogCutoffDistance = 0.0f; public: diff --git a/Source/Shaders/ExponentialHeightFog.hlsl b/Source/Shaders/ExponentialHeightFog.hlsl index 2e34936eb..f6fb918f5 100644 --- a/Source/Shaders/ExponentialHeightFog.hlsl +++ b/Source/Shaders/ExponentialHeightFog.hlsl @@ -29,7 +29,7 @@ struct ExponentialHeightFogData float StartDistance; }; -float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance) +float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance, float sceneDistance) { float3 cameraToPos = posWS - camWS; float cameraToPosSqr = dot(cameraToPos, cameraToPos); @@ -78,7 +78,7 @@ float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, fl // Disable fog after a certain distance FLATTEN - if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToPosLen > exponentialHeightFog.FogCutoffDistance) + if (exponentialHeightFog.FogCutoffDistance > 0 && sceneDistance > exponentialHeightFog.FogCutoffDistance) { expFogFactor = 1; directionalInscattering = 0; @@ -87,4 +87,9 @@ float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, fl return float4(inscatteringColor * (1.0f - expFogFactor) + directionalInscattering, expFogFactor); } +float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance) +{ + return GetExponentialHeightFog(exponentialHeightFog, posWS, camWS, skipDistance, distance(posWS, camWS)); +} + #endif diff --git a/Source/Shaders/Fog.shader b/Source/Shaders/Fog.shader index 7dcc679ec..dfea921cc 100644 --- a/Source/Shaders/Fog.shader +++ b/Source/Shaders/Fog.shader @@ -24,41 +24,17 @@ Texture2D Depth : register(t0); Texture3D IntegratedLightScattering : register(t1); #endif -// Get world space position at given pixel coordinate -float3 GetWorldPos(float2 uv) -{ - float depth = SAMPLE_RT(Depth, uv).r; - GBufferData gBufferData = GetGBufferData(); - float3 viewPos = GetViewPos(gBufferData, uv, depth); - return mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz; -} - -float4 CalculateCombinedFog(float3 posWS, float sceneDepth, float3 volumeUV) -{ - float skipDistance = 0; - -#if VOLUMETRIC_FOG - skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0); -#endif - - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, posWS, GBuffer.ViewPos, skipDistance); - -#if VOLUMETRIC_FOG - float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0); - fog = float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a); -#endif - - return fog; -} - META_PS(true, FEATURE_LEVEL_ES2) META_PERMUTATION_1(VOLUMETRIC_FOG=0) META_PERMUTATION_1(VOLUMETRIC_FOG=1) float4 PS_Fog(Quad_VS2PS input) : SV_Target0 { - // Calculate pixel world space position - float3 posWS = GetWorldPos(input.TexCoord); - float3 viewVector = posWS - GBuffer.ViewPos; + // Get world space position at given pixel coordinate + float rawDepth = SAMPLE_RT(Depth, input.TexCoord).r; + GBufferData gBufferData = GetGBufferData(); + float3 viewPos = GetViewPos(gBufferData, input.TexCoord, rawDepth); + float3 worldPos = mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz; + float3 viewVector = worldPos - GBuffer.ViewPos; float sceneDepth = length(viewVector); // Calculate volumetric fog coordinates @@ -67,17 +43,28 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0 // Debug code #if VOLUMETRIC_FOG && 0 - volumeUV = posWS / 1000; + volumeUV = worldPos / 1000; if (!all(volumeUV >= 0 && volumeUV <= 1)) return 0; return float4(IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0).rgb, 1); //return float4(volumeUV, 1); - //return float4(posWS / 100, 1); + //return float4(worldPos / 100, 1); #endif - // Calculate fog color - float4 fog = CalculateCombinedFog(posWS, sceneDepth, volumeUV); + float skipDistance = 0; +#if VOLUMETRIC_FOG + skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0); +#endif + + // Calculate exponential fog color + float4 fog = GetExponentialHeightFog(ExponentialHeightFog, worldPos, GBuffer.ViewPos, skipDistance, viewPos.z); + +#if VOLUMETRIC_FOG + // Sample volumetric fog and mix it in + float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0); + fog = float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a); +#endif return fog; }