exponential height fog (#275)

This commit is contained in:
Silas Oler
2021-07-05 14:12:59 +02:00
committed by GitHub
parent deca61d793
commit 4adbb67660
17 changed files with 136 additions and 39 deletions
+40 -12
View File
@@ -11,7 +11,7 @@ using namespace wiGraphics;
void WeatherWindow::Create(EditorComponent* editor)
{
wiWindow::Create("Weather Window");
SetSize(XMFLOAT2(660, 560));
SetSize(XMFLOAT2(660, 610));
float x = 180;
float y = 20;
@@ -19,6 +19,15 @@ void WeatherWindow::Create(EditorComponent* editor)
float step = hei + 2;
heightFogCheckBox.Create("Height fog: ");
heightFogCheckBox.SetSize(XMFLOAT2(hei, hei));
heightFogCheckBox.SetPos(XMFLOAT2(x + 100, y += step));
heightFogCheckBox.OnClick([&](wiEventArgs args) {
auto& weather = GetWeather();
weather.SetHeightFog(args.bValue);
});
AddWidget(&heightFogCheckBox);
fogStartSlider.Create(0, 5000, 0, 100000, "Fog Start: ");
fogStartSlider.SetSize(XMFLOAT2(100, hei));
fogStartSlider.SetPos(XMFLOAT2(x, y += step));
@@ -35,13 +44,29 @@ void WeatherWindow::Create(EditorComponent* editor)
});
AddWidget(&fogEndSlider);
fogHeightSlider.Create(0, 1, 0, 10000, "Fog Height: ");
fogHeightSlider.SetSize(XMFLOAT2(100, hei));
fogHeightSlider.SetPos(XMFLOAT2(x, y += step));
fogHeightSlider.OnSlide([&](wiEventArgs args) {
GetWeather().fogHeight = args.fValue;
fogHeightStartSlider.Create(-100, 100, 1, 10000, "Fog Height Start: ");
fogHeightStartSlider.SetSize(XMFLOAT2(100, hei));
fogHeightStartSlider.SetPos(XMFLOAT2(x, y += step));
fogHeightStartSlider.OnSlide([&](wiEventArgs args) {
GetWeather().fogHeightStart = args.fValue;
});
AddWidget(&fogHeightStartSlider);
fogHeightEndSlider.Create(-100, 100, 3, 10000, "Fog Height End: ");
fogHeightEndSlider.SetSize(XMFLOAT2(100, hei));
fogHeightEndSlider.SetPos(XMFLOAT2(x, y += step));
fogHeightEndSlider.OnSlide([&](wiEventArgs args) {
GetWeather().fogHeightEnd = args.fValue;
});
AddWidget(&fogHeightEndSlider);
fogHeightSkySlider.Create(0, 1, 0, 10000, "Fog Height Sky: ");
fogHeightSkySlider.SetSize(XMFLOAT2(100, hei));
fogHeightSkySlider.SetPos(XMFLOAT2(x, y += step));
fogHeightSkySlider.OnSlide([&](wiEventArgs args) {
GetWeather().fogHeightSky = args.fValue;
});
AddWidget(&fogHeightSlider);
AddWidget(&fogHeightSkySlider);
cloudinessSlider.Create(0, 1, 0.0f, 10000, "Cloudiness: ");
cloudinessSlider.SetSize(XMFLOAT2(100, hei));
@@ -445,7 +470,7 @@ void WeatherWindow::Create(EditorComponent* editor)
weather.cloudiness = 0.4f;
weather.fogStart = 100;
weather.fogEnd = 1000;
weather.fogHeight = 0;
weather.fogHeightSky = 0;
InvalidateProbes();
@@ -465,7 +490,7 @@ void WeatherWindow::Create(EditorComponent* editor)
weather.cloudiness = 0.36f;
weather.fogStart = 50;
weather.fogEnd = 600;
weather.fogHeight = 0;
weather.fogHeightSky = 0;
InvalidateProbes();
@@ -485,7 +510,7 @@ void WeatherWindow::Create(EditorComponent* editor)
weather.cloudiness = 0.75f;
weather.fogStart = 0;
weather.fogEnd = 500;
weather.fogHeight = 0;
weather.fogHeightSky = 0;
InvalidateProbes();
@@ -505,7 +530,7 @@ void WeatherWindow::Create(EditorComponent* editor)
weather.cloudiness = 0.28f;
weather.fogStart = 10;
weather.fogEnd = 400;
weather.fogHeight = 0;
weather.fogHeightSky = 0;
InvalidateProbes();
@@ -552,9 +577,12 @@ void WeatherWindow::Update()
colorgradingButton.SetText(wiHelper::GetFileNameFromPath(weather.colorGradingMapName));
}
heightFogCheckBox.SetCheck(weather.IsHeightFog());
fogStartSlider.SetValue(weather.fogStart);
fogEndSlider.SetValue(weather.fogEnd);
fogHeightSlider.SetValue(weather.fogHeight);
fogHeightStartSlider.SetValue(weather.fogHeightStart);
fogHeightEndSlider.SetValue(weather.fogHeightEnd);
fogHeightSkySlider.SetValue(weather.fogHeightSky);
cloudinessSlider.SetValue(weather.cloudiness);
cloudScaleSlider.SetValue(weather.cloudScale);
cloudSpeedSlider.SetValue(weather.cloudSpeed);
+4 -1
View File
@@ -14,9 +14,12 @@ public:
wiScene::WeatherComponent& GetWeather() const;
void InvalidateProbes() const;
wiCheckBox heightFogCheckBox;
wiSlider fogStartSlider;
wiSlider fogEndSlider;
wiSlider fogHeightSlider;
wiSlider fogHeightStartSlider;
wiSlider fogHeightEndSlider;
wiSlider fogHeightSkySlider;
wiSlider cloudinessSlider;
wiSlider cloudScaleSlider;
wiSlider cloudSpeedSlider;
+1
View File
@@ -1,5 +1,6 @@
This file contains changelog of wiArchive versions
71: serialized WeatherComponent::fogHeightStart and fogHeightEnd
70: serialized VolumetricCloudParameters
69: serialized AABB:: layerMask and userdata parameters
68: serialized MaterialComponent SPECULARMAP (for KHR_materials_specular)
@@ -533,9 +533,10 @@ static const uint OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED = 1 << 3;
static const uint OPTION_BIT_VOXELGI_RETARGETTED = 1 << 4;
static const uint OPTION_BIT_SIMPLE_SKY = 1 << 5;
static const uint OPTION_BIT_REALISTIC_SKY = 1 << 6;
static const uint OPTION_BIT_RAYTRACED_SHADOWS = 1 << 7;
static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 8;
static const uint OPTION_BIT_SHADOW_MASK = 1 << 9;
static const uint OPTION_BIT_HEIGHT_FOG = 1 << 7;
static const uint OPTION_BIT_RAYTRACED_SHADOWS = 1 << 8;
static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 9;
static const uint OPTION_BIT_SHADOW_MASK = 1 << 10;
// ---------- Common Constant buffers: -----------------
@@ -562,10 +563,11 @@ CBUFFER(FrameCB, CBSLOT_RENDERER_FRAME)
float3 g_xFrame_Ambient;
float g_xFrame_Cloudiness;
float3 g_xFrame_padding0;
float g_xFrame_SkyExposure;
float4 g_xFrame_Fog; // Fog Start,End,Height Start,Height End
float3 g_xFrame_Fog; // Fog Start,End,Height
float g_xFrame_padding0;
float g_xFrame_FogHeightSky;
float g_xFrame_SkyExposure;
float g_xFrame_VoxelRadianceMaxDistance; // maximum raymarch distance for voxel GI in world-space
float g_xFrame_VoxelRadianceDataSize; // voxel half-extent in world space units
+40 -2
View File
@@ -67,9 +67,47 @@ inline float GetTime() { return g_xFrame_Time; }
inline uint2 GetTemporalAASampleRotation() { return uint2((g_xFrame_TemporalAASampleRotation >> 0u) & 0x000000FF, (g_xFrame_TemporalAASampleRotation >> 8) & 0x000000FF); }
inline bool IsStaticSky() { return g_xFrame_StaticSkyGamma > 0.0; }
inline float GetFogAmount(float dist)
// Exponential height fog based on: https://www.iquilezles.org/www/articles/fog/fog.htm
// Non constant density function
// distance : sample to point distance
// O : sample position
// V : sample to point vector
inline float GetFogAmount(float distance, float3 O, float3 V)
{
return saturate((dist - g_xFrame_Fog.x) / (g_xFrame_Fog.y - g_xFrame_Fog.x));
float fogDensity = saturate((distance - g_xFrame_Fog.x) / (g_xFrame_Fog.y - g_xFrame_Fog.x));
if (g_xFrame_Options & OPTION_BIT_HEIGHT_FOG)
{
float fogHeightStart = g_xFrame_Fog.z;
float fogHeightEnd = g_xFrame_Fog.w;
float fogFalloffScale = 1.0 / max(0.01, fogHeightEnd - fogHeightStart);
// solve for x, e^(-h * x) = 0.001
// x = 6.907755 * h^-1
float fogFalloff = 6.907755 * fogFalloffScale;
float originHeight = O.y;
float Z = -V.y;
float effectiveZ = max(abs(Z), 0.001);
float endLineHeight = originHeight + distance * Z; // Isolated vector equation for y
float minLineHeight = min(originHeight, endLineHeight);
float heightLineFalloff = max(minLineHeight - fogHeightStart, 0);
float baseHeightFogDistance = clamp((fogHeightStart - minLineHeight) / effectiveZ, 0, distance);
float exponentialFogDistance = distance - baseHeightFogDistance; // Exclude distance below base height
float exponentialHeightLineIntegral = exp(-heightLineFalloff * fogFalloff) * (1.0 - exp(-exponentialFogDistance * effectiveZ * fogFalloff)) / (effectiveZ * fogFalloff);
float opticalDepthHeightFog = fogDensity * (baseHeightFogDistance + exponentialHeightLineIntegral);
float transmittanceHeightFog = exp(-opticalDepthHeightFog);
float fogAmount = transmittanceHeightFog;
return 1.0 - fogAmount;
}
else
{
return fogDensity;
}
}
float3 tonemap(float3 x)
+1 -1
View File
@@ -49,7 +49,7 @@ GBuffer main(VertexToPixel input)
ApplyLighting(surface, lighting, color);
ApplyFog(dist, color);
ApplyFog(dist, g_xCamera_CamPos, V, color);
return CreateGBuffer(color, surface);
}
+1 -1
View File
@@ -47,7 +47,7 @@ GBuffer main(VSOut input)
ApplyLighting(surface, lighting, color);
ApplyFog(dist, color);
ApplyFog(dist, g_xCamera_CamPos, V, color);
return CreateGBuffer(color, surface);
}
+6 -4
View File
@@ -1166,17 +1166,19 @@ inline void ApplyLighting(in Surface surface, in Lighting lighting, inout float4
color.rgb = lerp(surface.albedo * combined_lighting.diffuse, surface.refraction.rgb, surface.refraction.a) + combined_lighting.specular;
}
inline void ApplyFog(in float dist, inout float4 color)
inline void ApplyFog(in float distance, float3 P, float3 V, inout float4 color)
{
const float fogAmount = GetFogAmount(distance, P, V);
if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY)
{
const float3 skyLuminance = texture_skyluminancelut.SampleLevel(sampler_point_clamp, float2(0.5, 0.5), 0).rgb;
color.rgb = lerp(color.rgb, skyLuminance, GetFogAmount(dist));
color.rgb = lerp(color.rgb, skyLuminance, fogAmount);
}
else
{
const float3 V = float3(0.0, -1.0, 0.0);
color.rgb = lerp(color.rgb, GetDynamicSkyColor(V, false, false, false, true), GetFogAmount(dist));
color.rgb = lerp(color.rgb, GetDynamicSkyColor(V, false, false, false, true), fogAmount);
}
}
@@ -1927,7 +1929,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET
#ifdef OBJECTSHADER_USE_POSITION3D
ApplyFog(dist, color);
ApplyFog(dist, g_xCamera_CamPos, surface.V, color);
#endif // OBJECTSHADER_USE_POSITION3D
+1 -1
View File
@@ -62,7 +62,7 @@ float4 main(PSIn input) : SV_TARGET
ApplyLighting(surface, lighting, color);
ApplyFog(dist, color);
ApplyFog(dist, g_xCamera_CamPos, V, color);
return color;
}
+1 -1
View File
@@ -119,7 +119,7 @@ float3 CustomAtmosphericScattering(float3 V, float3 sunDirection, float3 sunColo
const float zenith = V.y; // how much is above (0: horizon, 1: directly above)
const float sunScatter = saturate(sunDirection.y + 0.1f); // how much the sun is directly above. Even if sunis at horizon, we add a constant scattering amount so that light still scatters at horizon
const float atmosphereDensity = 0.5 + g_xFrame_Fog.z; // constant of air density, or "fog height" as interpreted here (bigger is more obstruction of sun)
const float atmosphereDensity = 0.5 + g_xFrame_FogHeightSky; // constant of air density, or "fog height" as interpreted here (bigger is more obstruction of sun)
const float zenithDensity = atmosphereDensity / pow(max(0.000001f, zenith), 0.75f);
const float sunScatterDensity = atmosphereDensity / pow(max(0.000001f, sunScatter), 0.75f);
@@ -48,8 +48,9 @@ float4 main(VertexToPixel input) : SV_TARGET
{
float3 attenuation = shadowCascade(light, ShPos, ShTex.xy, cascade);
attenuation *= GetFogAmount(cameraDistance - marchedDistance) * scattering;
// Evaluate sample height for height fog calculation, given 0 for V:
attenuation *= GetFogAmount(cameraDistance - marchedDistance, P, float3(0.0, 0.0, 0.0)) * scattering;
accumulation += attenuation;
marchedDistance += stepSize;
@@ -49,8 +49,9 @@ float4 main(VertexToPixel input) : SV_TARGET
attenuation *= shadowCube(light, L, Lunnormalized);
}
attenuation *= GetFogAmount(cameraDistance - marchedDistance);
// Evaluate sample height for height fog calculation, given 0 for V:
attenuation *= GetFogAmount(cameraDistance - marchedDistance, P, float3(0.0, 0.0, 0.0));
accumulation += attenuation;
marchedDistance += stepSize;
@@ -58,7 +58,8 @@ float4 main(VertexToPixel input) : SV_TARGET
}
}
attenuation *= GetFogAmount(cameraDistance - marchedDistance);
// Evaluate sample height for exponential fog calculation, given 0 for V:
attenuation *= GetFogAmount(cameraDistance - marchedDistance, P, float3(0.0, 0.0, 0.0));
accumulation += attenuation;
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include <fstream>
// this should always be only INCREMENTED and only if a new serialization is implemeted somewhere!
uint64_t __archiveVersion = 70;
uint64_t __archiveVersion = 71;
// this is the version number of which below the archive is not compatible with the current version
uint64_t __archiveVersionBarrier = 22;
+6 -1
View File
@@ -3552,7 +3552,8 @@ void UpdatePerFrameData(
frameCB.g_xFrame_Cloudiness = vis.scene->weather.cloudiness;
frameCB.g_xFrame_CloudScale = vis.scene->weather.cloudScale;
frameCB.g_xFrame_CloudSpeed = vis.scene->weather.cloudSpeed;
frameCB.g_xFrame_Fog = float3(vis.scene->weather.fogStart, vis.scene->weather.fogEnd, vis.scene->weather.fogHeight);
frameCB.g_xFrame_Fog = float4(vis.scene->weather.fogStart, vis.scene->weather.fogEnd, vis.scene->weather.fogHeightStart, vis.scene->weather.fogHeightEnd);
frameCB.g_xFrame_FogHeightSky = vis.scene->weather.fogHeightSky;
frameCB.g_xFrame_Horizon = vis.scene->weather.horizon;
frameCB.g_xFrame_Zenith = vis.scene->weather.zenith;
frameCB.g_xFrame_SkyExposure = vis.scene->weather.skyExposure;
@@ -3668,6 +3669,10 @@ void UpdatePerFrameData(
{
frameCB.g_xFrame_Options |= OPTION_BIT_REALISTIC_SKY;
}
if (vis.scene->weather.IsHeightFog())
{
frameCB.g_xFrame_Options |= OPTION_BIT_HEIGHT_FOG;
}
if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE) && GetRaytracedShadowsEnabled())
{
frameCB.g_xFrame_Options |= OPTION_BIT_RAYTRACED_SHADOWS;
+6 -1
View File
@@ -1112,6 +1112,7 @@ namespace wiScene
SIMPLE_SKY = 1 << 1,
REALISTIC_SKY = 1 << 2,
VOLUMETRIC_CLOUDS = 1 << 3,
HEIGHT_FOG = 1 << 4,
};
uint32_t _flags = EMPTY;
@@ -1119,11 +1120,13 @@ namespace wiScene
inline bool IsSimpleSky() const { return _flags & SIMPLE_SKY; }
inline bool IsRealisticSky() const { return _flags & REALISTIC_SKY; }
inline bool IsVolumetricClouds() const { return _flags & VOLUMETRIC_CLOUDS; }
inline bool IsHeightFog() const { return _flags & HEIGHT_FOG; }
inline void SetOceanEnabled(bool value = true) { if (value) { _flags |= OCEAN_ENABLED; } else { _flags &= ~OCEAN_ENABLED; } }
inline void SetSimpleSky(bool value = true) { if (value) { _flags |= SIMPLE_SKY; } else { _flags &= ~SIMPLE_SKY; } }
inline void SetRealisticSky(bool value = true) { if (value) { _flags |= REALISTIC_SKY; } else { _flags &= ~REALISTIC_SKY; } }
inline void SetVolumetricClouds(bool value = true) { if (value) { _flags |= VOLUMETRIC_CLOUDS; } else { _flags &= ~VOLUMETRIC_CLOUDS; } }
inline void SetHeightFog(bool value = true) { if (value) { _flags |= HEIGHT_FOG; } else { _flags &= ~HEIGHT_FOG; } }
XMFLOAT3 sunColor = XMFLOAT3(0, 0, 0);
XMFLOAT3 sunDirection = XMFLOAT3(0, 1, 0);
@@ -1134,7 +1137,9 @@ namespace wiScene
XMFLOAT3 ambient = XMFLOAT3(0.2f, 0.2f, 0.2f);
float fogStart = 100;
float fogEnd = 1000;
float fogHeight = 0;
float fogHeightStart = 1;
float fogHeightEnd = 3;
float fogHeightSky = 0;
float cloudiness = 0.0f;
float cloudScale = 0.0003f;
float cloudSpeed = 0.1f;
+12 -2
View File
@@ -939,7 +939,7 @@ namespace wiScene
archive >> ambient;
archive >> fogStart;
archive >> fogEnd;
archive >> fogHeight;
archive >> fogHeightSky;
archive >> cloudiness;
archive >> cloudScale;
archive >> cloudSpeed;
@@ -1074,6 +1074,11 @@ namespace wiScene
archive >> volumetricCloudParameters.GroundContributionSampleCount;
}
if (archive.GetVersion() >= 71)
{
archive >> fogHeightStart;
archive >> fogHeightEnd;
}
}
else
{
@@ -1085,7 +1090,7 @@ namespace wiScene
archive << ambient;
archive << fogStart;
archive << fogEnd;
archive << fogHeight;
archive << fogHeightSky;
archive << cloudiness;
archive << cloudScale;
archive << cloudSpeed;
@@ -1202,6 +1207,11 @@ namespace wiScene
archive << volumetricCloudParameters.GroundContributionSampleCount;
}
if (archive.GetVersion() >= 71)
{
archive << fogHeightStart;
archive << fogHeightEnd;
}
}
}
void SoundComponent::Serialize(wiArchive& archive, EntitySerializer& seri)