<p>When spawning the refraction/transmission ray, don't adjust the ray origin by adding the normal: adjust it by <em>subtracting</em> the normal. This moves the ray origin inside the object, so it won't immediately self-intersect. Your current problem is caused by all your refraction rays immediately hitting the surface.</p>

<p>Don't forget that for accurate refractions, the ray needs to be able to intersect with the inside or back face of the object as well. If you're intersecting back-facing surfaces, you need to flip the normal before shading or adding/subtracting it to the origin.</p>

CC BY-SA 4.0
2018-07-10T09:32:54.727Z
2018-07-10T09:32:54.727Z
Dan Hulme
<p>I am getting weird artifacts in my simple ray tracer that I made using the book <a href="https://rads.stackoverflow.com/amzn/click/B01B5AODD8" rel="nofollow noreferrer">Ray Tracing in One Weekend</a> by Peter Shirley. </p>

<p>Example:</p>

<p><a href="https://i.sstatic.net/3Gl6W.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/3Gl6W.png" alt="enter image description here"></a>
(circular pattern on the ground and black tint on the spheres.)</p>

<p>I suspect these artifacts are due to hit point of the primary rays being under or above the surface, which causes secondary rays to intersect with the object itself. </p>

<p>I tried to fix this by moving the hit point of primary rays along the surface normal at that point. Here's the result :</p>

<p><a href="https://i.sstatic.net/bjk8e.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/bjk8e.png" alt="enter image description here"></a>  </p>

<p>The artifacts are gone but that broke the dielectric material (sphere on the left). It is acting as a reflective sphere rather than a transparent one. </p>

<p>Code for the dielectric material :</p>

<pre><code>virtual bool scatter(const Ray &amp;inRay, const HitInfo &amp;hitInfo, Vector3 &amp;attenuation, Ray &amp;scatteredRay) const {
    attenuation = Vector3(1.0f);
    Vector3 normal;
    Vector3 refracted;
    float refractiveIndexRatio; //n1/n2 = sin(a2)/sin(a)
    float cosine = 0.0f;

    if (hitInfo.hitNormal * inRay.direction() &gt; 0) {
        normal = -hitInfo.hitNormal;
        refractiveIndexRatio = refractiveIndex;
        cosine = hitInfo.hitNormal * inRay.direction();
    }
    else {
        normal = hitInfo.hitNormal;
        refractiveIndexRatio = 1.0f/refractiveIndex;
        cosine = -hitInfo.hitNormal * inRay.direction();
    }


    float reflectProb = 0.0f;

    if (Vector3::refract(inRay.direction(), normal, refractiveIndexRatio, refracted)) {
        reflectProb = schlickApproximation(cosine, refractiveIndex);
    }
    else {
        reflectProb = 1.0f;
    }

    if (randomfloatGenerator() &lt; reflectProb) {
        Vector3 reflected(Vector3::reflect(inRay.direction(), normal));
        scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, reflected);
    }
    else {
        scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, refracted);
    }

    return true;
}
</code></pre>

<p>I changed <code>hitInfo.hitPoint</code> to <code>hitInfo.hitPoint + normal * CORRECTION_FACTOR</code>, in the <code>if - else</code> case at the bottom of the function, to correct those artifacts. (<code>CORRECTION_FACTOR = 0.0001f</code>)  </p>

<p>How can I correct this "self intersection" problem without breaking my materials ?</p>

CC BY-SA 4.0
2018-07-10T09:12:31.327Z
FWIW the self-intersection problem is sometimes referred to as (surface) acne. That might help with searching for solutions, e.g. : https://graphics.stanford.edu/pub/Graphics/RTNews/html/rtnews2c.html
Simon F
<rendering><raytracing><c++>
Weird artifacts in my ray tracer
user9002
# Weird artifacts in my ray tracer

(Asked by: username_0 on 2018-07-10)

I am getting weird artifacts in my simple ray tracer that I made using the book [Ray Tracing in One Weekend](https://rads.stackoverflow.com/amzn/click/B01B5AODD8) by Peter Shirley.

Example:

[![enter image description here](https://i.sstatic.net/3Gl6W.png)](https://i.sstatic.net/3Gl6W.png)
(circular pattern on the ground and black tint on the spheres.)

I suspect these artifacts are due to hit point of the primary rays being under or above the surface, which causes secondary rays to intersect with the object itself.

I tried to fix this by moving the hit point of primary rays along the surface normal at that point. Here's the result :

[![enter image description here](https://i.sstatic.net/bjk8e.png)](https://i.sstatic.net/bjk8e.png)

The artifacts are gone but that broke the dielectric material (sphere on the left). It is acting as a reflective sphere rather than a transparent one.

Code for the dielectric material :

```
virtual bool scatter(const Ray &inRay, const HitInfo &hitInfo, Vector3 &attenuation, Ray &scatteredRay) const {
    attenuation = Vector3(1.0f);
    Vector3 normal;
    Vector3 refracted;
    float refractiveIndexRatio; //n1/n2 = sin(a2)/sin(a)
    float cosine = 0.0f;

    if (hitInfo.hitNormal * inRay.direction() > 0) {
        normal = -hitInfo.hitNormal;
        refractiveIndexRatio = refractiveIndex;
        cosine = hitInfo.hitNormal * inRay.direction();
    }
    else {
        normal = hitInfo.hitNormal;
        refractiveIndexRatio = 1.0f/refractiveIndex;
        cosine = -hitInfo.hitNormal * inRay.direction();
    }

    float reflectProb = 0.0f;

    if (Vector3::refract(inRay.direction(), normal, refractiveIndexRatio, refracted)) {
        reflectProb = schlickApproximation(cosine, refractiveIndex);
    }
    else {
        reflectProb = 1.0f;
    }

    if (randomfloatGenerator() < reflectProb) {
        Vector3 reflected(Vector3::reflect(inRay.direction(), normal));
        scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, reflected);
    }
    else {
        scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, refracted);
    }

    return true;
}

```

I changed `hitInfo.hitPoint` to `hitInfo.hitPoint + normal * CORRECTION_FACTOR`, in the `if - else` case at the bottom of the function, to correct those artifacts. (`CORRECTION_FACTOR = 0.0001f`)

How can I correct this "self intersection" problem without breaking my materials ?

**Tags:** rendering, raytracing, c++

> **Comments:**
> **username_1**: FWIW the self-intersection problem is sometimes referred to as (surface) acne. That might help with searching for solutions, e.g. : https://graphics.stanford.edu/pub/Graphics/RTNews/html/rtnews2c.html  

---

## 1 answers

### Answer by username_2 on 2018-07-10. Score: 3 | Accepted answer

When spawning the refraction/transmission ray, don't adjust the ray origin by adding the normal: adjust it by *subtracting* the normal. This moves the ray origin inside the object, so it won't immediately self-intersect. Your current problem is caused by all your refraction rays immediately hitting the surface.

Don't forget that for accurate refractions, the ray needs to be able to intersect with the inside or back face of the object as well. If you're intersecting back-facing surfaces, you need to flip the normal before shading or adding/subtracting it to the origin.


---

