Boxels
In this project, you will create an application that renders “boxel” sculptures. A sculpture made of boxels is an approximation of a real-life object using only box primitives. The locations, sizes, and colors of a sculpture's boxes are stored in a text file that your renderer reads in.
Requirements
To receive credit for this project, you must meet all of the following requirements. No partial credit is given. Submit on a later ready date if a requirement is not yet met.
- Complete this project as an individual, not in a group.
-
Place your renderer in
renderers/boxels
in your individual Git repository. - Render a single model made out of boxes. Illuminate it and allow it to be rotated.
-
Define two distinct models composed only of boxes in plain text files. For example, a barbell might be modeled as two cubes at the ends of a narrow dowel running between them. A model's file follows this format:
Each line is nine numbers and describes a single box. The first three specify the x-, y-, and z-coordinates of the box's center. The middle three specify its width, height, and depth. The last three specify its RGB color.
0 0 0 2 3 4 1 0 0 0 5 0 1 1 1 0 1 0 ...
0 0 0 2 3 4 1 0 0 0 5 0 1 1 1 0 1 0 ...
- Make models that are more interesting than a barbell. Approximate recognizable creatures or things; avoid random or abstract. The models must be made of boxes of various sizes, positions, and colors. They must not all live in the same line or plane. Each model must be unique amongst both your own models and others'.
-
Load the model to be rendered with
fetch
. -
Allow the user to rotate the model using the cursor keys. Each new rotation must build on the last. That is, the transformation chain should effectively be this matrix multiplication, with matrix \(\mathbf{R}_0\) being the first rotation applied:
$$\mathbf{R}_{n} \times \mathbf{R}_{n - 1} \times \ldots \times \mathbf{R}_1 \times \mathbf{R}_0$$Accumulate these rotations in a single matrix; do not store them as an array.
- Shift the loaded sculpture so that it is centered the viewport. In other words, its centroid's xyz-coordinates in world space are \(\begin{bmatrix}0&0&0\end{bmatrix}\).
- Size the viewing frustum so that it is large enough to show the whole sculpture. When it rotates, no portion is clipped.
-
Illuminate the model using a flat shading hack. Emit the position as an
out
variable from the vertex shader. In the fragment shader, use the GLSL derivative functions to compute a normal, like this:vec3 lightDirection = normalize(vec3(1.0, 1.0, 1.0)); // ... void main() { vec3 right = dFdx(position); vec3 up = dFdy(position); vec3 normal = normalize(right.cross(up)); float litness = max(0.0, dot(normal, lightDirection)); // scale color by litness }
vec3 lightDirection = normalize(vec3(1.0, 1.0, 1.0)); // ... void main() { vec3 right = dFdx(position); vec3 up = dFdy(position); vec3 normal = normalize(right.cross(up)); float litness = max(0.0, dot(normal, lightDirection)); // scale color by litness }
- Ensure that you can load others' designs into your renderer and reproduce their results.
- Your code must be cleanly formatted, the variable names must be meaningful, and comments should explain non-obvious code.
Submission
Share in the Discord #boxels channel a video of you interacting with your two models. Upload the video to a streaming service like YouTube, Vimeo, or Canvas Studio and share only the URL. Share also the text of your two models (between triple backticks).
Commit and push your work to GitHub.