242 lines
6.0 KiB
C
242 lines
6.0 KiB
C
|
#ifndef SLOAD_H
|
||
|
#define SLOAD_H
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
uniform float4 ssfx_pom; // Samples, Range, Height, AO
|
||
|
|
||
|
#ifdef MSAA_ALPHATEST_DX10_1
|
||
|
#if MSAA_SAMPLES == 2
|
||
|
static const float2 MSAAOffsets[2] = { float2(4,4), float2(-4,-4) };
|
||
|
#endif
|
||
|
#if MSAA_SAMPLES == 4
|
||
|
static const float2 MSAAOffsets[4] = { float2(-2,-6), float2(6,-2), float2(-6,2), float2(2,6) };
|
||
|
#endif
|
||
|
#if MSAA_SAMPLES == 8
|
||
|
static const float2 MSAAOffsets[8] = { float2(1,-3), float2(-1,3), float2(5,1), float2(-3,-5),
|
||
|
float2(-5,5), float2(-7,-1), float2(3,7), float2(7,-7) };
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Bumped surface loader
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
struct surface_bumped
|
||
|
{
|
||
|
float4 base;
|
||
|
float3 normal;
|
||
|
float gloss;
|
||
|
float height;
|
||
|
};
|
||
|
|
||
|
float3 NormalBlend(float3 A, float3 B)
|
||
|
{
|
||
|
return normalize(float3(A.rg + B.rg, A.b * B.b));
|
||
|
}
|
||
|
|
||
|
float3 NormalBlend_Reoriented(float3 A, float3 B)
|
||
|
{
|
||
|
float3 t = A.xyz + float3(0.0, 0.0, 1.0);
|
||
|
float3 u = B.xyz * float3(-1.0, -1.0, 1.0);
|
||
|
return (t / t.z) * dot(t, u) - u;
|
||
|
}
|
||
|
|
||
|
float4 tbase( float2 tc )
|
||
|
{
|
||
|
return s_base.Sample( smp_base, tc);
|
||
|
}
|
||
|
|
||
|
#if defined(ALLOW_STEEPPARALLAX) && defined(USE_STEEPPARALLAX)
|
||
|
|
||
|
/**
|
||
|
* @ Version: SCREEN SPACE SHADERS - UPDATE 22
|
||
|
* @ Description: POM Shader - Modified version from the terrain POM implementation
|
||
|
* @ Author: https://www.moddb.com/members/ascii1457
|
||
|
* @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders
|
||
|
*/
|
||
|
void UpdateTC( inout p_bumped I, inout float H )
|
||
|
{
|
||
|
// Distance attenuation
|
||
|
float dist_att = 1.0f - smoothstep(ssfx_pom.y * 0.8f, ssfx_pom.y, I.position.z);
|
||
|
|
||
|
if (I.position.z >= ssfx_pom.y)
|
||
|
return;
|
||
|
|
||
|
float3 eye = normalize(mul(float3x3(I.M1.x, I.M2.x, I.M3.x,
|
||
|
I.M1.y, I.M2.y, I.M3.y,
|
||
|
I.M1.z, I.M2.z, I.M3.z), -I.position));
|
||
|
|
||
|
float view_angle = abs(dot(float3(0.0, 0.0, 1.0), eye));
|
||
|
|
||
|
// Dynamic steps
|
||
|
float _step = rcp(lerp(ssfx_pom.x, 3, view_angle));
|
||
|
_step *= 0.5; // We are working with 0.0 ~ 0.5
|
||
|
|
||
|
// View direction + bias to try to minimize issues with some slopes.
|
||
|
float2 viewdir = eye.xy / (abs(eye.z) + 0.41f);
|
||
|
|
||
|
// Offset direction
|
||
|
float2 tc_step = _step * viewdir * ssfx_pom.z * dist_att;
|
||
|
|
||
|
// Init vars to store steps
|
||
|
float curr_step = 0;
|
||
|
float2 parallax_tc = I.tcdh;
|
||
|
|
||
|
// Store the previous & current sample to do the [POM] calc and [Contact Refinement] if needed.
|
||
|
float prev_Height = 0;
|
||
|
float curr_Height = 0.5f;
|
||
|
|
||
|
do // Step Parallax
|
||
|
{
|
||
|
// Save previous data
|
||
|
prev_Height = curr_Height;
|
||
|
|
||
|
// Step TexCoor
|
||
|
parallax_tc -= tc_step;
|
||
|
curr_step += _step;
|
||
|
|
||
|
// Sample
|
||
|
curr_Height = 0.5f - s_bumpX.SampleLevel( smp_base, parallax_tc, 0 ).a;
|
||
|
|
||
|
} while(curr_Height >= curr_step);
|
||
|
|
||
|
// [ Contact Refinement ]
|
||
|
#ifdef SSFX_POM_REFINE
|
||
|
|
||
|
// Step back
|
||
|
parallax_tc += tc_step;
|
||
|
curr_step -= _step;
|
||
|
curr_Height = prev_Height; // Previous height
|
||
|
|
||
|
// Increase precision ( 3 times seems like a good balance )
|
||
|
_step /= 3;
|
||
|
tc_step /= 3;
|
||
|
|
||
|
do // Step Parallax
|
||
|
{
|
||
|
// Save previous data ( Used for interpolation )
|
||
|
prev_Height = curr_Height;
|
||
|
|
||
|
// Step TexCoor
|
||
|
parallax_tc -= tc_step;
|
||
|
curr_step += _step;
|
||
|
|
||
|
// Sample
|
||
|
curr_Height = 0.5f - s_bumpX.SampleLevel( smp_base, parallax_tc, 0 ).a;
|
||
|
|
||
|
} while(curr_Height >= curr_step);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// [ POM ] Interpolation between the previous offset and the current offset
|
||
|
float currentDiff = curr_Height - curr_step;
|
||
|
float ratio = currentDiff / (currentDiff - saturate(prev_Height - curr_step + _step));
|
||
|
|
||
|
// Final TexCoor
|
||
|
float2 final_tc = lerp(parallax_tc, parallax_tc + tc_step, ratio);
|
||
|
|
||
|
#if defined(USE_TDETAIL)
|
||
|
I.tcdbump = final_tc * dt_params; // Apply detail_scaler
|
||
|
#endif
|
||
|
|
||
|
// Apply Parallax TC
|
||
|
I.tcdh = final_tc;
|
||
|
|
||
|
}
|
||
|
|
||
|
#elif defined(USE_PARALLAX) || defined(USE_STEEPPARALLAX)
|
||
|
|
||
|
void UpdateTC( inout p_bumped I, inout float H )
|
||
|
{
|
||
|
float3 eye = mul (float3x3(I.M1.x, I.M2.x, I.M3.x,
|
||
|
I.M1.y, I.M2.y, I.M3.y,
|
||
|
I.M1.z, I.M2.z, I.M3.z), -I.position.xyz);
|
||
|
|
||
|
float height = s_bumpX.Sample( smp_base, I.tcdh).w;
|
||
|
H = height;
|
||
|
height = height * (parallax.x) + (parallax.y);
|
||
|
float2 new_tc = I.tcdh + height * normalize(eye);
|
||
|
|
||
|
// Output the result
|
||
|
I.tcdh.xy = new_tc;
|
||
|
|
||
|
#if defined(USE_TDETAIL)
|
||
|
I.tcdbump = new_tc * dt_params; // Apply detail_scaler
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
void UpdateTC( inout p_bumped I, inout float H ) { }
|
||
|
|
||
|
#endif
|
||
|
|
||
|
surface_bumped sload_i( p_bumped I )
|
||
|
{
|
||
|
surface_bumped S;
|
||
|
|
||
|
float H = 0;
|
||
|
|
||
|
UpdateTC(I, H); // Parallax
|
||
|
|
||
|
float4 Nu = s_bump.Sample( smp_base, I.tcdh );
|
||
|
|
||
|
#if defined(ALLOW_STEEPPARALLAX) && defined(USE_STEEPPARALLAX)
|
||
|
H = s_bumpX.Sample( smp_base, I.tcdh ); // Only requiered when the full parallax is used
|
||
|
#endif
|
||
|
|
||
|
S.base = tbase(I.tcdh);
|
||
|
S.normal = unpack_normal( Nu.wzy );
|
||
|
S.gloss = Nu.x;
|
||
|
S.height = H;
|
||
|
|
||
|
#if defined(ALLOW_STEEPPARALLAX) && defined(USE_STEEPPARALLAX)
|
||
|
S.base.rgb *= lerp(1.0f, saturate((S.height + 0.15f) * 2.0f), ssfx_pom.w); // Apply AO
|
||
|
#endif
|
||
|
|
||
|
#ifdef USE_TDETAIL
|
||
|
#ifdef USE_TDETAIL_BUMP
|
||
|
|
||
|
float4 NDetail = s_detailBump.Sample( smp_base, I.tcdbump);
|
||
|
float4 NDetailX = s_detailBumpX.Sample( smp_base, I.tcdbump);
|
||
|
|
||
|
float3 DetailNormal = unpack_normal(NDetail.wzy) + unpack_normal(NDetailX.xyz);
|
||
|
S.normal = NormalBlend (S.normal, DetailNormal);
|
||
|
S.gloss = S.gloss * NDetail.x * 2;
|
||
|
|
||
|
float4 detail = s_detail.Sample( smp_base, I.tcdbump);
|
||
|
S.base.rgb = S.base.rgb * detail.rgb * 2;
|
||
|
|
||
|
#else
|
||
|
|
||
|
float4 detail = s_detail.Sample( smp_base, I.tcdbump);
|
||
|
S.base.rgb = S.base.rgb * detail.rgb * 2;
|
||
|
S.gloss = S.gloss * detail.w * 2;
|
||
|
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
return S;
|
||
|
}
|
||
|
|
||
|
surface_bumped sload ( p_bumped I )
|
||
|
{
|
||
|
return sload_i(I);
|
||
|
}
|
||
|
|
||
|
surface_bumped sload ( p_bumped I, float2 pixeloffset )
|
||
|
{
|
||
|
|
||
|
// Apply MSAA offset
|
||
|
#ifdef MSAA_ALPHATEST_DX10_1
|
||
|
I.tcdh.xy += pixeloffset.x * ddx(I.tcdh.xy) + pixeloffset.y * ddy(I.tcdh.xy);
|
||
|
#ifdef USE_TDETAIL
|
||
|
I.tcdbump.xy += pixeloffset.x * ddx(I.tcdbump.xy) + pixeloffset.y * ddy(I.tcdbump.xy);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
return sload_i(I);
|
||
|
}
|
||
|
|
||
|
#endif
|