Generate a ray that goes from the camera’s origin through the pixel location (pixelPosX, pixelPosY) of the camera. Note that pixelPosX and pixelPosY can be non-integer. The image origin is at the bottom-leftmost corner, that means:

The bottom-leftmost corner of the image is (0, 0).

The top-rightmost corner of the image is (imageWidth, imageHeight).

The center of the bottom-leftmost pixel is (0.5, 0.5).

The center of the top-rightmost pixel is (imageWidth-0.5, imageHeight-0.5).

if(reflectLevels > 0) { Vector3d dir = mirrorReflect(V, N); Ray rRay(nearestHitRec.p,dir); result += nearestHitRec.mat_ptr->k_rg * TraceRay(rRay,scene,--reflectLevels,hasShadow); }

Hammersley Sampling

We know that binary numbers are used to represent data in the computer. The corresponding relations between decimal and binary systems are shown in the following table.

Decimal

Binary

1

1

2

10

3

11

4

100

And Hammersley Sampling is to generate uniformly distributed 2D random sampliong points by using this characteristics.

It constructs a value by implementing a Radical Inverse method for a binary number. Its process is as follows

Decimal

Binary

Radical Inverse

Value

1

1

.1 = 1 * 1/2

0.5

2

10

.01 = 0 1/2 + 1 1/4

0.25

3

11

.11 = 1 1/2 + 1 1/4

0.75

4

100

.001 = 0 1/2 + 0 1/4 + 1 * 1/8

0.125

Constructing a set of 2D random sampling points for Hammersley Sampling

Anti-Aliasing

In ray tracing world, Anti-Aliasing method is simply, it only just increase the amount of sampling.

Anti-Aliasing in GLSL

1 2 3 4 5 6

for(uint i = 0 ; i < NumSample; i++) { vec2 offset = Hammersley(i, NumSample); Ray ray = getRay(float(pos.x) + offset.x, float(pos.y) + offset.y); // create ray from camera color += RayTrace(ray,ReflectLevels,HasShadow); }

for (uint32_t y = task->beginHeight; y < task->endHeight; y++) { for (uint32_t x = 0; x < task->width; x++) { Color pixelColor = Color(0, 0, 0); for (uint32_t i = 0; i < task->numSample; i++) { float xx; float yy; Math::Hammersley(i, task->numSample, &xx, &yy); double pixelPosX = x + xx; double pixelPosY = y + yy; Ray ray = task->scene->camera.getRay(pixelPosX, pixelPosY); pixelColor += Raytrace::TraceRay(ray, *task->scene, task->reflectLevels, task->hasShadow); } pixelColor /= (float)task->numSample; pixelColor.clamp(); task->output->setPixel(x, y, pixelColor);

Color Raytrace::TraceRay( const Ray &ray, const Scene &scene, int reflectLevels, bool hasShadow ) { Ray uRay( ray ); uRay.makeUnitDirection(); // Normalize ray direction.

if ( !hasHitSomething ) return scene.backgroundColor;

nearestHitRec.normal.makeUnitVector(); Vector3d N = nearestHitRec.normal; // Unit vector. Vector3d V = -uRay.direction(); // Unit vector. Color result( 0.0f, 0.0f, 0.0f ); // The result will be accumulated here.

bool shadow = 1.0f; for(int i = 0 ; i < scene.numPtLights ; i++) { Vector3d Lin = scene.ptLight[i].position - nearestHitRec.p; double MaxLength = (Lin).length(); double invLen = 1 / MaxLength; Vector3d L = (Lin)*invLen;