2017-09-20 62 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)是导致此问题的原因。

相关问题