EDA101: Advanced Shading and Rendering Ray Tracing and Sampling Michael Doggett Copyright 2008 Tomas Akenine-Möller 1
What is ray tracing? Another rendering algorithm Fundamentally different from polygon rendering Rasterization (OpenGL, DirectX) Renders one triangle at a time Z-buffer stores nearest pixels Local lighting (per-vertex or per-pixel) Ray tracing Renders one pixel at a time [Kind of] Sorts the geometry per pixel Global lighting equation (reflections, shadows) Copyright 2008 Tomas Akenine-Möller 2
Why ray tracing? Simple concept Higher quality rendering Global lighting equation Accurate shadows, reflections, refraction, etc Soft shadows, more realistic materials and lighting All computations done per pixel No interpolation Base for many advanced algorithms Global illumination, e.g., path tracing, photon mapping A disadvantage: can take long to render images! Copyright 2008 Tomas Akenine-Möller 3
Original goal: Add reflections Copyright 2008 Tomas Akenine-Möller 4
Side by side comparison (1980 s) Images courtesy of Eric Haines Copyright 2008 Tomas Akenine-Möller 5
Newer example [Image courtesy of ARTVPS www.artvps.com] Copyright 2008 Tomas Akenine-Möller 6
More reflections [Image courtesy of IBM] Copyright 2008 Tomas Akenine-Möller 7
Card Ray Tracer #include <stdlib.h> // card > aek.ppm #include <stdio.h> #include <math.h> typedef int i;typedef float f;struct v{f x,y,z;v operator+(v r){return v(x+r.x,y+r.y,z +r.z);}v operator*(f r){return v (x*r,y*r,z*r);}f operator%(v r){return x*r.x +y*r.y+z*r.z;}v(){}v operator^(v r){return v (y*r.z-z*r.y,z*r.x-x*r.z,x*r.y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v operator!(){return*this* (1/sqrt(*this%*this));}};i G[]= {247570,280596,280600,249748,18578,18577,23118 4,16,16};f R(){return(f)rand()/RAND_MAX;}i T(v o,v d,f&t,v&n){t=1e9;i m=0;f p=-o.z/d.z;if(. 01<p)t=p,n=v(0,0,1),m=1;for(i k=19;k--;)for(i j=9;j--;)if(g[j]&1<<k){v p=o+v(-k,0,-j-4);f b=p%d,c=p%p-1,q=b*b-c;if(q>0){f s=-b-sqrt (q);if(s<t&&s>.01)t=s,n=!(p+d*t),m=2;}}return m;}v S(v o,v d){f t;v n;i m=t(o,d,t,n);if(!m) return v(.7,.6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v (9+R(),9+R(),16)+h*-1),r=d+n*(n%d*-2);f b=l %n;if(b<0 T(h,l,t,n))b=0;f p=pow(l%r*(b>0), 99);if(m&1){h=h*.2;return((i)(ceil(h.x)+ceil (h.y))&1?v(3,1,1):v(3,3,3))*(b*.2+.1);}return v(p,p,p)+s(h,r)*.5;}i main(){printf("p6 512 512 255 ");v g=!v(-6,-16,0),a=!(v(0,0,1)^g)*. 002,b=!(g^a)*.002,c=(a+b)*-256+g;for(i y=512;y--;)for(i x=512;x--;){v p(13,13,13);for (i r=64;r--;){v t=a*(r()-.5)*99+b*(r()-.5) *99;p=S(v(17,16,8)+t,!(t*-1+(a*(R()+x)+b*(y+R ())+c)*16))*3.5+p;}printf("%c%c%c",(i)p.x,(i) p.y,(i)p.z);}} courtesy Andrew Kensler from http://www.cs.utah.edu/%7eaek/code/
Some Terminology Solid angle: Ω=A/r 2 Flux (radiant power): Φ [W] Ω r=1 Irradiance: E=dΦ/dA [W/m 2 ] Incoming radiant power on surface Radiosity (radiant exitance) dω A Same as Irradiance but outgoing Radiance: Important: captures appearance of objects Flux per unit projected area per unit solid angle L(x,Θ) 5 dimensions θ [Read about these terms in the book good for next lecture] BRDF: Bidirectional Reflectance Distribution Function Copyright 2008 Tomas Akenine-Möller 9
To be physically correct, follow photons from light source Not what we do for a simple ray tracer Though this is almost what we do for more advanced techniques (photon mapping) Image plane Light source Not effective, not many rays will arrive at the eye Copyright 2008 Tomas Akenine-Möller 10
Instead: follow photons backwards from the eye Rationale: find photons that arrive through each pixel How do one find the visible object at a pixel? With intersection testing Ray, r(t)=o+td, against geometrical objects Use object that is closest to camera! Valid intersections have t > 0 t is a signed distance Image For fast intersection testing, use a spatial data structure! Closest intersection point Copyright 2008 Tomas Akenine-Möller 11
Intersection testing? Ray/sphere test Sphere center: c, and radius r Ray: r(t)=o+td Sphere formula: p-c =r Replace p by r(t), and square it: o d r c Similarly for other objects!! Copyright 2008 Tomas Akenine-Möller 12
Precision problems in intersection testing Exaggerated: light eye ray point of intersection: p The point, p, will be incorrectly self-shadowed, due to imprecision Solution: after p has been computed, update as: p =p+εn (n is normal at p, ε is small number >0) Copyright 2008 Tomas Akenine-Möller 13
trace() and directillumination() We now know how to find the visible object at a pixel How about finding the color of the pixel? Basic ray tracing is essentially only two functions with recursive calls trace() and directillumination() trace(): finds the first intersection with an object Calls directillumination(), and then trace() directionillumination(): computes the direct lighting at that intersection point Copyright 2008 Tomas Akenine-Möller 14
Whitted-style ray tracer: A very simple type of ray tracing light Image plane trace() Point is in shadow directillumination() trace() trace() directillumination() First call trace() to find first intersection directillumaintion() computes direct illumination from light sources trace() then calls trace() for reflection and refraction directions (this is the indirect illumination for Whitted RT) directillumination() applies the BRDF of the surface, and so on... Copyright 2008 Tomas Akenine-Möller 15
trace() in detail Color trace(ray R) { bool hit; Intersection is; Color col,col_tmp; hit=intersectscene(r,is); if(hit) { col=directillumination(is); if(is indicates reflective object) { col_tmp=trace(reflected ray); col = weighttogether(col,col_tmp); } if(is indicates transmissive object) { col_tmp=trace(refracted ray); col = weighttogether(col,col_tmp); } } } else col=background_color; return col; [recursion should also be terminated.. could be done after fixed depth] Copyright 2008 Tomas Akenine-Möller 16
directillumination() computes direct lighting For now, we will use the simple standard lighting equation that we used so far Diffuse + Specular Could use other models for the BRDF More realistic materials Copyright 2008 Tomas Akenine-Möller 17
directillumination() in detail Color directillumination(const Intersection &is) { Color col(0,0,0); for each light L { // create shadow ray; is is in shadow // use intersectscene for this... if(not inshadow(l,is)) { col+=diffuseandspecular(l,is); } } return col; } Note: this is not exactly as done in the programming assignments Copyright 2008 Tomas Akenine-Möller 18
In directillumination(), we need a function inshadow() Compute distance from intersection point, p, to light source: t max Then use intersection testing: Point is in shadow if 0 < t < t max is true for at least one object Copyright 2008 Tomas Akenine-Möller 19
Who calls trace() to begin with? Someone need to spawn rays One or more per pixel A simple routine, computeimage(), computes rays, and calls trace() for each ray. Use camera parameters to compute rays Resolution, fov, camera direction & position & up Copyright 2008 Tomas Akenine-Möller 20
When does recursion stop? Recurse until ray does not hit anything? Does not work for closed models One solution is to allow for max N levels of recursion N=3 is often sufficient (sometimes 10 is sufficient) Another is to look at material parameters E.g., if specular material color is (0,0,0), then the object is not reflective, and we don t need to spawn a reflection ray More systematic: send a weight, w, with recursion Initially w=1, and after each bounce, w*=o.specular_color (); and so on. Will give faster rendering, if we terminate recursion when weight is too small (say <0.01) Next lecture will present the correct way of doing it! Copyright 2008 Tomas Akenine-Möller 21
Quick recap: Reflection Image courtesy of Illuminate Labs Copyright 2008 Tomas Akenine-Möller 22
Refraction [Image courtesy of slartybartfast at ompf.org] Copyright 2008 Tomas Akenine-Möller 23
Refraction [ Glasses by Gilles Tran 2006] Copyright 2008 Tomas Akenine-Möller 24
Refraction: need a transmission vector, t Known as Heckbert s method n, i, t are unit vectors η 1 & η 2 are refraction indices c 1 =cos(θ 1 )=-n. i Decompose i into: i par =-c 1 n, i perp =i+c 1 n t=sin(θ 2 )m - cos(θ 2 )n, where Copyright 2008 Tomas Akenine-Möller 25 i i perp m=i perp / i perp =(i+c 1 n)/sin(θ 2 ) Use Snell s law: sin(θ 2 )/sin(θ 1 )= η 1 /η 2 = η t = ηi + (ηc 1 - c 2 ) n, where c 2 =cos(θ 2 ) Simplify: c 2 =sqrt[ 1 η 2 (1-c 1 2) ] t n θ 2 θ 1 i par η 1 -i η 2
Some refraction indices, η Measured with respect to vacuum Air: 1.0003 Water: 1.33 Glass: around 1.45 1.65 Diamond: 2.42 Salt: 1.54 Note 1: the refraction index varies with wavelength, but we often only use one index for all three color channels, RGB Or use 3 slightly different diffraction! Note 2: can get Total Internal Reflection (TIR) Means no transmission, only reflection Copyright 2008 Tomas Akenine-Möller 26
Diffraction Diffraction Copyright 2008 Tomas Akenine-Möller 27
Ready to trace some rays? All tools are in place... First programming assignment is a Whitted ray tracer......meaning one that can handle shadows, and recursive reflections and refractions Turner Whitted = Father of ray tracing Copyright 2008 Tomas Akenine-Möller 28
CG is a sampling and filtering process Pixels Texture Time Copyright 2008 Tomas Akenine-Möller 29
Sampling and reconstruction Sampling: from continuous signal to discrete Reconstruction recovers the original signal Care must be taken to avoid aliasing Copyright 2008 Tomas Akenine-Möller 30
Sampling is simple: now turn to reconstruction Assume we have a bandlimited signal (e.g., a texture) Use filters for reconstruction Copyright 2008 Tomas Akenine-Möller 31
Reconstruction with tent filter Nearest neighbor Linear 32x32 texture Copyright 2008 Tomas Akenine-Möller 32
Reconstruction with sinc-filter In theory, the ideal filter Not practical (infinite extension, negative) Practical: Gaussian filter, symmetric piecewise cubic filter (Mitchell & Netravali) Copyright 2008 Tomas Akenine-Möller 33
Sampling theorem Nyquist theorem: the sampling frequency should be at least twice the max frequency in the signal f=1 rpm 1 sample per revolution A little more than 1 sample/revolution 2 samples per revolution >2 samples per revolution Often the max freq. may be impossible to know, or even be infinite. What to do?? Copyright 2008 Tomas Akenine-Möller 34
Screen-based antialiasing Hard case: edge has infinite frequency Supersampling: use more than one sample per pixel 1 sample per pixel 4x4 samples per pixel Copyright 2008 Tomas Akenine-Möller 35
Weighting formula and some examples wi are the weights in [0,1] c(i,x,y) is the color of sample i inside pixel Copyright 2008 Tomas Akenine-Möller 36
How do we get rid of aliasing? What we really want: integrate the color (radiance) over the entire pixel In fact, over a region slightly larger than a pixel... Depends on filter! Randomize sample positions replaces aliasing with noise! Better for HSV (human visual system) Spend next minutes of lecture on: Monte Carlo integration Jittering Copyright 2008 Tomas Akenine-Möller 37
Monte Carlo integration Rendering equation=integral. Many integrals in CG... Hard to evaluate MC can estimate integrals: Assume we can compute the mean of f(x) over the interval [a,b] Then the integral is mean*(b-a) Thus, focus on estimating mean of f(x) Idea: sample f at n uniformly distributed random locations, x i : Monte Carlo estimate When n infinity, I MC I Standard deviation convergence is slow: Thus, to halve error, must use 4x number of samples!! Copyright 2008 Tomas Akenine-Möller 38
More MC integration X is stochastic random variable, drawn from PDF p(x) How to evaluate the integral of f(x) when x is drawn from PDF p(x)? x i drawn from PDF Simple example 1 0 0 1 0 0 1 x Copyright 2008 Tomas Akenine-Möller i 39 1 0 0 1
Back to sampling... So, randomize sample position within pixel: Works well many times But not always! How to avoid clumping? Instead use jittering (stratified sampling): Divide pixel into nxn subpixels Randomly position a sample in each subpixel Variance always smaller than pure MC (3.6.2) Copyright 2008 Tomas Akenine-Möller 40
Adaptive supersampling (1) Quincunx sampling pattern to start with 2 samples per pixel, 1 in center, 1 in upper-left Note: adaptive sampling is not feasible in graphics hardware, but simple in a ray tracer Colors of AE, DE are quite similar, so don t waste more time on those. The colors of B & E are different, so add more samples there with the same sampling pattern Same thing again, check FG, BG, HG, EG: only EG needs more sampling So, add rays for J, K, and L Copyright 2008 Tomas Akenine-Möller 41
Adaptive supersampling (2) C & E were different too Add N & M Compare EM, HM, CM, NM C & M are too different So add rays at P, Q, and R At this point, we consider the entire pixel to be sufficiently sampled Time to weigh (filter) the colors of all rays Copyright 2008 Tomas Akenine-Möller 42
Adaptive supersampling (3) Final sample pattern for pixel: How to filter the colors of the rays? Think of the pattern differently: And use the area of each ray sample as its weight: Copyright 2008 Tomas Akenine-Möller 43
Caveats with adaptive supersampling (4) May miss really small objects anyway It s still supersampling, but smart supersampling Cannot fool Nyquist! Only reduce aliasing does not eliminate it Copyright 2008 Tomas Akenine-Möller 44
Sampling conclusion Be careful when sampling Do it well good quality Do it in a clever way reasonably fast Copyright 2008 Tomas Akenine-Möller 45
The END: Reading Advanced Global Illumination by Dutré, Bala, and Bekaert, AK Peters, 2006: Section 2.2-2.5 Section 3.2, 3.3, 3.4, 3.6.2 Appendix B.2 (solid angle) Programming Assignment 1: Due Tuesday 20 April, 13:00-15:00 or 15:00-17:00 in E:Saturnus Use Online discussion forum (Discus) to ask about this Seminar tomorrow, 10:00-12:00 Copyright 2008 Tomas Akenine-Möller 46