I am trying to write the depth map of a scene in a 16-bit PNG, without any sort of normalization. I would like to pixels of such depth image to be set to the distance with respect to the camera, and of course the far clip plane value if no object present.

I tried with the following node setup, but I get values up in the PNG pixels which do not make any sense, in the range of [3100,65000] while my object is located rougly at 1 meter from the camera. Near and far clipping plans are 1cm and 10m respectively. I guess they are suffering some sort of normalization, but I cannot figure it out.

enter image description here


  • 1
    $\begingroup$ The z depth map contain values higher than 1,to store it in an image you will have to normalize it,Can you clarify the result yo want? $\endgroup$ – Omar Emara May 10 '16 at 16:42
  • $\begingroup$ How do these numbers relate to the coordinates of your objects? Remember that 'meters' is an abstraction. Nothing in Blender is actually measured in 'meters.' It just says that some number of Blender units is called a "meter." Take a look at the "real" numbers of those distances, and I'll be they make more sense. $\endgroup$ – Matt May 10 '16 at 16:43
  • $\begingroup$ @Matt I set my scene to use Units in Metric, and I can see the location of each object in meters when I look at the properties. For example, my camera is located at (0,0,0) and a plane object at (0,0,10m) (this are meters, explicitly displayed in the Transform box). I would like then the Z values of my depth maps to 10, if the object is in the camera view. $\endgroup$ – Dan May 10 '16 at 16:54
  • $\begingroup$ @OmarAhmad I want the z depth map values to be the distance with respect the camera, in Metric units (as my scene is set) $\endgroup$ – Dan May 10 '16 at 16:55
  • $\begingroup$ @Dan that might be much more difficult than you think it is. There's conversion going on behind the scenes, and you're going to have to confirm what numbers Blender actually uses, rather than what it shows the user. $\endgroup$ – Matt May 10 '16 at 16:58

Short Answer

If you are looking for accuracy, Do not save the Z pass as PNG or any other display referred format. OpenEXR is the only format that will allow you to use the linear information from the Z pass.

The only way to get a Z depth pass without distortion is by avoiding any kind of processing except [proper] inversion or normalization. Just plug the Z information to a file output node, and save as OpenEXR.

Long Answer

First let's separate the apples from the oranges:

The Z pass should not be thought of as an image, since its values do not fall into the parameters set for most image formats.

  • What is the Z pass then?

    The Z pass is the absolute distance from the camera to objects in the scene for every given pixel on the image. The camera is the 0 on the scale and the units used for its values are the working units set for the scene (blender units, meters, cm, inches, etc). The minimum and maximum value are clipped according to the camera's start and end clip distances.

    The Z depth values work in a linear scale, meaning that 6 will be twice as far than 3 and one half of 3 will always be 1.5

  • The Z pass is not meant to be viewed.

    The main issue is that Z depth information, will generate values larger than 1 and image formats cannot deal with values larger than 1 (where 0 is black, and 1 is white)

  • What happens when you normalize the Z pass?

    The minimum and maximum values are set as 0 and 1 respectively and all other values are spread in a linear scale in between.

    The real effect of doing this is that the scale is both compressed and offset from the real values. The values for absolute distance are converted in relative values and from then on you have to do conversions to find what the real values are.

  • What happens when you invert the Z pass?

    The maximum value is set to 0 and the minimum value is set to the maximum value. All other numbers in between are also inverted. Inversion is a reversible (invertible) operation (source)

  • Why do people normalize the Z pass then?

    Because the information contained can then be viewed as an image, since it has values from 0 to 1 that can then be expressed as an image. Normalize only when you want to make sure that the Z pass is working, or to use it on programs that cannot deal with the Z channel properly and need the information as an image in grayscale.

  • So why not PNGs or other formats?

    Normalizing the image to make it fit on a 0 to 1 scale is really not the problem (because even though normalizing has moved the values for the scale, it has kept the values linear). But when you save as an image format you are re-mapping those values yet again to a very limited number of values. Saving to an 8bit format will result in 255 possible values, greatly reducing the precision of the information. Even on 16 bit where you can have a much larger different gradations from black to white (4096) you might find that values that are close together are no longer represented.

    But the main reason not to use display referred formats like PNG is that those formats presume to be encoding values in sRGB, that is not a linear format anymore, but has a transfortmation curve in which 3+3 might not equal 6 anymore... The values will have been re-mapped yet again to a point that will not reflect the proper scale of the distances represented on the Z depth information.

  • How is OpenEXR different?

    OpenEXR is a format that has been designed to store linear data and has no issues with values larger than 1. The information suffers no distortion and is as precise as when you rendered your scene in the first place.

  • $\begingroup$ there is an option in blender to store png images as BW. This should preserve the linearity? Can you confirm this? $\endgroup$ – Armen Avetisyan Jan 6 '17 at 1:27
  • $\begingroup$ @ArmenAvetisyan Z depth shouldn't be thought of as images but as data. If you use PNG and save as data (with no display transform applied to it by disabling save as render) you will still only be able to store only the values between 0 and 1, or a compressed scale if you normalize. Display referred image formats like PNG are probably useful for very small scale scenes... .. $\endgroup$ – user1853 Jan 6 '17 at 3:34
  • $\begingroup$ I understand that 8-bits do not resolve 32-bits which is your point in essence. Apart from that, the normalization in [0...255] or [0.0 ... 1.0] is a linear transform where magnitude/extent information vanish. However, my question is more if saving in BW png file format you are able to preserve linearity which may be distorted by sRGB file format. Because BW is not sRGB. $\endgroup$ – Armen Avetisyan Jan 6 '17 at 13:42
  • 1
    $\begingroup$ @ArmenAvetisyan you are confusing things: black and white (and color) can be encoded as non linear or not, the display transform set in the color management section determines that. The default options on blender will encode images through a sRGB transform, which has a "gamma" curve, It is a misconception that black and white images are exempt from such a transform. You can indeed save an image without the sRGB transform as raw or "data", color or not has nothing to with it. $\endgroup$ – user1853 Jan 6 '17 at 15:12
  • 1
    $\begingroup$ @Amir I was referring to saving the image as EXR instead of display referred formats. If you use the viewer you can sample the depth pass correctly as well. $\endgroup$ – user1853 Mar 10 '18 at 7:29

Use the z output and divide it by the value you set as the far clipping plane of the camera. Your output image will be black for a pixel located in the camera and completely white for positions at the far clipping plane. I'd switch to Blender units for the values and than back to metrics, just to be sure.

Node setup

In this example I have the "end" clipping value to 100.

You shouldn't use the normalize node because you won't know the farthest distance from the camera. Let's say you have a plane in the background at 80 from the camera, with normalizing it will output a value of 1 (since it is the biggest distance in the scene) instead of 0.8 the divide node will output.

  • $\begingroup$ Sounds good! Any idea if this can be saved as PNG-16 bit, or must use EXR? $\endgroup$ – Dan May 10 '16 at 18:36
  • $\begingroup$ The image will be outputted where and how you set it in the Properties panel -> Render tab -> Output $\endgroup$ – piegames May 10 '16 at 19:18
  • 1
    $\begingroup$ Do not use PNG! Export the Z pass with no processing or any nodes in between. PNG will destroy the linear scale of the Z inormation. Use OpenEXR, is the only format that will keep your information undistorted. $\endgroup$ – user1853 May 10 '16 at 19:49
  • $\begingroup$ How doeas PNG destroy/distort the data? The z pass output returns the distance of the pixel to the camera in Blender units. The maximum distance it will return is the distance of the far clipping plane of the camera. If I divide the z value by this, I'll get a factor from 0 to one that will be mapped to 0-255 in PNG without any errors. I use this quite often and never had any problems. $\endgroup$ – piegames May 11 '16 at 14:28
  • 1
    $\begingroup$ Besides the clipping issues of data larger than 1, and the loss of precision (by mapping the full range to 255 values in 8bit or 4096 in 16 bit) PNG being a display refered format will use a sRGB transform curve. So the data will not be linear any more. $\endgroup$ – user1853 May 11 '16 at 15:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.