{"id":664,"date":"2025-05-23T14:47:43","date_gmt":"2025-05-23T12:47:43","guid":{"rendered":"https:\/\/cammonte.com\/?page_id=664"},"modified":"2025-07-01T15:42:10","modified_gmt":"2025-07-01T13:42:10","slug":"rendering-an-image-of-a-3d-scene-by-scratchapixel","status":"publish","type":"page","link":"https:\/\/cammonte.com\/index.php\/rendering-an-image-of-a-3d-scene-by-scratchapixel\/","title":{"rendered":"Rendering an Image of a 3D Scene by Scratchapixel"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Graphics and discretisation<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Raster graphics\/displays<\/strong>: images and screens that use a two-dimensional array of pixels to represent or display images<\/li>\n\n\n\n<li><strong>Colour quantisation<\/strong>: find the closest possible matching colour from the palette to the colour you ideally want and display this matching colour -&gt; banding if not enough colours available, (continuous gradients of colour tones, see below)<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"780\" height=\"390\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image.png\" alt=\"\" class=\"wp-image-674\" style=\"width:338px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image.png 780w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-300x150.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-768x384.png 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Aliasing<\/strong>: occurs when having to break down a continuous function into discrete values. Small details, smaller than a pixel, can&#8217;t be displayed properly<\/li>\n\n\n\n<li><strong>Vector graphics vs bitmap graphics<\/strong>: do not store pixels but represent the shape of objects and their colours using mathematical expressions -&gt; shapes can be rendered on the fly at the desired resolution<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Geometry representation<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Implicit surfaces<\/strong>: objects for which the surface can be described with an equation, ex: x\u00b2 + y\u00b2 + z\u00b2 = r\u00b2<\/li>\n\n\n\n<li><strong>Parametric surfaces<\/strong>: each coordinate is given by a parameterised formula, ex: (x, y, z)=(r*cos\u03b8*sin\u03d5, r*sin\u03b8*sin\u03d5, r*cos\u03d5)<\/li>\n\n\n\n<li><strong>Rendering primitive<\/strong>: convert the surface to a representation made of only the same geometry primitive to achieve better performance\n<ul class=\"wp-block-list\">\n<li>Triangle is preferred: coplanar, indivisible, the barycentric coordinates maths is simple and robust.<\/li>\n\n\n\n<li>Extensive research to find best algorithm for computing ray-triangle intersections<\/li>\n\n\n\n<li>Modern hardware is optimised for triangles<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">The rendering process: two essential steps<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Visibility problem<\/h3>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Define which geometry is visible at the pixel we&#8217;re considering<\/mark><\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Foreshortening effect<\/strong>: objects further away from our eyes appear smaller than those closer<\/li>\n\n\n\n<li><strong>Hidden surface elimination\/determination, occlusion culling<\/strong>: determining which surfaces and parts of surfaces are not visible from the viewpoint, can be solved by rasterisation (<strong>z-buffer <\/strong>and <strong>painter&#8217;s algorithms<\/strong>) or ray-tracing<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Shading<\/h3>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">The simulation of light (light transport) and the simulation of the appearance of objects (shading)<\/mark><\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Light emitted by sources travels straight until meets an object, then some is reflected and some is absorbed<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Absorption<\/strong>: gives objects their colour, a black object absorbs all light colors, while a white object reflects them all<\/li>\n\n\n\n<li><strong>Reflection<\/strong>: outgoing direction is a reflection of the incoming direction with respect to the normal<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"263\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-4.png\" alt=\"\" class=\"wp-image-683\" style=\"width:229px;height:auto\"\/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Reflection<\/strong> happens at the object level but <strong>scattering<\/strong> (re-emission of incoming photon to a random direction) happens at the atomic level -&gt; <strong>shaders<\/strong> model the light interaction with materials at the microscopic level.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">The Visibility Problem<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Perspective projection<\/h2>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Projecting 3D shapes onto the surface of a canvas and determining which parts of these surfaces are visible from a given point of view.<\/mark><\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"432\" height=\"383\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective1.drawio.png\" alt=\"\" class=\"wp-image-668\" style=\"width:292px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective1.drawio.png 432w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective1.drawio-300x266.png 300w\" sizes=\"auto, (max-width: 432px) 100vw, 432px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"530\" height=\"271\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective2.drawio1.png\" alt=\"\" class=\"wp-image-671\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective2.drawio1.png 530w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/perspective2.drawio1-300x153.png 300w\" sizes=\"auto, (max-width: 530px) 100vw, 530px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"868\" height=\"328\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-2.png\" alt=\"\" class=\"wp-image-677\" style=\"width:151px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-2.png 868w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-2-300x113.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-2-768x290.png 768w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"861\" height=\"328\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-3.png\" alt=\"\" class=\"wp-image-678\" style=\"width:144px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-3.png 861w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-3-300x114.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-3-768x293.png 768w\" sizes=\"auto, (max-width: 861px) 100vw, 861px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Projected points coordinates are in <strong>screen space<\/strong>. Normalising them to the 0,1 range, we get the coordinates in <strong>NDC (Normalised Device Coordinates)<\/strong> space. We can multiply them by the dimensions of the image to get the coordinates <strong>raster space<\/strong> (in the image as a 2D grid of pixels with origin in the top-left corner of the image).<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"530\" height=\"219\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-6.png\" alt=\"\" class=\"wp-image-693\" style=\"width:394px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-6.png 530w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-6-300x124.png 300w\" sizes=\"auto, (max-width: 530px) 100vw, 530px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Coordinate spaces<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Object space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Local coordinate system of a 3D object<\/li>\n\n\n\n<li>Origin at center\/corner of the object, range between 0 and 1 or -1 and 1<\/li>\n\n\n\n<li>Useful to model, transform object independently (scale, rotate, &#8230;)<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>World space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Shared coordinate system for entire 3D scene<\/li>\n\n\n\n<li>Useful to place objects relative to each other<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>View\/Camera space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Coordinate system from the camera&#8217;s viewpoint: camera at the origin looking down he negative z-axis<\/li>\n\n\n\n<li>Useful to convert the scene so that everything is relative to the camera<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Clip space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Coordinate space after a vertex has been transformed by the projection matrix (perspective or orthographic), but before the perspective divide<\/li>\n\n\n\n<li>Space where the GPU determines whether a vertex is inside or outside the view frustum (whether to &#8220;clip&#8221; it or not)<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"647\" height=\"143\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2025\/07\/image.png\" alt=\"\" class=\"wp-image-1701\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2025\/07\/image.png 647w, https:\/\/cammonte.com\/wp-content\/uploads\/2025\/07\/image-300x66.png 300w\" sizes=\"auto, (max-width: 647px) 100vw, 647px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Normalised Device Coordinates (NDC)<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Coordinates normalized into a cube where all axes range from -1 to 1<\/li>\n\n\n\n<li>Useful to determine whether geometry is in the view frustum<\/li>\n\n\n\n<li>Basically clip coordinates \/ w<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Screen space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>2D coordinates on your screen, in pixels<\/li>\n\n\n\n<li>Range from 0 to screen width\/height<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Raster space<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Discrete grid of pixels on the screen<\/li>\n\n\n\n<li>Useful to run pixel shaders and per-pixel operations (texturing)<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>From<\/strong><\/th><th><strong>To<\/strong><\/th><th><strong>Transformation<\/strong><\/th><th><strong>Description<\/strong><\/th><\/tr><\/thead><tbody><tr><td><strong>Object Space<\/strong><\/td><td><strong>World Space<\/strong><\/td><td>Model Matrix (<strong>M<\/strong>)<\/td><td>Places the object into the world (translation, rotation, scaling).<\/td><\/tr><tr><td><strong>World Space<\/strong><\/td><td><strong>View Space<\/strong><\/td><td>View Matrix (<strong>V<\/strong>)<\/td><td>Transforms everything relative to the camera\u2019s position and orientation.<\/td><\/tr><tr><td><strong>View Space<\/strong><\/td><td><strong>Clip Space<\/strong><\/td><td>Projection Matrix (<strong>P<\/strong>)<\/td><td>Applies perspective or orthographic projection.<\/td><\/tr><tr><td><strong>Clip Space<\/strong><\/td><td><strong>NDC<\/strong><\/td><td>Perspective Divide (<strong>divide by w<\/strong>)<\/td><td>Normalizes coordinates into the range [-1, 1] for x, y, z.<\/td><\/tr><tr><td><strong>NDC<\/strong><\/td><td><strong>Screen Space<\/strong><\/td><td>Viewport Transform<\/td><td>Maps from NDC to pixel coordinates on the screen.<\/td><\/tr><tr><td><strong>Screen Space<\/strong><\/td><td><strong>Raster Space<\/strong><\/td><td>Rasterization (Discrete Pixel Sampling)<\/td><td>Converts continuous screen coordinates to actual pixel fragments.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Projection matrix<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Perspective projection matrix<\/strong>: when applied to points on the geometry, projects them onto the screen<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Rasterisation<\/strong>: project P onto the screen to compute P&#8217; -&gt; <strong>need the projection matrix<\/strong><\/li>\n\n\n\n<li><strong>Ray-tracing<\/strong>: trace a ray passing through P&#8217; and search for P -&gt; <strong>projection matrix not needed<\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Rasterisation solution<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Rasterisation is moving a point along a line that connects a point on a geometry surface, to the eye until it lies on the canvas surface<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Several points can project onto the same point on the canvas but the only visible one is the closest to the eye -&gt; visibility problem<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"237\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-5.png\" alt=\"\" class=\"wp-image-691\" style=\"width:178px;height:auto\"\/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Depth sorting algorithm<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Project all points onto the screen\n<ul class=\"wp-block-list\">\n<li>For each projected point, convert coordinates from screen space to raster space<\/li>\n\n\n\n<li>Determine the pixel to which the point maps and store the distance from that point to the eye in the depth list of that pixel<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Sort the points in each pixel&#8217;s list in order of increasing distance -&gt; point visible for a given pixel is the first point in its depth list<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Well-known depth sorting algorithms:<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-orange-color\"> z-buffering algorithm, painter algorithm, newell&#8217;s algorithm<\/mark><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ray-tracing solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ray-tracing starts with the pixel and converts it into a point on the image plane.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Trace a ray from the eye passing through the center of the pixel and extending it into the scene<\/li>\n\n\n\n<li>If that ray intersects with an object then this intersection point is the point visible through that pixel -&gt; solve the visibility problem by directly tracing rays from the eye into the scene<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Rasterisation vs ray-tracing solutions<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ray-tracing is more complicated because we have to solve ray-geometry intersection problems.<\/li>\n\n\n\n<li>Ray-tracing is slower and the render time increases linearly with the amount of geometry in the scene: have to check whether any given ray intersects any of the triangles in the scene<\/li>\n\n\n\n<li><strong>Acceleration structures<\/strong> can alleviate cost of ray-tracing: divide the space into subspaces\n<ul class=\"wp-block-list\">\n<li>Test if a ray intersects with a given subspace before testing if it intersects with objects in this subspace<\/li>\n\n\n\n<li>Issues with acceleration structures:\n<ul class=\"wp-block-list\">\n<li>Building takes time -&gt; impractical in real-time scenarios where a new structure needs to be built for each frame<\/li>\n\n\n\n<li>Takes space in memory -&gt; less space for geometry -&gt; can render less geometry with ray-tracing than with rasterisation<\/li>\n\n\n\n<li>Finding an good acceleration structure that subdivides the space in a practical way is difficult, example below of a situation where it&#8217;s difficult to find a good subdivision of space:<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"280\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-8.png\" alt=\"\" class=\"wp-image-704\" style=\"width:150px;height:auto\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Light Simulation<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Real-world light effects<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Reflection<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Light interacts with perfect mirror-like surfaces -&gt; reflected back in the environment in a predictable direction given by the <strong>law of reflection<\/strong>: angle of reflection of a ray departing a surface equals the angle of incidence at which the incoming ray strikes the surface. around the normal to the surface.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"245\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-11.png\" alt=\"\" class=\"wp-image-722\" style=\"width:301px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-11.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-11-300x199.png 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Transparency<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Transparent object reflect and refract light.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Snell&#8217;s law<\/mark><\/strong> gives the direction of refraction<\/li>\n\n\n\n<li><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Fresnel equations<\/mark><\/strong> specify the proportions of light that are reflected and refracted<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"377\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-9.png\" alt=\"\" class=\"wp-image-718\" style=\"width:273px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-9.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-9-294x300.png 294w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Glossy or specular reflection (scattering)<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Glossy\/specular reflection == is not perfectly reflective and not perfectly diffuse, glossiness == roughness <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also referred as <strong>scattering<\/strong><\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"467\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-12.png\" alt=\"\" class=\"wp-image-723\" style=\"width:186px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-12.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-12-238x300.png 238w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"375\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-10.png\" alt=\"\" class=\"wp-image-719\" style=\"width:238px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-10.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-10-296x300.png 296w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Diffuse reflection<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Diffuse surface is the opposite of a perfeclty reflective surface. Incident light is equally spread in every direction above the point of incidence and as a result, a diffuse surface appears equally bright from all viewing directions -&gt; <strong>the direction of incidence does not affect the light rays&#8217; outing directions<\/strong><\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"278\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-13.png\" alt=\"\" class=\"wp-image-725\" style=\"width:248px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-13.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-13-300x225.png 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Subsurface scattering<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Subsurface scattering == translucency: light travels through the material, changing direction along its path, exiting object at a different location and direction<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"523\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-14.png\" alt=\"\" class=\"wp-image-727\" style=\"width:200px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-14.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-14-212x300.png 212w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Indirect lighting (indirect diffuse)<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Some part of the surface is not facing any light source, but other illuminated surfaces (here, the floor) reflects light back in on them -&gt; indirect lighting<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"493\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-15.png\" alt=\"\" class=\"wp-image-728\" style=\"width:188px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-15.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-15-225x300.png 225w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Caustics (indirect specular)<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Reflective objects  can indirectly illuminate other objects: concentrate light rays into specific lines or patterns<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"457\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-16.png\" alt=\"\" class=\"wp-image-729\" style=\"width:254px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-16.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-16-243x300.png 243w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Soft shadows<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Soft shadows are unrelated to material, purely geometric problem to simulate<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"264\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-17.png\" alt=\"\" class=\"wp-image-730\" style=\"width:262px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-17.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-17-300x214.png 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Light transport and shading<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Light effects can be categorised into two groups:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Relate to the appearance of objects: reflection, transparency, specular reflection diffuse reflection, subsurface scattering -&gt; <strong>shading<\/strong><\/li>\n\n\n\n<li>Relate to the amount of light an object receives: indirect diffuse, indirect specular, soft shadows -&gt; <strong>light transport<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Shading<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Interaction between light and matter, everything that happens to light from the moment it reaches an object to the moment it departs<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Light transport<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Studies journey of light as it bounces from surface to surface, focuses on the paths light rays follow as they move from light source to observer<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Global illumination<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Global illumination = ability to simulate both direct and indirect lighting effects<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Expensive: simulating indirect lighting in addition to direct lighting requires not twice as many rays (compared to the number used for direct lighting) but orders of magnitude more: this effect is recursive, making indirect lighting a potentially very expensive effect to simulate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Naive&#8221; backward ray tracing is clearly not the solution to everything, and you might look for alternative methods. Photon maps are a good example of a technique designed to efficiently simulate caustics<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Light Transport<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Light paths are defined by all the successive materials with which the light rays interact on their way to the eye.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>LE is the smallest possible path<\/li>\n\n\n\n<li>LDE or LSE are direct illumination paths<\/li>\n\n\n\n<li>L(D|S)*E are indirect illumination paths<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"783\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-18.png\" alt=\"\" class=\"wp-image-733\" style=\"width:131px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-18.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-18-115x300.png 115w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Ray tracing main idea: trace a ray from the eye (primary ray) and check if it intersects geometry. If it does we need to compute how much light arrives at this intersection P directly from the light sources (direct contribution) and how much light arrives indirectly as a result of reflection on other surfaces (indirect contribution).<\/mark><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Direct contribution<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>Trace a ray from intersection point to light source (shadow ray)<\/li>\n\n\n\n<li>If it intersects another object, then initial point is in the shadow of this object<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-19.png\" alt=\"\" class=\"wp-image-734\" style=\"width:231px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-19.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-19-150x150.png 150w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Indirect contribution<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Need to spawn secondary rays from the intersection point into the scene<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If secondary ray intersects other surface, need to determine how much light is reflected towards the intersection point along these rays -&gt; recursive process: cast again a shadow ray and a secondary ray from this intersection:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compute the amount of light arriving at the point of intersection between the secondary ray and the surface<\/li>\n\n\n\n<li>Measure how much of that light is reflected by the surface towards the intersection point (depends on surface properties, done with shaders)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Number of such bounces may be infinite -&gt; <strong>Monte Carlo ray tracing:<\/strong> shooting a few rays to approximate the exact amount of light arriving at a point<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-20.png\" alt=\"\" class=\"wp-image-735\" style=\"width:372px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-20.png 300w, https:\/\/cammonte.com\/wp-content\/uploads\/2024\/08\/image-20-150x150.png 150w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Whitted-style ray tracing (<strong>Unidirectional path tracing<\/strong><\/strong>)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Simple light transport model that only accounts for direct illumination, perfect reflection, refraction and sharp shadows. At intersection point, you only compute local illumination, cast a shadow ray, and cast a reflection or refraction ray if the surface requires it -&gt; light only bounces once -&gt; <strong>no global illumination<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Light transport algorithms<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Try to solve what can&#8217;t be solved by unidirectional path tracing, mostly the LS+DE problem (bounces from light to multiple specular surfaces before a diffuse one and the eye. Can be categorised into two groups<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Not using ray tracing: photon\/shadow mapping, radiosity, &#8230;<\/li>\n\n\n\n<li>Exclusively using ray tracing<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">-&gt; Ray tracing is not the only way to solve global illumination<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Shading<\/h1>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Model light real world light interactions that are too complex to simulate with light transport approach<\/mark><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Albedo vs Luminance vs Chromaticity<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Albedo: what colour the object <em>is<\/em><\/strong>\n<ul class=\"wp-block-list\">\n<li>True colour without any lighting involved<\/li>\n\n\n\n<li>Can be measured precisely for an object<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Luminance: how bright the object <em>looks<\/em><\/strong>\n<ul class=\"wp-block-list\">\n<li>Depends on how much light energy the surface reflects into your eye: bright in direct sunlight but dark or even black at night, but albedo has not changed<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Chromaticity: what hue\/saturation the object has<\/strong>\n<ul class=\"wp-block-list\">\n<li>Colour &#8220;type&#8221; without brightness, &#8220;what kind of colour is it? red, green, blue? how pure?&#8221;<\/li>\n\n\n\n<li>Albedo includes brightness while chromaticity is normalised to show hue\/saturation only<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What is shading<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Brightness of a point P on the surface of an object under lighting conditions needs to account for:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>How much light falls on the object at this point: contributions from light sources (direct lighting) and other surfaces (indirect lighting) -&gt; <strong>light transport issue<\/strong><\/li>\n\n\n\n<li>How much light is reflected from this point in the viewing direction -&gt; <strong>shading issue<\/strong>, more complex, depends on:\n<ul class=\"wp-block-list\">\n<li>Viewing direction: diffuse surfaces appear equally bright from all viewing angles but specular surfaces do not, most objects are a mix of the two<\/li>\n\n\n\n<li>Incoming light&#8217;s direction: <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"393\" src=\"https:\/\/cammonte.com\/wp-content\/uploads\/2025\/05\/image-2.png\" alt=\"\" class=\"wp-image-1144\" style=\"width:294px;height:auto\" srcset=\"https:\/\/cammonte.com\/wp-content\/uploads\/2025\/05\/image-2.png 370w, https:\/\/cammonte.com\/wp-content\/uploads\/2025\/05\/image-2-282x300.png 282w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Shader<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Takes incident light direction and viewing direction as input and returns the fraction of light reflected by the surface for these directions<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">[math]\\text{ratio of reflected light}=\\text{shader}(\\omega_i, \\omega_O)[\/math]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Graphics and discretisation Geometry representation The rendering process: two essential steps Visibility problem Define which geometry is visible at the pixel we&#8217;re considering Shading The simulation of light (light transport) and the simulation of the appearance of objects (shading) Light emitted by sources travels straight until meets an object, then some is reflected and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"ub_ctt_via":"","site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"class_list":["post-664","page","type-page","status-publish","hentry"],"featured_image_src":null,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/pages\/664","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/comments?post=664"}],"version-history":[{"count":47,"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/pages\/664\/revisions"}],"predecessor-version":[{"id":1702,"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/pages\/664\/revisions\/1702"}],"wp:attachment":[{"href":"https:\/\/cammonte.com\/index.php\/wp-json\/wp\/v2\/media?parent=664"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}