sorry for a third post, promise I’m not bumping it.
I finally understood the kernel enough to get
(I - 2 * dot(N, I) * N)
working without errors.
It’s a really, super naive approach, where all I am doing is reflecting the vector. I realized after testing that I should have removed the Z component from the vector, but overall it still got me… passable results, at least something I’m proud of for my first real change of blender’s code.
Default:
Corrected (replacement method):
Corrected (my really bad reflection method):
Ground Truth Displacement
from top to bottom, they are the default, the current corrected normals, and my corrected normals, and then the displacement version of that same normal map.
it’s obvious from this that mine does not pass muster in either a furnace test or visually. This is almost unusable because there is a black band- a situation which allows normals to self-intersect, somewhere between a normal bounce and one that triggers “correction via reflection”
however… reflection does seem to be more accurate as a whole, then “normal damping”, where it does work.
look closely- the “ground truth” displacement map shows almost zero of the orange part of the sky here, but the corrected normals shows a whole lot of it! This is because at extreme angles of incoming rays, the normal map acts as if it were flat.
This totally destroys the usefulness of normal maps, whose single use is to provide detailing and shading that appears non-flat.
also note how my code accurately handles the reflections of the green sphere, compared to the “ground truth” displacement map.
I want to propose a refined implementation of normal reflection as a correction method. It’s super inaccurate when it comes to lighting, but is visually and perceptually more accurate in most cases.
these are the diffuse tests. They aren’t significantly different from one another, but if you flip them back and forth you can see that reflected normals does have a slight effect on lighting at glancing angles.
some more information; I’ve not finished working on this yet, or stopped in these couple weeks.
I noticed it was very strange that something tagged “only used for glossy normals” was affecting diffuse only normals with an IOR of 1. That’s theoretically 0% glossy.
I’ve been scouring the code, and finally found it almost 2 weeks later.
the bulk of it is that Blender is using this as a reference: Taming the Shadow Terminator
it’s a siggraph talk from disney, but after even just a brief look at it, it… doesn’t really pass muster. Sure, the method does exactly what it’s supposed to, but the samples are clearly cherry picked in order to show the best case for their method. One of them isn’t, and, well, I’ve spliced all the slides together, so you can actually compare them fairly… (yes, the bump tests are a couple pixels wider for some reason)
I see nothing wrong with the original bump here, and it’s achingly clear that their solution (the one Blender now uses), is the worst presented on the slides, both visually and functionally from a lighting perspective, whereas the original bump method allows peaks to catch light past the terminator, and the Esteves method doesn’t knock down peaks even if it dims them. The Chiang-Li-Burley method seems to prematurely remove detail around the terminator. It essentially takes normals at certain angles and past, and replaces it with a shaded gradient. This is hardly unbiased, and results in very unusual shading at glancing angles, where normally, the tips of bumps receive striking highlights. The corrected ones, however, simply see all the normals pointed toward the light act as if they’re nearly flat.
the issue is not limited to this bump smoothing, however. part of it… is that this bump smoothing uses the same flag as correcting normals for glossy reflections. this means that if an object has both glossy and diffuse parts in its texture, you’re forced to choose between corrected reflection normals, or accurate edge shading on diffuse normals.
after a hefty amount of commenting out and tinkering, I was able to get this battery of tests:
and it turns out that my reflection normals are almost totally useless from above! interesting! here’s another angle to prove they’re “working”:
Corrected glossy normals and corrected diffuse normals should be separate flags, as their solutions and effects on a rendered scene are different, and both correction solutions at the moment need to be replaced with more accurate ones.
and now to figure out algorithms that do those things. easier said than done.
@Thomas_Kole @Atair that seems like it would solve the issues in your initial posts… at least the normal mapping ones.
as per the geometric normals, I’m totally unsure how to fix that- it seems that you’d need to figure out a way for all the shaders to “talk” and figure out how a normal map should be processed in line. I think the best solution would be @Alaska 's, but it would take some real rough work to reduce bias to invisible levels, I think. still worth a shot- but definitely a level above what I know to do.