Helgard opened this issue on Jun 26, 2010 · 195 posts
bagginsbill posted Fri, 09 July 2010 at 1:59 AM
In any system that does something wrong, it sometimes seems there is no way to make it right. But quite often, there is. Any time the wrongness is reversible, then there is a way to transform what you have into what you want. This comes up all the time. For example, monitors display luminance wrong. Dark things appear darker than they should. But if we have an understanding of what it does mathematically, as a function, and that function can be inverted with precision, then we can transform what we pass into that bad function such that it ends up doing nothing wrong. In the case of bad monitor response functions, we know that the displayed luminance is a power function, and if we pre-condition our output with the opposite power function, those things will cancel out and we'll get what we want. That's what gamma correction is. Feeding a bad function precisely constructed wrong data will cause the badness to go away.
So we know our "bad" function is:
1 - x/b
Well what can we manipulate here? We can't change the number 1 - that's a constant. We can't change x - that is the distance between the camera and the object and it is what it is. We're running out of options. What's left? Can we mess with the end distance, b, in some way as to make the bad function into a good one?
Hmmm.
What I'm saying is we want to arrange things so that 1 - x / b (the bad function) becomes the same as .5^(x/h), the good function. Algebra to the rescue!
We want to force this to be true:
1 - x / b = .5 ^ (x / h)
I'm suggesting that if I can solve for b, I'll end up with a new "wrong" function that will produce exactly what I want.
In order to avoid some typing, let's let G represent the good function I want, so G = .5 ^ (x / h)
Rewriting with G I have:
1 - x / b = G
Subtract G from both sides:
1 - x / b - G = 0
Add x / b to both sides:
1 - G = x / b
Multiply both sides by b:
b ( 1 - G) = x
And divide both sides by 1 - G.
b = x / (1 - G)
We have to pause for moment. During a proof, you have to make sure that each step is legal. For adding, subtracting, and multiplying, everything is legal. But for dividing, we must promise not to divide by 0, otherwise we can get into trouble, since dividing by 0 is impossible. I just divided by 1 - G. Can that ever be 0?
Indeed it can. Remember that G is the correct and good attenuation function, and that this function does equal 1 at some point. Therefore, 1 - G could be 0. But where is it that G is 1? Only when the distance is 0. Meaning, we're talking about dividing by 0 if and only if we're rendering an object that is actually touching the camera. I happen to know that will never happen - renders can't render anything that is touching the camera. That would entail a divide by 0 when trying to do the perspective projection. So - we can safely ignore the possibility that G is 1, and therefore ignore the possibility of dividing by 0 in this proof.
OK. With that safely out of the way, we've managed to isolate b, the end distance. All that remains is to put back the definition of G:
b = x / (1 - .5 ^ (x / h))
Wow - Yay! This is exactly the compensation function we need to make the Poser Atmosphere attenuation function do what we want. We need to plug a node network into DepthCue_EndDist, also known as "b", that implements the function we just arrived at.
Great. So all we need is the distance from the camera to the point being rendered.
Uhoh. There is no node that does that. I wish there was. Are we dead?
Nope. If we accept a tiny bit of manual work setting up a shader, we can get this done.
But ... it's really late and I've got to go to bed. So, more tomorrow.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)