Advertisement
Calneon

Eikonal 3D implementation

Dec 18th, 2021
1,924
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. float neighborMin(float3 uv, float3 delta)
  2. {
  3.     float a = unpack(sdfSample(uv + delta));
  4.     float b = unpack(sdfSample(uv - delta));
  5.     return min(abs(a), abs(b));
  6. }
  7.  
  8. float eikonal1d(float h, float v, float g)
  9. {
  10.     return min(h, v) + g;
  11. }
  12.  
  13. float eikonal2d(float h, float v, float g)
  14. {
  15.     if (abs(h - v) >= g)
  16.     {
  17.         return eikonal1d(h, v, g);
  18.     }
  19.     else
  20.     {
  21.         float hv = h + v;
  22.         float d = hv * hv - 2.0 * (h * h + v * v - g * g);
  23.         return 0.5 * (hv + sqrt(d));
  24.     }
  25. }
  26.  
  27. bool eikonal3d(float3 u, out float e, float g)
  28. {
  29.     float xyz = u.x + u.y + u.z;
  30.     float n = 3.0;
  31.     float d = (xyz * xyz) - n * ((u.x * u.x + u.y * u.y + u.z * u.z) - (g * g));
  32.     if (d < 0.0)
  33.     {
  34.         return false;
  35.     }
  36.     else
  37.     {
  38.         e = (1.0 / n) * (xyz + sqrt(d));
  39.         return true;
  40.     }
  41. }
  42.  
  43. float eikonal(float3 u, float g)
  44. {
  45.     // 3d
  46.     float e = 0.0;
  47.     if (eikonal3d(u, e, g))
  48.     {
  49.         return e;
  50.     }
  51.     else
  52.     {
  53.         // 2d
  54.         float e1 = eikonal2d(u.x, u.y, g);
  55.         float e2 = eikonal2d(u.x, u.z, g);
  56.         float e3 = eikonal2d(u.y, u.z, g);
  57.         return min(min(e1, e2), e3);
  58.     }
  59. }
  60.  
  61. [numthreads(8, 8, 8)]
  62. void SDFFix(uint3 id : SV_DispatchThreadID)
  63. {
  64.     float3 kernel = float3(float(id.x), float(id.y), float(id.z));
  65.     float3 sdfSize = float3(float(_sdfTexSizeX), float(_sdfTexSizeY), float(_sdfTexSizeZ));
  66.     float3 uv = (kernel + float3(0.5, 0.5, 0.5)) / sdfSize;
  67.     float3 worldPos = (uv - float3(0.5, 0.5, 0.5)) * _sdfRadius * 2.0;
  68.     float current = unpack(sdfSample(uv));
  69.  
  70.     float3 u;
  71.     u.x = neighborMin(uv, float3(1.0 / _sdfTexSizeX, 0.0, 0.0));
  72.     u.y = neighborMin(uv, float3(0.0, 1.0 / _sdfTexSizeY, 0.0));
  73.     u.z = neighborMin(uv, float3(0.0, 0.0, 1.0 / _sdfTexSizeZ));
  74.  
  75.     float g = (_sdfRadius * 2.0) / _sdfTexSizeX;
  76.     float e = eikonal(u, g);
  77.  
  78.     if (current > g) current = e;
  79.  
  80.     _sdfTexOut[id.xyz] = pack(current);
  81. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement