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:
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;
}