<p>So this does in fact seem to be a self-collision issue. I was able to determine this by giving each triangle/sphere an ID and filtering that ID out when checking collisions. </p>

CC BY-SA 4.0
2018-08-26T23:20:55.320Z
2018-08-26T23:20:55.320Z
Cluny
<p>I've been working on a new ray tracer recently, but after adding reflections I'm seeing these strange small highlights on my models, particularly on the ear of the silver rabbit below. </p>

<p>I've read that these can be caused by my reflection rays re-colliding with the object they're reflection from, but I believe I'm properly accounting for this by slightly translating the outgoing rays away from the intersect point. They also seem to consistently occur on the same parts of the model (the ears, and "creases") regardless of the scene. I am taking 8 random samples per pixel, which seems to help a bit, but not entirely.</p>

<p>Any thoughts on what could be causing this? is it possible that I'm simply not taking enough samples or structuring them well enough? </p>

<p><a href="https://i.sstatic.net/eirtt.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/eirtt.png" alt="Rendering"></a></p>

<p><strong>EDIT:</strong> </p>

<p>I've added the code for my recursive coloring/reflectance function and my shadow function below, sorry if it's messy</p>

<pre><code>public Color getIntersectColor(Scene theScene, Vector3D theNormal, Vector3D theIntersectPoint, Vector3D theRay, int aDepth)
{
    // Initialize to ambient colors
    double aRed = myKa * myDiffuseColor.getDecimalRed();
    double aBlue = myKa * myDiffuseColor.getDecimalBlue();
    double aGreen = myKa * myDiffuseColor.getDecimalGreen();

    final Color aColor = new Color(aRed, aGreen, aBlue);

    theScene.getLights().parallelStream().forEach(theLight -&gt;
    {
        Vector3D L = theLight.getL(theIntersectPoint);
        Vector3D V = theScene.getCamera().getPosition().subtract(theIntersectPoint).normalize();
        Vector3D H = L.add(V).scale((1.0 / (L.add(V).getLength()))).normalize();

        Color aLC = theLight.getColor();
        Double aI = Math.abs(theNormal.dot(L));
        Double aR = Math.abs(theNormal.dot(H));

       double aLightDistance = theLight.getDistance(theIntersectPoint);

       double aShadow = 1.0;

       if (hasShadows)
       {
           aShadow = getShadow(theIntersectPoint, L, aLightDistance, theScene);
       }

        double aR = aLC.getDecimalRed() * aShadow *
                                  ((myKd * myDiffuseColor.getDecimalRed() * aI) +
                                      (myKs * mySpecularColor.getDecimalRed() * (Math.pow(aR, myShininess)))
                                  );

        double aG = aLC.getDecimalGreen() * aShadow *
                                    ((myKd * myDiffuseColor.getDecimalGreen() * aI) +
                                        (myKs * mySpecularColor.getDecimalGreen() * (Math.pow(aR, myShininess)))
                                    );

        double aB = aLC.getDecimalBlue() * aShadow *
                                    ((myKd * myDiffuseColor.getDecimalBlue() * aI) +
                                        (myKs * mySpecularColor.getDecimalBlue() * (Math.pow(aR, myShininess)))
                                    );

        aColor.setRed(aColor.getDecimalRed() + aR);
        aColor.setBlue(aColor.getDecimalBlue() + aB);
        aColor.setGreen(aColor.getDecimalGreen() + aG);

        if (isReflective &amp;&amp; aDepth &gt; 0)
        {
            double aReflectionAngle = theRay.dot(theNormal);

            Vector3D aReflectionVector = theRay.subtract(theNormal.scale(2.0 * aReflectionAngle)).normalize();

            double F0 = ((myIndexOfRefraction - 1)  /(1 + myIndexOfRefraction)) *
                    ((myIndexOfRefraction - 1) / (1 + myIndexOfRefraction));

            double FR = F0 + (1 - F0) * ((1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle)) *
                                         (1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle))
                                            * (1 - Math.cos(aReflectionAngle)));

            Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));

            Color aRefColor = theScene.getKDFilteredObjects(aReflectionVector, anAdjustedIntersect)
                .parallelStream()
                .unordered()
                .map(thePObject -&gt; new Pair&lt;&gt;(thePObject, thePObject.intersects(aReflectionVector, anAdjustedIntersect)))
                .filter(thePair -&gt; thePair.getValue() != null)
                .reduce((thePair, theOtherPair) -&gt; thePair.getValue() &gt;= theOtherPair.getValue() ? theOtherPair : thePair)
                .map(theIntersect -&gt;
                {
                    Vector3D aIntersectPoint = theIntersectPoint.add(aReflectionVector.scale(theIntersect.getValue()));
                    return theIntersect.getKey().getMaterial().getIntersectColor(theScene, theIntersect.getKey().getIntersectNormal(aIntersectPoint), aIntersectPoint, aReflectionVector, aDepth - 1);
                })
                .orElse(theScene.getBackgroundColor());

            aColor.setRed(aColor.getDecimalRed() + (FR * aRefColor.getDecimalRed()));
            aColor.setBlue(aColor.getDecimalBlue() + (FR * aRefColor.getDecimalBlue()));
            aColor.setGreen(aColor.getDecimalGreen() + (FR * aRefColor.getDecimalGreen()));
        }
    });

    return aColor;
}

// TODO: factor in opacity
public double getShadow(Vector3D theOrigin, Vector3D theLightDirection, double theLightDistance, Scene theScene)
{
    // Avoid self-collision
    Vector3D aAdjustedOrigin = theOrigin.add(theLightDirection.scale(.00001));

    return theScene.getKDFilteredObjects(theLightDirection, aAdjustedOrigin)
            .parallelStream()
            .unordered()
            .map(theObject -&gt; theObject.intersects(theLightDirection, aAdjustedOrigin))
            .filter(Objects::nonNull)
            .filter(theT -&gt; theT &gt; 0 &amp;&amp; theT &lt; theLightDistance)
            .findAny()
            .map(theT -&gt; 0.0)
            .orElse(1.0);
}
</code></pre>

CC BY-SA 4.0
2018-08-23T07:09:13.840Z
Are your triangles one sided? Your artefacts looks a lot like rays starting inside of a 1 sided triangle mesh, which usually occur were were you get AO, because of the V channels and your epsilon method it is easier to penetrate the surface and start a ray inside the mesh. If you are using 1 sided triangles then you can make them 2 sided so any rays starting from the inside get trapped in there and contribute something useful to AO :)
PaulHK
CC BY-SA 4.0
2018-08-23T14:48:24.897Z
**I'm properly accounting for this by slightly translating the outgoing rays** How do you offset your ray origins? Do you use an absolute or relative offset along the ray?
Matthias
CC BY-SA 4.0
2018-08-23T19:49:33.150Z
As there is more than one possible cause for these artefacts, it would help answerers to be able to see your code. Are you happy to include it here?
trichoplax is on Codidact now
CC BY-SA 4.0
2018-08-23T22:57:48.153Z
@Matthias added code, i'm current translating like this `Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));`  
---
@trichoplax I've added my code to the original post, sorry if it's a little hard to follow, it's kind of a first pass.  
---
@PaulHK I thought that I was, I will double check my intersection code to make sure
Cluny
<raytracing><rendering>
Bright artifacts in ray tracer rendering seemingly caused by reflections
Cluny
# Bright artifacts in ray tracer rendering seemingly caused by reflections

(Asked by: username_0 on 2018-08-23)

I've been working on a new ray tracer recently, but after adding reflections I'm seeing these strange small highlights on my models, particularly on the ear of the silver rabbit below.

I've read that these can be caused by my reflection rays re-colliding with the object they're reflection from, but I believe I'm properly accounting for this by slightly translating the outgoing rays away from the intersect point. They also seem to consistently occur on the same parts of the model (the ears, and "creases") regardless of the scene. I am taking 8 random samples per pixel, which seems to help a bit, but not entirely.

Any thoughts on what could be causing this? is it possible that I'm simply not taking enough samples or structuring them well enough?

[![Rendering](https://i.sstatic.net/eirtt.png)](https://i.sstatic.net/eirtt.png)

**EDIT:**

I've added the code for my recursive coloring/reflectance function and my shadow function below, sorry if it's messy

```
public Color getIntersectColor(Scene theScene, Vector3D theNormal, Vector3D theIntersectPoint, Vector3D theRay, int aDepth)
{
    // Initialize to ambient colors
    double aRed = myKa * myDiffuseColor.getDecimalRed();
    double aBlue = myKa * myDiffuseColor.getDecimalBlue();
    double aGreen = myKa * myDiffuseColor.getDecimalGreen();

    final Color aColor = new Color(aRed, aGreen, aBlue);

    theScene.getLights().parallelStream().forEach(theLight ->
    {
        Vector3D L = theLight.getL(theIntersectPoint);
        Vector3D V = theScene.getCamera().getPosition().subtract(theIntersectPoint).normalize();
        Vector3D H = L.add(V).scale((1.0 / (L.add(V).getLength()))).normalize();

        Color aLC = theLight.getColor();
        Double aI = Math.abs(theNormal.dot(L));
        Double aR = Math.abs(theNormal.dot(H));

       double aLightDistance = theLight.getDistance(theIntersectPoint);

       double aShadow = 1.0;

       if (hasShadows)
       {
           aShadow = getShadow(theIntersectPoint, L, aLightDistance, theScene);
       }

        double aR = aLC.getDecimalRed() * aShadow *
                                  ((myKd * myDiffuseColor.getDecimalRed() * aI) +
                                      (myKs * mySpecularColor.getDecimalRed() * (Math.pow(aR, myShininess)))
                                  );

        double aG = aLC.getDecimalGreen() * aShadow *
                                    ((myKd * myDiffuseColor.getDecimalGreen() * aI) +
                                        (myKs * mySpecularColor.getDecimalGreen() * (Math.pow(aR, myShininess)))
                                    );

        double aB = aLC.getDecimalBlue() * aShadow *
                                    ((myKd * myDiffuseColor.getDecimalBlue() * aI) +
                                        (myKs * mySpecularColor.getDecimalBlue() * (Math.pow(aR, myShininess)))
                                    );

        aColor.setRed(aColor.getDecimalRed() + aR);
        aColor.setBlue(aColor.getDecimalBlue() + aB);
        aColor.setGreen(aColor.getDecimalGreen() + aG);

        if (isReflective && aDepth > 0)
        {
            double aReflectionAngle = theRay.dot(theNormal);

            Vector3D aReflectionVector = theRay.subtract(theNormal.scale(2.0 * aReflectionAngle)).normalize();

            double F0 = ((myIndexOfRefraction - 1)  /(1 + myIndexOfRefraction)) *
                    ((myIndexOfRefraction - 1) / (1 + myIndexOfRefraction));

            double FR = F0 + (1 - F0) * ((1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle)) *
                                         (1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle))
                                            * (1 - Math.cos(aReflectionAngle)));

            Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));

            Color aRefColor = theScene.getKDFilteredObjects(aReflectionVector, anAdjustedIntersect)
                .parallelStream()
                .unordered()
                .map(thePObject -> new Pair<>(thePObject, thePObject.intersects(aReflectionVector, anAdjustedIntersect)))
                .filter(thePair -> thePair.getValue() != null)
                .reduce((thePair, theOtherPair) -> thePair.getValue() >= theOtherPair.getValue() ? theOtherPair : thePair)
                .map(theIntersect ->
                {
                    Vector3D aIntersectPoint = theIntersectPoint.add(aReflectionVector.scale(theIntersect.getValue()));
                    return theIntersect.getKey().getMaterial().getIntersectColor(theScene, theIntersect.getKey().getIntersectNormal(aIntersectPoint), aIntersectPoint, aReflectionVector, aDepth - 1);
                })
                .orElse(theScene.getBackgroundColor());

            aColor.setRed(aColor.getDecimalRed() + (FR * aRefColor.getDecimalRed()));
            aColor.setBlue(aColor.getDecimalBlue() + (FR * aRefColor.getDecimalBlue()));
            aColor.setGreen(aColor.getDecimalGreen() + (FR * aRefColor.getDecimalGreen()));
        }
    });

    return aColor;
}

// TODO: factor in opacity
public double getShadow(Vector3D theOrigin, Vector3D theLightDirection, double theLightDistance, Scene theScene)
{
    // Avoid self-collision
    Vector3D aAdjustedOrigin = theOrigin.add(theLightDirection.scale(.00001));

    return theScene.getKDFilteredObjects(theLightDirection, aAdjustedOrigin)
            .parallelStream()
            .unordered()
            .map(theObject -> theObject.intersects(theLightDirection, aAdjustedOrigin))
            .filter(Objects::nonNull)
            .filter(theT -> theT > 0 && theT < theLightDistance)
            .findAny()
            .map(theT -> 0.0)
            .orElse(1.0);
}

```

**Tags:** raytracing, rendering

> **Comments:**
> **username_1**: Are your triangles one sided? Your artefacts looks a lot like rays starting inside of a 1 sided triangle mesh, which usually occur were were you get AO, because of the V channels and your epsilon method it is easier to penetrate the surface and start a ray inside the mesh. If you are using 1 sided triangles then you can make them 2 sided so any rays starting from the inside get trapped in there and contribute something useful to AO :)  
> **username_2**: **I'm properly accounting for this by slightly translating the outgoing rays** How do you offset your ray origins? Do you use an absolute or relative offset along the ray?  
> **username_3**: As there is more than one possible cause for these artefacts, it would help answerers to be able to see your code. Are you happy to include it here?  
> **username_0**: @username_2 added code, i'm current translating like this `Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));`   --- @username_3 I've added my code to the original post, sorry if it's a little hard to follow, it's kind of a first pass.   --- @username_1 I thought that I was, I will double check my intersection code to make sure  

---

## 1 answers

### Answer by username_0 on 2018-08-26. Score: 1 | Accepted answer

So this does in fact seem to be a self-collision issue. I was able to determine this by giving each triangle/sphere an ID and filtering that ID out when checking collisions.


---

