「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
概述
使用图层选择为顶点着色器中的每个图元选择目标切片,可以将图元渲染到纹理数组、立方体纹理或 3D 纹理的多个层(切片)中。层是单个 1D、2D 或 3D 像素块,由目标纹理中的切片和 mipmap 级别指定。加载和存储操作适用于渲染通道附件的每个切片。
当你需要将内容渲染到来自同一源数据的多个相关纹理时,例如渲染环境立方体贴图或虚拟现实立体图像时,层选择非常有用。
有关演示图层选择的特定示例,请参阅使用更少的渲染通道渲染反射。
检查设备对象是否支持图层选择
macOS 系列中的所有 GPU 都支持层选择。从系列 5 开始的 Apple GPU 提供层选择支持。使用以下代码来测试是否支持图层选择:
- (Boolean) supportsLayerSelection
{
return
[_device supportsFamily: MTLGPUFamilyMac1 ] ||
[_device supportsFamily: MTLGPUFamilyApple5 ];
}
复制代码
添加图层选择
要指定将图元渲染到哪个切片,需要添加具有 [[render_target_array_index]] 属性的顶点输出。顶点着色器必须设置此值,以便 Metal 知道要渲染到哪个切片。
下面的示例使用实例化渲染将图元渲染到多个输出切片中。需要在顶点输出阶段添加一个层字段来指定目标切片。目标被当做每个实例属性的一部分作为输入,并被复制到顶点输出中。。
typedef struct
{
...
uint layer [[render_target_array_index]];
} ColorInOut;
vertex ColorInOut vertexTransform (
const Vertex in [[ stage_in ]],
const uint instanceId [[ instance_id ]],
const device InstanceParams* instanceParams [[ buffer ]],
{
ColorInOut out;
out.layer = instanceParams[instanceId].layer;
...
}
复制代码
顶点函数必须为构成任何给定图元的所有顶点返回相同的索引。
配置管道状态对象
可以渲染到层的渲染管线,必须指定可以渲染的图元类型。 此要求不同于普通渲染管道,此渲染管线中可以为每个绘制命令选择不同的图元。
当为渲染管线配置 MTLRenderPipelineDescriptor 时,设置 inputPrimitiveTopology 属性来指定渲染的图元类型。
MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];
descriptor.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
descriptor.sampleCount = 1
...
复制代码
配置渲染通道
配置 MTLRenderPassDescriptor 时,指定纹理数组、立方体贴图纹理或 3D 纹理作为颜色附件。 还必须将渲染通道描述符的 renderTargetArrayLength 属性设置为着色器可以选择的最大切片数。 例如,渲染到立方体贴图纹理时,将长度设置为 6。
渲染到纹理数组和立方体贴图时,可以指定多个附件并同时渲染所有附件。 如果指定 3D 纹理,则无法渲染到多个附件。 如下是一个示例,使用一个立方体贴图纹理来设置渲染通道描述符,其中一个用于颜色数据,另一个用于深度信息:
MTLRenderPassDescriptor* reflectionPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
reflectionPassDesc.colorAttachments[0].texture = _reflectionCubeMap;
reflectionPassDesc.depthAttachment.texture = _reflectionCubeMapDepth;
reflectionPassDesc.renderTargetArrayLength = 6;
...
复制代码
总结
本文介绍了使用 Metal 渲染到多个纹理的步骤,首先使用层选择为顶点着色器中的每个图元选择目标切片,其次为渲染管道配置渲染的图元类型,最后配置渲染通道。