Calneon

Eikonal 2D implementation

Aug 4th, 2021 (edited)
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.08 KB | None | 0 0
  1. #pragma kernel SDF2D
  2.  
  3. Texture2D<float> _sdfTexIn;
  4. SamplerState sampler_sdfTexIn;
  5. RWTexture2D<float> _sdfTexOut;
  6. uint _sdfTexSizeX;
  7. uint _sdfTexSizeY;
  8. float _sdfDistMod;
  9. uint _frame;
  10.  
  11. float2 _mousePos;
  12. bool _leftClick;
  13. bool _rightClick;
  14. bool _midClickPress;
  15. bool _midClickDown;
  16. bool _rPressed;
  17.  
  18. static const float MAXDIST = 1024.0;
  19.  
  20. float pack(float dist)
  21. {
  22. dist = min(dist, MAXDIST) / MAXDIST;
  23. dist /= _sdfDistMod;
  24. dist = dist * 0.5 + 0.5;
  25. return clamp(dist, 0.0, 1.0);
  26. }
  27.  
  28. float unpack(float dist)
  29. {
  30. dist = dist * 2.0 - 1.0;
  31. dist *= _sdfDistMod;
  32. dist *= MAXDIST;
  33. return dist;
  34. }
  35.  
  36. float2 toUV(float2 pos)
  37. {
  38. return float2(pos.x / _sdfTexSizeX, pos.y / _sdfTexSizeY);
  39. }
  40.  
  41. float sdSphere(float2 uv, float2 pos, float radius)
  42. {
  43. uv -= pos;
  44. return length(uv) - radius;
  45. }
  46.  
  47. float sdBox(float2 uv, float2 pos, float2 b)
  48. {
  49. uv -= pos;
  50. float2 d = abs(uv) - b;
  51. return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
  52. }
  53.  
  54. float opSub(float d1, float d2)
  55. {
  56. return max(d1, -d2);
  57. }
  58.  
  59. float opAdd(float d1, float d2)
  60. {
  61. return min(d1, d2);
  62. }
  63.  
  64. float sdf(float2 pos)
  65. {
  66. return _sdfTexIn.SampleLevel(sampler_sdfTexIn, toUV(pos), 0);
  67. }
  68.  
  69. float neighborMin(float2 uv, float2 delta)
  70. {
  71. float a = unpack(sdf(uv + delta));
  72. float b = unpack(sdf(uv - delta));
  73. return min(abs(a), abs(b));
  74. }
  75.  
  76. float eikonal1d(float h, float v, float g)
  77. {
  78. return min(h, v) + g;
  79. }
  80.  
  81. float eikonal2d(float h, float v, float g)
  82. {
  83. float hv = h + v;
  84. float d = hv * hv - 2.0 * (h * h + v * v - g * g);
  85. return 0.5 * (hv + sqrt(d));
  86. }
  87.  
  88. [numthreads(8, 8, 1)]
  89. void SDF2D(uint2 id : SV_DispatchThreadID)
  90. {
  91. float2 uv = float2(float(id.x), float(id.y)) + float2(0.5, 0.5);
  92. float current = unpack(sdf(uv));
  93.  
  94. if (_frame == 0 || _rPressed)
  95. {
  96. current = sdBox(uv, float2(-10.0, 128.0), float2(10.0, 256.0));
  97. current = opAdd(current, sdBox(uv, float2(266.0, 128.0), float2(10.0, 256.0)));
  98. current = opAdd(current, sdBox(uv, float2(128.0, -10.0), float2(256.0, 10.0)));
  99. current = opAdd(current, sdBox(uv, float2(128.0, 266.0), float2(256.0, 10.0)));
  100. }
  101. if (_leftClick)
  102. {
  103. float s = sdSphere(uv, float2(_mousePos.x, _mousePos.y), 25.0);
  104. current = opAdd(current, s);
  105. }
  106. if (_rightClick)
  107. {
  108. float s = sdSphere(uv, float2(_mousePos.x, _mousePos.y), 15.0);
  109. current = opSub(current, s);
  110. }
  111. //if (_midClickPress)
  112. //{
  113. // if (current > 1.0)
  114. // {
  115. // current = MAXDIST;
  116. // }
  117. // if (current < -1.0)
  118. // {
  119. // current = -MAXDIST;
  120. // }
  121. //}
  122. if (_midClickDown)
  123. {
  124. float c = abs(current);
  125. float h = neighborMin(uv, float2(1.0, 0.0));
  126. float v = neighborMin(uv, float2(0.0, 1.0));
  127.  
  128. float e = (abs(h - v) >= 1.0) ?
  129. eikonal1d(h, v, 1.0) :
  130. eikonal2d(h, v, 1.0);
  131.  
  132. if (c > 1.0) c = e;
  133. current = sign(current) * c;
  134. }
  135.  
  136. _sdfTexOut[id.xy] = pack(current);
  137. }
Add Comment
Please, Sign In to add comment