2017-09-20 25 views
0

Ich versuche, ein Pixel ausgerichtet 2D Quad mit Metall, aber kann nicht scheinen, es richtig zu machen.Rendering Quad von Vertex Buffer in Metall

My Vertex Pufferinhalt (wie von der CPU-Seite angemeldet, bei der Erzeugung) sind:

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

Indexpuffer zwei Dreiecke enthält die folgenden Indizes zu zeichnen:

0, 1, 2, 2, 1, 3 

Die Textur I bin mit ist:

enter image description here

... aber ich habe so etwas wie dies:

enter image description here

Wenn der Rahmen die Erfassung und die Eckpunktpufferspeicher Inspektion, bekomme ich diese:

enter image description here

klar, Position und Texturkoordinaten sind vermischt.

Dies ist der Code, den ich verwende, um die Geometrie zu erstellen:

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: []) 
    } 
} 

... die Shaders:

#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; 
} 

... und das ist der Code, um es (indexiert) zu machen:

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) 

Offensichtlich werden die Daten nicht in geeigneter Weise an den Eckenpuffer kopiert werden, und ich bin die Fortschritte falsch irgendwo bekommen, aber ich kann nicht ganz herausfinden, wo.

Das gesamte Projekt ist on GitHub.

Antwort

0

Es scheint dieser Teil die Probleme verursacht wurde:

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

Von der Debugger-Konsole auf der CPU-Seite:

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

Entfernen des packed_ Präfix es gelöst:

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

Aber ich denke, jetzt ist mein Puffer nicht optimal in Bezug auf den Platzverbrauch. Ich werde arbeiten müssen, wie die packed_ Version an die Arbeit ...

ich wirklich brauchen eine Auffrischung auf struct Ausrichtung und Verpackung ...

Hinweis: Ursprünglich habe ich angepasst die Code aus einem Beispielprojekt von Apple, wo die Vertex-Struktur hatte position und normal, beide vom Typ float4.Es ist klar, dass die Größe des Struct "net" von 8*sizeof(float) zu 6*sizeof(float) geändert wurde, was das Problem verursacht hat.

Verwandte Themen