camera_rays.html 19.9 KB
Newer Older
allai5's avatar
allai5 committed
1
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <title>(Task 1) Camera Rays - </title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="stylesheet" href="/assets/css/just-the-docs-default.css"> <script type="text/javascript" src="/assets/js/vendor/lunr.min.js"></script> <script type="text/javascript" src="/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.7.1 --> <title>(Task 1) Camera Rays</title> <meta name="generator" content="Jekyll v4.2.0" /> <meta property="og:title" content="(Task 1) Camera Rays" /> <meta property="og:locale" content="en_US" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="(Task 1) Camera Rays" /> <script type="application/ld+json"> {"headline":"(Task 1) Camera Rays","@type":"WebPage","url":"/pathtracer/camera_rays","@context":"https://schema.org"}</script> <!-- End Jekyll SEO tag --> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> </svg> <div class="side-bar"> <div class="site-header"> <a href="/" class="site-title lh-tight"> </a> <a href="#" id="menu-button" class="site-button"> <svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-menu"></use></svg> </a> </div> <nav role="navigation" aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/" class="nav-list-link">Home</a></li><li class="nav-list-item"><a href="/git/" class="nav-list-link">GitHub Setup</a></li><li class="nav-list-item"><a href="/build/" class="nav-list-link">Building Scotty3D</a></li><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/guide/" class="nav-list-link">User Guide</a><ul class="nav-list "><li class="nav-list-item "><a href="/guide/animate_mode/" class="nav-list-link">Animate</a></li><li class="nav-list-item "><a href="/guide/layout_mode/" class="nav-list-link">Layout</a></li><li class="nav-list-item "><a href="/guide/model_mode/" class="nav-list-link">Model</a></li><li class="nav-list-item "><a href="/guide/render_mode/" class="nav-list-link">Render</a></li><li class="nav-list-item "><a href="/guide/rigging_mode/" class="nav-list-link">Rig</a></li><li class="nav-list-item "><a href="/guide/simulate_mode/" class="nav-list-link">Simulate</a></li></ul></li><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/meshedit/" class="nav-list-link">A2: MeshEdit</a><ul class="nav-list "><li class="nav-list-item "><a href="/meshedit/halfedge" class="nav-list-link">Halfedge Mesh</a></li><li class="nav-list-item "><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/meshedit/local/" class="nav-list-link">Local Operations</a><ul class="nav-list"><li class="nav-list-item "> <a href="/meshedit/local/edge_flip" class="nav-list-link">Edge Flip Tutorial</a> </li><li class="nav-list-item "> <a href="/meshedit/local/bevel/" class="nav-list-link">Bevelling</a> </li></ul></li><li class="nav-list-item "><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/meshedit/global/" class="nav-list-link">Global Operations</a><ul class="nav-list"><li class="nav-list-item "> <a href="/meshedit/global/catmull/" class="nav-list-link">Catmull-Clark Subdivision</a> </li><li class="nav-list-item "> <a href="/meshedit/global/remesh/" class="nav-list-link">Isotropic Remeshing</a> </li><li class="nav-list-item "> <a href="/meshedit/global/linear/" class="nav-list-link">Linear Subdivision</a> </li><li class="nav-list-item "> <a href="/meshedit/global/loop/" class="nav-list-link">Loop Subdivision</a> </li><li class="nav-list-item "> <a href="/meshedit/global/simplify/" class="nav-list-link">Simplification</a> </li><li class="nav-list-item "> <a href="/meshedit/global/triangulate/" class="nav-list-link">Triangulation</a> </li></ul></li></ul></li><li class="nav-list-item active"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/pathtracer/" class="nav-list-link">A3: Pathtracer</a><ul class="nav-list "><li class="nav-list-item active"><a href="/pathtracer/camera_rays" class="nav-list-link active">(Task 1) Camera Rays</a></li><li class="nav-list-item "><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/pathtracer/intersecting_objects" class="nav-list-link">(Task 2) Intersections</a><ul class="nav-list"><li class="nav-list-item "> <a href="/pathtracer/ray_triangle_intersection" class="nav-list-link">Ray Triangle Intersection</a> </li><li class="nav-list-item "> <a href="/pathtracer/ray_sphere_intersection" class="nav-list-link">Ray Sphere Intersection</a> </li></ul></li><li class="nav-list-item "><a href="/pathtracer/bounding_volume_hierarchy" class="nav-list-link">(Task 3) BVH</a></li><li class="nav-list-item "><a href="/pathtracer/shadow_rays" class="nav-list-link">(Task 4) Shadow Rays</a></li><li class="nav-list-item "><a href="/pathtracer/path_tracing" class="nav-list-link">(Task 5) Path Tracing</a></li><li class="nav-list-item "><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/pathtracer/materials" class="nav-list-link">(Task 6) Materials</a><ul class="nav-list"><li class="nav-list-item "> <a href="/pathtracer/dielectrics_and_transmission" class="nav-list-link">Dielectrics and Transmission</a> </li></ul></li><li class="nav-list-item "><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/pathtracer/environment_lighting" class="nav-list-link">(Task 7) Environment Lighting</a><ul class="nav-list"><li class="nav-list-item "> <a href="/pathtracer/importance_sampling" class="nav-list-link">Environment Light Importance Sampling</a> </li></ul></li><li class="nav-list-item "><a href="/pathtracer/visualization_of_normals" class="nav-list-link">Visualization of normals</a></li></ul></li><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="/animation/" class="nav-list-link">A4: Animation</a><ul class="nav-list "><li class="nav-list-item "><a href="/animation/splines" class="nav-list-link">Splines</a></li><li class="nav-list-item "><a href="/animation/skeleton_kinematics" class="nav-list-link">Skeleton Kinematics</a></li><li class="nav-list-item "><a href="/animation/skinning" class="nav-list-link">Skinning</a></li><li class="nav-list-item "><a href="/animation/particles" class="nav-list-link">Particles</a></li></ul></li></ul> </nav> <footer class="site-footer"> This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </footer> </div> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search " aria-label="Search " autocomplete="off"> <label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div id="main-content-wrap" class="main-content-wrap"> <nav aria-label="Breadcrumb" class="breadcrumb-nav"> <ol class="breadcrumb-nav-list"> <li class="breadcrumb-nav-list-item"><a href="/pathtracer/">A3: Pathtracer</a></li> <li class="breadcrumb-nav-list-item"><span>(Task 1) Camera Rays</span></li> </ol> </nav> <div id="main-content" class="main-content" role="main"> <h1 id="task-1-generating-camera-rays"> <a href="#task-1-generating-camera-rays" class="anchor-heading" aria-labelledby="task-1-generating-camera-rays"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> (Task 1) Generating Camera Rays </h1> <h3 id="walkthrough-video"> <a href="#walkthrough-video" class="anchor-heading" aria-labelledby="walkthrough-video"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Walkthrough Video </h3> <iframe width="750" height="500" src="Task1_Camera_Rays_1.mp4" frameborder="0" allowfullscreen=""></iframe> <p>“Camera rays” emanate from the camera and measure the amount of scene radiance that reaches a point on the camera’s sensor plane. (Given a point on the virtual sensor plane, there is a corresponding camera ray that is traced into the scene.)</p> <p>Take a look at <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code> in <code class="language-plaintext highlighter-rouge">student/pathtracer.cpp</code>. The job of this function is to compute the amount of energy arriving at this pixel of the image. Conveniently, we’ve given you a function <code class="language-plaintext highlighter-rouge">Pathtracer::trace_ray(r)</code> that provides a measurement of incoming scene radiance along the direction given by ray <code class="language-plaintext highlighter-rouge">r</code>. See <code class="language-plaintext highlighter-rouge">lib/ray.h</code> for the interface of ray.</p> <p>Here are some <a href="https://drive.google.com/file/d/0B4d7cujZGEBqVnUtaEsxOUI4dTMtUUItOFR1alQ4bmVBbnU0/view">rough notes</a> giving more detail on how to generate camera rays.</p> <p>This tutorial from <a href="https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays">Scratchapixel</a> also provides a detailed walkthrough of what you need to do. (Note that the coordinate convention that Scratchpixel adopted is different from the one we use, and you should stick to the coordinate system from the <a href="https://drive.google.com/file/d/0B4d7cujZGEBqVnUtaEsxOUI4dTMtUUItOFR1alQ4bmVBbnU0/view">rough notes</a> all the time.)</p> <p><strong>Step 1:</strong> Given the width and height of the screen, and point in screen space, compute the corresponding coordinates of the point in normalized ([0-1]x[0-1]) screen space in <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code>. Pass these coordinates to the camera via <code class="language-plaintext highlighter-rouge">Camera::generate_ray</code> in <code class="language-plaintext highlighter-rouge">camera.cpp</code>.</p> <p><strong>Step 2:</strong> Implement <code class="language-plaintext highlighter-rouge">Camera::generate_ray</code>. This function should return a ray <strong>in world space</strong> that reaches the given sensor sample point. We recommend that you compute this ray in camera space (where the camera pinhole is at the origin, the camera is looking down the -Z axis, and +Y is at the top of the screen.). In <code class="language-plaintext highlighter-rouge">util/camera.h</code>, the <code class="language-plaintext highlighter-rouge">Camera</code> class stores <code class="language-plaintext highlighter-rouge">vert_fov</code> and <code class="language-plaintext highlighter-rouge">aspect_ratio</code> indicating the vertical field of view of the camera (in degrees, not radians) as well as the aspect ratio. Note that the camera maintains camera-space-to-world space transform matrix <code class="language-plaintext highlighter-rouge">iview</code> that will come in handy.</p> <p><strong>Step 3:</strong> Your implementation of <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code> must support super-sampling. The member <code class="language-plaintext highlighter-rouge">Pathtracer::n_samples</code> specifies the number of samples of scene radiance to evaluate per pixel. The starter code will hence call <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code> one time for each sample, so your implementation of <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code> should choose a new location within the pixel each time.</p> <p>To choose a sample within the pixel, you should implement <code class="language-plaintext highlighter-rouge">Rect::Uniform::sample</code> (see <code class="language-plaintext highlighter-rouge">src/student/samplers.cpp</code>), such that it provides (random) uniformly distributed 2D points within the rectangular region specified by the origin and the member <code class="language-plaintext highlighter-rouge">Rect::Uniform::size</code>. Then you may then create a <code class="language-plaintext highlighter-rouge">Rect::Uniform</code> sampler with a one-by-one region and call <code class="language-plaintext highlighter-rouge">sample()</code> to obtain randomly chosen offsets within the pixel.</p> <p>Once you have implemented <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code>, <code class="language-plaintext highlighter-rouge">Rect::Uniform::sample</code> and <code class="language-plaintext highlighter-rouge">Camera::generate_ray</code>, you should have a working camera.</p> <p><strong>Tip:</strong> Since it’ll be hard to know if you camera rays are correct until you implement primitive intersection, we recommend debugging your camera rays by checking what your implementation of <code class="language-plaintext highlighter-rouge">Camera::generate_ray</code> does with rays at the center of the screen (0.5, 0.5) and at the corners of the image.</p> <p>The code can log the results of raytracing for visualization and debugging. To do so, simply call function <code class="language-plaintext highlighter-rouge">Pathtracer::log_ray</code> in your <code class="language-plaintext highlighter-rouge">Pathtracer::trace_pixel</code>. Function <code class="language-plaintext highlighter-rouge">Pathtracer::log_ray</code> takes in 3 arguments: the ray tat you want to log, a float that specifies the distance to log that ray up to, and a color for the ray. If you don’t pass a color, it will default to white. You should only log only a portion of the generated rays, or else the result will be hard to interpret. To do so, you can add <code class="language-plaintext highlighter-rouge">if(RNG::coin_flip(0.0005f)) log_ray(out, 10.0f);</code> to log 0.05% of camera rays.</p> <p>Finally, you can visualize the logged rays by checking the box for Logged rays under Visualize and then <strong>starting the render</strong> (Open Render Window -&gt; Start Render). After running the path tracer, rays will be shown as lines in visualizer. Be sure to wait for rendering to complete so you see all rays while visualizing.</p> <p><img src="new_results/log_rays.png" alt="logged_rays" /></p> <p><strong>Step 4:</strong> <code class="language-plaintext highlighter-rouge">Camera</code> also includes the members <code class="language-plaintext highlighter-rouge">aperture</code> and <code class="language-plaintext highlighter-rouge">focal_dist</code>. These parameters are used to simulate the effects of de-focus blur and bokeh found in real cameras. Focal distance represents the distance between the camera aperture and the plane that is perfectly in focus. To use it, you must simply scale up the sensor position from step 2 (and hence ray direction) by <code class="language-plaintext highlighter-rouge">focal_dist</code> instead of leaving it on the <code class="language-plaintext highlighter-rouge">z = -1</code> plane. You might notice that this doesn’t actually change anything about your result, since this is just scaling up a vector that is later normalized. However, now aperture comes in: by default, all rays start a single point, representing a pinhole camera. But when <code class="language-plaintext highlighter-rouge">aperture &gt; 0</code>, we want to randomly choose the ray origin from an <code class="language-plaintext highlighter-rouge">aperture</code>x<code class="language-plaintext highlighter-rouge">aperture</code> square centered at the origin and facing the camera direction (-Z). Then, we use this point as the starting point of the ray while keeping its sensor position fixed (consider how that changes the ray direction). Now it’s as if the same image was taken from slightly off origin. This simulates real cameras with non-pinhole apertures: the final photo is equivalent to averaging images taken by pinhole cameras placed at every point in the aperture.</p> <p>Finally, we can see that non-zero aperture makes focal distance matter: objects on the focal plane are unaffected, since where the ray hits on the sensor is the same regardless of the ray’s origin. However, rays that hit objects objects closer or farther than the focal distance will be able to “see” slightly different parts of the object based on the ray origin. Averaging over many rays within a pixel, this results in collecting colors from a region larger slightly than that pixel would cover given zero aperture, causing the object to become blurry. We are using a square aperture, so bokeh effects will reflect this.</p> <p>You can test aperture/focal distance by adjusting <code class="language-plaintext highlighter-rouge">aperture</code> and <code class="language-plaintext highlighter-rouge">focal_dist</code> using the camera UI and examining logging rays. Once you have implemented primitive intersections and path tracing (tasks 3/5), you will be able to properly render <code class="language-plaintext highlighter-rouge">dof.dae</code>:</p> <p><img src="new_results/dof.png" alt="depth of field test" /></p> <p><strong>Extra credit ideas:</strong></p> <ul> <li>Write your own camera pixel sampler (replacing Rect::Uniform) that generates samples with improved distribution. Some examples include: <ul> <li>Jittered Sampling</li> <li>Multi-jittered sampling</li> <li>N-Rooks (Latin Hypercube) sampling</li> <li>Sobol sequence sampling</li> <li>Halton sequence sampling</li> <li>Hammersley sequence sampling</li> </ul> </li> </ul> </div> </div> <div class="search-overlay"></div> </div> </body> </html>