Glossy reflections - how to do a proper blur
Have a look at this presentation by Epic, they show how they deal with IBL for their shading pipeline in Unreal 4
Slides: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
Course notes: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
They do a split-sum approach where they encode one part of their BRDF data in a lookup texture and the irradiance data in an importance sampled cube texture. Every mip level of this cube texture represents a different roughness level, so you can achieve these rough glossy reflections.
Thanks for the information!
I'll idea of splitting up the lighting function (BRDF) in a 2D LUT and environment map, though I never really understand the formula's in such papers. But first, I guess that on itself doesn't improve the reflection sampling.
When I simply fetch the lower LOD's, for example:
float lodLevel = roughness * numOfMips;
vec3 reflDir = normalize( -V, N );
vec3 result = textureCubeLod( envMap, reflDir, lodLevel );
the result gets blocky or "cubic" (see left side of the attached image in 1st post), instead of "nicely blurred". It gets better by NOT accessing the deepest LOD's and doing multiple samples, yet I guess it can be done more efficient. Maybe my CubeMap just sucks to begin with (though with ATIcubeGen which should blur & still respect the seams, it still doesn't look good). Or maybe my OpenGL texture sampling method is just wrong?
The Unreal Engine paper notices "Pre-filtered Environment maps". Now maybe here's the catch, If I understand well, the EnvMap doesn't just contains a traditional (mipmapped) "snapshot of the environment", but encodes the 1st sum of the BRDF, where each mip filters its content with a certain roughness setting.
But what is this "First Sum"? The paper mentions the formula (1/N) Li (lk) - sorry can't write it, but its on page 12. Call me stupid, but I never understand how to interpretate that. It likely covers the diffuse and/or specular calculations, such as dot(L,N), but I miss the details plus a five-year-old explanation.
Sorry for the long post. I have to speak loud to understand myself hehe.
One simple thing that could help regarding your "Sampling lower LODs" idea:
Blur the texture before you make the next Mip Map level. Simply summing up 4 Texels * 0.25 is not so good.
(It may be that Graphics APIs or Cube Map Gen already do that, or it is related to the Mip Map generation quality settings in driver... i don't know)
Blurring makes the Mip Map smoother and also causes very bright pixels to bleed over a larger area, but energy is conserved.
@JoeJ
First I had OpenGL automatically generating the mipmaps. Having ATIgenCubeMap tool doing it indeed does a better job (plus you can do more filtering). The attached picture is showing results with OpenGL generated mipMaps.
Yet, when sampling the deepest levels, I keep getting that "box" effect, wether its blurred or not. In the ATI tool preview this "artefect" is far less visible, which makes me think maybe some sampler settings are wrong / too simplistic.
Either way, combined with multiple samples, the result gets acceptable. But I'm curious if someone can explain some details about the Epic paper that was posted by Radikalizm here above!
Subtle, but certainly another step forward! Doing glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)? & having higher quality lower LOD levels almost ellimated the ugly "box" effect and the need of multiple distorted samples. At least I can do with far less samples to get a pretty cool result. I always like these more simple solutions :)
http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/
There is trick called dominant direction. Basically it skews reflection vector towards normal vector with rough surfaces.