Divergent/mods/Shader 3D Scopes/gamedata/shaders/r3/gbuffer_stage.h

172 lines
3.9 KiB
C

#ifndef GBUFFER_STAGE_H
#define GBUFFER_STAGE_H
//GBuffer targets struct
struct f_deffer
{
float4 position : SV_Target0; //XY - Normal, Z - Depth, W - Hemi/M_ID
float4 C : SV_Target1; //XYZ - Albedo, W - Specular
float4 H : SV_Target2;
#ifdef EXTEND_F_DEFFER
uint mask : SV_COVERAGE;
#endif
};
uniform float4 L_hotness;
//Unpacked data struct
struct gbuffer_data
{
float3 P; //View space position
float mtl; //Material ID
float3 N; //Unpacked normal
float hemi; //Hemi
float3 C; //Albedo
float gloss; //Specular
};
#ifdef INTERNAL_AMD
float2 gbuf_pack_normal( float3 norm )
{
float2 res;
res.x = norm.z;
res.y = 0.5f * ( norm.x + 1.0f ) ;
res.y *= ( norm.y < 0.0f ? -1.0f : 1.0f );
return res;
}
float3 gbuf_unpack_normal( float2 norm )
{
float3 res;
res.z = norm.x;
res.x = ( 2.0f * abs( norm.y ) ) - 1.0f;
res.y = ( norm.y < 0 ? -1.0 : 1.0 ) * sqrt( abs( 1 - res.x * res.x - res.z * res.z ) );
return res;
}
#else
float2 gbuf_pack_normal( float3 norm )
{
float2 res;
res.x = atan2(norm.y, norm.x) / 3.14159f;
res.y = norm.z;
return res;
}
float3 gbuf_unpack_normal( float2 norm )
{
float2 theta;
sincos(norm.x * 3.14159f, theta.x, theta.y);
float2 phi = float2(sqrt(1.0 - norm.y * norm.y), norm.y);
return float3(theta.y * phi.x, theta.x * phi.x, phi.y);
}
#endif
float gbuf_pack_hemi_mtl( float hemi, float mtl )
{
uint packed_mtl = uint( ( mtl / 1.333333333 ) * 31.0 );
// Clamp hemi max value
uint packed = ( MUST_BE_SET + ( uint( saturate(hemi) * 255.9 ) << 13 ) + ( ( packed_mtl & uint( 31 ) ) << 21 ) );
if( ( packed & USABLE_BIT_13 ) == 0 )
packed |= USABLE_BIT_14;
if( packed_mtl & uint( 16 ) )
packed |= USABLE_BIT_15;
return asfloat( packed );
}
float gbuf_unpack_hemi( float mtl_hemi )
{
return float( ( asuint( mtl_hemi ) >> 13 ) & uint(255) ) * (1.0/254.8);
}
float gbuf_unpack_mtl( float mtl_hemi )
{
uint packed = asuint( mtl_hemi );
uint packed_hemi = ( ( packed >> 21 ) & uint(15) ) + ( ( packed & USABLE_BIT_15 ) == 0 ? 0 : 16 );
return float( packed_hemi ) * (1.0/31.0) * 1.333333333;
}
//Packing stage
#ifndef EXTEND_F_DEFFER
f_deffer pack_gbuffer( float4 norm, float4 pos, float4 col )
#else
f_deffer pack_gbuffer( float4 norm, float4 pos, float4 col, uint imask )
#endif
{
f_deffer res;
res.position = float4( gbuf_pack_normal( norm.xyz ), pos.z, gbuf_pack_hemi_mtl( norm.w, pos.w ) );
res.C = col;
if (L_hotness.x > 0.0)
res.H = float4(L_hotness.x, 0.0, 0.0, 1.0);
else
res.H = float4(0.0, 0.0, 0.0, 0.0);
#ifdef EXTEND_F_DEFFER
res.mask = imask;
#endif
return res;
}
//Unpacking stage
gbuffer_data gbuffer_load_data( float2 tc : TEXCOORD, float2 pos2d, uint iSample )
{
gbuffer_data gbd;
#ifndef USE_MSAA
float4 P = s_position.Sample( smp_nofilter, tc );
float4 C = s_diffuse.Sample( smp_nofilter, tc );
#else
float4 P = s_position.Load( int3( pos2d, 0 ), iSample );
float4 C = s_diffuse.Load( int3( pos2d, 0 ), iSample );
#endif
// 3d view space pos reconstruction math
gbd.P = float3( P.z * ( pos2d * pos_decompression_params.zw - pos_decompression_params.xy ), P.z );
// reconstruct N
gbd.N = gbuf_unpack_normal( P.xy );
// reconstruct material
gbd.mtl = gbuf_unpack_mtl( P.w );
// reconstruct hemi
gbd.hemi = gbuf_unpack_hemi( P.w );
gbd.C = C.xyz;
gbd.gloss = C.w;
return gbd;
}
gbuffer_data gbuffer_load_data( float2 tc : TEXCOORD, float2 pos2d )
{
return gbuffer_load_data( tc, pos2d, 0 );
}
gbuffer_data gbuffer_load_data_offset( float2 tc : TEXCOORD, float2 OffsetTC : TEXCOORD, float2 pos2d )
{
float2 delta = ( ( OffsetTC - tc ) * screen_res.xy );
return gbuffer_load_data( OffsetTC, pos2d + delta, 0 );
}
gbuffer_data gbuffer_load_data_offset( float2 tc : TEXCOORD, float2 OffsetTC : TEXCOORD, float2 pos2d, uint iSample )
{
float2 delta = ( ( OffsetTC - tc ) * screen_res.xy );
return gbuffer_load_data( OffsetTC, pos2d + delta, iSample );
}
#endif //GBUFFER_STAGE_H