Basic dynamic transforms in Optix 7

I’m trying to learn how to do simple dynamic object transforms in Optix7 (no motionblur yet) .I figured I’d start with the simplest and probably most naive way of just rebuilding the top level IAS on every tick. I refined this a bit by only doing a total rebuild when a new instance was added and using OPTIX_BUILD_OPERATION_UPDATE otherwise This worked suprisingly well … I can still get 30 fps in a scene with 100,000 geometry instances of a scanned rock with 1.2 million triangles on my Geforce RTX 2070 Super.

Is this the best way to do dynamic transforms?

When and why would I need to use the OptixStaticTransform? I think Static in this context just means no motion blur … is that correct?

When I add some random jitter and slow upward motion to the scene, the RTX 2070 Super(8GB) works like this

https://youtu.be/2AhvLrM-vQM

But the same scene does’t work well on my laptop with a GTX 1060(6GB)

https://youtu.be/OFVbrhGVoE8

Could someone tell me what is going on there? I actually expected OPTIX_BUILD_OPERATION_UPDATE not to work well with moving instances but it seems to do just fine with the 2070 Super.

Source code is here: https://github.com/Hurleyworks/Optix7Sandbox

Hey there!

So I don’t know what’s going wrong yet, but in the 1060 video, clearly the IAS bounding boxes are staying static and not updating like they should. Are you currently using OptixStaticTransform for your instances?

OptixStaticTransform is intended for when you have a scene graph that needs both motion transforms and static transforms, e.g., IAS -> motion xform -> static xform -> GAS. If you don’t have any motion transforms at all, then it’s better to use OptixInstance strictly, there’s no need for OptixStaticTransform if you don’t have any motion transforms.

If you are using static transforms, since you provide the AABBs, in general you need to be computing and uploading new AABBs before running the IAS update. It’s possible OptiX might be handling that automatically when you use an RTX GPU, which might explain why it’s working on your 2070 but not on your 1060. For OptixInstance transforms, the bounds should be computed for you on RTX/non-RTX devices, so you should only need to refit or rebuild your IAS.

Let us know if that doesn’t explain or help you resolve the problem case on your 1060.

Now as far as what the best way to do dynamic transforms is, what you’re doing is pretty good for a large group of instances that doesn’t move very much. Just be aware that while the refit (OPTIX_BUILD_OPERATION_UPDATE) of your IAS works best for small amounts of relative motion, the trace performance can go down when your instances move & mix a lot. Since your ducks are mostly all going in the same direction, and mostly staying in the same place relative to each other, a refit is a great choice. If they were put into a big physics simulation and ducks flew in random directions all over the place, you would probably want to do a rebuild operation (OPTIX_BUILD_OPERATION_BUILD) somewhere between occasionally, frequently, or even always. If the performance is acceptable with a full rebuild every frame, that’s the safest option. Refit is usually faster than rebuild (typically in the neighborhood of 5-10x faster) but the tradeoff is you can accidentally hurt traversal performance when things move too far, so in practice you have to actively manage refits when using dynamic geometry.


David.

Hi David,

Are you currently using OptixStaticTransform for your instances?

No, I’m just using OptixInstance and updating the .transform field. Speaking of which, the comment in the OptixInstance struct says

/// affine world-to-object transformation as 3x4 matrix in row-major layout
    float transform[12];

Shouldn’t that be object-to-world? That’s how I’m using it and it works fine

Also, I’m a little confused about the terminology. When you say motion transforms that means using OptixMatrixMotionTransform or OptixSRTMotionTransform with motion blur enabled and static transform just means using OptixStaticTransform or OptixInstance with no motion blur. Is that correct?

when you have a scene graph that needs both motion transforms and static transforms
Could you give me a simple example of a scene graph like that?

Thanks for the help!

Hi, yes, the comment in optix_7_types.h is supposed to say “object-to-world”. I just checked and it’s been fixed internally, so it should show up correctly in the SDK the next time we release.

And yes, your understanding of the terminology is correct. I’ll try to be careful with “static transform” and use that to refer to OptixStaticTransform, and use “instance transform” to mean OptixInstance.

For an example of needing both motion and static transforms, this just means that a large object or group is moving and contains sub-instances that aren’t moving relative to the large object. An airplane propeller might be a good example - the blades rotate as a group, but each individual blade has a unique static transform relative to the group.


David.

Hi David,

Okay, that clears things up for me. Thanks for the help!

If they were put into a big physics simulation and ducks flew in random directions all over the place, you would probably want to do a rebuild operation (OPTIX_BUILD_OPERATION_BUILD) somewhere between occasionally, frequently, or even always. If the performance is acceptable with a full rebuild every frame, that’s the safest option.

I’m getting pretty amazing(to me) performance just using OPTIX_BUILD_OPERATION_UPDATE on every tick on my Geforce 2070 Super

https://youtu.be/U0WJWECeZjA

Sorry. I am having a similar level on confusion with how to implement Optix 7 “dynamic” transforms.

Let’s assume for the moment I do not need motion blur (rendered in a single frame).

I want to have a physics simulation rotate the propeller (one object) on an aircraft.

– The aircraft is in one GAS. (It does not move)

– The propeller is in another GAS. (It moves relatively.)

I will be generating a (numbered) series of output images (i.e. frames) and turning that into an animation.

Would you please help me understand:

  1. What elements do I need (i.e. IAS, Static Transform, Motion Transforms, etc.) to best create this scene-graph?

  2. How do I update the transform between the propeller and the aircraft for each frame?

—> 2a) Where does the (new) transformation matrix data go?
—> 2b) What acceleration structures (if any) need to be rebuilt? (and how to best rebuild them)

  1. Do any of the SDK demos show an example of this?

  2. What if I have another GAS-object that moves relative to the plane? (e.g. a man inside) Does that require a different kind of rebuilding?

Hi @squeen,

If you don’t need motion blur, then you only need IAS. No Motion Transforms, no “Static Transform”, just the buffer of OptixInstance.

To update the transforms, you update your matrices in your OptixInstance array (and if you modified the array on the CPU, you need to cudaMemcpy the array onto the GPU), then rebuild your IAS.

You have 2 options for rebuild: do a complete rebuild, or a “re-fit” update. I described the trade-off between those above.

There is an SDK sample coming soon that demos moving instances, but it wasn’t ready before the last time we released the SDK.

If the geometry in your GAS moves around, then you need to rebuild the GAS in addition to rebuilding your IAS. But if the geometry is static and it’s only the instance transform that moves, you only need to rebuild your IAS.


David.

That seems wonderfully straightforward. Thank you for the response.