Friday, October 9, 2026
HomeiOS Development3D viewer for iOS utilizing MetalKit and Swift - Depth doesn’t work

3D viewer for iOS utilizing MetalKit and Swift – Depth doesn’t work

[ad_1]

I’m utilizing Metallic with Swift to construct a 3D viewer for iOS and I’ve some points to make the depth working. From now, I can draw and render a single form accurately in 3D (like a easy sq. airplane (4 triangles (2 for every face)) or a tetrahedron (4 triangles)).
Nevertheless, once I attempt to attract 2 shapes collectively, the depth between these two shapes doesn’t work. For instance, a airplane is positioned at Z axes = 0 behind a tetra which is positioned at Z > 0. If I look a this scene from the again (digital camera positioned someplace at Z < 0), it’s okay. However once I have a look at this scene from the entrance (digital camera positioned someplace at Z > 0), it doesn’t work. The airplane is drawn earlier than the tetra even whether it is positioned behind the tetra.

Look from the back
Look from the front

I believe that the airplane is at all times drawn on the display screen earlier than the tetra (irrespective of the place of the digital camera) as a result of the decision of drawPrimitives for the airplane is completed earlier than the decision for the tetra. Nevertheless, I used to be pondering that each one the depth and stencil settings will cope with that correctly.
I don’t know if the depth isn’t working as a result of depth texture, stencil state and so forth are usually not accurately set or as a result of every form is drawn in a special name of drawPrimitives.
In different phrases, do I’ve to attract all shapes in the identical name of drawPrimitives to make the depth working ? The concept of this a number of name to drawPrimitives is to cope with totally different sorts of primitive kind for every form (triangle or line or …).

That is how I set the depth stencil state and the depth texture and the render pipeline :

   // Stencil descriptor
   let depthStencilDescriptor = MTLDepthStencilDescriptor()
   depthStencilDescriptor.depthCompareFunction = .much less
   depthStencilDescriptor.isDepthWriteEnabled = true
   depthStencilState = machine.makeDepthStencilState(descriptor: depthStencilDescriptor)!
   
   // Depth Texture 

   let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .stencil8, width: 576, peak: 723, mipmapped: false)
   desc.storageMode = .personal
   desc.utilization = .pixelFormatView
   depthTexture = machine.makeTexture(descriptor: desc)!

   // create library and performance vertxFunction & fragmentFunction … 
   // …

   // render pipeline descriptor
   let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
   // …
   renderPipelineDescriptor.depthAttachmentPixelFormat = .depth32Float
   renderPipelineDescriptor.stencilAttachmentPixelFormat = .stencil8
   // … 
   // create render pipeline state : renderPipelineState = ..

And the draw operate :

operate draw(in view: MTKView) {
    // create render cross descriptor
    //let renderPassDescriptor = view.currentRenderPassDescriptor …
    
    renderPassDescriptor.depthAttachment.texture = depthTexture
    renderPassDescriptor.depthAttachment.clearDepth = 1.0
    renderPassDescriptor.depthAttachment.loadAction = .load
    renderPassDescriptor.depthAttachment.storeAction = .dontCare
    
    // Create a buffer from the commandQueue
    //let commandBuffer = …
    //let commandEncoder = …
    
    commandEncoder?.setRenderPipelineState(renderPipelineState)
    commandEncoder?.setFrontFacing(.counterClockwise)
    commandEncoder?.setCullMode(.again)
    commandEncoder?.setDepthStencilState(depthStencilState)
    
    // Draw all obj in objects
    // objects = array of Object; every object describing vertices and primitive kind of a form
    // objects[0] = Airplane, objects[1] = Tetra
    for obj in objects {
        createVertexBuffers(machine: view.machine!, vertices: obj.vertices)          
        commandEncoder?.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
        commandEncoder?.setVertexBuffer(uniformBuffer, offset: 0, index: 1)
       
        commandEncoder?.drawPrimitives(kind: obj.primitive, vertexStart: 0, vertexCount: obj.vertices.rely)
    }
    
    commandEncoder?.endEncoding()
    commandBuffer?.current(drawable)
    commandBuffer?.commit()
    

}

Does anybody has an concept of what’s fallacious or lacking ?
Any recommendation is welcome !

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments