#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 ); }