0

Now I have already known how to render multiple triangles in Metal:

let vertexBuffer = device.makeBuffer(vertices_triangles)
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: vertices_triangles.count)
renderEncoder.endEncoding()
commandBuffer.present(view.currentDrawable!)
commandBuffer.commit()

Here, vertices_triangles is an Array of element Vertex. The adjacent three vertices shows a triangle to render.

However, I don't really know how to render multiple triangleStrips in Metal.

let vertexBuffer = device.makeBuffer(vertices_triangleStrips)
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: vertices_triangleStrips.count)

If I put adjacent vertices in vertices_triangleStrips and set renderEncoder.drawPrimitives.type to .triangleStrip, I will get one triangleStrip. But how can I render multiple triangleStrips? I tried using for loop to make multiple vertexBuffers and use renderEncoder.drawPrimitives to draw each triangleStrip. It seems that it's not a good idea to do this for performance reasons.

Yang_____
  • 117
  • 8
  • Could you elaborate what you mean by multiple triangle strips? Do you mean disjoint sets of triangles? If so, you would need to use indexed geometry and use primitive restart, see more info here: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515520-drawindexedprimitives. If you mean just multiple triangles, you would need to just put `n + 2` triangles into the buffer and pass the same count to `vertexCount` parameter. – JustSomeGuy Jan 22 '22 at 21:06
  • To elaborate: triangle strip means that the next triangle is going to use two vertices of the previous triangle and then grab one more vertex. And so on and so forth until you run out of vertices. That gives us two vertices to start the strip and one more for each triangle, giving us `n + 2` vertices for `n` triangles. – JustSomeGuy Jan 22 '22 at 21:08
  • Thinking of it a bit more, you could probably also produce two or more disjoint triangle strips by introducing degenerate triangles. You can do that by outputting double the last vertex in the last triangle of first part of the strip and then double the first vertex in the first triangle of the second part of the strip. – JustSomeGuy Jan 22 '22 at 21:40
  • @JustSomeGuy I want to render multiple `stroke` using triangleStrip. These strokes have different count of vertices. – Yang_____ Jan 23 '22 at 06:51

1 Answers1

0

Referring to documentation of drawIndexedPrimitives(type:indexCount:indexType:indexBuffer:indexBufferOffset:instanceCount:baseVertex:baseInstance:) in Metal:

Primitive restart functionality is enabled with the largest unsigned integer index value, relative to indexType (0xFFFF for MTLIndexTypeUInt16 or 0xFFFFFFFF for MTLIndexTypeUInt32). This feature finishes drawing the current primitive at the specified index and starts drawing a new one with the next index.

You could render multiple triangleStrips by defining an indexBuffer seperated by 0xFFFF or 0xFFFFFFFF.

eg. rendering triangleStrips at vertex [0,1,2,3] [4,5,6,7] [8,9,10] [11,12,13,14,15,16]

let indexBytes: [UInt32] = [0, 1, 2, 3, 0xFFFFFFFF, 4, 5, 6, 7, 0xFFFFFFFF, 8, 9, 10, 0xFFFFFFFF, 11, 12, 13, 14, 15, 16, 0xFFFFFFFF]

let vertexBuffer = device.makeBuffer(bytes: vertices_triangleStrips,
                                     length: vertices_triangleStrips.count * MemoryLayout<MetalPosition2>.stride,
                                     options: [])!
let indexBuffer = device.makeBuffer(bytes: indexBytes,
                                    length: indexBytes.count * MemoryLayout<UInt32>.stride,
                                    options: [])!

renderEncoder.setVertexBuffer(vertexBuffer,
                              offset: 0,
                              index: 0)
renderEncoder.drawIndexedPrimitives(type: .triangleStrip,
                                    indexCount: indexBytes.count,
                                    indexType: .uint32,
                                    indexBuffer: indexBuffer,
                                    indexBufferOffset: 0) // only one instance
Yang_____
  • 117
  • 8