<p>I'm writing a raytracer in Java that draws a scene containing the elliptic paraboloid defined by the equation <span class="math-container">$F(x,y,z)=x^2+z^2-y=0$</span>, as well as the hyperbolic paraboloid defined by <span class="math-container">$G(x,y,z)=x^2-z^2-y=0$</span>.</p>
<p>To compute the surface normal to this, I'm taking the normalized gradients of the equations:
<span class="math-container">$\vec{\nabla} F(x,y,z) = \left&lt;2x, -1, 2z\right&gt;\\
\vec{\nabla} G(x,y,z) = \left&lt;2x, -1, -2z\right&gt;$</span>.</p>
<p>To ensure that the normal is on the correct surface, I take the dot product with the incident ray and flip the normal if the dot product is negative.</p>
<p>However, when I render the image, I observe this strange outline around the object:</p>
<p><a href="https://i.sstatic.net/HBdQO.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/HBdQO.png" alt="enter image description here" /></a></p>
<p>I can tell that this is a normal-related issue because when I color the objects based on their normals, I can see discontinuities:</p>
<p><a href="https://i.sstatic.net/e4eDF.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/e4eDF.png" alt="enter image description here" /></a></p>
<p>I have no idea why this is, but I believe it has something to do with rounding errors during this sign-change step. I'm not sure why this would be though; I'm using double-precision floating-point  numbers (Java's <code>double</code> type) for all calculations. When I remove this check, the normals are broken, but the outline disappears. How might I be able to fix this?</p>
<p>Here's where the normal is computed:</p>
<pre class="lang-java prettyprint-override"><code>Vec3 dP = pt.sub(pos);
Vec3 normal = new Vec3(2 * dP.x, -1, 2 * dP.z)
       .getNormalized()
       .faceForward(ray.rd);
</code></pre>
<p>where <code>pos</code> is the object's local position, and <code>ray.rd</code> is the ray's direction.</p>
<p>Here's the code responsible for the check (the <code>faceForward</code> function in the above code):</p>
<pre class="lang-java prettyprint-override"><code>public Vec3 faceForward(Vec3 incident) {
    boolean outside = (this.dot(incident) &lt; 0);
    return (outside ? this : this.negate());
}
</code></pre>

CC BY-SA 4.0
2023-08-25T01:33:27.237Z
You can add the results without the check. Also, if you think this is caused by rounding errors then you can verify by simply change to `this.dot(incident) < 0` to something like `this.dot(incident) < 1e-4` to see if anything changes.
Enigmatisms
<raytracing>
Precision errors with raytracing normal
zenzicubic
# Precision errors with raytracing normal

(Asked by: username_0 on 2023-08-24)

I'm writing a raytracer in Java that draws a scene containing the elliptic paraboloid defined by the equation $F(x,y,z)=x^2+z^2-y=0$, as well as the hyperbolic paraboloid defined by $G(x,y,z)=x^2-z^2-y=0$.
To compute the surface normal to this, I'm taking the normalized gradients of the equations:
$\vec{\nabla} F(x,y,z) = \left<2x, -1, 2z\right>\\
\vec{\nabla} G(x,y,z) = \left<2x, -1, -2z\right>$.
To ensure that the normal is on the correct surface, I take the dot product with the incident ray and flip the normal if the dot product is negative.
However, when I render the image, I observe this strange outline around the object:

I can tell that this is a normal-related issue because when I color the objects based on their normals, I can see discontinuities:

I have no idea why this is, but I believe it has something to do with rounding errors during this sign-change step. I'm not sure why this would be though; I'm using double-precision floating-point  numbers (Java's double type) for all calculations. When I remove this check, the normals are broken, but the outline disappears. How might I be able to fix this?
Here's where the normal is computed:
Vec3 dP = pt.sub(pos);
Vec3 normal = new Vec3(2 * dP.x, -1, 2 * dP.z)
       .getNormalized()
       .faceForward(ray.rd);

where pos is the object's local position, and ray.rd is the ray's direction.
Here's the code responsible for the check (the faceForward function in the above code):
public Vec3 faceForward(Vec3 incident) {
    boolean outside = (this.dot(incident) < 0);
    return (outside ? this : this.negate());
}

**Tags:** raytracing
> **Comments:**
> **username_1**: You can add the results without the check. Also, if you think this is caused by rounding errors then you can verify by simply change to `this.dot(incident) < 0` to something like `this.dot(incident) < 1e-4` to see if anything changes.  

---

## 0 answers

