title: Normal estimation of signed distance function just won't work
body: <p>I'm trying to create a compute shader in Unity that performs raymarching. So far I have an SDF of a box and a ray generation / marching function all of which seems to work fine:</p>
  <pre class="lang-c prettyprint-override"><code>struct Ray {
      float3 position;
      float3 direction;
  };
  
  Ray CreateCameraRay(float2 uv) {
      Ray ray;
      ray.position = mul(CameraToWorld, float4(0, 0, 0, 1)).xyz;
      ray.direction = mul(CameraInverseProjection, float4(uv, 0, 1)).xyz;
      ray.direction = mul(CameraToWorld, float4(ray.direction, 0)).xyz;
      ray.direction = normalize(ray.direction);
      return ray;
  }
  
  float sdf_box (float3 p)
  {
      float3 c = float3(0.0f, 0.0f, 0.0f);
      float3 s = float3(1.0f, 1.0f, 1.0f);
      float x = max
      (   p.x - c.x - float3(s.x / 2., 0, 0),
          c.x - p.x - float3(s.x / 2., 0, 0)
      );
      float y = max
      (   p.y - c.y - float3(s.y / 2., 0, 0),
          c.y - p.y - float3(s.y / 2., 0, 0)
      );
      
      float z = max
      (   p.z - c.z - float3(s.z / 2., 0, 0),
          c.z - p.z - float3(s.z / 2., 0, 0)
      );
      float d = x;
      d = max(d,y);
      d = max(d,z);
      return d;
  }
  
  [numthreads(32,32,1)]
  void CSMain (uint3 id : SV_DispatchThreadID)
  {
      uint width, height;
      Result.GetDimensions(width, height);
      float2 uv = id.xy / float2(width, height) * 2.0 - 1.0;
      Ray ray = CreateCameraRay(uv);
  
      float4 colour = float4(0, 0, 0, 0);
      bool cont = true;
      int step = 0;
  
      while (cont) {
          step++;
          float dist = sdf_box(ray.position);
          ray.position += ray.direction * dist;
          if (dist &lt; 0.01f) {
              colour = float4(ray.position, 0.0f);
          }
          cont = (dist &gt; 0.01f) &amp;&amp; (step &lt; 500);
      }
  
      Result[id.xy] = colour;
  }
  </code></pre>
  <p>The above code generates the following image:</p>
  <p><a href="https://i.stack.imgur.com/rB2ao.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rB2ao.png" alt="Successfully rendering a cube" /></a></p>
  <p>The next step is to add a bit of lighting. To do this I need a surface normal function, which I've defined as:</p>
  <pre class="lang-c prettyprint-override"><code>float EPSILON = 0.001f;
  float3 normal(float3 p) {
      float2 e = float2(EPSILON, 0);
      return normalize(float3(
          sdf_box(p + e.xyy) - sdf_box(p + e.xyy),
          sdf_box(p + e.yxy) - sdf_box(p + e.yxy),
          sdf_box(p + e.yyx) - sdf_box(p + e.yyx))
      );
  }
  </code></pre>
  <p>Now, to check that the normal function is working properly I decided to draw the normal of each contact point on the box (by replacing <code>colour = float4(ray.position, 0.0f);</code> with <code>colour = float4(normal(ray.position), 0.0f)</code>. What I'm expecting is for 3 of the 6 face of the cube to be coloured red, green and blue (i.e. the top face should be green as it has a normal of (0, 1, 0)). However, what I get instead is a totally black cube:
  <a href="https://i.stack.imgur.com/ezqgE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ezqgE.png" alt="broken cube" /></a></p>
  <p>This seems wrong. The <code>normalize()</code> should mean that there is at least some colour if the normal generated is non-zero, which suggests to me that the normal of all the points is just (0, 0, 0). But this can't be right because nowhere in or on the cube has a surface normal of 0 (other than the centre point).</p>
  <p>I've now tried 4 different normal evaluation functions which I've found online, NONE of which work. I'm seriously questioning my sanity at this point.</p>