Transformations, Smooth Shading and Multi Threading
I have improved my ray tracer by incorporating transformation support, mesh instancing, multi-thread support.
For transformations, I am basically transforming all vertices of triangles while creating associated mesh and triangle objects in pre-render step and all the ray-triangle intersection tests, shading goes as smooth as possible.
For the spheres we are not that lucky, for the ray-sphere intersection tests I am first applying inverse transformation to rays to find the intersection point in the local space of sphere. For finding the normals after transformations of sphere, we need to be careful ! We can not simply transform the normal vectors by transformation matrix. We need to multiply it by the inverse transpose of transformation matrix [1].
I also added support for instancing meshes that inherits from a base mesh in the scene and define its own transformations. For that purpose I created a new class called MeshInstance which inherits Mesh class of my ray tracer and overrides its intersectRay function as follows:
bool MeshInstance::intersectRay(Ray r, HitRecord& hitRecord)
{
HitRecord minimumHitRecord(vec3(0.0f), vec3(0.0f), MAXFLOAT);
bool hit = false;
for (int i = 0; i < this->instanceMesh->faces.size(); i++)
{
Triangle* triangle = this->instanceMesh->faces[i];
//Create a new triangle by transforming base mesh's triangle
//by additional transformation of this mesh instance
Triangle newTriangle = Triangle(triangle, this->additionalTransformation);
if (newTriangle.intersectRay(r, hitRecord))
{
if (hitRecord.getDistance() < minimumHitRecord.getDistance())
{
minimumHitRecord = HitRecord(hitRecord);
hit = true;
}
}
}
hitRecord = HitRecord(minimumHitRecord);
return hit;
}
As result of multi-threading, my render times are reduced significantly. For instance, old and new render times for bunny model is as follows:
//Old bunny model render time
Rendered model bunny.png in 69.19 seconds
//New bunny model render time
Rendered model bunny.png in 13.93 seconds
I have added multi-threading support using C11 threads, Basically I am running 8 threads where each of the threads processes 8 different rows from image.
I have also added smooth shading support. Basically, in pre-render step I assigned a normal vector for each vertex of triangles in the scene, which is computed as sum of all its neighboring triangle normals. In that case when smooth shading is enabled, if a ray intersects a triangle in the scene, weighted average of these vertex normals in each triangle, according to the barycentric coordinates of intersection point provides nice results in terms of smooth shading.
Here are my other results from my ray tracer:
As it can be seen from the images above, there is a shading bug in my ray tracer which I could not figured out yet :..:
Render times are as follows:
Rendered model simple_transform.png in 0.051 seconds
Rendered model spheres_transform.png in 0.10 seconds
Rendered model horse.png in 330.10 seconds
Just to show smooth shading I have rendered horse model with shading mode is set to “smooth”:
Unfortunately I am still waiting for instanced horse scene to render since I recently finished coding, I will update this post as soon as instanced horse scene renders.
Update:
Finally managed to render the instanced horse scene:
Sadly, render time is not good :..:
I even apply multi threading… and render time is ~40 mins, seriously …. Something seems really wrong here :)
I need to figure it out or maybe I can try implementing Bounding Volume Hierarchies for spatial indexing, as soon as possible.
Rendered model horse_instanced.png in 2629.204674 seconds
Update
I finally located that little shading bug and rendered the scenes again, before going into my little and beloved bug, I will share my final results:
For the shading bug, If you are using glm in your ray tracer keep an eye on following mistake. It was a really hard thing to spot :)
References
1 - https://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations