I am trying to implement BRDF microfacet path tracing and I think I need a little push. I will explain what I understand so that you can correct my mistakes.

I start with simple rendering equation: enter image description here Le and Li are radiance we have no control of so I cannot change anything about them. The only thing I can change is function F which is called BRDF. Specifically, I am using this Cook-Torrance microfacet specular BRDF I found here. enter image description here For functions F, G and D I choose these formulas. enter image description here

Let's start with the Fresnel function. Greater the angle between H and Wo (or Wi, it should be the same) the more light is reflected. When the angle between H and Wo will be 90° then the function will return 1. That means that all of the light is reflected. That is understandable, but when I will look directly down to normal the result will be 0.14163. is really so little light reflected back? I thought that Fresnel gives percentage between reflection and refraction on the water surface for example. Is this right?

Following with function G - Geometric shading. I want to use the Smith shadowing model because I want to improve it later for multiple scattering BSDF. The equation goes like this: enter image description here

As G1 can be used more types of functions, but I like GGX. D_GGX is evaluated for both incoming light and outgoing light. It describes how much light will NOT be blocked by surface imperfections.

And last function D - Normal distribution function. With this one, I have the biggest problems. It describes the probability that a new microfacet normal will be pointing to the given direction. This depends on roughness. So perfectly smooth surface will have every normal pointing upward, but as the surface gets rougher and rougher normals will start to point to different directions. With 100% rough material the chance of normal pointing a given direction should be uniform over the whole hemisphere. Because we are talking about probability the integral of probability over hemisphere should be 1. as this equation says, but I don't understand why there is a dot product of N and H. enter image description here

Now I will explain how I am using these equations.

I start with generation microfacet normal H with distribution D_ggx. Spherical coordinates a generated like this: (epsilon is a random number from the interval (0;1>. I can't use 1 because we cannot divide by 0) enter image description here

With H defined I can reflect Wo and get Wi. H is now half vector between Wo and Wi. Now I calculate F and G. I am not using D anymore because I already used it for generating the microfacet normal H (that is against what I read in this answer). I divide them by 4 * dot(H, Wi)dot(nWo). This final number should be weight describing how much light [Li(Wi)] is reflected towards Wo. Together with a dot product of n and Wi from rendering equation. I think I have this part wrong.

I am not using any importance sampling for now because I think it is not necessary to work. Am I right? Of cause with importance sampling, the image would converge faster. This is my final equation.

Of cause, as you might guess when I implement this it returns almost totally black image. If you don't find any mistake in the math then the error has to be in code (but I will bet a 10$ it is a math problem)

enter image description here

If you need any specification of my decisions or goals I will happy to answer you.

  • $\begingroup$ The integral of the microfacets distribution is NOT over the hemisphere. It is over the area of the surface. The cosine term is related to the projected areas of the microfacets. and the integral basically says that the sum of projected areas of microfacets must equal the surface area. $\endgroup$
    – ali
    Commented May 4, 2020 at 4:29
  • $\begingroup$ Have a look at pbrt here somewhere in the middle of the page has the diagram: pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html $\endgroup$
    – ali
    Commented May 4, 2020 at 4:29

2 Answers 2


Some more clarity on the fresnel.

F tells you how much light is reflected, and (1 - F) therefore tells you how much light is transmitted through the layer/material/surface.

Generally we put fresnels into two types Dielectric(water/glass) and Conductor(metals).

The approximation you are using is for a dielectric fresnel, so what you are actually modelling is a thin layer over the top of your diffuse. In renderers this layer is normally called the coat or clearcoat. It can be used to emulate laminated materials or a coating of water/sweat.

If you want to render metals you would need to swap out the fresnel for a conductive one. There are better approximations, but an easy artistic approximation is to swap the F0 of your schlick approximation with the rgb of your material. You can layer a diffuse below this if you need to but you may find with conductive it's not nessisary.


This is a good article on the topic for further reading.


So I found out where was a problem.

This whole equation is for specular BRDF which is only one part of light interaction. When you hit the surface you have to generate new microfacet normal from distribution D. Then use it to calculate Fresnel. it gives you value from 0 to 1. That is now much light is directly reflected from the surface, but there is another part I forgot about, the diffuse component also contributes to the equation with (1 - Fresnel value).

So the only problem was using just one component.

And I also introduced the importance of sampling, which negates the D resulting in:

Integral over omega = incoming light from wi * (F * G * dot(wo, H(new microfacet normal))) / (dot(N, wo) * dot(N, H))

There is also one check. New direction wi cannot point towards the surface, because it would go through.

if (dot(wi, N) < 0) ray.mask = (float3)(0.0, 0.0, 0.0);

This can darken an image quite a lot especially when you use it on the glass. But there is a solution in BSSRDF. This equation takes a multiple scattering of the light on surface into a count.

This is the specular part. For the diffuse, I used a basic cosine weighted distribution with (1 - Fresnel) multiplier.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.