Divergent/mods/Global Textures Reworked - .../gamedata/shaders/r3/deffer_impl_flat.ps

142 lines
3.3 KiB
PostScript

#define USE_TDETAIL
#include "common.h"
#define PARALLAX_NEAR_PLANE 0.01
#define PARALLAX_FAR_PLANE 35
#define PARALLAX_DEPTH 0.02
//Height maps
Texture2D s_dnE_r;
Texture2D s_dnE_g;
Texture2D s_dnE_b;
Texture2D s_dnE_a;
struct surface {
float4 base;
float3 normal;
float gloss;
};
void perform_tc_offset(inout p_bumped p, in Texture2D s_bumpX_new)
{
if ((p.position.z > PARALLAX_NEAR_PLANE) && (p.position.z < PARALLAX_FAR_PLANE))
{
float3 eye = normalize(mul(float3x3(p.M1.x, p.M2.x, p.M3.x,
p.M1.y, p.M2.y, p.M3.y,
p.M1.z, p.M2.z, p.M3.z), -p.position));
// steps minmax and refines minmax
int4 steps = int4(8, 24, 4, 8); // 3..10, 7..16
bool need_disp_lerp = true;
bool need_refine = true;
float view_angle = abs(dot(float3(0.0, 0.0, 1.0), eye));
float layer_step = rcp(lerp(steps.y, steps.x, view_angle));
float2 tc_step = layer_step * eye.xy * PARALLAX_DEPTH;
float2 displaced_tc = p.tcdbump;
float curr_disp, curr_layer = 0.0;
do
{
displaced_tc -= tc_step;
curr_disp = 1 - s_bumpX_new.SampleLevel(smp_base, displaced_tc, 0).w;
curr_layer += layer_step;
} while (curr_layer < curr_disp);
if (need_refine)
{
displaced_tc += tc_step;
curr_layer -= layer_step;
float refine_steps = lerp(steps.w, steps.z, view_angle);
tc_step /= refine_steps;
layer_step /= refine_steps;
do
{
displaced_tc -= tc_step;
curr_disp = 1.0 - s_bumpX_new.SampleLevel(smp_base, displaced_tc, 0).w;
curr_layer += layer_step;
} while (curr_layer < curr_disp);
}
if (need_disp_lerp)
{
float2 displaced_tc_prev = displaced_tc + tc_step;
float after_depth = curr_disp - curr_layer;
float before_depth = 1.0 - s_bumpX_new.SampleLevel(smp_base, displaced_tc_prev, 0).w - curr_layer + layer_step;
float weight = after_depth / (after_depth - before_depth);
displaced_tc = lerp(displaced_tc, displaced_tc_prev, weight);
}
p.tcdbump = displaced_tc;
}
}
surface fill(p_bumped p, Texture2D s_base_det, Texture2D s_bump_det, Texture2D s_bumpX_det, uint need_mask, float mask)
{
surface S;
mask = need_mask ? mask : 1;
if (mask <= 0)
{
S.base = (0.0, 0.0, 0.0, 0.0);
S.gloss = 0.0;
S.normal = (0.0, 0.0, 0.0);
return S;
}
perform_tc_offset(p, s_base_det);
S.base = s_base_det.Sample(smp_base, p.tcdbump) * mask;
float4 Nu = s_bump_det.Sample(smp_base, p.tcdbump);
S.gloss = Nu.x * mask;
S.normal = (Nu.wzy - 0.5) * mask;
return S;
}
f_deffer main(p_bumped I)
{
float4 C = s_base.Sample(smp_base, I.tcdh.xy);
float4 mask = s_mask.Sample(smp_base, I.tcdh.xy);
mask /= dot(mask, 1.0);
surface Sr = fill(I, s_dt_r, s_dn_r, s_dnE_r, 1, mask.r);
surface Sg = fill(I, s_dt_g, s_dn_g, s_dnE_g, 1, mask.g);
surface Sb = fill(I, s_dt_b, s_dn_b, s_dnE_b, 1, mask.b);
surface Sa = fill(I, s_dt_a, s_dn_a, s_dnE_a, 1, mask.a);
float4 Ne = float4(normalize(mul(float3x3(I.M1, I.M2, I.M3), Sr.normal + Sg.normal + Sb.normal + Sa.normal)), C.w);
C.xyz = (Sr.base.xyz + Sg.base.xyz + Sb.base.xyz + Sa.base.xyz) * C.xyz * 2.0;
float G = Sr.gloss + Sg.gloss + Sb.gloss + Sa.gloss;
#ifdef USE_R2_STATIC_SUN
float ms = s_lmap.Sample(smp_base, I.tcdh.xy).w;
#else
float ms = xmaterial;
#endif
return pack_gbuffer(
Ne, // normal.hemi
float4(I.position.xyz, ms), // depth.( mtl or sun )
float4(C.rgb, G * 0.6) // color.gloss
);
}