Strange problem when rendering with iray (black floor)


we are mass rendering images of different configurations of a product inside our product configurator. To do this, we update a usd scene with our own Omniverse Connector and after that, we call an omni-service that wait some seconds, captures the result and send the result back to out application.

When using rtx-renderer this works fine (regardless if using PathTracing or RaytracedLighting). But when using iray some results have a “black floor” (the floor is just a plane with white, reflecting material).

Here is the code of our omni-extension:"/render", description="Renders a session", summary="Renders the current session from a specified camera")
async def post_render(data: dict = fastapi.Body(None)):
    carbSettings = carb.settings.get_settings_interface()
    renderer = omni.renderer_capture.acquire_renderer_capture_interface()
    viewportWindow = omni.kit.viewport_legacy.get_default_viewport_window()

    currentCameraPath = viewportWindow.get_active_camera()
    currentRendererResolutionWidth = carbSettings.get("/app/renderer/resolution/width")
    currentRendererResolutionHeight = carbSettings.get("/app/renderer/resolution/height")
    currentRendererResolutionMultiplier = carbSettings.get("/app/renderer/resolution/multiplier")

    requestId = data.get("requestId", "00000000-0000-0000-0000-000000000000")
    acceptRenderedImageUri = data.get("acceptRenderedImageUri", "https://localhost:6001/api/session/00000000-0000-0000-0000-000000000000/AcceptRenderedImage")
    cameraPath = data.get("cameraPath", "/Stage/Cameras/Interactive")

    cameraPositionX = float(data.get("cameraPositionX", "0"));
    cameraPositionY = float(data.get("cameraPositionY", "0"));
    cameraPositionZ = float(data.get("cameraPositionZ", "5"));

    cameraTargetX = float(data.get("cameraTargetX", "0"));
    cameraTargetY = float(data.get("cameraTargetY", "0"));
    cameraTargetZ = float(data.get("cameraTargetZ", "0"));

    renderDuration = data.get("renderDuration", 3);

    def renderImageIntoMemeryCallback(capsule, length, width, height, textureFormat):
            ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
            ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]

            pointer = ctypes.pythonapi.PyCapsule_GetPointer(capsule, None)
            ap = ctypes.cast(pointer, ctypes.POINTER(ctypes.c_byte * length))
            imageData = base64.b64encode(ap.contents)

            carbSettings.set("/app/renderer/resolution/width", currentRendererResolutionWidth)
            carbSettings.set("/app/renderer/resolution/height", currentRendererResolutionHeight)
            carbSettings.set("/app/renderer/resolution/multiplier", currentRendererResolutionMultiplier)
            carbSettings.set("/app/asyncRendering", True)
            carbSettings.set("/app/asyncRenderingLowLatency", True)


            req = urllib.request.Request(acceptRenderedImageUri, method="POST")
            req.add_header('RequestId', requestId)
            req.add_header('ImageWidth', width)
            req.add_header('ImageHeight', height)
            req.add_header('ImageFormat', str(textureFormat))
            req.add_header('CameraPath', cameraPath)
            gcontext = ssl.SSLContext()

            urllib.request.urlopen(req, imageData, context=gcontext)

    if currentCameraPath != cameraPath:

    carbSettings.set("/app/asyncRendering", False)
    carbSettings.set("/app/asyncRenderingLowLatency", False)
    carbSettings.set("/app/renderer/resolution/width", data.get("rendererResolutionWidth", 1280))
    carbSettings.set("/app/renderer/resolution/height", data.get("rendererResolutionHeight", 720))
    carbSettings.set("/app/renderer/resolution/multiplier", data.get("rendererResolutionMultiplier", 1))

    viewportWindow.set_camera_position(cameraPath, cameraPositionX, cameraPositionY, cameraPositionZ, True)
    viewportWindow.set_camera_target(cameraPath, cameraTargetX, cameraTargetY, cameraTargetZ, True)

    renderingTime = 0.0

    while renderingTime < renderDuration:
        renderingTime += await

    viewport_ldr_rp = viewportWindow.get_drawable_ldr_resource()
    renderer.capture_next_frame_rp_resource_callback(renderImageIntoMemeryCallback, viewport_ldr_rp)

    return {"status": "success"}

As kit expirience we use an own minimal composition (to optimize start up performance and memory consumption). Perhaps there is missing some setting. Here is the kit file:

title = "XcalibuR - Renderer (IRAY)"
description = "Kit app that is used by XcalibuR for rendering (IRAY)"
version = "1.0.0"

# That makes it browsable in UI with "app" filter
keywords = ["app"]

flushStandardStreamOutput = true
#detail = true
#fullDetail = true
outputStreamLevel = "Info"

"omni.kit.uiapp" = {}
#"" = {}
#"omni.kit.window.extensions" = {}
"omni.kit.window.viewport" = {}
"omni.kit.registry.nucleus" = {}
"omni.renderer" = { tag = "rtx" }
"omni.hydra.iray" = { order = -1000 }
#"omni.rtx.settings.core" = {}
"" = {}
#"omni.kit.livestream.websocket" = {}

exts."omni.kit.renderer.core".imgui.enableMips = true

app.window.title = "XcalibuR - Renderer (IRAY)"

app.runLoops.main.rateLimitEnabled = true
app.runLoops.main.rateLimitFrequency = 60
app.runLoops.main.rateLimitUseBusyLoop = false

renderer.enabled = "iray"

# Camera Inertia = true = 0.55

# Fast shutdown by default
app.fastShutdown = true

# Eco Mode
rtx.ecoMode.enabled = true

#registries = [
#   { name = "kit/public", url = ""}

args = [

Any idea what could cause this behavior?

Thank you very much


Hi @WendyGram,

could you please forward this topic to someone who nows details about the iray-renderer? Ficing this topic is the last missing peace for us to launch our first Omniverse-based product.


You very much


Hi @c.bickmeier I can check with the iray team on this.

One that that may help debugging is to render with AOVs or alpha to confirm the floor isn’t missing entirely. The alpha would likely be solid white for the thumbnails you shared.

Also, is it happening with all iray renders or some? I wonder if it’s an issue with the environemnt/dome or you need more reflection bounces since the metal legs are rendering pretty dark too.

Hi @mati-nvidia,

here are two samples… one that works and one that does not…

As you can see, there is a floor (in the first image). The changes that are made between those two images are to the sofa itself (the armrest is wider in the second image). The floor plane ist definitely present in both scene graphs.

It does not happen to all iray renderings. The two images above are both rendered with iray. it even does not happen always to the same scene (reder a scene one, get black floor… render it again the floor is present). When using rtx-render it works in all cases.

Can you explain a little more “render with AOVs or alpha”? Can you tell me exact what to do?



Hi @c.bickmeier. Thanks for the additional info. Ignore my previous suggestions about AOVs and alpha. I just realized it doesn’t look like we support AOVs in OV for iray yet and I found a bug with iray and alphas.

I’ve let the iray team know. In the meantime, if you’re able to provide:

  1. A scene and some steps to reproduce the issue. This could be manual steps with Movie Capture or if you could pare down your code to just a script that might make it easy to debug.
  2. Log files found here: How to Report an issue with Omniverse

omni.kit.xcalibur.renderer.iray.kit (1.5 KB) (7.1 MB)

Hi @mati-nvidia,

please have a look at the attached files. The contains an usd you can use to reproduce the problem. The kit file is the kit expirience we use in this case (but you can use create too, if you enable iray BEFORE loading the scene).

Background: When opening the scene you have to zoom in to see something because the camera is too far away. The missing floor comes from a sublayer. When hiding und unhiding the layer with this button…


…the environment is rendered correctly.

I think I have found the problem…

The default camera (Perspective) is very far away when you open the scene (because we are using 1 unit = 1 meter, so out models are very “smal”).


  1. Zoom in unitl you can see the model
  2. Save the scene
  3. Reopen the scene

The problem is gone.

But now there is the question how to solve this programmatically? When we create a new usd scene the position of the default camera is already set. Is there a way to access the perspective camera from python?

Thanks for the files!

The primPath for the Perspective camera is /OmniverseKit_Persp

Let me know how it goes!

Hi! I am trying to reproduce this with the scene you sent but it seems to be missing a shader:

Failed to resolve USD Asset Identifier ‘XcalibuRPBR.mdl’ from prim ‘/Root/Looks/BlackMetal/BlackMetal’


sorry I forgot about the material…
XcalibuRPBR.mdl (12.1 KB)
XcalibuRPBR_ClearCoat.mdl (15.0 KB)
XcalibuRPBR_ClearCoat_Opacity.mdl (30.2 KB)
XcalibuRPBR_Opacity.mdl (15.5 KB)

In the mean time I found a workaround by positioning the camera limitedly after loading the scene, with this code:

    viewport_window = omni.kit.viewport_legacy.get_default_viewport_window()

    cameraPath = viewport_window.get_active_camera()

    viewport_window.set_camera_position(cameraPath, 0, 2, 8, True)
    viewport_window.set_camera_target(cameraPath, 0, 0.5, 0, True)

Hi @mati-nvidia ,
@jhedstrom ,

can you guys have a look at this topic (thats the reason why we have a special material instead of using OmniPBR)

Request to adopt a change I made to the pbr material - Platform / Kit - NVIDIA Developer Forums

Thanks you very much


Thanks for the shaders, I was able to reproduce and identify the problem. Turns out that this is because of a precision issue because instancing is on. This scene has a huge very thin cylinder under the sofa, and when the camera is very far away something strange happens because of this precision issue. Moving the camera close to the sofa and then hide/unhide the cylinder makes things work again. This is also why your workaround works, which is doing that before the cylinder is created in the first place.

As an alternative to that workaround you can also turn off instancing (by setting /rtx/iray/iray_instancing to “off”). This might actually also have some small benefit for rendering speed at the expense of memory consumption (depending on the scene) and the speed at which geometry can be moved in the scene. Not sure it will be noticeable, but might be worth trying.

A final option would be to get rid of the huge cylinder altogether and use the matte ground plane natively supported by Iray, but that won’t work for the non-Iray renderers.

We are working on ways to improve the precision to avoid these cases where things break apart, so hopefully the issue will be gone in the future, but hope this information helps in the meantime.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.