# Rendering in Haskell, Part 2: Flat Shading

Now that I’ve got the business of being able to write image files from Haskell sorted, I need to move on to the next most simple thing: projecting three-dimensional shapes onto the screen. Here I’m not going to worry about lighting - everything will be flat shaded.

The main source on Github is split into separate folders for each ‘experiment’. Each folder starts as a copy-paste of the previous, so you can see what’s changed to get from the previous stage to the next just by diffing the source trees.

## Core Maths

I’ve collected the core maths routines, into a single file:

https://github.com/stu-smith/rendering-in-haskell/blob/master/src/experiment01/Core.hs

It’s all pretty standard stuff so I won’t show the code, but suffice to say I defined the following types:

`Vector`

`Point`

`Ray`

(a combination of a`Point`

and a`Vector`

)

I have a typeclass `Transform`

that allows me to translate (move) `Point`

s and `Vector`

s.

Finally I have utility functions:

`to`

: Get a`Vector`

between two`Point`

s;`normalize`

: Convert a`Vector`

to have unit length;`magnitude`

and`magnitudeSquared`

, to get the length of a vector;`neg`

, to reverse a vector;`|*|`

, for vector scaling;`|+|`

, to add two vectors;`cross`

, to find the cross-product between two vectors;`|.|`

, to take the dot product between two vectors.

## Surfaces

I represent three-dimensional objects in the scene as surfaces. Each surface only needs two pieces of information: a function that determines whether a ray intersects the surface, and a color to shade the surface.

In this first example, I only support two kinds of surfaces: planes and spheres.

Spheres are always created at the origin for simplicity:

That’s clearly very limiting, so I allow a `Surface`

to be translated using the `Transform`

typeclass,
in exactly the same way that I allow `Point`

s and `Vector`

s to be translated:

## Scenes

A `Scene`

is simply a collection of `Surface`

s. In keeping with much of the rest of the code, the actual
data constructur is private to the module, and only a constructor function is exposed:

The primary function of a `Scene`

is to manage testing rays against the surfaces within it. If a `Ray`

intersects a `Surface`

, we want to know details about that intersection:

When a `Ray`

is cast into a `Scene`

, we need to know the closest `Surface`

that intersected. Here
I do this via a very simple brute-force linear scan of all `Surface`

s, ordered by distance from
the ray’s origin. (Later I expect I’ll have to change this to a more optimal algorithm, but it will
do for now).

Everything here is in terms of `Maybe`

s - a `Ray`

might or might not intersect a `Surface`

.

## Rendering

The rendering function for this experiment is very simple: if we intersect a `Surface`

, we simply
use its defined flat color:

Generating the `Ray`

s from pixel positions is slightly more involved, but is a basic perspective
transform:

(This function matches the x,y,width,height format used previously, so it slots straight into the bitmap render function we used before).

For my example scene, I’m using a modified Cornell box:

Finally, my `main`

function is modified slightly to tie everything together, viewed from a suitable
camera angle (supplied as a `Ray`

):

The final image is as follows:

It’s still nowhere near being photorealistic, but at least we have basic intersection tests in place, plus perspective transforms.

Code is in Github, if you want to take a look.