#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