In the glossy shader I think there's a part that pseudorandomly perturbs the reflection vector so that it's not a perfect mirror reflection. How does one go about perturbing the reflection vector to get good visuals? Is there a formula?
Glossiness, pseudorandom perturbation
3 hours ago, taby said:In the glossy shader I think there's a part that pseudorandomly perturbs the reflection vector so that it's not a perfect mirror reflection. How does one go about perturbing the reflection vector to get good visuals? Is there a formula?
If you're purely talking about the reflection direction, I would be tempted to say that the magic simply happen with your normal map as long as the normals don't all point perfectly in the same direction.
14 hours ago, taby said:Is there a formula?
Yes! There's essentially a whole family of formulas that are based around the idea of treating the surface as a heightfield made up of microscopic facets (or "microfacets"). If you search for "microfacet BRDF" or "microfacet specular" you will find many links that go into this in detail (such as this one). The basic idea is that you describe this microfacet heightfield using some sort of statistical distribution (called a Normal Distribution Function), typically parameterized on some sort of "roughness" or "smoothness" value that tells you how much the facets are pointing in random directions. Rougher surfaces will give you blurrier reflections since the the light will reflect in random directions, while smoother surfaces will have more mirror-like like reflections. If you take your statistical distribution and add a few other components to form a full specular BRDF, you then have a function that can answer the question "if some light hits the surface from this direction, what percentage of the lighting will be reflected towards the camera?".
Strictly speaking, you don't actually need to randomly perturb the reflection vector to handle reflections from a microfacet BRDF. If you only have point light sources (infinitely small), you just evaluate the BRDF for the lighting direction and multiply it with the amount of incident irradiance resulting from that light source (nDotL * lightColor * attenuation). For a full environment of lighting you can just shoot rays all over the hemisphere and evaluate the BRDF for each one. The problem with that latter approach is that it will be noisy, since most of the rays won't result in any reflections that reach the camera (this is particularly true for smoother surfaces). You can significantly reduce that noise by importance sampling your specular BRDF, which basically means that you pick your rays in such a way that they (mostly) match the directions that will give you valid reflections. The way this normally works is that you use your pseudo-random numbers to generate a random microfacet with from your normal distribution function, and then reflect the eye vector off of that microfacet and sample the lighting in that direction. Which is pretty similar to what you initially described! The trick part is that you need the right math for sampling your chosen distribution, and then you also need to make sure that your weighting your samples correctly according to the probably density function in order for the monte carlo integration to work out correctly. I have some code here for sampling the popular GGX distribution if you want to have a look.