Simple GPU Path Tracing, Part 7.0 : Transparency

 

From the previous renders, we can see that we're lacking something on the front glass of our car : Transparency ! we should be able to see through this glass.

In this post, we will be implementing that.


Here's the commit for today's post.

Opacity

 We want to have materials with opacity, meaning that we can see through them like the glass of the car for example.
To do that, let's add a field in the material struct, and in the materialPoint struct as well : 

struct material
{
    glm::vec3 Emission = {};
    float Roughness = 0;
   
    glm::vec3 Colour = {};
    float Metallic = 0;
   
    glm::vec2 Padding;
    float MaterialType = 0;
    float Opacity = 1;

    int EmissionTexture = InvalidID;
    int ColourTexture = InvalidID;
    int RoughnessTexture = InvalidID;
    int NormalTexture = InvalidID;
};

struct materialPoint
{
    glm::vec3 Emission;
    glm::vec3 Colour;
    int MaterialType;
    float Roughness, Metallic, Opacity;
};

then in the EvalMaterial function in PathTraceCode, we can fill in the materialPoint opacity value : 
    Point.Opacity = Material.Opacity * ColourTexture.w;

Note that we modulate the material opacity with the opacity read from the texture.

Next, we will be using that in the main loop : 

The way it's going to work is quite simple : if an object is transparent, we want our ray to pass through it. But we don't want all the rays to pass through, otherwise the object would become invisible ! So we want some rays to pass through, and some rays to still interact with the object.
 
to do that, we generate a random number between 0 and 1 and compare it with the opacity. If the number is higher than the opacity value, we let the ray pass through :
 
What happens effectively is that we just shift the ray origin by a small amount, just enough to pass through the surface, and then restart the routine as if the ray was shot from behind the transparent surface.
 
If the random number is less than the opacity, we calculate lighting as we would do otherwise.
 
 
We also keep track of an "opacity bounces" number, which calculates how many times we hit a transparent material and had to shif the ray origin by a small amount. 
That's because when we hit a transparent material and have to shift the ray, it doesn't count as a bounce, and we effectively have to restart shooting the ray from beyond the surface. Now imagine if we have a very complex object with many layers, and it's transparent. We would have do this ray origin shifting many many times, and this would become inefficient. 
So if we do more than 128 opacity bounces, we just want to break out of the bounces loop.
Here's the full code : 

                // Opacity
                if(Material.Opacity < 1 && RandomUnilateral(Isect.RandomState) >= Material.Opacity)
                {
                    if(OpacityBounces++ > 128) break;
                    Ray.Origin = Position + Ray.Direction * 1e-2f;
                    Bounce--;
                    continue;
                }
               

Again, that's very simple, and here's the result : 
 
We can see through the glass, with a slightly green tinted colour. Nice ! 

Commentaires

Articles les plus consultés