Recommendations on specifying elevation maps to OptiX

Hey. I’m currently looking on ways to specify elevation maps to OptiX to create scenes to be raytraced, using the least amount of GPU RAM available.

As you know, in order to create a scene in OptiX, just like you would in the graphics pipeline, you have a few options. I haven’t found yet, in the documentation, a way to create an elevation map using anything other than the classic vertex / index buffer pair.

Let’s assume you have a grid of 1024 x 1024 points, with the Z coordinate representing an elevation value from the ground. Building vertex and index buffers with these maps is quite simple. A vertex buffer containing 1024 x 1024 points, in this case, would be:

1024 * 1024 (points) * 3 (coords per vertex) * 4 (bytes per float) = 12,582,912 bytes long.

As for the index buffer, assuming we go with regular separate triangles (which seems to be the only way OptiX does it now), the thing would be:

1023 * 1023 * 2 (triangles) * 3 (points per triangle) * 4 (bytes per int32) = 25,116,696 bytes long.

Which is basically double the amount of data in the vertex buffer (but then, of course, that beats having to specify the vertices separately per triangle, by a significant margin :D )

Thing is, if we already know that the vertex buffer contains an elevation map, we should kind of not need an index buffer - points for the triangles do have a specific and well known pattern that OptiX can follow to assemble the scene, with no need for the library user to explicitly lay out using costly GPU RAM.

But then, again, maybe there is an option in OptiX that allows me to do this, and I’m currently unable to see it in docs. Do you guys have an idea on how to specify elevation maps to OptiX using anything other than what I described above?

And, if that is not possible right now, may I convince you guys into adding this in a future release of OptiX? I can’t possibly be the only one that would benefit from such a change :D .

HI @heriberto.delgado,

This is a good question.

One new option in OptiX 7.7 that you might want to consider is the Displaced Micro Mesh: https://raytracing-docs.nvidia.com/optix7/guide/index.html#acceleration_structures#accelstruct-dmm

This is a primitive constructed from a displacement map texture you provide, and it has hardware support on Ada generation GPUs. This does indeed alleviate the need for an index buffer, but be aware that it also has a special compressed format for the internal vertices, so you should take some time to evaluate whether this format will meet your needs.

Another option you have for saving memory is to create a custom primitive that works directly on an elevation map. This option will explicitly trade away performance for memory, and avoid using some of the benefits of the RT cores, so you will also want to think carefully about your priorities with this one, but it is quite possible to ray trace an elevation map directly with anywhere from modest to very large memory savings, depending on how much performance you’re willing to sacrifice. We’ve provided an example of how to do this kind of thing in the older OptiX 6 SDK samples, see the one titled “optixMDLDisplacement” for an example of a custom intersector that can handle a coarse mesh with a displacement texture that creates micro-triangles.

We are indeed researching other options that might be generally useful, so stay tuned for future updates.


David.