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