├── 00-introduction.md ├── 01-common-concepts.md ├── 02-basic-raytracing.md ├── 03-light.md ├── 04-shadows-and-reflections.md ├── 05-extending-the-raytracer.md ├── 06-lines.md ├── 07-filled-triangles.md ├── 08-shaded-triangles.md ├── 09-perspective-projection.md ├── 10-describing-and-rendering-a-scene.md ├── 11-clipping.md ├── 12-hidden-surface-removal.md ├── 13-shading.md ├── 14-textures.md ├── 15-extending-the-rasterizer.md ├── A0-linear-algebra.md ├── LICENSE.md ├── README.md ├── acknowledgements.md ├── afterword.md ├── cover.jpg ├── dedication.md ├── demos ├── checkerboard.png ├── crate-texture.jpg ├── raster-01.html ├── raster-02.html ├── raster-03.html ├── raster-04.html ├── raster-05.html ├── raster-06.html ├── raster-07.html ├── raster-08.html ├── raster-09.html ├── raster-10.html ├── raster-11.html ├── raster-12.html ├── raster-13.html ├── raster-rt-scene.html ├── raytracer-01.html ├── raytracer-02.html ├── raytracer-03.html ├── raytracer-04.html ├── raytracer-05.html └── raytracer-06.html ├── diagrams ├── 00-coordinates1.svg ├── 00-coordinates2.svg ├── 01-primaries1.svg ├── 01-primaries2.svg ├── 01-primaries3.svg ├── 03-basic-raytracer.svg ├── 03-camera-orientation.svg ├── 03-viewport.svg ├── 04-parameter-space.svg ├── 04-parametric.svg ├── 04-simple-scene.svg ├── 04-sphere-solutions.svg ├── 04-sphere.svg ├── 05-directional-light.svg ├── 05-point-light.svg ├── 06-diffuse-diagram.svg ├── 06-light-spread.svg ├── 06-mirror.svg ├── 06-qrp.svg ├── 06-rough-surface.svg ├── 06-sphere-normal.svg ├── 07-specular-decay.svg ├── 07-specular-diagram.svg ├── 08-mirror.svg ├── 08-nl.svg ├── 08-shadow-cases.svg ├── 08-shadow-directional.svg ├── 08-shadow-point.svg ├── 08-vec-r.svg ├── 09-csg.svg ├── 09-refraction.svg ├── 09-shadow-coherence.svg ├── 15-shadow-volume.svg ├── 15-sv-direct.svg ├── 15-sv-reverse.svg ├── 15-sv-simple.svg ├── aa-point-diff.svg ├── aa-point-plus-vector.svg ├── aa-points.svg ├── aa-vector-cross-product.svg ├── aa-vector-dot-product.svg ├── aa-vector-plus-vector.svg ├── aa-vector-scaling.svg ├── aa-vectors.svg ├── bad-texture-minification.svg ├── bilinear-texture-weights.svg ├── camera-movement-1.svg ├── camera-movement-2.svg ├── coordinate-system.svg ├── mipmap-levels.svg ├── r12-perspective.svg ├── r12-perspective2.svg ├── r12-perspective3.svg ├── r13-cube.svg ├── r13-rotate-translate.svg ├── r13-translate-rotate.svg ├── r14-clip-plane-sphere.svg ├── r14-clip-spheres-1.svg ├── r14-clip-spheres-2.svg ├── r14-clip-spheres-3.svg ├── r14-clip-spheres-4.svg ├── r14-clip-triangle1.svg ├── r14-clip-triangle2.svg ├── r14-clip1.svg ├── r14-clip2.svg ├── r14-clip3.svg ├── r14-clip4.svg ├── r14-clipping-planes.svg ├── r14-unclipped-object.svg ├── r14-vertex-classification.svg ├── r15-closed-objects.svg ├── r15-cube-normals.svg ├── r15-culling.svg ├── r15-depth.svg ├── r15-depth2.svg ├── r15-impossible-sort.svg ├── r15-linear-z-1.svg ├── r15-linear-z-2.svg ├── r15-wrong-sort.svg ├── r16-flat-normals.svg ├── r16-sphere-normals.svg ├── r16-wrong-interpolation.svg ├── r17-linear-texture.svg ├── r17-texture-mapping.svg ├── rt-csg.svg └── triangle-horizontal-segments.svg └── images ├── 00-coordinates1.png ├── 00-coordinates2.png ├── 01-primaries1.png ├── 01-primaries2.png ├── 01-primaries3.png ├── 03-basic-raytracer.png ├── 03-camera-orientation.png ├── 03-viewport.png ├── 04-parameter-space.png ├── 04-parametric.png ├── 04-simple-scene.png ├── 04-sphere-solutions.png ├── 04-sphere.png ├── 05-directional-light.png ├── 05-point-light.png ├── 06-diffuse-diagram.png ├── 06-light-spread.png ├── 06-mirror.png ├── 06-qrp.png ├── 06-rough-surface.png ├── 06-sphere-normal.png ├── 07-cos-alpha.png ├── 07-specular-decay.png ├── 07-specular-diagram.png ├── 07-specular-exponent.png ├── 08-mirror.png ├── 08-nl.png ├── 08-shadow-cases.png ├── 08-shadow-directional.png ├── 08-shadow-point.png ├── 08-vec-r.png ├── 09-csg.png ├── 09-refraction.png ├── 09-shadow-coherence.png ├── 15-mp-ambient.png ├── 15-mp-composite.png ├── 15-mp-l1.png ├── 15-mp-l2.png ├── 15-shadow-volume.png ├── 15-sv-direct.png ├── 15-sv-reverse.png ├── aa-point-diff.png ├── aa-point-plus-vector.png ├── aa-points.png ├── aa-vector-cross-product.png ├── aa-vector-plus-vector.png ├── aa-vector-scaling.png ├── aa-vectors.png ├── aug1983.jpg ├── bad-texture-minification.png ├── bilinear-texture-weights.png ├── bump-bump1.jpg ├── bump-bump2.jpg ├── bump-flat.jpg ├── bump-map.png ├── camera-movement-1.png ├── camera-movement-2.png ├── camera-movement-redcube-1.png ├── camera-movement-redcube-2.png ├── checkerboard.png ├── comparison-1.png ├── comparison-2.png ├── coordinate-system.png ├── cover.jpg ├── crate-texture.jpg ├── image-000.jpg ├── image-001.png ├── linias.jpeg ├── mipmap-levels.png ├── r11-linear-function.png ├── r12-perspective.png ├── r12-perspective2.png ├── r12-perspective3.png ├── r13-cube.png ├── r13-rotate-translate.png ├── r13-translate-rotate.png ├── r14-clip-plane-sphere.png ├── r14-clip-spheres-1.png ├── r14-clip-spheres-2.png ├── r14-clip-spheres-3.png ├── r14-clip-spheres-4.png ├── r14-clip-triangle1.png ├── r14-clip-triangle2.png ├── r14-clip1.png ├── r14-clip2.png ├── r14-clip3.png ├── r14-clip4.png ├── r14-clipping-planes.png ├── r14-unclipped-object.png ├── r14-vertex-classification.png ├── r15-closed-objects.png ├── r15-cube-normals.png ├── r15-culling.png ├── r15-depth.png ├── r15-impossible-sort.png ├── r15-linear-z-1.png ├── r15-linear-z-2.png ├── r15-linear-z.png ├── r16-flat-normals.png ├── r16-gouraud-sequence.png ├── r16-phong-sequence.png ├── r16-sphere-normals.png ├── r16-wrong-interpolation.png ├── r17-linear-texture.png ├── r17-texture-mapping.png ├── raster-01.png ├── raster-01b.png ├── raster-01c.png ├── raster-01d.png ├── raster-02.png ├── raster-03.png ├── raster-03b.png ├── raster-04.png ├── raster-05.png ├── raster-06.png ├── raster-07.png ├── raster-08.png ├── raster-10a.png ├── raster-10b.png ├── raster-11.png ├── raster-11b.png ├── raster-11c.png ├── raster-11d.png ├── raster-11e.png ├── raster-12-sxs.png ├── raster-12.png ├── raster-12b.png ├── raster-rt.png ├── raytracer-01.png ├── raytracer-02.png ├── raytracer-03.png ├── raytracer-04.png ├── raytracer-05-r1-zoom.png ├── raytracer-05-r3-zoom.png ├── raytracer-05.png ├── raytracer-06.png ├── rt-csg.png ├── texture-close-linear.png ├── texture-close-nearest.png └── triangle-horizontal-segments.png /00-introduction.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Introduction - Computer Graphics from Scratch 3 | # Introduction {#ch:Introduction .unnumbered} 4 | 5 | Computer graphics is a fascinating topic. How do you go from a few algorithms and some geometric data to the special effects for movies like *Star Wars* and *The Avengers*, animated movies like *Toy Story* and *Frozen*, or the graphics of popular video games like *Fortnite* or *Call of Duty*? 6 | 7 | Computer graphics is also a frighteningly broad topic: from rendering 3D scenes to creating image filters, from digital typography to simulating particle systems, there are a multitude of disciplines that can be thought of as part of computer graphics. One book couldn't hope to cover all these subjects; it would take a library. This book focuses exclusively on the topic of rendering 3D scenes. 8 | 9 | *Computer Graphics from Scratch* is my humble attempt to present this one slice of computer graphics in an accessible way. It is written to be easily understood by high-school students, while staying rigorous enough for professional engineers. It covers the same topics as a full university course---it is, in fact, based on my years of teaching the subject at university. 10 | 11 | ## Who This Book Is For 12 | 13 | This book is for anyone with an interest in computer graphics, from high-school students to seasoned professionals. 14 | 15 | I have made a conscious choice to favor simplicity and clarity in the presentation. This is reflected in the choice of ideas and algorithms within the book. While the algorithms are industry-standard, whenever there's more than one way to achieve a certain result, I have chosen the one that is easiest to understand. At the same time, I've put considerable effort into making sure there's no hand-waving or trickery. I tried to keep in mind Albert Einstein's advice: "Everything should be made as simple as possible, but no simpler." 16 | 17 | There's little prerequisite knowledge and no hardware or software dependencies. The only primitive used in this book is a method that lets us set the color of a pixel---as close to *from scratch* as we can get. The algorithms are conceptually simple, and the math is straightforward---at most, a tiny bit of high-school trigonometry. We also use some linear algebra, but the book includes a short appendix presenting everything we need in a very practical way. 18 | 19 | ## What This Book Covers 20 | 21 | This book starts from scratch and builds up to two complete, fully functional renderers: a raytracer and a rasterizer. Although they follow very different approaches, they produce similar results when used to render a simple scene. Figure 1 shows a comparison. 22 | 23 | ![Figure 1: A simple scene rendered by the raytracer (left) and the rasterizer (right) developed in this book.](/computer-graphics-from-scratch/images/comparison-1.png){#fig:result-comparison-1} 24 | 25 | While the features of the raytracer and rasterizer have considerable overlap, they are not identical, and this book explores their specific strengths, some of which can be seen in Figure 2. 26 | 27 | ![Figure 2: The raytracer and the rasterizer have their own unique features. Left: raytraced shadows and recursive reflections; right: rasterized textures.](/computer-graphics-from-scratch/images/comparison-2.png){#fig:result-comparison-2} 28 | 29 | The book provides informal pseudocode throughout the text, as well as links to fully working implementations written in JavaScript that can run directly in any web browser. 30 | 31 | ## Why Read This Book? {#why-read-this} 32 | 33 | This book should give you all the knowledge you need to write software renderers. It does not make use of, or teach you how to use, existing rendering APIs such as OpenGL, Vulkan, Metal, or DirectX. 34 | 35 | Modern GPUs are powerful and ubiquitous, and few people have good reason to write a pure software renderer. However, the experience of writing one is valuable for the following reasons: 36 | 37 | Shaders are software. 38 | 39 | : The first, ancient GPUs of the early 1990s implemented their rendering algorithms directly in hardware, so you could use them but not modify them (which is why most games from the mid-1990s look so similar to each other). Today, you write your own rendering algorithms (called *shaders* in this context) and they run in the specialized chips of a GPU. 40 | 41 | Knowledge is power. 42 | 43 | : Understanding the theory behind the different rendering techniques, rather than copying and pasting half-understood fragments of code or cargo-culting popular approaches, lets you write better shaders and rendering pipelines. 44 | 45 | Graphics are fun. 46 | 47 | : Few areas of computer science provide the kind of instant gratification offered by computer graphics. The sense of accomplishment you get when your SQL query runs just right is *nothing* compared to what you feel the first time you get raytraced reflections right. I taught computer graphics at university for five years, and I often wondered why I enjoyed teaching the same thing semester after semester for so long; in the end, what made it worth it was seeing the faces of my students light up and seeing them use their first rendered scenes as their desktop backgrounds. 48 | 49 | ## About This Book 50 | 51 | This book is divided into two parts, *Raytracing* and *Rasterization*, corresponding to the two renderers we are going to build. 52 | 53 | The first chapter introduces some basic knowledge necessary to understand these two parts. I suggest you read the chapters in order, but both parts of the book are self-contained enough that they can be read mostly independently. 54 | 55 | Here's a brief overview of what you'll find in each chapter. 56 | 57 | Chapter 1: Introductory Concepts 58 | 59 | : We define the *canvas*, the abstract surface we'll be drawing on, and `PutPixel`, our only tool to draw on it. We also learn to represent and manipulate colors. 60 | 61 | ```{=html} 62 | 63 | ``` 64 | 65 | Part I: Raytracing 66 | 67 | : 68 | 69 | ```{=html} 70 | 71 | ``` 72 | 73 | Chapter 2: Basic Raytracing 74 | 75 | : We develop a basic raytracing algorithm capable of rendering a few spheres, which look like colored circles. 76 | 77 | Chapter 3: Light 78 | 79 | : We establish a model of how light interacts with objects and extend the raytracer to simulate light. The spheres now look like spheres. 80 | 81 | Chapter 4: Shadows and Reflections 82 | 83 | : We improve the appearance of the spheres: they cast shadows on each other and can have mirror-like surfaces where we can see reflections of other spheres. 84 | 85 | Chapter 5: Extending the Raytracer 86 | 87 | : We present an overview of additional features that can be added to the raytracer, but which are beyond the scope of this book. 88 | 89 | ```{=html} 90 | 91 | ``` 92 | 93 | Part II: Rasterization 94 | 95 | : 96 | 97 | ```{=html} 98 | 99 | ``` 100 | 101 | Chapter 6: Lines 102 | 103 | : We start from a blank canvas and develop an algorithm to draw line segments. 104 | 105 | Chapter 7: Filled Triangles 106 | 107 | : We reuse some core ideas from the previous chapter to develop an algorithm to draw triangles filled with a single color. 108 | 109 | Chapter 8: Shaded Triangles 110 | 111 | : We extend the algorithm from the previous chapter to fill our triangles with a smooth color gradient. 112 | 113 | Chapter 9: Perspective Projection 114 | 115 | : We take a break from drawing 2D shapes to look at the geometry and math we need to convert a 3D point into a 2D point we can draw on the canvas. 116 | 117 | Chapter 10: Describing and Rendering a Scene 118 | 119 | : We develop a representation for objects in the scene and explore how to use perspective projection to draw them on the canvas. 120 | 121 | Chapter 11: Clipping 122 | 123 | : We develop an algorithm to remove the parts of the scene that the camera can't see. Now we can safely render the scene from any camera position. 124 | 125 | Chapter 12: Hidden Surface Removal 126 | 127 | : We combine perspective projection and shaded triangles to render solid-looking objects; for this to work correctly, we need to ensure distant objects don't cover closer objects. 128 | 129 | Chapter 13: Shading 130 | 131 | : We explore how to apply the lighting equation developed in Chapter 3 to entire triangles. 132 | 133 | Chapter 14: Textures 134 | 135 | : We develop an algorithm to "paint" images on our triangles as a way to fake surface detail. 136 | 137 | Chapter 15: Extending the Rasterizer 138 | 139 | : We present an overview of features that can be added to the rasterizer, but which are beyond the scope of this book. 140 | 141 | ```{=html} 142 | 143 | ``` 144 | 145 | Appendix: Linear Algebra 146 | 147 | : We introduce the basic concepts from linear algebra that are used throughout this book: points, vectors, and matrices. We present the operations we can do with them and provide some examples of what we can use them for. 148 | 149 | ## About the Author 150 | 151 | I'm a senior software engineer at Google. In the past, I've worked at Improbable (), who have a good shot at building the Matrix for real (or at the very least revolutionizing multiplayer game development), and at Mystery Studio (), a game development company I founded and ran for about a decade and which released almost 20 games you've probably never heard of. 152 | 153 | I taught computer graphics for five years at university, where it was a semester-long third-year subject. I am grateful to all of my students, who served as unwitting guinea pigs for the materials that inspired this book. 154 | 155 | I have other interests besides computer graphics, engineering-related and otherwise. See my website, , for more details and contact information. -------------------------------------------------------------------------------- /07-filled-triangles.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Filled Triangles - Computer Graphics from Scratch 3 | # Filled Triangles {#ch:filled_triangles} 4 | 5 | In the previous chapter, we took our first steps toward drawing simple shapes---namely, straight line segments---using only `PutPixel` and an algorithm based on simple math. In this chapter, we'll reuse some of the math to draw something more interesting: a filled triangle. 6 | 7 | ## Drawing Wireframe Triangles 8 | 9 | We can use the `DrawLine` method to draw the outline of a triangle: 10 | 11 | ~~~ 12 | DrawWireframeTriangle (P0, P1, P2, color) { 13 | DrawLine(P0, P1, color); 14 | DrawLine(P1, P2, color); 15 | DrawLine(P2, P0, color); 16 | } 17 | ~~~ 18 | 19 | This kind of outline is called a *wireframe*, because it looks like a triangle made of wires, as you can see in Figure 7-1. 20 | 21 | ![Figure 7-1: A wireframe triangle with vertices (--200,--250), (200,50), and (20,250)](/computer-graphics-from-scratch/images/raster-03.png){#fig:triangle_wireframe} 22 | 23 | This is a promising start! Next we'll explore how to fill that triangle with a color. 24 | 25 | ## Drawing Filled Triangles 26 | 27 | We want to draw a triangle filled with a color of our choice. As is often the case in computer graphics, there's more than one way to approach this problem. We'll draw filled triangles by thinking of them as a collection of horizontal line segments that look like a triangle when drawn together. Figure 7-2 shows what one such triangle would look like if we could see the individual segments. 28 | 29 | ![Figure 7-2: Drawing a filled triangle using horizontal segments](/computer-graphics-from-scratch/images/triangle-horizontal-segments.png){#fig:filled_triangle_segments} 30 | 31 | The following is a very rough first approximation of what we want to do: 32 | 33 | ~~~ 34 | for each horizontal line y between the triangle's top and bottom 35 | compute x_left and x_right for this y 36 | DrawLine(x_left, y, x_right, y) 37 | ~~~ 38 | 39 | Let's start with "between the triangle's top and bottom." A triangle is defined by its three vertices $P_0$, $P_1$, and $P_2$. If we sort these points by increasing value of $y$, such that $y_0 \le y_1 \le y_2$, then the range of values of $y$ occupied by the triangle is $[y_0, y_2]$: 40 | 41 | ~~~ 42 | if y1 < y0 { swap(P1, P0) } 43 | if y2 < y0 { swap(P2, P0) } 44 | if y2 < y1 { swap(P2, P1) } 45 | ~~~ 46 | 47 | Sorting the vertices this way makes things easier: after doing this, we can always assume $P_0$ is the lowest point of the triangle and $P_2$ is the highest, so we won't have to deal with every possible ordering. 48 | 49 | Next we have to compute the `x_left` and `x_right` arrays. This is slightly tricky, because the triangle has three sides, not two. However, considering only the values of $y$, we always have a "tall" side from $P_0$ to $P_2$, and two "short" sides from $P_0$ to $P_1$ and $P_1$ to $P_2$. 50 | 51 | There's a special case when $y_0 = y_1$ or $y_1 = y_2$---that is, when one of the sides of the triangle is horizontal. When this happens, the two other sides have the same height, so either could be considered the "tall" side. Should we choose the right side or the left side? Fortunately, it doesn't matter; the algorithm will support both left-to-right and right-to-left horizontal lines, so we can stick to our definition that the "tall" side is the one from $P_0$ to $P_2$. 52 | 53 | The values for `x_right` will come either from the tall side or from joining the short sides; the values for `x_left` will come from the other set. We'll start by computing the values of $x$ for the three sides. Since we'll be drawing horizontal segments, we want exactly one value of $x$ for each value of $y$; this means we can compute these values by using `Interpolate`, with $y$ as the independent variable and $x$ as the dependent variable: 54 | 55 | ~~~ 56 | x01 = Interpolate(y0, x0, y1, x1) 57 | x12 = Interpolate(y1, x1, y2, x2) 58 | x02 = Interpolate(y0, x0, y2, x2) 59 | ~~~ 60 | 61 | The $x$ values for one of the sides are in `x02`; the values for the other side come from the concatenation of `x01` and `x12`. Note that there's a repeated value in `x01` and `x12`: the $x$ value for $y_1$ is both the last value of `x01` and the 62 | 63 | first value of `x12`. We just need to get rid of one of them (we arbitrarily choose the last value of `x01`), and then concatenate the arrays: 64 | 65 | ~~~ 66 | remove_last(x01) 67 | x012 = x01 + x12 68 | ~~~ 69 | 70 | We finally have `x02` and `x012`, and we need to determine which is `x_left` and which is `x_right`. To do this, we can choose any horizontal line (for example, the middle one) and compare its $x$ values in `x02` and `x012`: if the $x$ value in `x02` is smaller than the one in `x012`, then we know `x02` must be `x_left`; otherwise, it must be `x_right`. 71 | 72 | ~~~ 73 | m = floor(x02.length / 2) 74 | if x02[m] < x012[m] { 75 | x_left = x02 76 | x_right = x012 77 | } else { 78 | x_left = x012 79 | x_right = x02 80 | } 81 | ~~~ 82 | 83 | Now we have all the data we need to draw the horizontal segments. We could use `DrawLine` for this. However, `DrawLine` is a very generic function, and in this case we're always drawing horizontal, left-to-right lines, so it's more efficient to use a simple `for` loop. This also gives us more "control" over every pixel we draw, which will be especially useful in the following chapters. 84 | 85 | Listing 7-1 has the completed `DrawFilledTriangle`. 86 | 87 | ~~~ { data-label="lst:draw_filled_triangle" data-caption="Listing 7-1: A function to draw filled triangles" } 88 | DrawFilledTriangle (P0, P1, P2, color) { 89 | ❶// Sort the points so that y0 <= y1 <= y2 90 | if y1 < y0 { swap(P1, P0) } 91 | if y2 < y0 { swap(P2, P0) } 92 | if y2 < y1 { swap(P2, P1) } 93 | 94 | ❷// Compute the x coordinates of the triangle edges 95 | x01 = Interpolate(y0, x0, y1, x1) 96 | x12 = Interpolate(y1, x1, y2, x2) 97 | x02 = Interpolate(y0, x0, y2, x2) 98 | 99 | ❸// Concatenate the short sides 100 | remove_last(x01) 101 | x012 = x01 + x12 102 | 103 | ❹// Determine which is left and which is right 104 | m = floor(x012.length / 2) 105 | if x02[m] < x012[m] { 106 | x_left = x02 107 | x_right = x012 108 | } else { 109 | x_left = x012 110 | x_right = x02 111 | } 112 | 113 | ❺// Draw the horizontal segments 114 | for y = y0 to y2 { 115 | for x = x_left[y - y0] to x_right[y - y0] { 116 | canvas.PutPixel(x, y, color) 117 | } 118 | } 119 | } 120 | ~~~ 121 | 122 | Let's see what's going on here. The function receives the three vertices of the triangle as arguments, in any order. Our algorithm needs them to be in bottom-to-top order, so we sort them that way ❶. Next, we compute the `x` values for each `y` value of the three sides ❷, and concatenate the arrays from the two "short" sides ❸. Then we figure out which is `x_left` and which is `x_right` ❹. Finally, for each horizontal segment between the top and the bottom of the triangle, we get its left and right `x` coordinates, and draw the segment pixel by pixel ❺. 123 | 124 | Figure 7-3 shows the results; for verification purposes, we call `DrawFilledTriangle` and then `DrawWireframeTriangle` with the same coordinates but different colors. Verify your results whenever you can---this is a very effective way to find bugs in the code! 125 | 126 | ![Figure 7-3: A filled triangle, with wireframe edges for verification](/computer-graphics-from-scratch/images/raster-03b.png){#fig:filled_triangle_with_edges} 127 | 128 | Source code and live demo >> 129 | 130 | 131 | You may notice the black outline of the triangle doesn't *exactly* match the green interior region; this is especially visible in the lower-right edge of the triangle. This is because `DrawLine` is computing $y = f(x)$ for that edge but `DrawTriangle` is computing $x = f(y)$, and this can produce slightly different results due to rounding. This is the kind of approximation error we're willing to accept in order to make our rendering algorithms fast. 132 | 133 | ## Summary 134 | 135 | In this chapter, we've developed an algorithm to draw a filled triangle on the canvas. This is a step up from drawing line segments. We've also learned to think of triangles as a set of horizontal segments that we can work with individually. 136 | 137 | In the next chapter, we'll extend the math and the algorithm to draw a triangle filled with a color gradient; the math and the reasoning behind the algorithm will be key to the rest of the features developed in this book. -------------------------------------------------------------------------------- /08-shaded-triangles.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Shaded Triangles - Computer Graphics from Scratch 3 | # Shaded Triangles {#ch:shaded_triangles} 4 | 5 | In the previous chapter, we developed an algorithm to draw a triangle filled with a solid color. Our goal for this chapter is to draw a *shaded* triangle---that is, a triangle filled with a color gradient. 6 | 7 | ## Defining Our Problem 8 | 9 | We want to fill the triangle with different *shades* of a single color. It will look like Figure 8-1. 10 | 11 | We need a more formal definition of what we're trying to draw. To do this, we'll assign a real value $h$ to each vertex, denoting the intensity of the color at the vertex. $h$ is in the $[0.0, 1.0]$ range, where $0.0$ represents the darkest possible shade (that is, black) and $1.0$ represents the brightest possible shade (that is, the original color---not white!). 12 | 13 | ![Figure 8-1: A shaded triangle](/computer-graphics-from-scratch/images/raster-04.png){#fig:shaded_triangle} 14 | 15 | To compute the exact color shade of a pixel given the base color of the triangle $C$ and the intensity at that pixel $h$, we'll multiply channel-wise: $C_h = (R_C \cdot h, G_C \cdot h, B_C \cdot h)$. Therefore $h = 0.0$ yields pure black, $h = 1.0$ yields the original color $C$, and $h = 0.5$ yields a color half as bright as the original one. 16 | 17 | ## Computing Edge Shading 18 | 19 | In order to draw a shaded triangle, all we need to do is compute a value of $h$ for each pixel of the triangle, compute the corresponding shade of the color, and paint the pixel. Easy! 20 | 21 | At this point, however, we only know the values of $h$ for the triangle vertices, because we chose them. How do we compute values of $h$ for the rest of the triangle? 22 | 23 | Let's start with the edges of the triangle. Consider the edge $AB$. We know $h_A$ and $h_B$. What happens at $M$, the midpoint of $AB$? Since we want the intensity to vary smoothly from $A$ to $B$, the value of $h_M$ must be between $h_A$ and $h_B$. Since $M$ is in the middle of $AB$, why not choose $h_M$ to be in the middle of $h_A$ and $h_B$---that is, their average? 24 | 25 | More formally, we have a function $h = f(P)$ that gives each point $P$ an intensity value $h$; we know its values at $A$ and $B$, $h(A) = h_A$ and $h(B) = h_B$, respectively. We want this function to be smooth. Since we know nothing else about $h = f(P)$, we can choose any function that is compatible with what we *do* know, such as a linear function (Figure 8-2). 26 | 27 | ![Figure 8-2: A linear function *h*(*P*), compatible with what we know about *h*(*A*) and *h*(*B*)](/computer-graphics-from-scratch/images/r11-linear-function.png){#fig:linear_function} 28 | 29 | This is suspiciously similar to the situation in the previous chapter: we had a linear function $x = f(y)$, we knew the values of this function at the vertices of the triangle, and we wanted to compute values of $x$ along its sides. We can compute values of $h$ along the sides of the triangle in a very similar way, using `Interpolate` with y as the independent variable (the values we know) and h as the dependent variable (the values we want): 30 | 31 | ~~~ 32 | x01 = Interpolate(y0, x0, y1, x1) 33 | h01 = Interpolate(y0, h0, y1, h1) 34 | 35 | x12 = Interpolate(y1, x1, y2, x2) 36 | h12 = Interpolate(y1, h1, y2, h2) 37 | 38 | x02 = Interpolate(y0, x0, y2, x2) 39 | h02 = Interpolate(y0, h0, y2, h2) 40 | ~~~ 41 | 42 | Next, we concatenated the $x$ arrays for the "short" sides and then determined which of `x02` and `x012` was `x_left` and which was `x_right`. Again, we can do something very similar here for the $h$ vectors. 43 | 44 | However, we will always use the $x$ values to determine which side is left and which side is right, and the $h$ values will just "follow along." $x$ and $h$ are properties of actual points on the screen, so we can't freely mix-and-match left- and right-side values. 45 | 46 | We can code this as follows: 47 | 48 | ~~~ 49 | // Concatenate the short sides 50 | remove_last(x01) 51 | x012 = x01 + x12 52 | 53 | remove_last(h01) 54 | h012 = h01 + h12 55 | 56 | // Determine which is left and which is right 57 | m = floor(x012.length / 2) 58 | if x02[m] < x012[m] { 59 | x_left = x02 60 | h_left = h02 61 | 62 | x_right = x012 63 | h_right = h012 64 | } else { 65 | x_left = x012 66 | h_left = h012 67 | 68 | x_right = x02 69 | h_right = h02 70 | } 71 | ~~~ 72 | 73 | This is very similar to the relevant section of the code in the previous chapter (Listing 7-1), except that every time we do something with an `x` vector, we do the same with the corresponding `h` vector. 74 | 75 | ## Computing Interior Shading 76 | 77 | The last step is drawing the actual horizontal segments. For each segment, we know `x_left` and `x_right`, as in the previous chapter; now we also know `h_left` and `h_right`. But this time we can't just iterate from left to right and draw every pixel with the base color: we need to compute a value of $h$ for *each pixel* of the segment. 78 | 79 | Again, we can assume $h$ varies linearly with $x$, and use `Interpolate` to compute these values. In this case, the independent variable is $x$, and it goes from the `x_left` value to the `x_right` value of the specific horizontal segment we're shading; the dependent variable is $h$, and its corresponding values for `x_left` and `x_right` are `h_left` and `h_right` for that segment: 80 | 81 | ~~~ 82 | x_left_this_y = x_left[y - y0] 83 | h_left_this_y = h_left[y - y0] 84 | 85 | x_right_this_y = x_right[y - y0] 86 | h_right_this_y = h_right[y - y0] 87 | 88 | h_segment = Interpolate(x_left_this_y, h_left_this_y, 89 | x_right_this_y, h_right_this_y) 90 | ~~~ 91 | 92 | Or, expressed in a more compact way: 93 | 94 | ~~~ 95 | h_segment = Interpolate(x_left[y - y0], h_left[y - y0], 96 | x_right[y - y0], h_right[y - y0]) 97 | ~~~ 98 | 99 | Now it's just a matter of computing the color for each pixel and painting it! Listing 8-1 shows the complete pseudocode for `DrawShadedTriangle`. 100 | 101 | ~~~ { data-label="lst:draw_shaded_triangle" data-caption="Listing 8-1: A function for drawing shaded triangles" } 102 | DrawShadedTriangle (P0, P1, P2, color) { 103 | ❶// Sort the points so that y0 <= y1 <= y2 104 | if y1 < y0 { swap(P1, P0) } 105 | if y2 < y0 { swap(P2, P0) } 106 | if y2 < y1 { swap(P2, P1) } 107 | 108 | // Compute the x coordinates and h values of the triangle edges 109 | x01 = Interpolate(y0, x0, y1, x1) 110 | h01 = Interpolate(y0, h0, y1, h1) 111 | 112 | x12 = Interpolate(y1, x1, y2, x2) 113 | h12 = Interpolate(y1, h1, y2, h2) 114 | 115 | x02 = Interpolate(y0, x0, y2, x2) 116 | h02 = Interpolate(y0, h0, y2, h2) 117 | 118 | // Concatenate the short sides 119 | remove_last(x01) 120 | x012 = x01 + x12 121 | 122 | remove_last(h01) 123 | h012 = h01 + h12 124 | 125 | // Determine which is left and which is right 126 | m = floor(x012.length / 2) 127 | if x02[m] < x012[m] { 128 | x_left = x02 129 | h_left = h02 130 | 131 | x_right = x012 132 | h_right = h012 133 | } else { 134 | x_left = x012 135 | h_left = h012 136 | 137 | x_right = x02 138 | h_right = h02 139 | } 140 | 141 | // Draw the horizontal segments 142 | ❷for y = y0 to y2 { 143 | x_l = x_left[y - y0] 144 | x_r = x_right[y - y0] 145 | 146 | ❸h_segment = Interpolate(x_l, h_left[y - y0], x_r, h_right[y - y0]) 147 | for x = x_l to x_r { 148 | ❹shaded_color = color * h_segment[x - x_l] 149 | canvas.PutPixel(x, y, shaded_color) 150 | } 151 | } 152 | } 153 | ~~~ 154 | 155 | The pseudocode for this function is very similar to that for the function developed in the previous chapter (Listing 7-1). Before the horizontal segment loop ❷, we manipulate the $x$ vectors and the $h$ vectors in similar ways, as explained above. Inside the loop, we have an extra call to `Interpolate` ❸ to compute the $h$ values for every pixel in the current horizontal segment. Finally, in the inner loop we use the interpolated values of $h$ to compute a color for each pixel ❹. 156 | 157 | Note that we're sorting the triangle vertices as before ❶. However, we now consider these vertices and their attributes, such as the intensity value $h$, to be an indivisible whole; that is, swapping the coordinates of two vertices must also swap their attributes. 158 | 159 | Source code and live demo >> 160 | 161 | 162 | ## Summary 163 | 164 | In this chapter, we've extended the triangle-drawing code developed in the previous chapter to support smoothly shaded triangles. Note that we can still use it to draw single color triangles by using 1.0 as the value of $h$ for all three vertices. 165 | 166 | The idea behind this algorithm is actually more general than it seems. The fact that $h$ is an intensity value has no impact on the "shape" of the algorithm; we assign meaning to this value only at the very end, when we're about to call `PutPixel`. This means we could use this algorithm to compute the value of any *attribute* of the vertices of the triangle, for every pixel of the triangle, as long as we assume this value varies linearly on the screen. 167 | 168 | We will indeed use this algorithm to improve the visual appearance of our triangles in the upcoming chapters. For this reason, it's a good idea to make sure you really understand this algorithm before proceeding further. 169 | 170 | In the next chapter, however, we take a small detour. Having mastered the drawing of triangles on a 2D canvas, we will turn our attention to the third dimension. -------------------------------------------------------------------------------- /09-perspective-projection.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Perspective Projection - Computer Graphics from Scratch 3 | # Perspective Projection {#ch:perspective_projection} 4 | 5 | So far, we have learned to draw 2D triangles on the canvas, given the 2D coordinates of their vertices. However, the goal of this book is to render 3D scenes. So in this chapter, we'll take a break from 2D triangles and focus on how to turn 3D scene coordinates into 2D canvas coordinates. We'll then use this to draw 3D triangles on the 2D canvas. 6 | 7 | ## Basic Assumptions 8 | 9 | Just like we did at the beginning of [Chapter 2 (Basic Raytracing)](02-basic-raytracing.html), we'll start by defining a *camera*. We'll use the same conventions as before: the camera is at $O = (0, 0, 0)$, looking in the direction of $\vec{Z_+}$, and its "up" vector is $\vec{Y_+}$. We'll also define a rectangular *viewport* of size $V_w$ and $V_h$ whose edges are parallel to $\vec{X}$ and $\vec{Y}$, at a distance $d$ from the camera. The goal is to draw on the canvas whatever the camera sees through the viewport. If you need a refresher on these concepts, refer to [Chapter 2 (Basic Raytracing)](02-basic-raytracing.html). 10 | 11 | Consider a point $P$ somewhere in front of the camera. We're interested in finding $P\, '$, the point on the viewport through which the camera sees $P$, as shown in Figure 9-1. 12 | 13 | ![Figure 9-1: A simple perspective projection setup. The camera sees *P* through *P '*, which is on the projection plane.](/computer-graphics-from-scratch/images/r12-perspective.png){#fig:perspective_projection} 14 | 15 | This is the opposite of what we did with raytracing. Our raytracer started with a point in the canvas, and determined what it could see through that point; here, we start from a point in the scene and want to determine where it is seen on the viewport. 16 | 17 | ## Finding P' 18 | 19 | To find $P\, '$, let's look at the setup shown in Figure 9-1 from a different angle, literally. Figure 9-2 shows a diagram of the setup viewed from the "right," as if we were standing on the $\vec{X}$ axis: $\vec{Y_+}$ points up, $\vec{Z_+}$ points to the right, and $\vec{X_+}$ points at us. 20 | 21 | ![Figure 9-2: The perspective projection setup, viewed from the right](/computer-graphics-from-scratch/images/r12-perspective2.png){#fig:perspective_side_view} 22 | 23 | In addition to $O$, $P$, and $P\, '$, this diagram also shows the points $A$ and $B$, which help us reason about it. 24 | 25 | We know that $P\, '_z = d$ because we defined $P\, '$ to be a point on the viewport, and we know the viewport is embedded in the plane $Z = d$. 26 | 27 | We can also see that the triangles $OP\, ' A$ and $OPB$ are similar, because their corresponding sides ($P\, 'A$ and $PB$, $OP$ and $OP\, '$, and $OA$ and $OB$) are parallel. This implies that the proportions of their sides are the same; for example: 28 | 29 | $${|P\, 'A| \over |OA|} = {|PB| \over |OB|}$$ 30 | 31 | From that, we get 32 | 33 | $$|P\, 'A| = {|PB| \cdot |OA| \over {|OB|}}$$ 34 | 35 | The (signed) length of each segment in that equation is a coordinate of a point we know or we're interested in: $|P\, 'A| = P\, '_y$, $|PB| = P_y$, $|OA| = P\, '_z = d$, and $|OB| = P_z$. If we substitute these in the equation we get 36 | 37 | $$P\, '_y = {P_y \cdot d \over P_z}$$ 38 | 39 | We can draw a similar diagram, this time viewing the setup from above: $\vec{Z_+}$ points up, $\vec{X_+}$ points to the right, and $\vec{Y_+}$ points at us (Figure 9-3). 40 | 41 | ![Figure 9-3: Top view of the perspective projection setup](/computer-graphics-from-scratch/images/r12-perspective3.png){#fig:perspective_top_view} 42 | 43 | Using similar triangles again in the same way, we can deduce that 44 | 45 | $$P\, '_x = {P_x \cdot d \over P_z}$$ 46 | 47 | We now have all three coordinates of $P\, '$. 48 | 49 | ## The Projection Equation 50 | 51 | Let's put all this together. Given a point $P$ in the scene and a standard camera and viewport setup, we can compute the projection of $P$ on the viewport, which we call $P\, '$, as follows: 52 | 53 | $$P\, '_x = {P_x \cdot d \over P_z}$$ 54 | 55 | $$P\, '_y = {P_y \cdot d \over P_z}$$ 56 | 57 | $$P\, '_z = d$$ 58 | 59 | $P\, '$ is on the viewport, but it's still a point in 3D space. How do we get the corresponding point in the canvas? 60 | 61 | We can immediately drop $P\, '_z$, because every projected point is on the viewport plane. Next we need to convert $P\, '_x$ and $P\, '_y$ to canvas coordinates $C_x$ and $C_y$. $P\, '$ is still a point in the scene, so its coordinates are expressed in scene units. We can divide them by the width and height of the viewport. These are also expressed in scene units, so we obtain temporarily unit-less values. Finally, we multiply them by the width and height of the canvas, expressed in pixels: 62 | 63 | $$C_x = {{P\, '_x \cdot C_w} \over {V_w}}$$ 64 | 65 | $$C_y = {{P\, '_y \cdot C_h} \over {V_h}}$$ 66 | 67 | This viewport-to-canvas transform is the exact inverse of the canvas-to-viewport transform we used in the raytracing part of this book. And with this, we can finally go from a point in the scene to a pixel on the screen! 68 | 69 | ## Properties of the Projection Equation 70 | 71 | Before we move on, there are some interesting properties of the projection equation that are worth discussing. 72 | 73 | The equations above should be compatible with our day-to-day experience of looking at things in the real world. For example, the farther away an object is, the smaller it looks; and indeed, if we increase $P_z$, we get smaller values of $P\, '_x$ and $P\, '_y$. 74 | 75 | However, things stop being so intuitive when we decrease the value of $P_z$ too much; for negative values of $P_z$, that is, when an object is *behind* the camera, the object is still projected, but upside down! And, of course, when $P_z = 0$ we'd divide by zero and the universe would implode. We'll need to find a way to avoid these unpleasant situations; for now, we'll assume that every point is in front of the camera and deal with this in a later chapter. 76 | 77 | Another fundamental property of the perspective projection is that it preserves point alignment: if three points are aligned in space, their projections will be aligned on the viewport. In other words, a straight line is always projected as a straight line. This might sound too obvious to be worth mentioning, but note, for example, that the *angle* between two lines isn't preserved: in real life, we see parallel lines "converge" at the horizon, such as when driving on a highway. 78 | 79 | The fact that a straight line is always projected as a straight line is extremely convenient for us: so far we have talked about projecting a point, but how about projecting a line segment, or even a triangle? Because of this property, the projection of a line segment between two points is the line segment between the projection of two points; and the projection of a triangle is the triangle formed by the projections of its vertices. 80 | 81 | ## Projecting Our First 3D Object 82 | 83 | This means we can go ahead and draw our first 3D object: a cube. We define the coordinates of its 8 vertices, and we draw line segments between the projections of the 12 pairs of vertices that make the edges of the cube, as seen in Listing 9-1: 84 | 85 | ~~~ { data-label="lst:draw_cube" data-caption="Listing 9-1: Drawing a cube" } 86 | ViewportToCanvas(x, y) { 87 | return (x * Cw/Vw, y * Ch/Vh); 88 | } 89 | 90 | ProjectVertex(v) { 91 | return ViewportToCanvas(v.x * d / v.z, v.y * d / v.z) 92 | } 93 | 94 | // The four "front" vertices 95 | vAf = [-2, -0.5, 5] 96 | vBf = [-2, 0.5, 5] 97 | vCf = [-1, 0.5, 5] 98 | vDf = [-1, -0.5, 5] 99 | 100 | // The four "back" vertices 101 | vAb = [-2, -0.5, 6] 102 | vBb = [-2, 0.5, 6] 103 | vCb = [-1, 0.5, 6] 104 | vDb = [-1, -0.5, 6] 105 | 106 | // The front face 107 | DrawLine(ProjectVertex(vAf), ProjectVertex(vBf), BLUE); 108 | DrawLine(ProjectVertex(vBf), ProjectVertex(vCf), BLUE); 109 | DrawLine(ProjectVertex(vCf), ProjectVertex(vDf), BLUE); 110 | DrawLine(ProjectVertex(vDf), ProjectVertex(vAf), BLUE); 111 | 112 | // The back face 113 | DrawLine(ProjectVertex(vAb), ProjectVertex(vBb), RED); 114 | DrawLine(ProjectVertex(vBb), ProjectVertex(vCb), RED); 115 | DrawLine(ProjectVertex(vCb), ProjectVertex(vDb), RED); 116 | DrawLine(ProjectVertex(vDb), ProjectVertex(vAb), RED); 117 | 118 | // The front-to-back edges 119 | DrawLine(ProjectVertex(vAf), ProjectVertex(vAb), GREEN); 120 | DrawLine(ProjectVertex(vBf), ProjectVertex(vBb), GREEN); 121 | DrawLine(ProjectVertex(vCf), ProjectVertex(vCb), GREEN); 122 | DrawLine(ProjectVertex(vDf), ProjectVertex(vDb), GREEN); 123 | ~~~ 124 | 125 | We get something like Figure 9-4. 126 | 127 | ![Figure 9-4: Our first 3D object projected on a 2D canvas: a cube](/computer-graphics-from-scratch/images/raster-05.png){#fig:perspective_cube} 128 | 129 | Source code and live demo >> 130 | 131 | 132 | Success! We've managed to go from the geometrical 3D representation of an object to its 2D representation as seen from our synthetic camera! 133 | 134 | Our approach is very artisanal, though. It has many limitations. What if we want to render *two* cubes? Would we have to duplicate most of the code? What if we want to render something other than a cube? What if we want to let the user load a 3D model from a file? We clearly need a more data-driven approach to representing 3D geometry. 135 | 136 | ## Summary 137 | 138 | In this chapter, we've developed the math to go from a 3D point in the scene to a 2D point on the canvas. Because of the properties of the perspective projection, we can immediately extend this to projecting line segments and then to 3D objects. 139 | 140 | But we have left two important issues unresolved. First, Listing 9-1 mixes the perspective projection logic with the geometry of the cube; this approach clearly won't scale. Second, because of the limitations of the perspective projection equation, it can't handle objects that are behind the camera. We will address these issues in the next two chapters. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Computer Graphics from scratch 2 | 3 | ## Source code of the demos 4 | 5 | All the JavaScript code is licensed under the **MIT license**: 6 | 7 | MIT License 8 | 9 | Copyright © Gabriel Gambetta, 2017 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | (End MIT License) 30 | 31 | 32 | ## Text and images 33 | 34 | The text and images are licensed under the **Attribution-NonCommercial-NoDerivatives 4.0 International** 35 | license, also known as **CC BY-NC-ND 4.0**. You can find it [here](https://creativecommons.org/licenses/by-nc-nd/4.0/). -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computer Graphics from scratch 2 | 3 | This repository contains the text, diagrams and demos for the book 4 | [Computer Graphics from scratch](http://gabrielgambetta.com/computer-graphics-from-scratch), 5 | published by [No Starch Press](https://nostarch.com/computer-graphics-scratch). 6 | 7 | ![]() 8 | -------------------------------------------------------------------------------- /acknowledgements.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Acknowledgments - Computer Graphics from Scratch 3 | # Acknowledgments {#acknowledgments .unnumbered} 4 | 5 | Few books happen overnight; the one you're about to read has been almost 20 years in the making. As you might suspect, many people have been part of its story, in one way or another, and I want to thank them. In chronological order: 6 | 7 | Omar Paganini and Ernesto Ocampo Edye 8 | 9 | : As the Dean of the School of Engineering and the Director of Computer Science at Universidad Católica del Uruguay, they put considerable trust in me by letting me take the reins of Computer Graphics when I was but a fourth-year student, and by letting me completely reshape its curriculum in the way I thought best. Fellow professor **Roberto Lublinerman** was a great mentor throughout my first year of teaching. 10 | 11 | My students from 2003 to 2008 12 | 13 | : Besides being the unwitting guinea pigs of my continuously evolving teaching methodology, they accepted and respected a professor barely a year older than them (and, in some cases, younger than them). The joy in their faces when they created their first raytraced images made it all worth it. 14 | 15 | Alejandro Segovia Azapian 16 | 17 | : A student turned teaching assistant turned friend, his input has helped me evolve the material over time; having been a tiny part of his subsequent, very successful professional career specialized in realtime rendering and performance optimization fills me with pride. He was also a technical reviewer of this book, and his contributions ranged from fixing typos to suggesting deep structural improvements of some chapters. 18 | 19 | JC Van Winkel 20 | 21 | : He did his own editing pass and came up with a lot of valuable suggestions for improvement. 22 | 23 | The readers of *Hacker News* 24 | 25 | : My lecture notes, diagrams, and demos made the front page of *Hacker News*, and attracted considerable attention---including that of No Starch Press. If this hadn't happened, this book might have never existed. 26 | 27 | Bill Pollock, Alex Freed, Kassie Andreadis, and the entire No Starch Press team 28 | 29 | : They guided me through cleaning up and reshaping my lecture notes and diagrams, which in my mind were essentially ready to be published as a book, into an actual book. They took the raw materials to a whole new level; I had no idea this took so much work and effort, and Alex, Kassie, and the team did a stellar job. My name is the only one on the cover, but make no mistake, this was a group effort. -------------------------------------------------------------------------------- /afterword.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Afterword - Computer Graphics from Scratch 3 | # Afterword {#afterword .unnumbered} 4 | 5 | Congratulations! You now have a good understanding of how 3D rendering works. You've created a raytracer and a rasterizer and gained a good conceptual understanding of the algorithms and math that power them. 6 | 7 | However, as I explained in the introduction, it's impossible to cover the entirety of 3D rendering in a single book. Here's a few topics you might want to explore on your own to expand your horizons: 8 | 9 | Global illumination, including radiosity and path tracing 10 | 11 | : Find out how deep the "ambient light" rabbit hole goes! 12 | 13 | Physically based rendering 14 | 15 | : Illumination and shading models that don't just look good, but model real-life physics. 16 | 17 | Voxel rendering 18 | 19 | : Think Minecraft, or MRI scans in hospitals. 20 | 21 | Level-of-detail algorithms 22 | 23 | : This includes offline and dynamic mesh simplification, impostors, and billboards. These algorithms are how we efficiently render forests with billions of plants, crowds of millions of people, or extremely detailed 3D models. 24 | 25 | Acceleration structures 26 | 27 | : This includes binary space partition trees, k-d trees, quadtrees, and octrees. These structures help efficiently render massive scenes, such as an entire city. 28 | 29 | Terrain rendering 30 | 31 | : How to efficiently render a terrain model that might be as big as a country yet have human-scale detail. 32 | 33 | Atmospheric effects and particle systems 34 | 35 | : Fog, rain, and smoke, but also some less intuitive materials like grass and hair. 36 | 37 | Image-based lighting 38 | 39 | : Similar to environment mapping, but for diffuse lighting. 40 | 41 | High dynamic range, gamma correction 42 | 43 | : The color representation rabbit hole also goes deep. 44 | 45 | Caustics 46 | 47 | : Also known as "the moving white patterns at the bottom of the swimming pool." 48 | 49 | Procedural generation of textures and models 50 | 51 | : Add more variety and possibly infinitely big scenes. 52 | 53 | Hardware acceleration 54 | 55 | : Using OpenGL, Vulkan, DirectX, and others to run graphics algorithms on GPUs. 56 | 57 | Of course, there are many other topics, and that's just 3D rendering! Computer graphics is an even broader subject. Here are some areas you might want to investigate: 58 | 59 | Font rendering 60 | 61 | : This is surprisingly more complex than you might think. 62 | 63 | Image compression 64 | 65 | : How to store images in the least amount of space. 66 | 67 | Image processing (e.g. transforming and filtering) 68 | 69 | : Think Instagram filters. 70 | 71 | Image recognition 72 | 73 | : Is that a dog or a cat? 74 | 75 | Curve rendering, including Bezier curves and splines 76 | 77 | : Find out what these weird arrows on the curves of your favorite drawing program really are! 78 | 79 | Computational photography 80 | 81 | : How does the camera on your phone take such good pictures with almost no light? 82 | 83 | Image segmentation 84 | 85 | : Before you can "blur the background" of your video call, you need to determine which pixels are background and which aren't. 86 | 87 | Congratulations again on taking your first step into the world of computer graphics. Now you get to choose where to go next! -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/cover.jpg -------------------------------------------------------------------------------- /dedication.md: -------------------------------------------------------------------------------- 1 | !!html_class cgfs 2 | !!html_title Dedication - Computer Graphics from Scratch 3 | # Dedication {#dedication .unnumbered} 4 | 5 | To my dad (1947--2007), architect and self-taught programmer, who got me started on this path. 6 | 7 | ![My dad, my two-and-a-half-year-old self, and the ZX81.](/computer-graphics-from-scratch/images/aug1983.jpg) 8 | 9 | ![My earliest documented program ever, written at six-and-a-half years old, drew some lines on the screen of my ZX Spectrum+.](/computer-graphics-from-scratch/images/linias.jpeg) 10 | 11 |   -------------------------------------------------------------------------------- /demos/checkerboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/demos/checkerboard.png -------------------------------------------------------------------------------- /demos/crate-texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/demos/crate-texture.jpg -------------------------------------------------------------------------------- /demos/raster-01.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Lines demo 1 6 | 7 | This is an implementation of the initial, buggy [line drawing algorithm](../06-lines.html#drawing-lines). 8 | It works correctly for lines with |slope| ≤ 1, but not for the rest. 9 | 10 |
11 | 12 |
13 | 14 | 71 | -------------------------------------------------------------------------------- /demos/raster-02.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Lines demo 2 6 | 7 | This is an implementation of the general case [line drawing algorithm](../06-lines.html#drawing-lines-with-any-slope). 8 | It can handle lines of any slope, including vertical ones. 9 | 10 |
11 | 12 |
13 | 14 | 114 | -------------------------------------------------------------------------------- /demos/raster-03.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Filled triangle demo 6 | 7 | This is an implementation of the [filled triangle algorithm](../07-filled-triangles.html#drawing-filled-triangles). 8 | 9 |
10 | 11 |
12 | 13 | 159 | -------------------------------------------------------------------------------- /demos/raster-04.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Shaded triangle demo 6 | 7 | This is an implementation of the [shaded triangle algorithm](../08-shaded-triangles.html#computing-edge-shading). 8 | 9 |
10 | 11 |
12 | 13 | 174 | -------------------------------------------------------------------------------- /demos/raster-05.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Perspective projection demo 6 | 7 | This is an implementation of the [perspective projection equations](../09-perspective-projection.html#projecting-our-first-3d-object). 8 | We use them to project the vertices of a cube, and then draw line segments between these, to render 9 | a wireframe cube. 10 | 11 | We use the same color for the edges of each face of the cube. Because each edge is shared by two faces, 12 | the color you see depends on the order in which we draw them. 13 | 14 |
15 | 16 |
17 | 18 | 175 | -------------------------------------------------------------------------------- /demos/raster-06.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Scene setup demo 1 6 | 7 | In this demo we replace the hardcoded cube from the [previous demo](raster-05.html) with a cube 8 | defined as a set of vertices and triangles, as described in the [Representing a Cube](../10-describing-and-rendering-a-scene.html#representing-a-cube) section. 9 | 10 | This lets us draw any object made of triangles by using the appropriate lists of vertices and triangles, 11 | but leaving the rendering code unmodified. 12 | 13 |
14 | 15 |
16 | 17 | 216 | -------------------------------------------------------------------------------- /demos/raster-07.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Scene setup demo 2 6 | 7 | This demo extends the [previous one](raster-06.html) by adding support for rendering multiple instances 8 | of the same model, as described in the [Models and Instances](../10-describing-and-rendering-a-scene.html#models-and-instances) section. 9 | 10 |
11 | 12 |
13 | 14 | 242 | -------------------------------------------------------------------------------- /demos/raytracer-01.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Basic raytracing demo 6 | 7 | This demo implements [basic raytracing](../02-basic-raytracing.html). Whenever a ray from the camera 8 | hits an object, we set the corresponding canvas pixel to the object's color. 9 | 10 |
11 | 12 |
13 | 14 | 158 | -------------------------------------------------------------------------------- /demos/raytracer-02.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Diffuse reflection demo 6 | 7 | This demo extends the [previous demo](raytracer-01.html) by implementing [diffuse reflection](../03-light.html#diffuse-reflection). 8 | The spheres now look like spheres. 9 | 10 |
11 | 12 |
13 | 14 | 212 | -------------------------------------------------------------------------------- /demos/raytracer-03.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Specular reflection demo 6 | 7 | This demo extends the [previous demo](raytracer-02.html) by implementing [specular reflection](../03-light.html#specular-reflection). 8 | The surface of each sphere looks polished to a different degree. 9 | 10 |
11 | 12 |
13 | 14 | 227 | -------------------------------------------------------------------------------- /demos/raytracer-04.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Shadows demo 6 | 7 | This demo extends the [previous demo](raytracer-03.html) by implementing [shadows](../04-shadows-and-reflections.html#shadows). 8 | 9 | You can control whether the shadow rays start at t=0 or at t=ε and see the impact of this choice on the output. 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 |
Shadow ray start 19 |
20 | 21 |
25 |
26 | 27 | 285 | -------------------------------------------------------------------------------- /demos/raytracer-05.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Reflections demo 6 | 7 | This demo extends the [previous demo](raytracer-04.html) by implementing [reflections](../04-shadows-and-reflections.html#reflections). 8 | 9 | You can set the recursion limit to a value between 0 and 5. Try at least 0, 1, and a higher number to 10 | see the effect this has on the output. 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 |
Recursion limit 20 | 21 |
25 |
26 | 27 | 313 | -------------------------------------------------------------------------------- /demos/raytracer-06.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Camera position demo 6 | 7 | This demo extends the [previous demo](raytracer-05.html) by implementing [arbitrary camera positioning](../05-extending-the-raytracer.html#arbitrary-camera-positioning). 8 | 9 |
10 | 11 |
12 | 13 | 291 | -------------------------------------------------------------------------------- /diagrams/00-coordinates1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 43 | 48 | 49 | 58 | 63 | 64 | 72 | 78 | 79 | 87 | 93 | 94 | 95 | 113 | 115 | 116 | 118 | image/svg+xml 119 | 121 | 122 | 123 | 124 | 125 | 129 | 132 | 139 | 144 | 145 | 0 156 | 1920 167 | x 178 | 0 189 | 1080 200 | y 211 | 212 | 213 | -------------------------------------------------------------------------------- /diagrams/00-coordinates2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 44 | 49 | 50 | 58 | 63 | 64 | 72 | 78 | 79 | 87 | 93 | 94 | 95 | 113 | 115 | 116 | 118 | image/svg+xml 119 | 121 | 122 | 123 | 124 | 125 | 129 | 136 | 0 147 | -960 158 | x 169 | 960 180 | 540 191 | y 202 | 207 | 212 | -540 223 | 224 | 225 | -------------------------------------------------------------------------------- /diagrams/01-primaries1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 63 | 71 | 79 | 86 | 93 | 100 | 107 | 114 | 121 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /diagrams/01-primaries3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 63 | 71 | 79 | 86 | 93 | 100 | 107 | 114 | 121 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /diagrams/r16-flat-normals.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 44 | 49 | 50 | 58 | 64 | 65 | 74 | 80 | 81 | 90 | 96 | 97 | 106 | 112 | 113 | 114 | 132 | 134 | 135 | 137 | image/svg+xml 138 | 140 | 141 | 142 | 143 | 144 | 148 | 153 | 158 | 163 | 168 | 169 | 174 | 179 | 184 | 189 | 190 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /diagrams/r16-sphere-normals.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 43 | 49 | 50 | 59 | 65 | 66 | 75 | 81 | 82 | 91 | 97 | 98 | 99 | 117 | 119 | 120 | 122 | image/svg+xml 123 | 125 | 126 | 127 | 128 | 129 | 133 | 141 | 148 | 156 | 163 | 170 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /images/00-coordinates1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/00-coordinates1.png -------------------------------------------------------------------------------- /images/00-coordinates2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/00-coordinates2.png -------------------------------------------------------------------------------- /images/01-primaries1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/01-primaries1.png -------------------------------------------------------------------------------- /images/01-primaries2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/01-primaries2.png -------------------------------------------------------------------------------- /images/01-primaries3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/01-primaries3.png -------------------------------------------------------------------------------- /images/03-basic-raytracer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/03-basic-raytracer.png -------------------------------------------------------------------------------- /images/03-camera-orientation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/03-camera-orientation.png -------------------------------------------------------------------------------- /images/03-viewport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/03-viewport.png -------------------------------------------------------------------------------- /images/04-parameter-space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/04-parameter-space.png -------------------------------------------------------------------------------- /images/04-parametric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/04-parametric.png -------------------------------------------------------------------------------- /images/04-simple-scene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/04-simple-scene.png -------------------------------------------------------------------------------- /images/04-sphere-solutions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/04-sphere-solutions.png -------------------------------------------------------------------------------- /images/04-sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/04-sphere.png -------------------------------------------------------------------------------- /images/05-directional-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/05-directional-light.png -------------------------------------------------------------------------------- /images/05-point-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/05-point-light.png -------------------------------------------------------------------------------- /images/06-diffuse-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-diffuse-diagram.png -------------------------------------------------------------------------------- /images/06-light-spread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-light-spread.png -------------------------------------------------------------------------------- /images/06-mirror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-mirror.png -------------------------------------------------------------------------------- /images/06-qrp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-qrp.png -------------------------------------------------------------------------------- /images/06-rough-surface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-rough-surface.png -------------------------------------------------------------------------------- /images/06-sphere-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/06-sphere-normal.png -------------------------------------------------------------------------------- /images/07-cos-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/07-cos-alpha.png -------------------------------------------------------------------------------- /images/07-specular-decay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/07-specular-decay.png -------------------------------------------------------------------------------- /images/07-specular-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/07-specular-diagram.png -------------------------------------------------------------------------------- /images/07-specular-exponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/07-specular-exponent.png -------------------------------------------------------------------------------- /images/08-mirror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-mirror.png -------------------------------------------------------------------------------- /images/08-nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-nl.png -------------------------------------------------------------------------------- /images/08-shadow-cases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-shadow-cases.png -------------------------------------------------------------------------------- /images/08-shadow-directional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-shadow-directional.png -------------------------------------------------------------------------------- /images/08-shadow-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-shadow-point.png -------------------------------------------------------------------------------- /images/08-vec-r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/08-vec-r.png -------------------------------------------------------------------------------- /images/09-csg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/09-csg.png -------------------------------------------------------------------------------- /images/09-refraction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/09-refraction.png -------------------------------------------------------------------------------- /images/09-shadow-coherence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/09-shadow-coherence.png -------------------------------------------------------------------------------- /images/15-mp-ambient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-mp-ambient.png -------------------------------------------------------------------------------- /images/15-mp-composite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-mp-composite.png -------------------------------------------------------------------------------- /images/15-mp-l1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-mp-l1.png -------------------------------------------------------------------------------- /images/15-mp-l2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-mp-l2.png -------------------------------------------------------------------------------- /images/15-shadow-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-shadow-volume.png -------------------------------------------------------------------------------- /images/15-sv-direct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-sv-direct.png -------------------------------------------------------------------------------- /images/15-sv-reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/15-sv-reverse.png -------------------------------------------------------------------------------- /images/aa-point-diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-point-diff.png -------------------------------------------------------------------------------- /images/aa-point-plus-vector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-point-plus-vector.png -------------------------------------------------------------------------------- /images/aa-points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-points.png -------------------------------------------------------------------------------- /images/aa-vector-cross-product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-vector-cross-product.png -------------------------------------------------------------------------------- /images/aa-vector-plus-vector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-vector-plus-vector.png -------------------------------------------------------------------------------- /images/aa-vector-scaling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-vector-scaling.png -------------------------------------------------------------------------------- /images/aa-vectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aa-vectors.png -------------------------------------------------------------------------------- /images/aug1983.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/aug1983.jpg -------------------------------------------------------------------------------- /images/bad-texture-minification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bad-texture-minification.png -------------------------------------------------------------------------------- /images/bilinear-texture-weights.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bilinear-texture-weights.png -------------------------------------------------------------------------------- /images/bump-bump1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bump-bump1.jpg -------------------------------------------------------------------------------- /images/bump-bump2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bump-bump2.jpg -------------------------------------------------------------------------------- /images/bump-flat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bump-flat.jpg -------------------------------------------------------------------------------- /images/bump-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/bump-map.png -------------------------------------------------------------------------------- /images/camera-movement-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/camera-movement-1.png -------------------------------------------------------------------------------- /images/camera-movement-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/camera-movement-2.png -------------------------------------------------------------------------------- /images/camera-movement-redcube-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/camera-movement-redcube-1.png -------------------------------------------------------------------------------- /images/camera-movement-redcube-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/camera-movement-redcube-2.png -------------------------------------------------------------------------------- /images/checkerboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/checkerboard.png -------------------------------------------------------------------------------- /images/comparison-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/comparison-1.png -------------------------------------------------------------------------------- /images/comparison-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/comparison-2.png -------------------------------------------------------------------------------- /images/coordinate-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/coordinate-system.png -------------------------------------------------------------------------------- /images/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/cover.jpg -------------------------------------------------------------------------------- /images/crate-texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/crate-texture.jpg -------------------------------------------------------------------------------- /images/image-000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/image-000.jpg -------------------------------------------------------------------------------- /images/image-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/image-001.png -------------------------------------------------------------------------------- /images/linias.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/linias.jpeg -------------------------------------------------------------------------------- /images/mipmap-levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/mipmap-levels.png -------------------------------------------------------------------------------- /images/r11-linear-function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r11-linear-function.png -------------------------------------------------------------------------------- /images/r12-perspective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r12-perspective.png -------------------------------------------------------------------------------- /images/r12-perspective2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r12-perspective2.png -------------------------------------------------------------------------------- /images/r12-perspective3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r12-perspective3.png -------------------------------------------------------------------------------- /images/r13-cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r13-cube.png -------------------------------------------------------------------------------- /images/r13-rotate-translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r13-rotate-translate.png -------------------------------------------------------------------------------- /images/r13-translate-rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r13-translate-rotate.png -------------------------------------------------------------------------------- /images/r14-clip-plane-sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-plane-sphere.png -------------------------------------------------------------------------------- /images/r14-clip-spheres-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-spheres-1.png -------------------------------------------------------------------------------- /images/r14-clip-spheres-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-spheres-2.png -------------------------------------------------------------------------------- /images/r14-clip-spheres-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-spheres-3.png -------------------------------------------------------------------------------- /images/r14-clip-spheres-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-spheres-4.png -------------------------------------------------------------------------------- /images/r14-clip-triangle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-triangle1.png -------------------------------------------------------------------------------- /images/r14-clip-triangle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip-triangle2.png -------------------------------------------------------------------------------- /images/r14-clip1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip1.png -------------------------------------------------------------------------------- /images/r14-clip2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip2.png -------------------------------------------------------------------------------- /images/r14-clip3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip3.png -------------------------------------------------------------------------------- /images/r14-clip4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clip4.png -------------------------------------------------------------------------------- /images/r14-clipping-planes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-clipping-planes.png -------------------------------------------------------------------------------- /images/r14-unclipped-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-unclipped-object.png -------------------------------------------------------------------------------- /images/r14-vertex-classification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r14-vertex-classification.png -------------------------------------------------------------------------------- /images/r15-closed-objects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-closed-objects.png -------------------------------------------------------------------------------- /images/r15-cube-normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-cube-normals.png -------------------------------------------------------------------------------- /images/r15-culling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-culling.png -------------------------------------------------------------------------------- /images/r15-depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-depth.png -------------------------------------------------------------------------------- /images/r15-impossible-sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-impossible-sort.png -------------------------------------------------------------------------------- /images/r15-linear-z-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-linear-z-1.png -------------------------------------------------------------------------------- /images/r15-linear-z-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-linear-z-2.png -------------------------------------------------------------------------------- /images/r15-linear-z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r15-linear-z.png -------------------------------------------------------------------------------- /images/r16-flat-normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r16-flat-normals.png -------------------------------------------------------------------------------- /images/r16-gouraud-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r16-gouraud-sequence.png -------------------------------------------------------------------------------- /images/r16-phong-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r16-phong-sequence.png -------------------------------------------------------------------------------- /images/r16-sphere-normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r16-sphere-normals.png -------------------------------------------------------------------------------- /images/r16-wrong-interpolation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r16-wrong-interpolation.png -------------------------------------------------------------------------------- /images/r17-linear-texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r17-linear-texture.png -------------------------------------------------------------------------------- /images/r17-texture-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/r17-texture-mapping.png -------------------------------------------------------------------------------- /images/raster-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-01.png -------------------------------------------------------------------------------- /images/raster-01b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-01b.png -------------------------------------------------------------------------------- /images/raster-01c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-01c.png -------------------------------------------------------------------------------- /images/raster-01d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-01d.png -------------------------------------------------------------------------------- /images/raster-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-02.png -------------------------------------------------------------------------------- /images/raster-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-03.png -------------------------------------------------------------------------------- /images/raster-03b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-03b.png -------------------------------------------------------------------------------- /images/raster-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-04.png -------------------------------------------------------------------------------- /images/raster-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-05.png -------------------------------------------------------------------------------- /images/raster-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-06.png -------------------------------------------------------------------------------- /images/raster-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-07.png -------------------------------------------------------------------------------- /images/raster-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-08.png -------------------------------------------------------------------------------- /images/raster-10a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-10a.png -------------------------------------------------------------------------------- /images/raster-10b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-10b.png -------------------------------------------------------------------------------- /images/raster-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-11.png -------------------------------------------------------------------------------- /images/raster-11b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-11b.png -------------------------------------------------------------------------------- /images/raster-11c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-11c.png -------------------------------------------------------------------------------- /images/raster-11d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-11d.png -------------------------------------------------------------------------------- /images/raster-11e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-11e.png -------------------------------------------------------------------------------- /images/raster-12-sxs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-12-sxs.png -------------------------------------------------------------------------------- /images/raster-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-12.png -------------------------------------------------------------------------------- /images/raster-12b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-12b.png -------------------------------------------------------------------------------- /images/raster-rt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raster-rt.png -------------------------------------------------------------------------------- /images/raytracer-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-01.png -------------------------------------------------------------------------------- /images/raytracer-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-02.png -------------------------------------------------------------------------------- /images/raytracer-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-03.png -------------------------------------------------------------------------------- /images/raytracer-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-04.png -------------------------------------------------------------------------------- /images/raytracer-05-r1-zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-05-r1-zoom.png -------------------------------------------------------------------------------- /images/raytracer-05-r3-zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-05-r3-zoom.png -------------------------------------------------------------------------------- /images/raytracer-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-05.png -------------------------------------------------------------------------------- /images/raytracer-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/raytracer-06.png -------------------------------------------------------------------------------- /images/rt-csg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/rt-csg.png -------------------------------------------------------------------------------- /images/texture-close-linear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/texture-close-linear.png -------------------------------------------------------------------------------- /images/texture-close-nearest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/texture-close-nearest.png -------------------------------------------------------------------------------- /images/triangle-horizontal-segments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggambetta/computer-graphics-from-scratch/6a13d5a9ed419b7c5268bc668dc07270612f7025/images/triangle-horizontal-segments.png --------------------------------------------------------------------------------