Stanford CS148 Computer Graphics and Imaging Project
Plan
The first week was an introduction to the course and to the physics, human perception and computer representation of of light and color (e.g. trichromatic theory, tone mapping, RGB vs CMYK). The assignment consisted of setting up the programming environment and learning the course code base that was in C/C++/OpenGL. I chose Visual Studio as my IDE, using CMake to generate the makefiles. I also began planning my image and decided upon a rough sketch in high school while volunteering at the Brooklyn Botanical Gardens, inspired in part by the BBG's Japanese Garden and the Itsukushima Torii (a UNESCO World Heritage Site in Japan). The boat at the gate was inspired by in part by the Tōrō nagashi floating lanterns festival where the dead are mourned and sent off.
Geometry/3D Models
The next week focused on scanline rendering and geometric modeling, which meant topics included OpenGL's rendering pipeline, triangles, rasterization used to color the triangles, and matrix transformations such as that for rotation and translation. The assignment consisted of setting up part of the scanline image scene by loading in a mesh found online and a mesh of one's own creation. For the online mesh, I downloaded a Torii gate from blendswap. For the mesh of my own creation, I CAD'ed a boat-lantern using Solidworks (since I am more familiar with mechE design than Blender) with a photo from a Tōrō nagashi festival as a reference. I then exported the boat as an stl and opened it in Blender to export it as an obj with the triangles and set other properties so it'll be acceptable to OpenGL.
BRDF lighting eqn and shading
The next week focused on Bidirectional Reflectance Distribution Function (BRDF), lighting equations and shading. Basic idea is that when light hits a surface, it gets reflected, absorbed, and/or transmitted. BRDF calculates how much light is reflected and BTDF calculated how much light is transmitted (the T in BTDF is for transmission). The resulting light from a particular point is the result of all surrounding light, so the equation is an integral accounting for light in all directions. The default BRDF model in the source code was Blinn-Phong shading/reflectance model. The assignment was to code in C++ and GLSL the BRDF model used by Epic Games, which has three tune material parameters (roughness, specular, and metallic) and uses Lambertian equation for the BRDF's diffuse component and the Cook-Torrance Microface model for the BRDF's specular component. The assignment also included coding for point lights, directional lights, and hemisphere lights with light attenuation for the point lights. The scanline image didn't progress this week, so no pics.
UV mapping, texture mapping
The next topic was texture maps, normal maps (to bump-ify smooth surface) and displacement maps (to bump-ify the smooth edges). The assignment was to texture two obj's for my scanline scene with unique textures. I wanted to use the Epic shader built last week, so coded in C++/GLSL to include texture capabilities in that shader, but I also used the Blinn-Phong shader for some of the obj's. For the torii gate and the boat-lantern, I used Blender for UV mapping and used Pinta, a Linux paint program, to splice images of wood, paper, copper, etc into the textures. The process is shown in the photos.
Final Scanline Image
No class this week as students worked on their final scanline image and presentations. I decided a scene with just small boat-lanterns looked a bit plain, so CAD'ed a more complicated and bigger boat-lantern in Solidworks, just a quarter of it since I can do mirroring to get the rest due to the symmetry. I then UV-mapped it in Blender and textured it with Pinta. For the water, I used Blender to make and UV map a plane that I then textured with a photo of water and a normal map I made using CrazyBump software. The sky is just a plane obj UV-mapped and then textured with a photo. I placed all the objs in the scene, using a loop to get all the smaller boats and their respective point lights in (only lights in the scene were point lights that corresponded to each water lantern). I then fixed the lighting, added attenuation, adjusted the color, etc. For funsies, I painted mountains on the background image.
Intro Ray Tracing and Sampling
This week, the goals were to introduce the concept of ray tracing and sampling. Instead of a per triangle operation like in scanline rendering, ray tracing generates an image by starting from a screen pixel and tracing the light paths backwards into the object space. When the ray intersects with an object, rays are cast from that intersection to the light sources and the final shading is the combination of all those sources, which is how ray tracing produces shadows (whereas scanline rendering doesn't automatically produce shadows). Sampling at a low rate, below the Nyquist frequency of 2 samples per period, results in aliasing artifacts, aka 'jaggies' because the screen pixels aren't in line with the object's lines. Assignment consisted of setting up the raytracer starter code and experiments in jittered sampling and adaptive sampling (stop sampling a pixel after a threshold if the color is uniform). Brainstorming on final raytracer project scene.
Reflection, Transmission and Acceleration Structures
This week, topics were reflection (opaque objects reemit the light for reflection), transmission (transparent object allow light to pass through neighboring atoms and reemit on the opposite side of the object calculated via Snell's law), and acceleration structures (speed up rendering with bounding volumes). With reflection/transmission, must avoid recursive stack overflow when setting the maximum depth of the ray tree since each ray reflected or transmitted recursively spawns their own reflected/transmitted/shadow rays. Instead of complex ray-objection intersection tests for whole scene, bound the complex objects in boxes or other simpler geometries because if the ray doesn't hit the bounds, then it doesn't hit the object. Assignment involved experimenting with uniform grids (when have uniform spread of objects) vs bounding volume hierarchies tree (contain subparts of complex objects in their own bounding boxes) as the acceleration structures. Decided to stick with scanline image scene for the ray tracer, no raytraced scene yet, but the water will be low transmission and high reflectance.
Global Illumination
This week, the topics were global illumination (model indirect lighting to get soft shadows and color bleeding) and photon mapping (a technique for achieving global illumination). Global illumination models surface-surface bouncing of light to get indirect lighting effects, such as diffuse interreflections (allows for color bleeding) and caustics (kind of like a sun+magnifying glass effect with a bright concentration of light). A technique to achieve GI is photon mapping, which scatters rays (photons) from light sources and when an object intersection occurs, stores the photo in a photon map. Assignment was implementing photon mapping by creating and scattering photos recursively, storing their information in a photon map, and implementing a Monte Carlo method called Russian roulette to determine whether to bounce or absorb the photon, and then displaying the photons as red dots on the Cornell Box scene. GI would be cool for my raytracer image, but it's an outdoor scene, which means most of the photons generated would be lost anyway.
Advanced Rendering
The last week of lectures before Thanksgiving break was on advanced rendering, covering motion blur, depth of field, the gathering step of photon mapping (using the photon map) and volumetric rendering (for smoke and fire). The assignment allowed a choice of implementing one of the techniques learned that week, but none of the advanced rendering techniques would make sense of my final raytraced scene, so I chose photon gathering as the assignment I would implement, since it's a pretty cool concept.
Final Raytraced Image
I started with placing some of the objects in the scene, noticed that the ray tracer's automatic shadow effects on the sky plane and edited the code and the material section to ignore that. Then I placed the rest of the objects along with the respective lights with attenuation and color. I turned on reflections and tweaked the max depth and other parameters. I edited the texture of the torii with Pinta and added more boats to the scene to get a diagonal leading line. I edited the texture of the smaller boats with Pinta to have writing on them as they would if in a Tōrō nagashi festival. I then rendered in higher resolution with 36 samples, taking about 5 hours, resulting in the the final image.