Monday, 12 February 2018

ABAP Ray Tracer – Part 5 – The Sample

Objectives


In this fifth blog I am updating my ray tracer to use different sampling algorithms to tackle the problem of aliasing.

I will demonstrate the aliasing effect by showing images created by my ray tracer and allow you to compare different sampling algorithms to minimize the aliasing effect.

Aliasing & Antialiasing


The aliasing effect, in the context of computer generated images, describes artefacts, which are often unpleasant to look at.

Aliasing is an inherent problem of ray tracing, which can never be fully overcome.

This problem results from the fact, that the mathematical definition of the objects allows for infinite detail.
But to make these details visible to our eyes, we have to map them to the finite area of a pixel.

We are squeezing more information into a pixel, which only can hold a single color, this in return leads to a loss of details/information and creates patterns/artifacts in the rendered image.

The following image shows my very first rendering.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Sphere with one ray per pixel.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Magnified border of the sphere

The jagged border line is a very common artefact caused by aliasing.

When shooting a ray from the center of each pixel, it either hits the object surface or misses it. In the end the pixel gets the full opaque color of the object or the background.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Suffern, (2007). Figure04.01. [EPS image]
Available at: raytracegroundup.com (2) [Accessed 28. Jan. 2018]

One solution to this problem is to cast more than one ray for a single pixel and to average the colors to define the visible pixel color. This is called sampling. So, one could also say, using more than one sample helps to have a better approximation of the world being rendered.

The following figure 04.03 shows the top left pixel from the figure 04.01.
25 samples are cast (left) and each returns either yellow or grey (center). The color values are then averaged so that the final color is a desaturated yellow. (right)

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Suffern, (2007). Figure04.03. [EPS image]
Available at: raytracegroundup.com (2) [Accessed 28. Jan. 2018]

Subdividing a pixel evenly and shooting rays from the center of each individual subpixel is also called uniform or regular sampling.

The following images have regular sampling applied to perform antialiasing on the sphere’s edge. Each pixel is determined by using 16 samples.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Sphere with regular sampling (16 samples)

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Magnified border of the sphere, which got antialiased.

 Another example to illustrate the problem of aliasing is the sinusoid function (3), which is a mathematical representation describing continuously shrinking waves.

The following image got rendered in the range (x,y) = [0, 3.79]². The smallest wave gets represented by around 5 pixel. No artifacts are present.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Sinusoid function

If the same resolution is used to display a larger range ((x,y) = [0, 10.83]²), a pattern unfolds, which is also known as moiré (4), which results from the waves getting so small that they cannot be represented by a single pixel.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Moiré pattern

Now I am applying regular sampling with 16 samples per pixel, as a result the strength of the pattern decreases, but it’s still visible. In fact, if the contrast of this image would be highly increased the same pattern unfolds again, as you can also see in the following picture.
This pattern results from the fact that the samples are all evenly and uniformly spaced from each other, which shifts the problem, but doesn’t solve it.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Regular sampling applied (16 samples)

As you can see in the next image: An alternative solution is to implement another sampling algorithm, where the samples are randomly distributed within the area a pixel spans. This will create a noise pattern to which the human eye is much more forgiving compared to a distinct pattern.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Random sampling applied (16 samples)

But random sampling can result in sample gaps or clusters, which cause under- or oversampling. Another algorithm called Jittered sampling randomizes the rays only inside the area of each subpixel, which causes more evenly spaced samples.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Suffern, (2007). Figure04.07. [EPS image]
Available at: raytracegroundup.com (2) [Accessed 28. Jan. 2018]

(left) 25 random samples
(center) 25 Jittered samples
(right) Like the center, but with subpixels displayed

The following rendering has Jittered sampling applied.

SAP ABAP Tutorials and Materials, SAP ABAP Development, SAP ABAP Guides
Jittered Sampling (16 samples)

There are many more sampling algorithms, like Multi-Jittered, Hammersley, N-Rooks, which are covered in the book but not covered in my blog as this would again make the length of the article awfully long and I try to learn from my mistakes ;).

Bottom line: Sampling helps to get a better approximation, like finer details, smoother edges, sharper textures at the cost of performance. Various algorithms exist which have different characteristics.

Sampling will be used in several occasions during ray tracing, not only when I fight jagged edges, but also when area lights and soft shadows are going to be implemented in later chapters.

Language Differences


Integer division

What caused me some serious headaches during the conversion of the C++ sampling algorithms to ABAP is the difference how both languages handle integer division. Look for yourself:

// C++
int val = 1;
val = val / 2; 
// val is zero

"ABAP
DATA val TYPE int4 VALUE 1.
val = val / 2.
"val is one

I ended up using trunc and a float value:

"ABAP
DATA val TYPE int4 VALUE 1.
val = trunc( val / '2.0' ).
"val is zero

No comments:

Post a Comment