Bug: Displacement from Height Map only uses 8-bit precision

I am testing out World Creator and it’s export functionality to Rhino. I am using their manual export of meshes and textures.

Importing the mesh works, but the meshes are extremely large and Rhino takes a very long time to import them. The .stl file of the terrain is 1.6GB.

Therefore I think it would be better to use the exported height map from World Creator and use Displacement on it.

As you can see there is some problem with the displacement. It’s almost like it is sampling from the opposite edge on 2 of the sides. Like UV might be over 1 or something.

Anybody know a) why it happens and b) how to fix it?

This is in Rhino 8.9

240820_World Creator Terrain.3dm (10.4 MB)

I don’t know if it helps, but if you set the repeat count to .99, the effect goes away:

You’re right, that helps. Obviously there must be a bug in the way the displacement map is read though. Probably a rounding error from not sampling in the middle of a pixel. Working with image samplers a lot in coding as well, I know it can happen quite easily that you actually sample a pixel on the edge and then there might be rounding errors. You actually have to offset by half a pixel to make sure you sample a pixel in the center of it.

I hope someone from McNeel can take a look. At those scales being off by just a pixel can mean a meter to dozens of meters difference.

I noticed that setting repeat at 0.999 still works, but at 0.9999 the error still occurs.

image

I also notice that using an .exr as a height map also does not seem to work at all. I export the texture and if I open it in Affinity Photo you can see it shows correctly with the information in the red channel.

In Rhino it just shows as a black texture!?

First test_Height Map_2048x2048_0_0.exr (16.0 MB)

Okay, I just keep finding things.

So in addition to .exr not working there are actually 32-bit and 16-bit tiffs we can save from World Creator, but it appears that Rhino somewhere turns them into 8-bit textures.

If I set the displacement precision to Extremely High you can actually see the steps in the terrain when looking at it from the side:

You can see 1 step is around 55cm of real height.

image

The actual height difference is 189 - 60 = 129 m

129 / 256 = 0.5 m resolution.

We can therefore deduct that even a 16 or 32 bit tiff texture is internally converted to an 8-bit texture. Not great! That means using height maps for terrains is basically not sensible to do at all in Rhino!

it might be related that sometimes when i snip a table from excel a put it in rhino as a picture a get unwanted black lining around the picture in the vicinity of actual table borders in the picture.

I also tried 16-bit PNG files and it’s the same. The vertical resolution never exceeds 256 steps:

That leaves only the “high” setting for the mesh details to still be usable. That has a minimum distance between vertices of around 100cm.

That means that even for 8k height texture, which in theory should have about a 12.5cm precision in X and Y for an area of 1 km square and a vertical precision of 1.5mm (at 16 bit with 100m height difference), now only has a precision of around a meter in all directions!!

Oh!
I never noticed displacement is 8 bits only.
When playing with your file, I also saw the steps with high settings.
But didn’t know why…
I assume _HeightField is 8 bit as well.
Not good.

It’s strange right. You would think that for displacement 256 steps is not a lot, but if you look at the use-cases it is geared towards - like adding some relief patterns to surfaces, it’s almost understandable.

But if you want to model terrain from height maps, like from World Creator and many others, where you can also use real world data as well, I would think that 256 steps precision vertically is laughably bad.

I hope some from McNeel can comment on this, maybe @wim or @dale ?

Could we get at least 16-bit support for displacement maps?

Okay, maybe @brian can help!? Is 16 or 32 bit support for displacement maps in the realm of possibilities?

As a reminder, here are the accuracies for terrain height maps for different bit depths:

@andy - is this something you can help with?

I haven’t checked 8 yet, but 7 did not have enough bump range.

I believe I have logged a bug about the precision part somewhere, let me see if I can dig it up.

edit: found the report from 3 years ago:

RH-64094 Support higher-bit channels for PNG and TIFF

edit2: actually, that is a different YT I was looking for, continuing. I know there was a topic started by @Holo about using high-precision TIFFs.

edit3: this is the YT I was searching for, contains link to the TIFF discusion from @Holo: RH-67413 HDR texture should support other formats

Rhino doesn’t like single channel textures. Best is to save it as an RGB EXR with the R channel duplicated in G and B as well.

edit: With the R channel extracted to G and B

I get this

The extracted mesh exported as 3dm - the resulting full file is too big to upload
Displaced_with_exr.3dm.zip (17.0 MB)

edit2: nvm, I just realized my plane is to small. I’ve put the full file with both displaced plane (hidden) and extracted render mesh, along with the adapted EXR texture here: displacement_height_map_from_exr 2.3dm.zip - Google Drive As far as I can tell this gives smooth result for the displacement. I used extremely high setting to create it


I have logged this error as: RH-83473 Displacement has sampling artifact

Okay, after some further testing I can confirm that it works well with .exr files. In our software we are now saving the height maps as .exr files with either 16 or 32 bit depth per channel, depending on the input texture.

The quality of the mesh is now much better. It’s doesn’t look quite as smooth, but at least the accuracy is there now. We are slightly blurring the normal map for that super smooth look:

And in Rhino with the same height and color texture:

Of course speed is still an issue. We calculate everything on the GPU at 60fps. In Rhino it takes a good minute for extremely high quality.

Thanks for looking into this and creating the YT items!

For fun here I put the EXR texture in a PBR material displacement channel. I used the render mesh generated by the displacement plugin, but scaled it to 0 on the Z axis to make it completely flat. Then assigned the PBR material to the mesh:

Since the PBR displacement happens only in the display or during rendering you can still see the flat mesh plane from the side in the front and right views.

Raytraced appears to be doing a better job than the Rendered mode - I wouldn’t be surprised if Rendered display mode here uses 8-bit version of the texture. @DavidEranen do you know if the texture in use by Rendered mode displacement is a 8-bit version of the EXR?

@nathanletwory Yes, it ends up being an 8-bit image, unfortunately. It’s something we need to fix.

Yes, I think this is exactly the main issue - if you want to use “ExtractRenderMesh”, which we do, you now only have 8-bit precision and therefore get those steps in the mesh as shown above.

I actually think for rendering it’s fine, but ExtractRenderMesh should use the full bitdepth of the texture for the extra accuracy.

Thanks for fixing this!

ExtractRenderMesh from the displaced geometry through the displacement modifier uses the full bitdepth as for as I can tell. At least the mesh I get does not exhibit the stepping when using the EXR image as displacement texture before extracting the resulting render mesh.

What I was showing via PBR material in Rendered mode is separate from that.