The purpose of this project was to provide a straightforward implementation of shadow volumes using the depth fail approach. The project is divided into the following sections: After loading an object, detect duplicate vertices. Build the object's edge list while identifying each face associated with an edge. Identify the profile edges from the perspective of the light source. Create the quadrilaterals defining the shadow volume by extruding the profile edges. Create the shadow volume Read more [...]

# Path tracing: sphere and triangle texture mapping

I had been planning to refine this project and offer a more detailed writeup on adding sphere and triangle texture mapping to the path tracer project, but for the time being I thought I would offer the code for download. Below are a couple of screen captures from the most recent version of the project. The code is available below. Download this project: path_tracer_texture_mapping.tar.bz2 Read more [...]

# kd tree construction using the surface area heuristic, stack-based traversal, and the hyperplane separation theorem

In this post we will employ the hyperplane separation theorem and the surface area heuristic for kd tree construction to improve the performance of our path tracer. Previous posts have relied simply on detecting intersections between an axis aligned bounding box and the minimum bounding box of a triangle primitive. By utilizing the hyperplane separation theorem, we can cull additional triangles from a list of potential intersection candidates. From here, we will set out to construct a kd tree Read more [...]

# Path tracer: thin lens, texture mapping, Fresnel equations, and smooth shading

A few new features have been added to our path tracer. The depth of field extension has been reworked slightly using the thin lens equation allowing us to specify a focal length and aperture. Fresnel equations have been added to more accurately model the behavior of light at the interface between media of different refractive indices. Textures can be applied to the plane primitive, and normals can be interpolated across the triangle primitive allowing for smooth shading. Below are three renders Read more [...]

# Path tracer with triangle primitives and binary space partitioning

UPDATE: The post below was a purely naive attempt at implementing a rudimentary bounding volume hierarchy. A much more efficient implementation using a kd tree is available in this post. We will continue with the project we left off with in this post. We will attempt to add triangles to our list of primitives. Once we are able to render triangles, this opens the door to rendering full scale models. However, because models will contain upwards of thousands of triangles, we need to be able to Read more [...]

# Path tracer depth of field

This is a small extension to the previous post. We will add a depth of field simulation to our path tracer project. I ran across this algorithm at this site. Below is a render of our path tracer with the depth of field extension. Essentially, we will define the distance to the focal plane and a blur radius. For each primary ray we find its intersection with the focal plane, $$\vec{p}$$, and jitter the ray origin by an amount, $$\vec{d}$$. We then define the new ray direction as $$\vec{r}=\vec{p}-\vec{d}$$. Read more [...]

# A basic path tracer with CUDA

The path tracer we will create in this project will run on CUDA-enabled GPUs. You will need to install the CUDA Toolkit available from NVIDIA. The device code for this project uses classes and must be compiled with compute capability 2.0. If you are unsure what compute capability your card has, check out this list. Below are two screen captures of this project in action. This path tracer is basic and fairly crude and inefficient. I'll provide a brief overview of the code before Read more [...]

# Using Fourier synthesis to generate a fractional Brownian motion surface

In this post we will discuss generating fractal terrain. In the previous post we implemented our own fast Fourier transform in order to simulate an ocean surface. In that post we implemented an unnormalized inverse transform. It seemed logical to employ our FFT object as a means of generating terrain, but in order to do so we will need to add a method to compute the forward transform. This will be a relatively brief post. Most of the foundation has been laid with our ocean simulation, so we Read more [...]

# Ocean simulation part two: using the fast Fourier transform

In this post we will analyze the equations for the statistical wave model presented in Tessendorf's paper[1] on simulating ocean water. In the previous post we used the discrete Fourier transform to generate our wave height field. We will proceed with the analysis in order to implement our own fast Fourier transform. With this implementation at our disposal we will be able to achieve interactive frame rates. Below are two screen captures of our result. The first uses a version of the shader Read more [...]

# Ocean simulation part one: using the discrete Fourier transform

In this post we will implement the statistical wave model from the equations in Tessendorf's paper[1] on simulating ocean water. We will implement this model using a discrete Fourier transform. In part two we will begin with the same equations but provide a deeper analysis in order to implement our own fast Fourier transform. Using the fast Fourier transform, we will be able to achieve interactive frame rates. Below are two screen captures. The first is a rendering of the surface using some Read more [...]

# Tangent space normal mapping with GLSL

In the previous post we discussed lighting and environment mapping, and our evaluation of the lighting contribution was performed in view space. Here we will discuss lighting in tangent space and extend our lighting model to include a normal map. If we apply a texture to a surface, then for every point in the texture we can define a set of vectors that are tangent to that point. Once we transform our light vector, halfway vector, and normal vector into tangent space, we can use the normal map Read more [...]

# Lighting and environment mapping with GLSL

In this post we will expand on our skybox project by adding an object to our scene for which we will evaluate lighting contributions and environment mapping. We will first make a quick edit to our Wavefront OBJ loader to utilize OpenGL's Vertex Buffer Object. Once we can render an object we will create a shader program to evaluate the lighting and reflections. Below are a couple of screen grabs of the final result. A couple of video captures are below. Your browser doesn't support Read more [...]

# Rendering a skybox using a cube map with OpenGL and GLSL

I realized in my previous posts the use of OpenGL wasn't up to spec. This post will attempt to implement skybox functionality using the more recent specifications. We'll use GLSL to implement a couple simple shaders. We will create an OpenGL program object to which we will bind our vertex and fragment shaders. A Vertex Buffer Object will be used to store our cube vertices and another to store the indices for the faces. Using a cube map texture will allow our vertices to double as texture coordinates. Read more [...]

# A preliminary Wavefront OBJ loader in C++

This post will examine the Wavefront OBJ file format and present a preliminary loader in C++. We will overlook the format's support for materials and focus purely on the geometry. Once our model has been loaded, an OpenGL Display List will be used to render the model. Below is a rendering of a dragon model available at The Stanford 3D Scanning Repository. In the OBJ file used for this render the vertex normals were not present. At run time, normals were evaluated at each face for lighting calculations Read more [...]