<h1>Two symptoms</h1>

<p>There appear to be two problems with the image.</p>

<ol>
<li>The background is showing through along the line between adjacent triangles.</li>
<li>The colour displayed is not always from the closest intersection.</li>
</ol>

<p>Note that the background colour is white, rather than black, due to the line:</p>

<pre><code>                PutPixelSDL(screen, x, y, vec3(1, 1, 1));
</code></pre>

<p>Why this background shows through at the triangle edges I do not know. However, the second problem is identified below, so I recommend you fix that first and then the first problem can be analysed in isolation without the additional distractions.</p>

<hr>

<h1>Cause of the problem with <code>ClosestIntersection</code></h1>

<p>The <code>ClosestIntesection</code> function returns <code>true</code> when an intersection is found, and updates an <code>Intersection</code> object called <code>closestIntersection</code>. However, the intersection stored here is not always the closest to the camera.</p>

<p>The reason for this is here:</p>

<pre><code>                closestIntersection.distance = glm::distance(start, x);
</code></pre>

<p>This appears in two places so it will need to be fixed in both.</p>

<p><code>start</code> is <code>cameraPos</code>, presumably in world coordinates. <code>x</code> appears to be in the local coordinates of the triangle being intersected (one of the triangle vertices being the origin). The distance between two points in different coordinate systems is meaningless, so that in different regions of a triangle it will appear to be behind or in front of another triangle for no immediately apparent reason.</p>

<p>If <code>x</code> is first converted to world coordinates then the distance will be correct and the intersection chosen will be the closest to the camera.</p>

CC BY-SA 3.0
2016-04-29T22:44:42.077Z
Thanks! You were right, but I should also make note for future readers that I had misunderstood the inverse of the matrix. What I got from that inverse matrix (variable called x) was actually 3 scalars, not a coordinate. Think about that and everything else will click once this is realized. The first value (x.x) is actually the scalar distance from the start vector along the direction vector where the intersection occurs!
swedish_fisk
CC BY-SA 3.0
2016-04-17T23:24:54.573Z
2016-04-17T23:24:54.573Z
trichoplax is on Codidact now
<p>So I have a vector of <code>glm::vec3</code> containing the triangles for the classic Cornell Box called triangles. The Draw method casts a ray for each pixel on the screen and calls <code>ClosestIntersection</code> which returns true or false and updates a struct containing things like colour and the point of that intersection. Then I simply draw the pixels based on the colours (black for no intersection). </p>

<p>The result is very inconsistent and I can't find the error:
<a href="https://i.sstatic.net/L1UbK.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/L1UbK.png" alt="enter image description here"></a></p>

<pre><code>void Draw()
{
    if (SDL_MUSTLOCK(screen))
        SDL_LockSurface(screen);

    // Loop through each pixel and cast ray
    for (int y = 0; y&lt;SCREEN_HEIGHT; ++y)
    {
        for (int x = 0; x&lt;SCREEN_WIDTH; ++x)
        {
            vec3 dir(x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength);
            Intersection isect;
            if (ClosestIntersection(cameraPos, dir, triangles, isect))
            {
                vec3 color = triangles[isect.triangleIndex].color;
                PutPixelSDL(screen, x, y, color);
            }
            else
            {
                PutPixelSDL(screen, x, y, vec3(1, 1, 1));
            }
        }
    }

    if (SDL_MUSTLOCK(screen))
        SDL_UnlockSurface(screen);

    SDL_UpdateRect(screen, 0, 0, 0, 0);
}
</code></pre>

<p>This is the function called from Draw:</p>

<pre><code>bool ClosestIntersection(vec3 start,
    vec3 dir,
    const vector&lt;Triangle&gt;&amp; triangles,
    Intersection&amp; closestIntersection)
{
    bool foundIntersection = false;

    // Loop through all the triangles and check for intersection with ray
    for (size_t i = 0; i &lt; triangles.size(); i++)
    {
        vec3 v0 = triangles[i].v0;
        vec3 v1 = triangles[i].v1;
        vec3 v2 = triangles[i].v2;
        vec3 e1 = v1 - v0;
        vec3 e2 = v2 - v0;
        vec3 b = start - v0;
        mat3 A(-dir, e1, e2);
        vec3 x = glm::inverse(A) * b;

        // Check that found scalars are within bounds
        if ((x.x &gt;= 0) &amp;&amp; (x.y &gt; 0) &amp;&amp; (x.z &gt; 0) &amp;&amp; (x.y + x.z &lt; 1))
        {
            if (foundIntersection)  // If there's a previvous intersection for this ray check that new one is closer to camera
            {
                if (glm::distance(start, x) &lt; closestIntersection.distance)
                {
                    closestIntersection.distance = glm::distance(start, x);
                    closestIntersection.triangleIndex = i;
                    closestIntersection.position = x;
                }
            }
            else
            {
                foundIntersection = true;
                closestIntersection.distance = glm::distance(start, x);
                closestIntersection.triangleIndex = i;
                closestIntersection.position = x;
            }
        }
    }
    return foundIntersection;
}
</code></pre>

<raytracing><c++><glm>
Ray-tracing the Cornell Box results in really inconsistent image
swedish_fisk
# Ray-tracing the Cornell Box results in really inconsistent image

(Asked by: username_0 on 2016-04-17)

So I have a vector of `glm::vec3` containing the triangles for the classic Cornell Box called triangles. The Draw method casts a ray for each pixel on the screen and calls `ClosestIntersection` which returns true or false and updates a struct containing things like colour and the point of that intersection. Then I simply draw the pixels based on the colours (black for no intersection).

The result is very inconsistent and I can't find the error:
[![enter image description here](https://i.sstatic.net/L1UbK.png)](https://i.sstatic.net/L1UbK.png)

```
void Draw()
{
    if (SDL_MUSTLOCK(screen))
        SDL_LockSurface(screen);

    // Loop through each pixel and cast ray
    for (int y = 0; y<SCREEN_HEIGHT; ++y)
    {
        for (int x = 0; x<SCREEN_WIDTH; ++x)
        {
            vec3 dir(x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength);
            Intersection isect;
            if (ClosestIntersection(cameraPos, dir, triangles, isect))
            {
                vec3 color = triangles[isect.triangleIndex].color;
                PutPixelSDL(screen, x, y, color);
            }
            else
            {
                PutPixelSDL(screen, x, y, vec3(1, 1, 1));
            }
        }
    }

    if (SDL_MUSTLOCK(screen))
        SDL_UnlockSurface(screen);

    SDL_UpdateRect(screen, 0, 0, 0, 0);
}

```

This is the function called from Draw:

```
bool ClosestIntersection(vec3 start,
    vec3 dir,
    const vector<Triangle>& triangles,
    Intersection& closestIntersection)
{
    bool foundIntersection = false;

    // Loop through all the triangles and check for intersection with ray
    for (size_t i = 0; i < triangles.size(); i++)
    {
        vec3 v0 = triangles[i].v0;
        vec3 v1 = triangles[i].v1;
        vec3 v2 = triangles[i].v2;
        vec3 e1 = v1 - v0;
        vec3 e2 = v2 - v0;
        vec3 b = start - v0;
        mat3 A(-dir, e1, e2);
        vec3 x = glm::inverse(A) * b;

        // Check that found scalars are within bounds
        if ((x.x >= 0) && (x.y > 0) && (x.z > 0) && (x.y + x.z < 1))
        {
            if (foundIntersection)  // If there's a previvous intersection for this ray check that new one is closer to camera
            {
                if (glm::distance(start, x) < closestIntersection.distance)
                {
                    closestIntersection.distance = glm::distance(start, x);
                    closestIntersection.triangleIndex = i;
                    closestIntersection.position = x;
                }
            }
            else
            {
                foundIntersection = true;
                closestIntersection.distance = glm::distance(start, x);
                closestIntersection.triangleIndex = i;
                closestIntersection.position = x;
            }
        }
    }
    return foundIntersection;
}

```

**Tags:** raytracing, c++, glm


---

## 1 answers

### Answer by username_1 on 2016-04-17. Score: 4 | Accepted answer

# Two symptoms

There appear to be two problems with the image.

1. The background is showing through along the line between adjacent triangles.
2. The colour displayed is not always from the closest intersection.

Note that the background colour is white, rather than black, due to the line:

```
                PutPixelSDL(screen, x, y, vec3(1, 1, 1));

```

Why this background shows through at the triangle edges I do not know. However, the second problem is identified below, so I recommend you fix that first and then the first problem can be analysed in isolation without the additional distractions.

---

# Cause of the problem with `ClosestIntersection`

The `ClosestIntesection` function returns `true` when an intersection is found, and updates an `Intersection` object called `closestIntersection`. However, the intersection stored here is not always the closest to the camera.

The reason for this is here:

```
                closestIntersection.distance = glm::distance(start, x);

```

This appears in two places so it will need to be fixed in both.

`start` is `cameraPos`, presumably in world coordinates. `x` appears to be in the local coordinates of the triangle being intersected (one of the triangle vertices being the origin). The distance between two points in different coordinate systems is meaningless, so that in different regions of a triangle it will appear to be behind or in front of another triangle for no immediately apparent reason.

If `x` is first converted to world coordinates then the distance will be correct and the intersection chosen will be the closest to the camera.

> **Comments:**
> **username_0**: Thanks! You were right, but I should also make note for future readers that I had misunderstood the inverse of the matrix. What I got from that inverse matrix (variable called x) was actually 3 scalars, not a coordinate. Think about that and everything else will click once this is realized. The first value (x.x) is actually the scalar distance from the start vector along the direction vector where the intersection occurs!  

---

