Showing a MTLTexture on an Entity in RealityKit

Is there any standard way of efficiently showing a MTLTexture on a RealityKit Entity? I can't find anything proper on how to , for example, generate a LowLevelTexture out of a MTLTexture. Closest match was this two year old thread.

In the old SceneKit app, we would just do

guard let material = someNode.geometry?.materials.first else { return }

material.diffuse.contents = mtlTexture

Our flow is as follows (for visualizing the currently detected object):

Camera-Stream -> CoreML Segmentation -> Send the relevant part of the MLShapedArray-Tensor to a MTLComputeShader that returns a MTLTexture -> Show the resulting texture on a 3D object to the user

Answered by DTS Engineer in 857479022

Hello @Bersaelor,

Creating a spatial drawing app with RealityKit uses LowLevelTexture for per-frame updates in the "SplashScreenBackgroundComponent".

If you already have a MTLTexture, you can blit its contents to a LowLevelTexture.

-- Greg

Accepted Answer

Hello @Bersaelor,

Creating a spatial drawing app with RealityKit uses LowLevelTexture for per-frame updates in the "SplashScreenBackgroundComponent".

If you already have a MTLTexture, you can blit its contents to a LowLevelTexture.

-- Greg

Mhmm, in my first simple Test I tried:

@MainActor
private static func generateTexture(width: Int, height: Int) throws -> LowLevelTexture {
    return try LowLevelTexture(descriptor: .init(pixelFormat: .rgba8Unorm_srgb,
                                                 width: width,
                                                 height: height,
                                                 depth: 1,
                                                 mipmapLevelCount: 1,
                                                 textureUsage: [.shaderWrite, .shaderRead]))
}


@MainActor
init(textureSize: SIMD2<Int>) async throws {
    lowLevelTexture = try Self.generateTexture(width: textureSize.x, height: textureSize.y)

    let textureResource = try await TextureResource(from: lowLevelTexture)

    var descriptor = UnlitMaterial.Program.Descriptor()
    descriptor.blendMode = .add

    let program = await UnlitMaterial.Program(descriptor: descriptor)
    material = UnlitMaterial(program: program)
    material.color = .init(texture: .init(textureResource))
    material.opacityThreshold = 0.0 // Enable transparency
    material.blending = .transparent(opacity: 1.0)
}

@MainActor
mutating func setTextureSize(_ textureSize: SIMD2<Int>) throws {
    lowLevelTexture = try Self.generateTexture(width: textureSize.x, height: textureSize.y)
    let textureResource = try TextureResource(from: lowLevelTexture)
    material.color = .init(texture: .init(textureResource))
}

mutating func blitMTLTextureIntoLowLevelTexture(_ mtlTexture: MTLTexture) {
    let size = self.textureSize
    guard mtlTexture.width == size.x, mtlTexture.height == size.y else {
        Logger.ar.error("MTLTexture size \(mtlTexture.width)x\(mtlTexture.height) does not match LowLevelTexture size \(size.x)x\(size.y)")
        return
    }

    MetalHelper.blitTextures(from: mtlTexture, to: lowLevelTexture)
}

And then the blit method:


    static func blitTextures(from inTexture: MTLTexture, to lowLevelTexture: LowLevelTexture) {
        guard let commandQueue = sharedCommandQueue else {
            Logger.ml.error("Failed to get command queue")
            return
        }

        guard let commandBuffer = commandQueue.makeCommandBuffer() else {
            Logger.ml.error("Failed to create command buffer")
            return
        }

        guard let blitEncoder = commandBuffer.makeBlitCommandEncoder() else {
            Logger.ml.error("Failed to create compute encoder")
            return
        }

        commandBuffer.enqueue()
        defer {
            blitEncoder.endEncoding()
            commandBuffer.commit()
        }

        let outTexture: MTLTexture = lowLevelTexture.replace(using: commandBuffer)

        blitEncoder.copy(from: inTexture, to: outTexture)
    }

which compiles and runs without error, but I only see a pink mesh.

@Bersaelor,

Nothing is jumping out at me in those code snippets as problematic. Can you provide a link to a focused sample project?

--Greg

Showing a MTLTexture on an Entity in RealityKit
 
 
Q