Skip to content

Instantly share code, notes, and snippets.

@msomeone
Created February 4, 2020 07:56
Show Gist options
  • Save msomeone/0918f7b1944d058920d8e280cfd75e8b to your computer and use it in GitHub Desktop.
Save msomeone/0918f7b1944d058920d8e280cfd75e8b to your computer and use it in GitHub Desktop.
vec3 ndc2world(mat4 inv_proj, mat4 inv_view, vec3 ndc_pos)
{
vec4 v = inv_proj * vec4(ndc_pos, 1.);
v.xyz /= v.w; // view space
vec4 w = inv_view * vec4(v.xyz, 1.); // world space, camera relative (origin = camera position)
return w.xyz;
//return v.xyz;
}
// Try reconstructing normal accurately from depth buffer.
// input DepthBuffer: stores linearized depth in range (0, 1).
// 5 taps on each direction: | z | x | * | y | w |, '*' denotes the center sample.
vec3 ReconstructNormal(sampler2D DepthBuffer, vec2 ndc0, vec2 uv0, vec2 texel_size, mat4 inv_proj, mat4 inv_view)
{
float depth = (textureLod(DepthBuffer, uv0, 0.).x);
vec4 H, H0;
H0.x = textureLod(DepthBuffer, uv0 - vec2(1. / texel_size.x, 0.), .0).x;
H0.y = textureLod(DepthBuffer, uv0 + vec2(1. / texel_size.x, 0.), .0).x;
H0.z = textureLod(DepthBuffer, uv0 - vec2(2. / texel_size.x, 0.), .0).x;
H0.w = textureLod(DepthBuffer, uv0 + vec2(2. / texel_size.x, 0.), .0).x;
H.x = (H0.x);
H.y = (H0.y);
H.z = (H0.z);
H.w = (H0.w);
//vec2 he = abs(H.xy * H.zw / (2. * H.zw - H.xy) - depth);
vec2 he = vec2(
abs((2. * H.x - H.z) - depth), // line eq. solutions for (x0 + 2), x0 = x0(z_tap)
abs((2. * H.y - H.w) - depth)
);
vec3 hDeriv;
if (he.x > he.y)
{ // Calculate horizontal derivative of world position from taps | z | x |
vec3 tap_x_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 - vec2(1. / texel_size.x, 0.) * 2., H0.x));
vec3 tap_z_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 - vec2(2. / texel_size.x, 0.) * 2., H0.z));
hDeriv = tap_x_wp - tap_z_wp; // may ignore 1./dx = 2., who cares if we gona normalize anyway
}
else
{// Calculate horizontal derivative of world position from taps | y | w |
vec3 tap_y_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 + vec2(0., 1. / texel_size.x) * 2., H0.y));
vec3 tap_w_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 + vec2(0., 2. / texel_size.x) * 2., H0.w));
hDeriv = tap_w_wp - tap_y_wp;
}
vec4 V, V0;
V0.x = textureLod(DepthBuffer, uv0 - vec2(0., 1. / texel_size.y), .0).x;
V0.y = textureLod(DepthBuffer, uv0 + vec2(0., 1. / texel_size.y), .0).x;
V0.z = textureLod(DepthBuffer, uv0 - vec2(0., 2. / texel_size.y), .0).x;
V0.w = textureLod(DepthBuffer, uv0 + vec2(0., 2. / texel_size.y), .0).x;
V.x = (V0.x);
V.y = (V0.y);
V.z = (V0.z);
V.w = (V0.w);
//vec2 ve = abs(V.xy * V.zw / (2. * V.zw - V.xy) - depth);
vec2 ve = vec2( // line eq. solutions for (y0 + 2), y0 = y0(z_tap)
abs((2. * V.x - V.z) - depth),
abs((2. * V.y - V.w) - depth)
);
vec3 vDeriv;
if (ve.x > ve.y)
{ // Calculate vertical derivative of world position from taps | z | x |
vec3 tap_x_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 - vec2(0., 1. / texel_size.y) * 2., V0.x));
vec3 tap_z_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 - vec2(0., 2. / texel_size.y) * 2., V0.z));
vDeriv = tap_x_wp - tap_z_wp;
}
else
{ // Calculate vertical derivative of world position from taps | y | w |
vec3 tap_y_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 + vec2(0., 1. / texel_size.y) * 2., V0.y));
vec3 tap_w_wp = ndc2world(inv_proj, inv_view, vec3(ndc0 + vec2(0., 2. / texel_size.y) * 2., V0.w));
vDeriv = tap_w_wp - tap_y_wp;
}
return normalize(cross(hDeriv, vDeriv));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment