290 lines
7.2 KiB
HLSL
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
|