Simple Lighting

Code so Far

Here is the code for this section

Rendering a Scene

Now that I can render a scene, and have the raytracing pipeline setup, I want to make the raytracing scene look better. In rasterization there is diffuse light, specular lighting, etc., but how do you do proper shading for a ray tracer? To answer this question I picked up the book Physically Based Rendering, Fourth Edition, by Matt Phar et al. This book goes in depth in the theory and implementation of how to achieve photorealistic renderers using raytracing. A critical understanding of how light actually works is necessary (at least at a macro level) in order to replicate its behavior. When a light source strikes an object it's light can either be reflected, refracted, or scattered in any direction due to subsurface scattering. The probability of each direction can be described by a probability distribution called bidirection scattering distribution function (BSDF). 

Surface scattering example (Matt Phar)

In the example above, incident light hits the surface by the vector ωi. It then is reflected to the camera in ω0. The amount of light reflected in the direction of ω0 is the energy of ωi multiplied by the BSDF. If there is multiple light sources, the intensity of the light is added for all sources. Therefore, all of the emitted radiance in the direction of ω0 at point p is any light that is emitted at p directly (if p was a light source) plus the sum of all lights from all ωis.

This is the equation described above where f(p, ω0, ωi) is the BSDF for the surface. Because there is infinite ωis this equation cannot be solved analytically. Instead different approaches are used to approximate this function such as using Monte Carlo integration.


I will be going more into this next week but in the meantime I wanted to get basic shadows rendered for my ray tracer. Adding these shadows also goes somewhat along with the theory because I am computing one incident ray from my initial hit point, p. The way this works is everywhere I am hitting an object in my ray tracer I want to create another ray from that hit point in the direction of my light source. If the ray hits an object along the way then the initial hit point is in shadow, otherwise it is not. 

Note: The light for my scene is supposed to be an area light, but for simplicity right now I am using a point light. I will be changing this later on.

To create shadows this way I needed to create new shaders, and set up an additional hit group for every hit group I already had. That means for each geometry I now have two hit groups. In addition I have an additional miss shader, totaling to two miss shaders. The new shadow hit group and miss shaders' only purpose is to set on the ray payload a boolean indicating whether the new ray hit an object or not; That's it. Firing the second ray is as simple as, inside the original closest hit shader, calling TraceRay with slightly different parameters. 

After all of that is done... my program started crashing. I spent the next approx. 4 grueling hours debugging the issue. I was getting an accessed denied errors on the swapchain Present method with no other information. I couldn't run any graphics debugger, because it was crashing before it could draw anything. In short, it was pretty difficult to find what was even happening, but eventually I figured it out. The problem? The InstanceContributionToHitGroupIndex parameter in each of the top level acceleration instances needed to be multiplied by 2.

So finally after fixing that I got this:


Which doesn't look right so back to debugging I went. Thankfully this one was a quicker find. When I generated my second ray to detect shadows I set the max distance the ray could travel to some really large number. Instead the max the ray should check for intersections is the distance from the surface to the light position. Here is the result after making that changed:


1SPP Ray Tracing with shadow rays



While I was at it I wanted to update the rasterizer to look better as well. I didn't want to do a second pass to achieve shadows like in the ray tracer so I compromised and at least added some point light diffuse shading. This required me to load in normals from assimp. This was quite simple after I realized the x on the normals was inverted, which I should have realized earlier because the x positions were inverted too from last week's work. This is the now the current state of the rasterizer: 

Rasterizer with diffuse shading and a point light



Lastly I added light attenuation to the ray tracer. This is now the current state of my ray tracer.


1SPP Ray Tracing with shadow rays and light attenuation


In the raytracer I am not accounting for that cosθ term in the rendering equation, but this is a start. I will be exploring more realistic rendering in next week's posting.

This is a side by side comparison of the rasterizer and ray tracer currently.



Up Next

In the next post, I will continue to explore the theory and implementations of physically based rendering. I will be improving the raytracer to be more photorealistic while remaining real-time.




Comments

Popular posts from this blog

Rendering a Scene

Denoising

Enabling Raytracing - Part 2