e4s-game/gamedata/shaders/d3d11/common_functions.hlsli
2026-06-18 01:18:29 +03:00

290 lines
7.2 KiB
HLSL

#ifndef common_functions_h_included
#define common_functions_h_included
// contrast function
float Contrast(float Input, float ContrastPower)
{
// piecewise contrast function
bool IsAbovefloat = Input > 0.5f;
float ToRaise = saturate(2.0f * (IsAbovefloat ? 1.0f - Input : Input));
float Output = 0.5f * pow(ToRaise, ContrastPower);
Output = IsAbovefloat ? 1.0f - Output : Output;
return Output;
}
#ifndef SRGB_GAMMA
#define SRGB_GAMMA 2.2
#endif
#ifndef USE_LEGACY_LIGHT
#define PushGamma(x) pow(abs(x), SRGB_GAMMA)
#define PopGamma(x) pow(abs(x), rcp(SRGB_GAMMA))
#else
#define PushGamma(x) abs(x)
#define PopGamma(x) abs(x)
#endif
#ifndef USE_CGIM_WHITE_TWEAK
#define RCP_WHITE_SQR 0.34602f
#define INV_TONEMAP_COEF_ONE 0.61592f
#define INV_TONEMAP_COEF_TWO 1.44565f
#else
#define RCP_WHITE_SQR 0.416233f
#define INV_TONEMAP_COEF_ONE 0.335068f
#define INV_TONEMAP_COEF_TWO 1.20125f
#endif
float3 tonemap(float3 rgb, float scale)
{
rgb = rgb * scale;
rgb = rgb * (1.0f + rgb * RCP_WHITE_SQR) * rcp(rgb + 1.0f);
return PopGamma(rgb);
}
float3 detonemap(float3 rgb)
{
rgb = PushGamma(rgb);
float3 scale = rgb * rgb - INV_TONEMAP_COEF_ONE * rgb + 1.0f;
rgb = rgb + sqrt(scale) - 1.0f;
return rgb * INV_TONEMAP_COEF_TWO;
}
void RemapVector(inout float3 View)
{
float3 ViewPos = abs(View);
float ViewPosMax = max(ViewPos.x, max(ViewPos.y, ViewPos.z));
View *= rcp(ViewPosMax);
View.y = View.y * 2.0 - 1.0;
}
// Функции генерации случайных чисел [0, 1]
// START
float Hash(float n)
{
return frac(sin(n) * 43758.5453123f);
}
float Hash(float2 n)
{
return Hash(Hash(n.x) + n.y);
}
float Hash(float3 n)
{
return Hash(Hash(dot(n.xy, float2(12.989, 78.233))) + n.z);
}
float2 Hash22(float2 value)
{
return float2(
Hash(dot(value, float2(12.989, 78.233))),
Hash(dot(value, float2(39.346, 11.135))));
}
float3 Hash23(float2 value)
{
return float3(
Hash(dot(value, float2(12.989, 78.233))),
Hash(dot(value, float2(39.346, 11.135))),
Hash(dot(value, float2(73.156, 52.235))));
}
float2 Hash32(float3 value)
{
return float2(
Hash(dot(value, float3(12.989, 78.233, 123.134f))),
Hash(dot(value, float3(39.346, 11.135, 543.142f))));
}
float3 Hash33(float3 value)
{
return float3(
Hash(dot(value, float3(12.989, 78.233, 123.134f))),
Hash(dot(value, float3(39.346, 11.135, 543.142f))),
Hash(dot(value, float3(73.156, 52.235, 143.425f))));
}
// END
float GetBorderAtten(float2 tc, float2 att)
{
att.x *= pos_decompression_params2.y * pos_decompression_params2.z;
float2 factors = saturate(min(1.0f - tc, tc) * rcp(att));
return factors.x * factors.y;
}
bool GetBorderAtten(float2 tc)
{
float2 factors = min(1.0f - tc, tc);
return min(factors.x, factors.y) > 0.0f;
}
float GetMaxDirLength(float3 Point, float3 RDir)
{
float3 FirstPoint = RDir - Point * RDir;
float3 LastPoint = -Point * RDir;
float3 MaxPoint = max(FirstPoint, LastPoint);
return min(MaxPoint.x, min(MaxPoint.y, MaxPoint.z));
}
// Hashed Alpha Testing
// The implementation was taken from https://cwyman.org/papers/i3d17_hashedAlpha.pdf document by Chris Wyman and Morgan McGuire
float hashed_alpha_test(float3 position)
{
if (m_taa_jitter.z < 0.0f)
{
return def_aref;
}
// Find the discretized derivatives of our coordinates
float maxDeriv = max(length(ddx(position.xyz)), length(ddy(position.xyz)));
float pixScale = rcp(def_aref * maxDeriv); // Let's use def_aref as temporary pixel scale
float pixScaleLog2 = log2(pixScale);
// Find two nearest log-discretized noise scales
float2 pixScales = float2(exp2(floor(pixScaleLog2)), exp2(ceil(pixScaleLog2)));
// Compute alpha thresholds at our two noise scales
float2 alpha = float2(Hash(floor(pixScales.x * position.xyz)), Hash(floor(pixScales.y * position.xyz)));
// Factor to interpolate lerp with
float lerpFactor = frac(log2(pixScale));
// Interpolate alpha threshold from noise at two scales
float x = lerp(alpha.x, alpha.y, lerpFactor);
// Pass into CDF to compute uniformly distrib threshold
float a = min(lerpFactor, 1.0 - lerpFactor);
float3 cases;
cases.x = x * x * rcp(2.0 * a * (1.0 - a));
cases.y = (x - 0.5 * a) * rcp(1.0 - a);
cases.z = 1.0 - ((1.0 - x) * (1.0 - x) * rcp(2.0 * a * (1.0 - a)));
// Find our final, uniformly distributed alpha threshold
float thresh = (x < (1.0 - a)) ? ((x < a) ? cases.x : cases.y) : cases.z;
// R1 sequence to animate our noise for TAA/FSR/DLSS
// Todo: Check if player has enabled TAA/upscaling to enable anim
thresh = frac(thresh + m_taa_jitter.z);
// Clamp alpha
return clamp(thresh, 0.063f, 1.0f);
}
#define IMAGE_BITRATE float3(255.f, 255.f, 255.f)
// Deband color function (by Hozar 2002) - may be huita
float3 deband_color(float3 image, float2 uv)
{
float3 dither = Hash23(cos(uv.xy * timers.x) * 1245.0f);
float3 color = saturate(image) * IMAGE_BITRATE;
float3 pq = frac(color);
color -= pq;
pq = step(dither, pq);
color += pq;
color *= rcp(IMAGE_BITRATE);
return color;
}
//Builds a cotangent frame. Source: http://www.thetenthplanet.de/archives/1180
void build_contangent_frame(float3 position, float3 normal, float2 uv, out float3 tangent, out float3 binormal)
{
float4 duv = float4(ddx(uv), ddy(uv));
float3 dp1perp = cross(normal, ddx(position));
float3 dp2perp = cross(ddy(position), normal);
tangent = dp2perp * duv.x + dp1perp * duv.z;
binormal = dp2perp * duv.y + dp1perp * duv.w;
float invmax = rsqrt(max(dot(tangent, tangent), dot(binormal, binormal)));
tangent *= invmax;
binormal *= invmax;
}
float4 combine_bloom(float3 low, float4 high)
{
return float4(low.xyz + high.xyz * high.w, 1.f);
}
float calc_fogging(float3 pos)
{
return saturate(length(pos - eye_position) * fog_params.w + fog_params.x);
}
float2 unpack_tc_base(float2 tc, float du, float dv)
{
return (tc.xy + float2(du, dv)) * (32.f / 32768.f); //! Increase from 32bit to 64bit floating point
}
float3 unpack_normal(float3 v)
{
return 2 * v - 1;
}
float3 unpack_bx2(float3 v)
{
return 2 * v - 1;
}
float3 unpack_bx4(float3 v)
{
return 4 * v - 2;
} //! reduce the amount of stretching from 4*v-2 and increase precision
float2 unpack_tc_lmap(float2 tc)
{
return tc * (1.f / 32768.f);
} // [-1 .. +1 ]
float4 unpack_color(float4 c)
{
return c.bgra;
}
float4 unpack_D3DCOLOR(float4 c)
{
return c.bgra;
}
float3 unpack_D3DCOLOR(float3 c)
{
return c.bgr;
}
float3 p_hemi(float2 tc)
{
float4 t_lmh = s_hemi.Sample(smp_rtlinear, tc);
return t_lmh.w;
}
float get_hemi(float4 lmh)
{
return lmh.w;
}
float get_sun(float4 lmh)
{
return lmh.y;
}
float3 v_sun(float3 N)
{
return L_sun_color.xyz * dot(N, -L_sun_dir_w.xyz);
}
float3 calc_reflection(float3 pos_w, float3 norm_w)
{
return reflect(normalize(pos_w - eye_position), norm_w);
}
#endif // common_functions_h_included