First set of components: Two Variable [Fixed], one set to E (this gives the position of the viewer) and the other set to P (this gives the position of the surface). Plug both of them into a Distance brick, and it gives you something that will spit out the distances between points on an object, and the viewer. I personally grouped this and saved it as a custom “Eye to Point Distance” brick so I could work with it more easily later.
Now, what that gives you isn’t usable straight out of the box. To be usable and intuitive, values should stretch from 0 to 1, as that’s basically from pure black to pure white. Anything else clips. If it was only being used for a pure math calculation, that might be fine. However, if you want to use it later to render a depth mask, you’re SOL. Besides, having values range from 0 to 1 makes them far more intuitive for further calculations.
So we’ll fix that. Add a Binary Operation brick, change the title to “Move to Scene Min,” and connect the Eye to Point Distance output to the first input. Add a Value brick, name its variable slider “Minimum Distance” and connect the output to the second input. Change the operation to “Subtract.” This will allow you to dial down the values of Eye to Point Distance all by the same amount, so you can set the position where pure black starts (yes, pure black, it’s in reverse at the moment, don’t worry about it for now) at the closest surface to to the camera.
Still unusable, of course. It goes way past pure white almost instantly. That’s what we fix next. In order to do that, we need to scale the current output by the visible scene size. Mathematically, this works out to maxdistance-mindistance, to take the camera position out of the equation. So add another Value brick and name its variable Maximum Distance. Add another Binary Operation brick and change the title to “Scene Size.” Plug the output of Maximum Distance into the first input of Scene Size. Plug the output of Minimum Distance into the second input. Change the operation to Subtract. That will give you a flat numeric value for the visible scene size, once the distance variables are set properly.
Now, we need to use that to scale the distance output properly. So add another Binary Operations brick and change the title to “Scale to Scene Size.” Plug the output of Move to Scene Min into the first input. Plug the output of Scene Size into the second input.Change the operation to Divide. This will scale all the values appropriately, so pure white (yep, still backwards) will be at the far side of the scene once the Distance variables are set correctly.
Now, we don’t really want a backwards depth shader. It’s “technically” accurate. Black is mapped to the closest distance, the closest distance is the smallest distance, and black represents zero. But for a intuitive shader, we want the closest part of the scene to be white, the closer to us the more “important.” It makes using the output to scale effects simpler. You can stop here if you like. However, I added one more Binary Operations brick, changed the title to “Invert,” changed the first value to 1, set it to hidden (not locked, never ever locked, this can cause fun, fun problems depending on the situation), plugged the output of Scale to Scene Size into the second input, and changed the operation to Subtract. This inverts the shader values so they run from high (close) to low (far).
The best thing about this is, since it’s based on the surface, it can be mapped with transparency. You have to mess with ray depth and such to get those camera shaders to work with it - they might be simpler at face value, but this will give you surface by surface control.