<- back
hw8 upload hw.cpp to glow codebase
NOTE: You will be working entirely in world coordinates 👍 NOTE: The position along the ray is vec3 p = o + t * dir; - vec3 o; is the ray origin (aka camera/renderer origin) - double t; is the distance along the ray - vec3 dir; is the direction of the ray a. (80 pts) software ray tracer Implement a software ray tracer. - An attempt will set up the rays properly (pressing 'z' on the keyboard will show them). - A bare bones solution will also draw the triangles in the right place (say, in blue). - A better solution will also draw them in the right color (not considering shadows or lighting). - A solid solution will also get overlap correct. - A wonderful solution will also have basic shadows. - A wow solution will also include Phong lighting (or something vaguely similar). - You can also at that point throw in multiple lights, reflective surfaces, etc. NOTE: Your grade will be based on how many of these features you include; A bare bones solution will score most of the points. Recommended development trajectory: - (math and code in class) set up the rays--origin and direction--properly - (math in class) intersect the ray with a triangle by solving a 4x4-matrix-vector equation; color pixel appropriate color if inside - use a for loop to intersect with all the triangles - get overlap correct by setting the color based on the closest hit - implement shadows (i moved some code out into a function called cast_ray(...), which i also used to cast shadow rays) - implement lighting (this actually isn't too bad once you've got the rest) ✨ NOTE: I shipped the code with a little snippet of gl_*(...) code that draws the rays. You can move this around; edit it; etc. I found it very useful to draw _only the rays that hit_, and to draw them from $\mathbf{o}$ to $\mathbf{p}$.
✨ HINT (iterating over the mesh) int num_triangles = mesh->num_vertices / 3; for (int triangle_i = 0; triangle_i < num_triangles; ++triangle_i) { // (a, b, c) -- triangle vertex positions in world coordinates // color_* -- vertex colors // n -- unit vector normal to triangle vec3 a, b, c; vec3 color_a, color_b, color_c; vec3 n; { a = mesh->vertex_positions[3 * triangle_i + 0]; b = mesh->vertex_positions[3 * triangle_i + 1]; c = mesh->vertex_positions[3 * triangle_i + 2]; vec3 e1 = b - a; vec3 e2 = c - a; n = normalized(cross(e1, e2)); if (mesh->vertex_colors != NULL) { color_a = mesh->vertex_colors[3 * triangle_i + 0]; color_b = mesh->vertex_colors[3 * triangle_i + 1]; color_c = mesh->vertex_colors[3 * triangle_i + 2]; } else { vec3 fallback_color = V3(.5, .5, .5) + .5 * n; color_a = fallback_color; color_b = fallback_color; color_c = fallback_color; } } }
✨ HINT (ray-triangle intersection) Consider ray with origin $\mathbf{o}$ and direction $\mathbf{dir}$. Let's intersect the ray with some triangle $(\mathbf{a}, \mathbf{b}, \mathbf{c})$. Call the (possible) intersection point $\mathbf{p}$ and get pumped. Our approach will be to express $\mathbf{p}$ in two different ways and set them equal. First, we can write down the definition of a ray $$ \begin{cases} \mathbf{p} = \mathbf{o} + t * \mathbf{dir} \end{cases} $$ where we can also write the condition for the $\mathbf{p}$ being in front of the camera (not behind it) $$ \begin{cases} t > 0 \end{cases} $$ Second, we can write down the definition barycentric coordinates $$ \begin{cases} \mathbf{p} = \alpha\mathbf{a} + \beta\mathbf{b} + \gamma\mathbf{c}\\ \alpha + \beta + \gamma = 1 \end{cases} $$ where we can also write the condition for $\mathbf{p}$ being inside the triangle $$ \begin{cases} \alpha,\beta,\gamma > 0 \end{cases} $$ Equating the different equations for $\mathbf{p}$ gives us the following system of equations $$ \begin{cases} \mathbf{o} + t * \mathbf{dir} = \alpha\mathbf{a} + \beta\mathbf{b} + \gamma\mathbf{c}\\ \alpha + \beta + \gamma = 1 \end{cases} $$ Taking on both conditions (in front of camera; inside of triangle) gives us the condition for a "hit" $$ \begin{cases} \alpha,\beta,\gamma,t > 0 \end{cases} $$ You can solve the system any way you like, but since we're not so concerned with speed, let's just bash it with a matrix solve. First, some algebra. $$ \begin{cases} \alpha\mathbf{a} + \beta\mathbf{b} + \gamma\mathbf{c} - t * \mathbf{dir} = \mathbf{o}\\ \alpha + \beta + \gamma = 1 \end{cases} $$ You are the One, Neo. $$ \begin{bmatrix} \mathbf{a} & \mathbf{b} & \mathbf{c} & -\mathbf{dir} \\ 1 & 1 & 1 & 0 \end{bmatrix} \begin{bmatrix} \alpha \\ \beta \\ \gamma \\ t \end{bmatrix} = \begin{bmatrix} \mathbf{o} \\ 1 \end{bmatrix} $$ Solving that system of equations gives us $\alpha,\beta,\gamma,t$. If they pass the condition for a hit, then we have a hit! :) And in the case of a hit, we can finally compute $\mathbf{p}$ in world coordinates as, for example, $\mathbf{p} = \mathbf{o} + t * \mathbf{dir}$. (NOTE: You won't need p until you implement shadows) Wow. 🐄
✨ HINT (closest hit) foreach (pixel (i, j)) { bool hit_at_least_one_triangle = false; double min_t = INFINITY; vec3 color = {}; { foreach (triangle) { ... // calculate alpha, beta, gamma, t bool hit = ...; if (hit) { hit_at_least_one_triangle = true; if (t < min_t) { min_t = t; // * don't forget this color = ...; } } } } if (hit_at_least_one_triangle) { hw8a_set_pixel(i, j, color); } }
b. (20 pts) ray marching distance shaders (Creative Coding) Ray march a scene of your own design. ✨ Include a _brief_ writeup of your goal and method in your submission comment on glow. You may copy and paste code from https://iquilezles.org/articles/distfunctions/. You may browse shadertoy for inspiration, but you may _not_ copy and paste code (apply the 50 ft rule applies). If you are heavily inspired by a shader, please link it in your glow comment. In order to prepare you for the upcoming final project, a bare bones submission will _not_ score full points. You will be graded on: - 50% - The clarity (not length) of your glow comment - 25% - The technical depth of your implementation - 25% - The creativity of your scene
🐄