Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ namespace ExponentialHeightFog
return SharedData::exponentialHeightFogSettings.respectVanillaFogFade != 0 ? vanillaFogFade : 1.0f;
}

bool ShouldDisableVanillaFog()
{
return SharedData::exponentialHeightFogSettings.enabled && SharedData::exponentialHeightFogSettings.disableVanillaFog != 0;
}

// Henyey-Greenstein phase function for physically-based inscattering.
// g: asymmetry parameter [-1, 1]. Positive = forward scattering, 0 = isotropic.
float HenyeyGreenstein(float cosTheta, float g)
{
float g2 = g * g;
float denom = 1.0f + g2 - 2.0f * g * cosTheta;
return (1.0f - g2) / (4.0f * Math::PI * pow(max(denom, 1e-5f), 1.5f));
}

float4 GetExponentialHeightFog(float3 positionWS, float3 cameraWS, float3 fogColor)
{
float fogHeightFalloff = SharedData::exponentialHeightFogSettings.fogHeightFalloff * 0.001f;
Expand Down Expand Up @@ -47,19 +61,25 @@ namespace ExponentialHeightFog

float expFogFactor = saturate(exp2(-exponentialHeightLineIntegral));

float3 fogInscatteringColor = fogColor * SharedData::exponentialHeightFogSettings.originalFogColorAmount;
fogInscatteringColor += SharedData::exponentialHeightFogSettings.fogInscatteringColor.rgb * SharedData::exponentialHeightFogSettings.fogInscatteringColor.a;

#if defined(DYNAMIC_CUBEMAPS)
if (SharedData::exponentialHeightFogSettings.useDynamicCubemaps > 0) {
float3 tintColor = lerp(fogColor, SharedData::exponentialHeightFogSettings.inscatteringTint.xyz, SharedData::exponentialHeightFogSettings.inscatteringTint.w);
float3 cubemapColor = DynamicCubemaps::EnvReflectionsTexture.SampleLevel(SampColorSampler, normalize(lerp(positionWS, float3(0, 0, 1), saturate((SharedData::exponentialHeightFogSettings.cubemapMipLevel + 1) / 8))), SharedData::exponentialHeightFogSettings.cubemapMipLevel).xyz;
fogColor = tintColor * cubemapColor * (1.0f - expFogFactor);
fogInscatteringColor += cubemapColor * SharedData::exponentialHeightFogSettings.inscatteringTint.rgb * SharedData::exponentialHeightFogSettings.inscatteringTint.a;
}
#endif

fogColor = fogInscatteringColor * (1.0f - expFogFactor);

float3 directionalInscattering = 0;

// Calculate directional light inscattering
// Calculate directional light inscattering using Henyey-Greenstein phase function
if (SharedData::exponentialHeightFogSettings.directionalInscatteringMultiplier > 0) {
float3 directionalLightInscattering = SharedData::DirLightColor.xyz * pow(saturate(dot(normalize(positionWS), SharedData::DirLightDirection.xyz)), SharedData::exponentialHeightFogSettings.directionalInscatteringExponent) / (2 * Math::TAU);
float cosTheta = dot(normalize(positionWS), SharedData::DirLightDirection.xyz);
float phase = HenyeyGreenstein(cosTheta, SharedData::exponentialHeightFogSettings.directionalInscatteringAnisotropy);
float3 directionalLightInscattering = SharedData::DirLightColor.xyz * phase;
float dirExponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * max(rayLength - SharedData::exponentialHeightFogSettings.startDistance, 0);
float dirExpFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral));
directionalInscattering = directionalLightInscattering * (1 - dirExpFogFactor) * SharedData::exponentialHeightFogSettings.directionalInscatteringMultiplier;
Expand All @@ -83,17 +103,16 @@ namespace ExponentialHeightFog
float3 lightDir = SharedData::DirLightDirection.xyz;
float lightDirZ = lightDir.z;

float exponentialHeightLineIntegral = 0.0f;
float sunlightFogAttenuation = 0.0f;

// Integral = Density * (1 - exp2(-slope * inf)) / slope
if (lightDirZ > 0.001f) {
float slope = max(fogHeightFalloff * lightDirZ, 1e-8f);
exponentialHeightLineIntegral = localDensity / slope;
} else {
return 0.0f;
float exponentialHeightLineIntegral = localDensity / slope;
sunlightFogAttenuation = saturate(exp2(-exponentialHeightLineIntegral));
}

return saturate(exp2(-exponentialHeightLineIntegral));
return lerp(1.0f, sunlightFogAttenuation, SharedData::exponentialHeightFogSettings.sunlightAttenuationAmount);
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Info]
Version = 1-1-0
Version = 1-2-0

[Nexus]
autoupload = false
8 changes: 6 additions & 2 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,15 @@ namespace SharedData
float fogHeightFalloff;
float fogDensity;
float directionalInscatteringMultiplier;
float directionalInscatteringExponent;
float directionalInscatteringAnisotropy;
float4 inscatteringTint;
float cubemapMipLevel;
float sunlightAttenuationAmount;
uint respectVanillaFogFade;
float2 pad;
uint disableVanillaFog;
float4 fogInscatteringColor;
float originalFogColorAmount;
float3 pad;
};

cbuffer FeatureData : register(b6)
Expand Down
20 changes: 20 additions & 0 deletions package/Shaders/Effect.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -854,23 +854,43 @@ PS_OUTPUT main(PS_INPUT input)
}
# endif
# if defined(EXP_HEIGHT_FOG)
float vanillaFogFactor = fogFactor;
float3 vanillaFogColor = fogColor;
float expFogFactor = 0;
if (SharedData::exponentialHeightFogSettings.enabled) {
float4 exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(input.WorldPosition.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, fogColor);
expFogFactor = exponentialHeightFog.w;
# if defined(ADDBLEND) || defined(MULTBLEND) || defined(MULTBLEND_DECAL)
fogColor = exponentialHeightFog.xyz;
fogFactor = exponentialHeightFog.w;
# else
fogColor = lightColor;
alpha *= 1 - exponentialHeightFog.w;
# endif
if (ExponentialHeightFog::ShouldDisableVanillaFog()) {
vanillaFogFactor = 0;
}
}
# endif
# if defined(ADDBLEND)
# if defined(EXP_HEIGHT_FOG)
float3 blendedColor = lightColor * (1 - vanillaFogFactor) * (1 - expFogFactor);
# else
float3 blendedColor = lightColor * (1 - fogFactor);
# endif
# elif defined(MULTBLEND) || defined(MULTBLEND_DECAL)
# if defined(EXP_HEIGHT_FOG)
float3 blendedColor = lerp(lightColor, 1.0.xxx, saturate(1.5 * vanillaFogFactor).xxx);
blendedColor = lerp(blendedColor, 1.0.xxx, saturate(1.5 * expFogFactor).xxx);
# else
float3 blendedColor = lerp(lightColor, 1.0.xxx, saturate(1.5 * fogFactor).xxx);
# endif
# else
# if defined(EXP_HEIGHT_FOG)
float3 blendedColor = lerp(lightColor, vanillaFogColor, vanillaFogFactor.xxx);
# else
float3 blendedColor = lerp(lightColor, fogColor, fogFactor.xxx);
# endif
# endif
# else
float3 blendedColor = lightColor.xyz;
Expand Down
16 changes: 12 additions & 4 deletions package/Shaders/ISSAOComposite.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,23 @@ PS_OUTPUT main(PS_INPUT input)
float4 positionWS = float4(2 * float2(monoUV.x, -monoUV.y + 1) - 1, depth, 1);
positionWS = mul(FrameBuffer::CameraViewProjInverse[eyeIndex], positionWS);
positionWS.xyz = positionWS.xyz / positionWS.w;
float4 exponentialHeightFog = (float4)0;
if (exponentialHeightFogEnabled) {
float4 exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(positionWS.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, fogColor);
fogColor = exponentialHeightFog.xyz;
fogFactor = exponentialHeightFog.w;
exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(positionWS.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, fogColor);
}
if (isGeometryDepth || exponentialHeightFogEnabled) {
float fogFade = exponentialHeightFogEnabled ? ExponentialHeightFog::GetVanillaFogFade(FogNearColor.w) : FogNearColor.w;
float3 fogSource = exponentialHeightFogEnabled && !isGeometryDepth ? composedColor.xyz : fogFade * composedColor.xyz;
composedColor.xyz = lerp(fogSource, fogFade * fogColor, fogFactor);
if (exponentialHeightFogEnabled && !ExponentialHeightFog::ShouldDisableVanillaFog()) {
// Apply vanilla fog first, then exp fog on top
composedColor.xyz = lerp(fogSource, fogFade * fogColor, Color::FogAlpha(fogFactor));
composedColor.xyz = lerp(composedColor.xyz, fogFade * exponentialHeightFog.xyz, exponentialHeightFog.w);
} else if (exponentialHeightFogEnabled) {
// Disable vanilla fog, only apply exp height fog
composedColor.xyz = lerp(fogSource, fogFade * exponentialHeightFog.xyz, exponentialHeightFog.w);
} else {
composedColor.xyz = lerp(fogSource, fogFade * fogColor, Color::FogAlpha(fogFactor));
}
}
# else
if (isGeometryDepth) {
Expand Down
16 changes: 15 additions & 1 deletion package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3087,14 +3087,28 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
}
# endif
# if defined(EXP_HEIGHT_FOG)
float3 vanillaFogColor = fogColor;
float vanillaFogFactor = fogFactor;
if (SharedData::exponentialHeightFogSettings.enabled) {
float4 exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(input.WorldPosition.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, fogColor);
fogColor = exponentialHeightFog.xyz;
fogFactor = exponentialHeightFog.w;
}
# endif
if (FrameBuffer::FrameParams.y && FrameBuffer::FrameParams.z)
if (FrameBuffer::FrameParams.y && FrameBuffer::FrameParams.z) {
# if defined(EXP_HEIGHT_FOG)
if (SharedData::exponentialHeightFogSettings.enabled) {
if (!ExponentialHeightFog::ShouldDisableVanillaFog()) {
color.xyz = lerp(color.xyz, vanillaFogColor, vanillaFogFactor);
}
color.xyz = lerp(color.xyz, fogColor, fogFactor);
} else {
color.xyz = lerp(color.xyz, fogColor, fogFactor);
}
# else
color.xyz = lerp(color.xyz, fogColor, fogFactor);
# endif
}
# endif

# if defined(TESTCUBEMAP) && defined(ENVMAP) && defined(DYNAMIC_CUBEMAPS)
Expand Down
41 changes: 33 additions & 8 deletions package/Shaders/Water.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -1279,13 +1279,26 @@ PS_OUTPUT main(PS_INPUT input)
# if defined(EXP_HEIGHT_FOG)
if (SharedData::exponentialHeightFogSettings.enabled) {
float4 exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(input.WPosition.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, fogColor);
fogColor = exponentialHeightFog.xyz;
fogDistanceFactor = exponentialHeightFog.w;
if (ExponentialHeightFog::ShouldDisableVanillaFog()) {
fogColor = exponentialHeightFog.xyz;
fogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, fogColor, exponentialHeightFog.w);
} else {
fogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, fogColor, fogDistanceFactor);
float3 expFogColor = exponentialHeightFog.xyz * GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, expFogColor, exponentialHeightFog.w);
}
} else {
fogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, fogColor, fogDistanceFactor);
}
# endif
# else
fogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, fogColor, fogDistanceFactor);
# endif

float3 finalColor = lerp(finalColorPreFog, fogColor, fogDistanceFactor);
float3 finalColor = finalColorPreFog;

# if defined(WETNESS_EFFECTS) && defined(DEBUG_WETNESS_EFFECTS)
// DEBUG MODE: Override water color with debug visualization
Expand Down Expand Up @@ -1317,20 +1330,32 @@ PS_OUTPUT main(PS_INPUT input)
# if defined(EXP_HEIGHT_FOG)
if (SharedData::exponentialHeightFogSettings.enabled) {
float4 exponentialHeightFog = ExponentialHeightFog::GetExponentialHeightFog(input.WPosition.xyz, FrameBuffer::CameraPosAdjust[eyeIndex].xyz, preFogColor);
preFogColor = exponentialHeightFog.xyz;
fogDistanceFactor = exponentialHeightFog.w;
if (ExponentialHeightFog::ShouldDisableVanillaFog()) {
preFogColor = exponentialHeightFog.xyz;
preFogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, preFogColor, exponentialHeightFog.w);
} else {
preFogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, preFogColor, fogDistanceFactor);
float3 expFogColor = exponentialHeightFog.xyz * GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, expFogColor, exponentialHeightFog.w);
}
} else {
preFogColor *= GetWaterFogFade(eyeIndex);
finalColorPreFog = lerp(finalColorPreFog, preFogColor, fogDistanceFactor);
}
Comment thread
jiayev marked this conversation as resolved.
# endif
# else
preFogColor *= GetWaterFogFade(eyeIndex);

finalColorPreFog = lerp(finalColorPreFog, preFogColor, fogDistanceFactor);
# endif

float3 refractionColor = diffuseOutput.refractionColor;

float fogFactor = min(FogParam.w, pow(saturate(-diffuseOutput.depth * FogParam.y - FogParam.x), FogParam.z));
float3 fogColor = Color::Fog(lerp(FogNearColor.xyz, FogFarColor.xyz, fogFactor));
# if defined(EXP_HEIGHT_FOG)
if (SharedData::exponentialHeightFogSettings.enabled) {
if (SharedData::exponentialHeightFogSettings.enabled && ExponentialHeightFog::ShouldDisableVanillaFog()) {
fogFactor = 0;
}
# endif
Expand Down
68 changes: 59 additions & 9 deletions src/Features/ExponentialHeightFog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
fogHeightFalloff,
fogDensity,
directionalInscatteringMultiplier,
directionalInscatteringExponent,
directionalInscatteringAnisotropy,
inscatteringTint,
cubemapMipLevel,
respectVanillaFogFade)
sunlightAttenuationAmount,
respectVanillaFogFade,
disableVanillaFog,
fogInscatteringColor,
originalFogColorAmount)

void ExponentialHeightFog::RestoreDefaultSettings()
{
Expand All @@ -37,9 +41,22 @@ void ExponentialHeightFog::DrawSettings()
Util::WeatherUI::SliderFloat("Start Distance", this, "startDistance", &settings.startDistance, 0.0f, 100000.0f, "%.1f");
Util::WeatherUI::SliderFloat("Fog Height", this, "fogHeight", &settings.fogHeight, -22000.0f, 22000.0f, "%.1f");
Util::WeatherUI::SliderFloat("Fog Height Falloff", this, "fogHeightFalloff", &settings.fogHeightFalloff, 0.001f, 2.0f, "%.3f");
Util::WeatherUI::ColorEdit4("Fog Inscattering Color", this, "fogInscatteringColor", (float*)&settings.fogInscatteringColor);
Util::WeatherUI::SliderFloat("Original Fog Color Amount", this, "originalFogColorAmount", &settings.originalFogColorAmount, 0.0f, 1.0f, "%.2f");
Util::WeatherUI::SliderFloat("Fog Density", this, "fogDensity", &settings.fogDensity, 0.0f, 1.0f, "%.3f");
Util::WeatherUI::SliderFloat("Directional Light Inscattering Multiplier", this, "directionalInscatteringMultiplier", &settings.directionalInscatteringMultiplier, 0.0f, 10.0f, "%.2f");
Util::WeatherUI::SliderFloat("Directional Light Inscattering Exponent", this, "directionalInscatteringExponent", &settings.directionalInscatteringExponent, 1.0f, 128.0f, "%.2f");
Util::WeatherUI::SliderFloat("Sunlight Attenuation Amount", this, "sunlightAttenuationAmount", &settings.sunlightAttenuationAmount, 0.0f, 1.0f, "%.2f");
Util::WeatherUI::SliderFloat("Directional Light Inscattering Anisotropy", this, "directionalInscatteringAnisotropy", &settings.directionalInscatteringAnisotropy, -0.99f, 0.99f, "%.3f");
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text(
"Controls the asymmetry of inscattering via the Henyey-Greenstein phase function.\n"
"Positive values produce forward scattering (glow around sun).\n"
"Zero is isotropic. Negative values produce back scattering.");
}
ImGui::Checkbox("Disable Vanilla Fog", (bool*)&settings.disableVanillaFog);
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Disables the vanilla fog entirely. Only exponential height fog will be applied.");
}
Util::WeatherUI::Checkbox("Apply Vanilla Fade", this, "respectVanillaFogFade", (bool*)&settings.respectVanillaFogFade);
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Applies vanilla fade brightness to exponential height fog.");
Expand Down Expand Up @@ -76,6 +93,21 @@ void ExponentialHeightFog::RegisterWeatherVariables()
0.2f,
0.001f, 2.0f));

registry->RegisterVariable(std::make_shared<WeatherVariables::Float4Variable>(
"Fog Inscattering Color",
"fogInscatteringColor",
"Color added to the fog inscattering contribution",
&settings.fogInscatteringColor,
float4{ 0.0f, 0.0f, 0.0f, 1.0f }));

registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Original Fog Color Amount",
"originalFogColorAmount",
"Amount of the original fog color added to fog inscattering",
&settings.originalFogColorAmount,
1.0f,
0.0f, 1.0f));

registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Fog Density",
"fogDensity",
Expand All @@ -93,12 +125,20 @@ void ExponentialHeightFog::RegisterWeatherVariables()
0.0f, 10.0f));

registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Directional Inscattering Exponent",
"directionalInscatteringExponent",
"Controls the size of the directional inscattering cone",
&settings.directionalInscatteringExponent,
4.0f,
1.0f, 128.0f));
"Sunlight Attenuation Amount",
"sunlightAttenuationAmount",
"Amount of fog attenuation applied to direct sunlight",
&settings.sunlightAttenuationAmount,
1.0f,
0.0f, 1.0f));

registry->RegisterVariable(std::make_shared<WeatherVariables::FloatVariable>(
"Directional Inscattering Anisotropy",
"directionalInscatteringAnisotropy",
"Henyey-Greenstein asymmetry parameter. Positive = forward scattering, 0 = isotropic, negative = back scattering.",
&settings.directionalInscatteringAnisotropy,
0.7f,
-0.99f, 0.99f));

registry->RegisterVariable(std::make_shared<WeatherVariables::Float4Variable>(
"Inscattering Cubemap Tint",
Expand All @@ -116,4 +156,14 @@ void ExponentialHeightFog::RegisterWeatherVariables()
[](const bool& from, const bool& to, float factor) {
return factor > 0.5f ? to : from;
}));

registry->RegisterVariable(std::make_shared<WeatherVariables::WeatherVariable<bool>>(
"disableVanillaFog",
"Disable Vanilla Fog",
"Disables vanilla fog entirely, only exponential height fog is applied",
(bool*)&settings.disableVanillaFog,
false,
[](const bool& from, const bool& to, float factor) {
return factor > 0.5f ? to : from;
}));
}
10 changes: 7 additions & 3 deletions src/Features/ExponentialHeightFog.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,15 @@ struct ExponentialHeightFog : Feature
float fogHeightFalloff = 0.2f;
float fogDensity = 0.02f;
float directionalInscatteringMultiplier = 1.0f;
float directionalInscatteringExponent = 4.0f;
float directionalInscatteringAnisotropy = 0.7f;
float4 inscatteringTint = { 1.0f, 1.0f, 1.0f, 1.0f };
float cubemapMipLevel = 3.0f;
float sunlightAttenuationAmount = 1.0f;
uint respectVanillaFogFade = 0;
float pad[2];
uint disableVanillaFog = 0;
float4 fogInscatteringColor = { 0.0f, 0.0f, 0.0f, 1.0f };
float originalFogColorAmount = 1.0f;
float3 pad;
} settings;
static_assert(sizeof(Settings) == sizeof(float4) * 4, "Settings must match HLSL ExponentialHeightFogSettings.");
static_assert(sizeof(Settings) == sizeof(float4) * 6, "Settings must match HLSL ExponentialHeightFogSettings.");
};
Loading