2017-09-20 6 views
0

J'essaie de rendre un pixel 2D aligné en pixels en utilisant Metal, mais je n'arrive pas à le faire correctement.Rendu Quad à partir de Vertex Buffer in Metal

Mon sommet contenu du tampon (comme connecté du côté du processeur, sur la création) sont:

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

Le tampon d'index pour dessiner deux triangles contient les indices suivants:

0, 1, 2, 2, 1, 3 

La texture I « utilise est:

enter image description here

... mais je reçois quelque chose comme ceci:

enter image description here

Lors de la capture du cadre et l'inspection du tampon de sommet, j'obtiens ceci:

enter image description here

De toute évidence, les coordonnées de position et de texture sont mélangés.

C'est le code que j'utilise pour créer la géométrie:

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

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

... et c'est le code pour le rendre (indexé):

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) 

de toute évidence, les données ne sont pas copiées dans la mémoire tampon de sommet de manière appropriée et je commence à les pas mal quelque part, mais je ne peux pas tout à fait comprendre .

L'ensemble du projet est on GitHub.

Répondre

0

Il semble que cette partie a été la cause du problème:

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

A partir de la console de débogage, sur le côté du processeur:

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

Suppression du préfixe packed_ résolu:

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

Mais je suppose que mon tampon n'est pas optimal en termes d'utilisation de l'espace. Je vais devoir travailler comment obtenir la version packed_ travailler ...

Je vraiment besoin d'une remise sur l'alignement de struct et d'emballage ...

Note: A l'origine, je me suis adapté à la code à partir d'un exemple de projet par Apple où la structure vertex avait position et normal, les deux de type float4.Cleary changer la taille de struct "net" de 8*sizeof(float) à 6*sizeof(float) est ce qui a causé le problème.