//****************************************************************************// //********* Ray Tracing Shadows & Effects - February 20th, 2019 *************// //**************************************************************************// - Alright, the midterm is going to be THIS MONDAY, February 25th - Weirdly, for the first time ever, we'll be taking the test online on Canvas, so BRING YOUR LAPTOP! It'll be open-note and open-book! - The test will be based on the topics we've covered in lecture, up to the stuff on Friday's lecture - Most of the questions will be multiple-choice/short-answer, with a few true/false questions ("what does this code snippet do?", etc.) - Most of the questions will be conceptual, but there might be a few along the lines of "do these matrix transformations," "what does the final matrix stack look like after these function calls?", etc. - Mercifully, Professor Turk has said he doesn't know how to add long text boxes to the online quizzes, so he won't ask any coding questions ------------------------------------------------------------------------- - Alright, we left off yesterday by trying to figure out how raytracing can deal with transparent surfaces, like glass or water (or a glass of water) - Part of the ray is reflected, like with specular surfaces, but the other part of it is TRANSMITTED through the surfaces - and due to the speed of light being different in different materials, it'll bend by a certain amount based on its index of refraction (IOR) - How much will it bend by, though? That's based on something you might remember from physics called SNELL'S LAW: sin(theta_incident) / sin(theta_trans) = IOR_trans / IOR_incident - Where "theta_incident" is the angle that the ray makes w/ the normal before it enters the material, and "theta_trans" is the angle the transmitted ray will make with the surface normal as it passes through - In general, a ray passing into a material with a higher IOR will bend towards the normal, and vice-versa - Another feature of these materials, though, is a thing called "total internal reflection:" if a ray is traveling through a material and is about to enter another one, but the angle is above some "critical angle," it'll actually bounce off instead and stay in the material! - This is critical to how fiber optic cables work, for example - So, with all this stuff considered, what should the color of our eye ray be now? - Here's our updated equation (I think? DOUBLE CHECK THIS): color = ambient + diffuse + specular + k_refl*c_refl + c_trans - Alright, so we've spent a lot of time talking about light in this class - but what about its opposite? What about SHADOWS? Well, let's shine a "light" on the topic now (HAHAHAHAHA -_-) - We'll start off with "hard shadows," with clearly defined, non-blurry edges - Let's suppose we have some point light source in our scene, and there's an object in front of another object that should be casting a shadow - what can we do? - Basically, when we first shoot an eye ray onto a surface, we shoot a "shadow ray" from the impact point to each light source in the scene - if we can reach the light's pont without hitting anything, hooray! The point is lit up! - If our shadow hits another object BEFORE it reaches the light, though, that means that we can't "see" that light source from that point - so we don't add its contribution to the lighting at that point - Cool! But more commonly in the real world, we see SOFT SHADOWS that are darker near the center of the shadow, then fade out to light towards the edges - This occurs when we have light sources that aren't just infinitesimal points, but have a non-zero area <insert outdated thine-mother joke here>, like a fluorescent tube - For these shadows, there'll be an area of darkness where can't see ANY of that light source's parts, known as the UMBRA (total shadow) - As we move out from behind the object's shadow, though, part of the light source's area will become "visible," and the surface will only be partly in shadow - this is the shadow's PENUMBRA (partial shadow) - Alright, these are the two types of shadows, so how do we calculate what a light's contribution to a point is NOW? Well, like THIS: Final Color = Cl * Cr * (N*L) * Visible(P,L) - Where: - Cl is the color of the light - Cr is the surface color - N is the surface normal, L is the vector to the light - Visible(P,L) is 0 if the light 'L' is blocked and point 'P', 1 if the light is unblocked - We COULD write this as an if statement, but being able to have fractional values between 0 and 1 for this'll be useful - Determining visibility is easy in the hard shadow case (just shoot a ray from P to L, 0 if blocked, 1 if unblocked), but how do we determine what percentage of the light is visible for an area light? - Well, for an area light, we'll shoot "n" shadow rays to equally-spaced points along the light source, and record if the light is visible or not for each ray - Then, we'll average their visibilities like so: Visible(P,L) = 1/n * sum{CLi * Visible(P, Li)} - This is one form of "distribution ray tracing," which is also done for other effects like motion blur, blurred reflections, depth-of-field blur, etc. - If we shoot too many rays, it'll really slow stuff down; if we don't shoot enough rays, the penumbra will look grainy and discretized ("it just looks like multiple point lights are lighting it") - "Why would we want motion blur, though? It makes my real-world photos look blurry, Greg!" Well, because it makes the image look more realistic - perfectly in-focus images look fake to our object, ESPECIALLY in the VFX world where you have to merge CGI with real footage - So, which type of shadow is faster to render? HARD SHADOWS, since we only have to shoot one ray to each light source! - Soft shadows, though, tend to look much more realistic; we get the effect of shadows getting blurrier with distance for free, and in general it just matches real life a lot better - Now, shadows are certainly very important, but how can we use distribution ray tracing to do other effects? - Let's think about glossy reflections, for instance, where we don't have perfectly smooth reflections - The "traditional" way of getting the surface color for a reflective surface is something like this: C = ambient + diffuse + specular + k_refl*Cr - Where 'Cr' is the reflect color (based on the reflected ray), and 'k_refl' is the coefficient for how much of that reflection should come through - To do it the distributed way, we do ALMOST the same thing, but replace the single "k_refl*Cr" with the average of multiple rays, to simulate the scattering of the reflected light: C = (...) + 1/n * sum{ k_refl * Cri} - Cool! Now, what about motion blur? - To do this, we need to distribute our rays not in space, but in TIME; our ray might hit the object at T=0 but miss it at T=1, for instance, and if we want that to show up in our frame as motion blur we need to average the two colors together - So, we'll go from our "traditional" color: C = Cl*Cr*(N*L) - To this: C = 1/n * sum(Cl*Cr_t * (N_t*L_t)) - As we advance the object in time, we need to average the color of the pixel across these "n" different times, which'll change if the object is moving - Usually, you'll need at least n ~= 20 so the blur effect looks smooth, instead of like a weird ghost-like object hovering over your scene - That's all the time we've got today, so FLEE!