1

我正在尝试加载模型(表单 .OBJ)并使用 MetalKit 在 iOS 上将其绘制到屏幕上。问题是我得到了一些随机多边形而不是我的模型......这是倾向于加载模型的代码(代码基于raywenderlich.com的教程:

        let allocator               = MTKMeshBufferAllocator(device: device)
        let vertexDescriptor        = MDLVertexDescriptor()
        let vertexLayout            = MDLVertexBufferLayout()
        vertexLayout.stride         = sizeof(Vertex)
        vertexDescriptor.layouts    = [vertexLayout]
        vertexDescriptor.attributes = [MDLVertexAttribute(name: MDLVertexAttributePosition, format: MDLVertexFormat.Float3, offset: 0, bufferIndex: 0),
                                       MDLVertexAttribute(name: MDLVertexAttributeColor, format: MDLVertexFormat.Float4, offset: sizeof(float3), bufferIndex: 0),
                                       MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: MDLVertexFormat.Float2, offset: sizeof(float3)+sizeof(float4), bufferIndex: 0),
                                       MDLVertexAttribute(name: MDLVertexAttributeNormal, format: MDLVertexFormat.Float3, offset: sizeof(float3)+sizeof(float4)+sizeof(float2), bufferIndex: 0)]
        var error: NSError?
        let asset = MDLAsset(URL: path, vertexDescriptor: vertexDescriptor, bufferAllocator: allocator, preserveTopology: true, error: &error)
        if error != nil{
            print(error)
            return nil
        }

        let model = asset.objectAtIndex(0) as! MDLMesh
        let mesh  = try MTKMesh(mesh: model, device: device)

这是我的绘图方法:

    func render(commandQueue: MTLCommandQueue, pipelineState: MTLRenderPipelineState,drawable: CAMetalDrawable,projectionMatrix: float4x4,modelViewMatrix: float4x4, clearColor: MTLClearColor){

    dispatch_semaphore_wait(bufferProvider.availibleResourcesSemaphore, DISPATCH_TIME_FOREVER)

    let renderPassDescriptor = MTLRenderPassDescriptor()
    renderPassDescriptor.colorAttachments[0].texture = drawable.texture
    renderPassDescriptor.colorAttachments[0].loadAction = .Clear
    renderPassDescriptor.colorAttachments[0].clearColor = clearColor
    renderPassDescriptor.colorAttachments[0].storeAction = .Store

    let commandBuffer = commandQueue.commandBuffer()
    commandBuffer.addCompletedHandler { (buffer) in
        dispatch_semaphore_signal(self.bufferProvider.availibleResourcesSemaphore)
    }

    let renderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor)
    renderEncoder.setCullMode(MTLCullMode.None)

    renderEncoder.setRenderPipelineState(pipelineState)
    renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, atIndex: 0)
    renderEncoder.setFragmentTexture(texture, atIndex: 0)
    if let samplerState = samplerState{
        renderEncoder.setFragmentSamplerState(samplerState, atIndex: 0)
    }


    var nodeModelMatrix = self.modelMatrix()
    nodeModelMatrix.multiplyLeft(modelViewMatrix)
    uniformBuffer = bufferProvider.nextUniformsBuffer(projectionMatrix, modelViewMatrix: nodeModelMatrix, light: light)
    renderEncoder.setVertexBuffer(self.uniformBuffer, offset: 0, atIndex: 1)
    renderEncoder.setFragmentBuffer(uniformBuffer, offset: 0, atIndex: 1)
    if indexBuffer != nil{
        renderEncoder.drawIndexedPrimitives(.Triangle, indexCount: self.indexCount, indexType: self.indexType, indexBuffer: self.indexBuffer!, indexBufferOffset: 0)
    }else{
        renderEncoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: vertexCount, instanceCount: vertexCount/3)
    }
    renderEncoder.endEncoding()

    commandBuffer.presentDrawable(drawable)
    commandBuffer.commit()
}

这是我的顶点着色器:

struct VertexIn{
   packed_float3 position;
   packed_float4 color;
   packed_float2 texCoord;
   packed_float3 normal;
};

struct VertexOut{
    float4 position [[position]];
    float3 fragmentPosition;
    float4 color;
    float2 texCoord;
    float3 normal;
};

struct Light{
    packed_float3 color;
    float ambientIntensity;
    packed_float3 direction;
    float diffuseIntensity;
    float shininess;
    float specularIntensity;
};

struct Uniforms{
    float4x4 modelMatrix;
    float4x4 projectionMatrix;
    Light light;
};

vertex VertexOut basic_vertex(
                          const device VertexIn* vertex_array [[ buffer(0) ]],
                          const device Uniforms&  uniforms    [[ buffer(1) ]],
                          unsigned int vid [[ vertex_id ]]) {

   float4x4 mv_Matrix = uniforms.modelMatrix;
   float4x4 proj_Matrix = uniforms.projectionMatrix;

    VertexIn VertexIn = vertex_array[vid];

    VertexOut VertexOut;
    VertexOut.position = proj_Matrix * mv_Matrix * float4(VertexIn.position,1);
    VertexOut.fragmentPosition = (mv_Matrix * float4(VertexIn.position,1)).xyz;
    VertexOut.color = VertexIn.color;
    VertexOut.texCoord = VertexIn.texCoord;
    VertexOut.normal = (mv_Matrix * float4(VertexIn.normal, 0.0)).xyz;
    return VertexOut;
}

这是它的样子:

关联

实际上,我还有一个完全由我编写的用于加载模型的类。它工作正常,问题是它没有使用索引,所以如果我尝试加载比低多边形球体更复杂的模型,GPU 崩溃......无论如何我试图修改它以使用索引并且我得到了同样的结果..比我添加硬编码索引进行测试,我得到了一个非常奇怪的结果。当我有 3 个索引时,它绘制了一个三角形,当我再添加 3 个时,它绘制了相同的三角形,在再增加 3 个顶点后,它绘制了 2 个三角形......

编辑: 这是我的Vertex结构:

struct Vertex:Equatable{
    var x,y,z: Float
    var r,g,b,a: Float
    var s,t: Float
    var nX,nY,nZ:Float

    func floatBuffer()->[Float]{
         return [x,y,z,r,g,b,a,s,t,nX,nY,nZ]
    }
}
4

1 回答 1

4

我在这里看到了几个潜在的问题。

1)您的顶点描述符不完全映射到您的Vertex结构。位置变量 ( x, y, z) 占用 12 个字节,因此颜色变量从 12 个字节的偏移量开始。这与packed_float3 position着色器VertexIn结构中的字段匹配,但在您提供给模型 I/O 的顶点描述符中,您使用sizeof(Float3)16 作为颜色属性的偏移量。因为您正在打包位置字段,所以您应该使用sizeof(Float) * 3这个值,并且在随后的偏移量中也是如此。我怀疑这是你的问题的主要原因。

更一般地说,使用strideof而不是sizeof考虑对齐是一个好主意,尽管 - 碰巧 - 它在这里不会有什么不同。

2)模型I/O允许使用single来存储顶点和索引,因此在设置顶点缓冲区或在每次绘制调用中指定索引缓冲区时MTLBuffer应该使用offseteach 的成员,而不是假设偏移量为0 MTKMeshBuffer.

于 2016-09-07T23:26:09.337 回答