2017-09-20 10 views
0

メタルを使用してピクセル整列された2Dクワッドをレンダリングしようとしていますが、それを正しく得ることはできません。メタルの頂点バッファからレンダリングするクォド

マイ頂点バッファの内容は、(作成時に、CPU側からログインして)、次のとおりです。

0, 1, 2, 2, 1, 3 

テクスチャI:

Vertex(position: float4(0.0, 0.0, 0.5, 1.0), textureCoordinate: float2(0.0, 0.0)) 
Vertex(position: float4(0.0, 64.0, 0.5, 1.0), textureCoordinate: float2(0.0, 1.0)) 
Vertex(position: float4(64.0, 0.0, 0.5, 1.0), textureCoordinate: float2(1.0, 0.0)) 
Vertex(position: float4(64.0, 64.0, 0.5, 1.0), textureCoordinate: float2(1.0, 1.0)) 

二つの三角形を描画するためのインデックスバッファには、次の指標が含まれています[使用してMは:

enter image description here

が...しかし、私はこのような何かを得る:

enter image description here

明らかに、位置およびテクスチャ座標:

enter image description here

フレームをキャプチャし、頂点バッファを検査、私はこれを取得しますはが混在しています。

これは私がジオメトリを作成するために使用するコードです:

import Metal 
import simd 

struct Vertex { 
    var position = float4(x: 0, y: 0, z: 0, w: 1) 
    var textureCoordinate = float2(x: 0, y: 0) 
} 

class Quad { 
    let vertexBuffer: MTLBuffer 
    let indexBuffer: MTLBuffer 
    let indexCount: Int 
    let indexType: MTLIndexType 
    let primitiveType: MTLPrimitiveType 

    init(sideLength: Float, device: MTLDevice) { 
     self.primitiveType = .triangle 

     var vertexData = [Vertex]() 

     var topLeft = Vertex() 
     topLeft.position.x = 0 
     topLeft.position.y = 0 
     topLeft.position.z = 0.5 
     topLeft.textureCoordinate.x = 0 
     topLeft.textureCoordinate.y = 0 
     vertexData.append(topLeft) 

     var bottomLeft = Vertex() 
     bottomLeft.position.x = 0 
     bottomLeft.position.y = sideLength 
     bottomLeft.position.z = 0.5 
     bottomLeft.textureCoordinate.x = 0 
     bottomLeft.textureCoordinate.y = 1 
     vertexData.append(bottomLeft) 

     var topRight = Vertex() 
     topRight.position.x = sideLength 
     topRight.position.y = 0 
     topRight.position.z = 0.5 
     topRight.textureCoordinate.x = 1 
     topRight.textureCoordinate.y = 0 
     vertexData.append(topRight) 

     var bottomRight = Vertex() 
     bottomRight.position.x = sideLength 
     bottomRight.position.y = sideLength 
     bottomRight.position.z = 0.5 
     bottomRight.textureCoordinate.x = 1 
     bottomRight.textureCoordinate.y = 1 
     vertexData.append(bottomRight) 

     for vertex in vertexData { 
      Swift.print(vertex) // logs the structs posted above 
     } 

     let vertexBufferSize = vertexData.count * MemoryLayout<Vertex>.stride 
     self.vertexBuffer = device.makeBuffer(bytes: vertexData, length: vertexBufferSize, options: []) 

     var indexData = [UInt32]() 

     // First triangle: Top left, bottom left, top right (CCW) 
     indexData.append(0) 
     indexData.append(1) 
     indexData.append(2) 

     // Second triangle: top right, bottom left, bottom right (CCW) 
     indexData.append(2) 
     indexData.append(1) 
     indexData.append(3) 

     for index in indexData { 
      Swift.print(index) // logs the integers posted before 
     } 

     self.indexType = .uint32 
     self.indexCount = indexData.count 

     let indexBufferSize = indexData.count * MemoryLayout<UInt32>.stride 
     self.indexBuffer = device.makeBuffer(bytes: indexData, length: indexBufferSize, options: []) 
    } 
} 

...シェーダー:

#include <metal_stdlib> 
using namespace metal; 

struct Constants { 
    float4x4 modelViewProjectionMatrix; 
    float4 tintColor; 
}; 
struct VertexIn { 
    packed_float4 position [[ attribute(0) ]]; 
    packed_float2 texCoords [[ attribute(1) ]]; 
}; 
struct VertexOut { 
    float4 position [[position]]; 
    float2 texCoords; 
}; 

vertex VertexOut sprite_vertex_transform(device VertexIn *vertices [[buffer(0)]], 
            constant Constants &uniforms [[buffer(1)]], 
            uint vertexId [[vertex_id]]) { 

    float4 modelPosition = vertices[vertexId].position; 

    VertexOut out; 

    out.position = uniforms.modelViewProjectionMatrix * modelPosition; 
    out.texCoords = vertices[vertexId].texCoords; 

    return out; 
} 

fragment half4 sprite_fragment_textured(
    VertexOut fragmentIn [[stage_in]], 
    texture2d<float, access::sample> tex2d [[texture(0)]], 
    sampler sampler2d [[sampler(0)]]){ 

    half4 surfaceColor = half4(tex2d.sample(sampler2d, fragmentIn.texCoords).rgba); 

    return surfaceColor; 
} 

...と、これは(インデックス化)、それをレンダリングするためのコードです:

renderEncoder.setVertexBuffer(quad.vertexBuffer, offset: 0, at: 0) 
renderEncoder.setVertexBytes(&constants, length: MemoryLayout<Constants>.stride, at: 1) 
renderEncoder.setFragmentTexture(texture, at: 0) 
renderEncoder.setFragmentSamplerState(sampler, at: 0) 

// quad is an instance of the class above, with sideLength == 64 
renderEncoder.drawIndexedPrimitives(
     type: quad.primitiveType, 
     indexCount: quad.indexCount, 
     indexType: quad.indexType, 
     indexBuffer: quad.indexBuffer, 
     indexBufferOffset: 0) 

明らかに、データが適切に頂点バッファにコピーされていないと私は間違ってどこか一歩を取得していますが、私はできません完全に把握するここで

プロジェクト全体がon GitHubです。

答えて

0

この部分は、トラブルの原因となったようだ。

struct VertexIn { 
    packed_float4 position [[ attribute(0) ]]; 
    packed_float2 texCoords [[ attribute(1) ]]; 
}; 

デバッガコンソールから、CPU側:packed_プレフィックスを削除

(lldb) print MemoryLayout<Vertex>.stride 
(Int) $R0 = 32 
(lldb) print MemoryLayout<Vertex>.size 
(Int) $R1 = 24 
(lldb) 

はそれを解決:

struct VertexIn { 
    float4 position [[ attribute(0) ]]; 
    float2 texCoords [[ attribute(1) ]]; 
}; 

しかし、私のバッファはスペース使用量に関して最適ではないと思う。 I

...私は本当には、構造体のアライメントおよび梱包の復習が必要...仕事をするpacked_バージョンを取得する方法を動作するように

を持っています注:もともと、私は適応アップルのサンプルプロジェクトのコードで、頂点構造体はfloat4positionnormalであった。Cleary構造体の "net"サイズを8*sizeof(float)から6*sizeof(float)に変更することが原因です。

関連する問題