63 lines
2.6 KiB
C
63 lines
2.6 KiB
C
|
#ifndef SLB_SHADOW_NORMAL_H
|
||
|
#define SLB_SHADOW_NORMAL_H
|
||
|
|
||
|
float3 SLB_Shadow_ViewSpacePosAtScreenUV(float2 pos) {
|
||
|
return float3(pos.x, pos.y, SLB_Shadow_Sample(pos)); // * float2(float(SMAP_size), 1.0).xxy;
|
||
|
}
|
||
|
|
||
|
float3 SLB_Shadow_Normal(float2 vpos) {
|
||
|
float2 texelSize = float2(1.0, 1.0)/float2(float(SMAP_size), float(SMAP_size));
|
||
|
// screen uv from vpos
|
||
|
float2 uv = floor(vpos/texelSize)*texelSize;
|
||
|
|
||
|
// current pixel's depth
|
||
|
float c = SLB_Shadow_Sample(uv);
|
||
|
|
||
|
// get current pixel's view space position
|
||
|
float3 viewSpacePos_c = SLB_Shadow_ViewSpacePosAtScreenUV(uv);
|
||
|
|
||
|
// get view space position at 1 pixel offsets in each major direction
|
||
|
float3 viewSpacePos_l = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2(-1.0, 0.0) * texelSize);
|
||
|
float3 viewSpacePos_r = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 1.0, 0.0) * texelSize);
|
||
|
float3 viewSpacePos_d = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 0.0,-1.0) * texelSize);
|
||
|
float3 viewSpacePos_u = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 0.0, 1.0) * texelSize);
|
||
|
|
||
|
// get the difference between the current and each offset position
|
||
|
float3 l = viewSpacePos_c - viewSpacePos_l;
|
||
|
float3 r = viewSpacePos_r - viewSpacePos_c;
|
||
|
float3 d = viewSpacePos_c - viewSpacePos_d;
|
||
|
float3 u = viewSpacePos_u - viewSpacePos_c;
|
||
|
|
||
|
// get depth values at 1 & 2 pixels offsets from current along the horizontal axis
|
||
|
float4 H = float4(
|
||
|
SLB_Shadow_Sample(uv + float2(-1.0, 0.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2( 1.0, 0.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2(-2.0, 0.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2( 2.0, 0.0) * texelSize)
|
||
|
);
|
||
|
|
||
|
// get depth values at 1 & 2 pixels offsets from current along the vertical axis
|
||
|
float4 V = float4(
|
||
|
SLB_Shadow_Sample(uv + float2(0.0,-1.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2(0.0, 1.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2(0.0,-2.0) * texelSize),
|
||
|
SLB_Shadow_Sample(uv + float2(0.0, 2.0) * texelSize)
|
||
|
);
|
||
|
|
||
|
// current pixel's depth difference from slope of offset depth samples
|
||
|
// differs from original article because we're using non-linear depth values
|
||
|
// see article's comments
|
||
|
float2 he = abs((2 * H.xy - H.zw) - c);
|
||
|
float2 ve = abs((2 * V.xy - V.zw) - c);
|
||
|
|
||
|
// pick horizontal and vertical diff with the smallest depth difference from slopes
|
||
|
float3 hDeriv = he.x < he.y ? l : r;
|
||
|
float3 vDeriv = ve.x < ve.y ? d : u;
|
||
|
|
||
|
// get view space normal from the cross product of the best derivatives
|
||
|
float3 viewNormal = normalize(cross(hDeriv, vDeriv));
|
||
|
|
||
|
return viewNormal;
|
||
|
}
|
||
|
|
||
|
#endif /// SLB_SHADOW_NORMAL_H
|