//****************************************************************************//
//********* 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!