2017-09-20 58 views
0

我試圖渲染一個像素對齊的2D使用金屬四元組,但似乎無法得到它的權利。從金屬的頂點緩衝區渲染四分之一

我的頂點緩衝區的內容(如CPU端登錄,在創作)是:

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)) 

索引緩衝區繪製兩個三角形包含以下指標:

0, 1, 2, 2, 1, 3 

紋理我使用「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方面:

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

卸下packed_前綴解決它:

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

但我想現在我的緩衝區在空間使用方面不是最佳的。我得工作,如何讓packed_版本工作...

我真的需要在結構調整和包裝進修...

注:本來,我適應了來自Apple的示例項目的代碼,其中頂點結構具有positionnormal,這兩個類型都是float4。Cleary將struct「net」大小從8*sizeof(float)更改爲6*sizeof(float)是導致此問題的原因。

相關問題