Skip to main content
The cover image for "Raytracer and Rasteriser"

Raytracer and Rasteriser

Sidebar

I wrote a raytracer and a rasteriser as part of my university course. The raytracer supported features such as indirect lighting, reflection, refraction, and a photon mapper capable of simulating the final positions of 60,000,000 photons in a few minutes (and quite a few GBs of RAM).

I wrote a raytracer and a rasteriser as part of my university course. The raytracer supported features such as indirect lighting, reflection, refraction, and a photon mapper capable of simulating the final positions of 60,000,000 photons in a few minutes (and quite a few GBs of RAM).

Raytracer #

Features #

  • Direct, specular, and ambient lighting.
  • Soft shadows.
  • Reflection.
  • Refraction with Snell’s law, Fresnel’s law,
  • Total Internal Reflection, and Beer’s law.
  • Material roughness and rough reflections.
  • Anti-aliasing.
  • Obj 3D model importer.
  • Ability to switch to and from rasteriser using F1 key. Other F keys can be used to enable/disable certain features, see README.
  • OpenMP support
  • Undersampling - render at a lower resolution than the window.

Direct Illumination, Shadows, and Reflection #

Once anti-aliasing is implemented, the triangle normal need only be randomised for each sample, in order to acquire roughness. For each sample, the rotation of the triangle normal - for the triangle which the ray intersects with - is given a random offset. The magnitude of this random offset is dictated by the roughness attribute of the triangle. This gives a rough, blurred, look to rough mirrors. It also makes specularity look more realistic.

Reflections can be implemented simply by firing another ray from the intersection position in the right direction, and using the colour it returns as the pixel colour. This colour is then blended with the diffuse color depending on material properties. You get rough mirrors for free by having roughness.

Direct illumination with shadows.
Direct illumination with shadows.
Rough reflection and soft shadows.
Rough reflection and soft shadows.

Refraction #

Refraction is achieved by firing rays through the material, accounting for the difference in refractive index. The amount of light which is refracted vs diffused depends on the transparency of the material.

If a ray hits a transparent triangle on the opposite side to the normal, then the refractive index is 1/R, where R is the index of the material. Otherwise it’s just R.

Fresnel’s Law determines how much of a ray is reflected when it hits a change in refractive index. Above a certain angle - the critical angle - the rays totally reflect, causing Total Internal Reflection.

Beer’s Law describes a property of semi-transparent materials where colour is absorbed from light per length it passes through the material. The application of Beer’s law gives a jelly-like effect.

refractedColor = incomingColor * exp(-absorbedColor * lengthInMaterial)
Pure refraction with Snell's law, Fresnel's law, and TIR.
Pure refraction with Snell's law, Fresnel's law, and TIR.
Refraction with beers law - colour of material seeps in depending on length of ray.
Refraction with beers law - colour of material seeps in depending on length of ray.

Photon Mapper #

Millions of photons are simulated after being emitted from the light, and then their final positions are recorded. The record of all the final positions is called a photon map. I used an OctTree (like a quad tree, but 2x2x2 rather than 2x2) to enable efficient querying of photon positions.

Hitting any surface will result in a certain percentage of the photon’s color being reflected, which results in indirect lighting. Photons will keep bouncing until their color is low enough to be negligible in which case they’ll stop. The percentage of color which isn’t reflected will be stored in the photon map as a final photon position (ie: diffuse) or sent split into colors and refracted if the triangle is transparent.

Warning: the default settings for the photon map require 4GB of free RAM. Reduce the photon count in drawRaytracer() if you don’t have that available.

Note the light from the sphere on the walls, and the double shadow from indirect lighting on the small cube.
Note the light from the sphere on the walls, and the double shadow from indirect lighting on the small cube.
A re-production of Newton’s light experiment.
A re-production of Newton’s light experiment.

Rasteriser #

Features #

  • Direct and ambient lighting.
  • Perspective Correct Interpolation.
  • “Real Time” Shadow Mapping.
  • Obj 3D model importer.
  • Ability to switch to and from rasteriser using F1 key. Other F keys can be used to enable/disable certain features, see README.
  • Undersampling - render at a lower resolution than the window.
Rasteriser with Shadows
Rasteriser with Shadows
rubenwardy's profile picture, the letter R

Hi, I'm Andrew Ward. I'm a software developer, an open source maintainer, and a graduate from the University of Bristol. I’m a core developer for Luanti, an open source voxel game engine.

Comments

Leave comment

Shown publicly next to your comment. Leave blank to show as "Anonymous".
Optional, to notify you if rubenwardy replies. Not shown publicly.
Max 1800 characters. You may use plain text, HTML, or Markdown.