Metal MTLBuffer大批量顶点处理

2020-08-26  本文已影响0人  Joker_King

在我们之前的案例Metal 使用渲染管道渲染基本图元一节中,我们使用setVertexBytes:length:atIndex:函数来将我们的顶点数据传递到顶点换冲过去中,但是这个函数有一个限制,那就是它只能传递4KB以下的数据,超过4KB的数据需要使用MTLBuffer对象配合setVertexBuffer:offset:atIndex:来进行传递。下面是苹果官方的释义。

Using this method is equivalent to creating a new MTLBuffer object from the specified data and then binding it to the vertex shader, with the setVertexBuffer:offset:atIndex: method. However, this method avoids the overhead of creating a buffer to store your data; instead, Metal manages the data.

Use this method for single-use data smaller than 4 KB. Create a MTLBuffer object if your data exceeds 4 KB in length or persists for multiple uses.

MTLBuffer

一个我们自定义的数据存储资源对象。

MTLBuffer创建

MTLBuffer对象可以使用MTLDevice来进行创建,我们可以使用MTLDevice以下几个方法来创建MTLBuffer。

Metal框架并不知道MTLBuffer的内容,只知道它的大小,自定义的数据格式,一定要确保应用程序和着色器知道如何读写,例如,您可以在着色器中创建一个结构,定义要存储在缓冲区中的数据以及其内存布局。

_vertexBuffer = [_device newBufferWithBytes:vertexData.bytes length:vertexData.length options:(MTLResourceStorageModeShared)];

其中vertexData是我们的顶点数据,这是我们自定义的顶点。

顶点的传递

接下来我们要将顶点传递到我们的顶点着色器中。

[renderEncoder setVertexBuffer:_vertexBuffer
                        offset:0
                       atIndex:CCVertexInputIndexVertices];

顶点的使用

在我们的顶点函数中我们这样使用传递过来的顶点数据。

vertex RasterizerData
vertexShader(uint vertexID [[vertex_id]],
             constant CCVertex *vertices [[buffer(CCVertexInputIndexVertices)]],
             constant vector_uint2 *viewportSizePointer [[buffer(CCVertexInputIndexViewportSize)]])
{
    /*
     处理顶点数据:
     1) 执行坐标系转换,将生成的顶点剪辑空间写入到返回值中.
     2) 将顶点颜色值传递给返回值
     */
    //定义out
    RasterizerData out;
    //初始化输出剪辑空间位置
    out.clipSpacePosition = vector_float4(0.0, 0.0, 0.0, 1.0);
    // 索引到我们的数组位置以获得当前顶点
    // 我们的位置是在像素维度中指定的.
    float2 pixelSpacePosition = vertices[vertexID].position.xy;
    //将vierportSizePointer 从verctor_uint2 转换为vector_float2 类型
    vector_float2 viewportSize = vector_float2(*viewportSizePointer);
    //每个顶点着色器的输出位置在剪辑空间中(也称为归一化设备坐标空间,NDC),剪辑空间中的(-1,-1)表示视口的左下角,而(1,1)表示视口的右上角.
    //计算和写入 XY值到我们的剪辑空间的位置.为了从像素空间中的位置转换到剪辑空间的位置,我们将像素坐标除以视口的大小的一半.
    out.clipSpacePosition.xy = pixelSpacePosition / (viewportSize / 2.0);
    //把我们输入的颜色直接赋值给输出颜色. 这个值将于构成三角形的顶点的其他颜色值插值,从而为我们片段着色器中的每个片段生成颜色值.
    out.color = vertices[vertexID].color;
    //完成! 将结构体传递到管道中下一个阶段:
    return out;
}
上一篇下一篇

猜你喜欢

热点阅读