Opacity Micromap (OMM) optimizes ray tracing by skipping transparent surface ray interactions due to opacity texture cutouts. OMMs encode opacity at a microtriangle level in a triangle and there can be thousands of microtriangles generated per a triangle. This is similar to many texels from a texture being applied to a triangle. OMMs need to be pre-built for a triangle and are encoded during a bottom level acceleration structure (BLAS) construction for a GPU driver to use during ray tracing. Any transparent parts of the surface due to opacity texture and/or texture and vertex blending will be skipped by the driver. Without OMMs such hits would be returned as opaque hits to the ray tracing shader code and depend on the ray tracer to resolve the opacity and skip the hit, returning the execution to continue ray tracing to the driver. OMMs avoid this unnecessary roundtrip altogether and, thus, provide a performance speed up. In cases, where there is a lot of triangles with opacity cutouts and, especially, with multiple layers of such geometry (i.e. for fences, particles, foliage, etc.) the performance uplift in Remix can be in the order of 10% or higher. While older NVIDIA architectures benefit from this feature as well, the speed ups due to OMMs is higher on Ada (40**) GPUs.
OMMs are enabled by default in Remix and generated at runtime. This can be controlled via GUI or rtx.conf parameter rtx.opacityMicromap.enable. OMMs are generated at runtime at a throttled pace so as to limit amount of GPU resources being used for them. It can take several seconds to generate OMMs for a scene. OMMs require enough free VRAM to get generated and, thus, their generation is dependant on enough VRAM being available. Disabling OMMs also releases the generated OMMs. Therefore, if you want to double check performance impact ON/OFF, it is advised to simply disable OMMs being bound via rtx.opacityMicromap.enableBinding so that they are not release in the process.
To take the best advantage of OMMs, author your assets considering following:
- Make transparent regions of assets resolve to opacity of 0 (i.e. fully transparent).
- Reuse UVs across triangles so that a same OMM can apply to multiple triangles in a geometry. Repeating textures are your friend. This reduces OMM build times and runtime memory cost.
- Avoid thin triangles.
- Avoid generating triangles with very high frequency of opaque and transparent regions changing back and forth across a triangle (i.e. a mesh in a high density fence, but represented with only few triangles). In such cases, tesselate your geometry further to lower the opacity frequency within a triangle. OMMs in Remix are generated roughly at up to 256x256 microtriangles per triangle. It is important that a good portion of such microtriangles correspond to fully transparent regions. If the underlying opacity for a triangle has a higher frequency of opaque and transparent features than the 256x256 and microtriangles cover areas that are both opaque and transparent, such microtriangles will be marked as non-transparent. In that case, there will be no speed up since the geometry is essentially treated as opaque by the driver. Therefore, make sure your geometry is tessellated enough such that opaque/transparent regions appear at a frequency lower than that and, preferably, end up with multiple neighboring microtriangles falling into the same opaque/transparent category.
Caveats:
- Similar to other instance tracking cases in Remix, the runtime hashes OMM signatures and uses the hashes to differentiate among the OMMs. However, although it's rarely the case, but should two OMMs hash collide they will be treated as equal. This will result in an incorrect OMM being bound for a triangle and, thus, having wrong opacity cutouts being applied. In that case, a triangle can appear transparent in areas where it should be opaque. If that happens, tag such texture as rtx.opacityMicromapIgnoreTextures to avoid generating OMMs for them and report this as an issue on github.