|
1 | 1 |
|
| 2 | +// https://iquilezles.org/articles/biplanar/ |
| 3 | + |
2 | 4 | struct Biplanar |
3 | 5 | { |
| 6 | + vec3 normal; |
| 7 | + ivec3 a1; // dominant axis indices |
| 8 | + ivec3 a2; // second axis indices |
| 9 | + ivec3 a3; // least significant axis indices |
4 | 10 | vec2 uv1, uv2; |
5 | | - vec2 d1x, d2x; |
6 | | - vec2 d1y, d2y; |
| 11 | + vec2 dx1, dx2; |
| 12 | + vec2 dy1, dy2; |
7 | 13 | vec2 w; |
8 | | - float div; |
9 | 14 | }; |
10 | 15 |
|
11 | 16 | Biplanar biplanarPrepare(vec3 p, vec3 n, float k) |
12 | 17 | { |
13 | 18 | Biplanar bip; |
| 19 | + bip.normal = n; |
14 | 20 | vec3 dpdx = dFdx(p); |
15 | 21 | vec3 dpdy = dFdy(p); |
16 | 22 | n = abs(n); |
17 | | - ivec3 ma = (n.x > n.y && n.x > n.z) ? ivec3(0, 1, 2) : (n.y > n.z) ? ivec3(1, 2, 0) : ivec3(2, 0, 1); |
18 | | - ivec3 mi = (n.x < n.y && n.x < n.z) ? ivec3(0, 1, 2) : (n.y < n.z) ? ivec3(1, 2, 0) : ivec3(2, 0, 1); |
19 | | - ivec3 me = ivec3(3) - mi - ma; |
20 | | - bip.uv1 = vec2(p[ma.y], p[ma.z]); |
21 | | - bip.uv2 = vec2(p[me.y], p[me.z]); |
22 | | - bip.d1x = vec2(dpdx[ma.y], dpdx[ma.z]); |
23 | | - bip.d2x = vec2(dpdx[me.y], dpdx[me.z]); |
24 | | - bip.d1y = vec2(dpdy[ma.y], dpdy[ma.z]); |
25 | | - bip.d2y = vec2(dpdy[me.y], dpdy[me.z]); |
26 | | - bip.w = vec2(n[ma.x], n[me.x]); |
| 23 | + bip.a1 = (n.x > n.y && n.x > n.z) ? ivec3(0, 1, 2) : (n.y > n.z) ? ivec3(1, 2, 0) : ivec3(2, 0, 1); |
| 24 | + bip.a3 = (n.x < n.y && n.x < n.z) ? ivec3(0, 1, 2) : (n.y < n.z) ? ivec3(1, 2, 0) : ivec3(2, 0, 1); |
| 25 | + bip.a2 = ivec3(3) - bip.a3 - bip.a1; |
| 26 | + bip.uv1 = vec2(p[bip.a1.y], p[bip.a1.z]); |
| 27 | + bip.uv2 = vec2(p[bip.a2.y], p[bip.a2.z]); |
| 28 | + bip.dx1 = vec2(dpdx[bip.a1.y], dpdx[bip.a1.z]); |
| 29 | + bip.dx2 = vec2(dpdx[bip.a2.y], dpdx[bip.a2.z]); |
| 30 | + bip.dy1 = vec2(dpdy[bip.a1.y], dpdy[bip.a1.z]); |
| 31 | + bip.dy2 = vec2(dpdy[bip.a2.y], dpdy[bip.a2.z]); |
| 32 | + bip.w = vec2(n[bip.a1.x], n[bip.a2.x]); |
27 | 33 | bip.w = saturate((bip.w - 0.5773) / (1 - 0.5773)); |
28 | 34 | bip.w = pow(bip.w, vec2(k / 8)); |
29 | | - bip.div = 1 / (bip.w.x + bip.w.y); |
| 35 | + bip.w /= bip.w[0] + bip.w[1]; |
30 | 36 | return bip; |
31 | 37 | } |
32 | 38 |
|
33 | 39 | vec4 biplanarSample(sampler2D sam, Biplanar bip) |
34 | 40 | { |
35 | | - vec4 x = textureGrad(sam, bip.uv1, bip.d1x, bip.d1y); |
36 | | - vec4 y = textureGrad(sam, bip.uv2, bip.d2x, bip.d2y); |
37 | | - return (x * bip.w.x + y * bip.w.y) * bip.div; |
| 41 | + vec4 v1 = textureGrad(sam, bip.uv1, bip.dx1, bip.dy1); |
| 42 | + vec4 v2 = textureGrad(sam, bip.uv2, bip.dx2, bip.dy2); |
| 43 | + return v1 * bip.w[0] + v2 * bip.w[1]; |
38 | 44 | } |
39 | 45 |
|
40 | 46 | vec4 biplanarSample(sampler2DArray sam, Biplanar bip, float arrayIndex) |
41 | 47 | { |
42 | | - vec4 x = textureGrad(sam, vec3(bip.uv1, arrayIndex), bip.d1x, bip.d1y); |
43 | | - vec4 y = textureGrad(sam, vec3(bip.uv2, arrayIndex), bip.d2x, bip.d2y); |
44 | | - return (x * bip.w.x + y * bip.w.y) * bip.div; |
| 48 | + vec4 v1 = textureGrad(sam, vec3(bip.uv1, arrayIndex), bip.dx1, bip.dy1); |
| 49 | + vec4 v2 = textureGrad(sam, vec3(bip.uv2, arrayIndex), bip.dx2, bip.dy2); |
| 50 | + return v1 * bip.w[0] + v2 * bip.w[1]; |
| 51 | +} |
| 52 | + |
| 53 | +vec3 egacBiplanarNormal(Biplanar bip, vec3 n1, vec3 n2) |
| 54 | +{ |
| 55 | + // https://bgolus.medium.com/normal-mapping-for-a-triplanar-shader-10bf39dca05a |
| 56 | + // whiteout blend |
| 57 | + n1.x *= -1; |
| 58 | + n2.x *= -1; |
| 59 | + n1 = vec3(n1.xy + vec2(bip.normal[bip.a1.z], bip.normal[bip.a1.y]), abs(n1.z) * bip.normal[bip.a1.x]); |
| 60 | + n2 = vec3(n2.xy + vec2(bip.normal[bip.a2.z], bip.normal[bip.a2.y]), abs(n2.z) * bip.normal[bip.a2.x]); |
| 61 | + n1 = vec3(n1[bip.a1.z], n1[bip.a1.y], n1[bip.a1.x]); |
| 62 | + n2 = vec3(n2[bip.a2.z], n2[bip.a2.y], n2[bip.a2.x]); |
| 63 | + return n1 * bip.w[0] + n2 * bip.w[1]; |
45 | 64 | } |
46 | 65 |
|
47 | | -vec3 biplanarSampleNormal(sampler2D sam, Biplanar bip, vec3 normal) |
| 66 | +vec3 biplanarSampleNormal(sampler2D sam, Biplanar bip) |
48 | 67 | { |
49 | | - vec3 n1 = restoreNormalMap(textureGrad(sam, bip.uv1, bip.d1x, bip.d1y)); |
50 | | - vec3 n2 = restoreNormalMap(textureGrad(sam, bip.uv2, bip.d2x, bip.d2y)); |
51 | | - mat3 tbn = makeTangentSpace(normal, varPosition - uniViewport.eyePos.xyz, bip.uv1); |
52 | | - n1 = tbn * n1; |
53 | | - tbn = makeTangentSpace(normal, varPosition - uniViewport.eyePos.xyz, bip.uv2); |
54 | | - n2 = tbn * n2; |
55 | | - return normalize(n1 * bip.w.x + n2 * bip.w.y); |
| 68 | + vec3 n1 = restoreNormalMap(textureGrad(sam, bip.uv1, bip.dx1, bip.dy1)); |
| 69 | + vec3 n2 = restoreNormalMap(textureGrad(sam, bip.uv2, bip.dx2, bip.dy2)); |
| 70 | + return egacBiplanarNormal(bip, n1, n2); |
56 | 71 | } |
57 | 72 |
|
58 | | -vec3 biplanarSampleNormal(sampler2DArray sam, Biplanar bip, vec3 normal, float arrayIndex) |
| 73 | +vec3 biplanarSampleNormal(sampler2DArray sam, Biplanar bip, float arrayIndex) |
59 | 74 | { |
60 | | - vec3 n1 = restoreNormalMap(textureGrad(sam, vec3(bip.uv1, arrayIndex), bip.d1x, bip.d1y)); |
61 | | - vec3 n2 = restoreNormalMap(textureGrad(sam, vec3(bip.uv2, arrayIndex), bip.d2x, bip.d2y)); |
62 | | - mat3 tbn = makeTangentSpace(normal, varPosition - uniViewport.eyePos.xyz, bip.uv1); |
63 | | - n1 = tbn * n1; |
64 | | - tbn = makeTangentSpace(normal, varPosition - uniViewport.eyePos.xyz, bip.uv2); |
65 | | - n2 = tbn * n2; |
66 | | - return normalize(n1 * bip.w.x + n2 * bip.w.y); |
| 75 | + vec3 n1 = restoreNormalMap(textureGrad(sam, vec3(bip.uv1, arrayIndex), bip.dx1, bip.dy1)); |
| 76 | + vec3 n2 = restoreNormalMap(textureGrad(sam, vec3(bip.uv2, arrayIndex), bip.dx2, bip.dy2)); |
| 77 | + return egacBiplanarNormal(bip, n1, n2); |
67 | 78 | } |
0 commit comments