122 lines
3.1 KiB
C
122 lines
3.1 KiB
C
|
//=================================================================================================
|
||
|
//Mip Fog for STALKER Anomaly
|
||
|
//Inspired by Uncharted 4
|
||
|
//=================================================================================================
|
||
|
#define HEIGHTFOGMAX 60
|
||
|
#define HEIGHTFOGMIN -75
|
||
|
|
||
|
#define FOGMAXSHARPNESS 0.895
|
||
|
#define FOGROUGHCURVE 1.0
|
||
|
|
||
|
#define MIPFOGAMOUNT 2.0
|
||
|
#define SUNFOGAMOUNT 0.35
|
||
|
|
||
|
#define MINFOGDENSITY 0.35
|
||
|
#define MAXFOGDENSITY 6.5
|
||
|
#define HEIGHTFOGCURVE 5.5
|
||
|
//=================================================================================================
|
||
|
float Calc_Exponent(float a)
|
||
|
{
|
||
|
return 1 / (pow(2, a));
|
||
|
}
|
||
|
|
||
|
float Calc_Height(float3 wpos)
|
||
|
{
|
||
|
return 1 - saturate((wpos.y - HEIGHTFOGMIN) / (HEIGHTFOGMAX-HEIGHTFOGMIN));
|
||
|
}
|
||
|
|
||
|
float Calc_FinalFog(float fog, float height)
|
||
|
{
|
||
|
float HeightLerp = pow(height, HEIGHTFOGCURVE);
|
||
|
/*
|
||
|
float CamHeight = Calc_Height(eye_position);
|
||
|
float CamLerp = pow(CamHeight, HEIGHTFOGCURVE);
|
||
|
//HeightLerp = max(HeightLerp, CamLerp);
|
||
|
HeightLerp = (HeightLerp * (1-CamLerp)) + CamLerp;
|
||
|
*/
|
||
|
float Fog = Calc_Exponent(fog * lerp(MINFOGDENSITY, MAXFOGDENSITY, HeightLerp));
|
||
|
return saturate(1 - Fog);
|
||
|
}
|
||
|
|
||
|
float3 Calc_SunFog(float3 pos, float3 fogrough)
|
||
|
{
|
||
|
float3 SunFog = saturate(dot(normalize(Ldynamic_dir), -normalize(pos)));
|
||
|
|
||
|
float gloss = lerp(FOGMAXSHARPNESS*0.5, 0, fogrough);
|
||
|
gloss = gloss*gloss;
|
||
|
gloss = pow(8192, gloss);
|
||
|
SunFog = pow(SunFog, gloss) * ((gloss + 2)/(8 * PI)); //BLOPS2 blinn
|
||
|
|
||
|
SunFog *= SRGBToLinear(Ldynamic_color.rgb);
|
||
|
|
||
|
return SunFog * SUNFOGAMOUNT;
|
||
|
}
|
||
|
|
||
|
float3 Calc_MipFog(float3 sky, float3 fogrough)
|
||
|
{
|
||
|
sky = normalize(sky);
|
||
|
|
||
|
//cubemap projection
|
||
|
float3 skyabs = abs(sky);
|
||
|
float skymax = max(skyabs.x, max(skyabs.y, skyabs.z));
|
||
|
sky /= skymax;
|
||
|
if (sky.y < 0.999)
|
||
|
sky.y = sky.y*2-1; //fake remapping
|
||
|
|
||
|
sky = normalize(sky);
|
||
|
|
||
|
float FogMip = lerp(CUBE_MIPS - (CUBE_MIPS * FOGMAXSHARPNESS), CUBE_MIPS, fogrough); //don't use base mip
|
||
|
|
||
|
float3 s0 = env_s0.SampleLevel(smp_base, sky, FogMip);
|
||
|
float3 s1 = env_s1.SampleLevel(smp_base, sky, FogMip);
|
||
|
|
||
|
float3 MipFog = lerp(s0,s1,env_color.w);
|
||
|
|
||
|
//srgb tint
|
||
|
float3 FogTint = lerp(fog_color.rgb * 2.0, env_color.rgb, fogrough*fogrough); //env for close, fog for far
|
||
|
|
||
|
MipFog *= FogTint;
|
||
|
|
||
|
//linear cubemap
|
||
|
MipFog = SRGBToLinear(MipFog);
|
||
|
|
||
|
return MipFog * MIPFOGAMOUNT;
|
||
|
}
|
||
|
|
||
|
float3 Calc_Fog(float3 pos, float3 color)
|
||
|
{
|
||
|
color = SRGBToLinear(color.rgb);
|
||
|
|
||
|
//view to world space
|
||
|
float3 sky = mul(m_inv_V, pos );
|
||
|
float3 wpos = sky + eye_position;
|
||
|
|
||
|
float distance = length(pos);
|
||
|
|
||
|
float fog = saturate(distance * fog_params.w + fog_params.x);
|
||
|
|
||
|
float height = Calc_Height(wpos);
|
||
|
|
||
|
float FinalFog = Calc_FinalFog(fog, height);
|
||
|
|
||
|
float fogrough = fog;
|
||
|
fogrough = pow(1 - fogrough , FOGROUGHCURVE);
|
||
|
|
||
|
float3 MipFog = Calc_MipFog(sky, fogrough);
|
||
|
float3 SunFog = Calc_SunFog(pos, fogrough);
|
||
|
|
||
|
float3 FogColor = MipFog + SunFog;
|
||
|
|
||
|
//fog blend
|
||
|
float3 FogBlend = FinalFog;
|
||
|
|
||
|
//fog alpha
|
||
|
float fogalpha = fog * fog;
|
||
|
FogBlend *= 1 - fogalpha;
|
||
|
FogBlend += fogalpha;
|
||
|
|
||
|
float3 Final = lerp(color, FogColor, FogBlend);
|
||
|
Final = LinearTosRGB(Final);
|
||
|
|
||
|
return Final;
|
||
|
}
|