概述
使用图层选择为顶点着色器中的每个图元选择目标切片,可以将图元渲染到纹理数组、立方体纹理或 3D 纹理的多个层(切片)中。层是单个 1D、2D 或 3D 像素块,由目标纹理中的切片和 mipmap 级别指定。加载和存储操作适用于渲染通道附件的每个切片。
当你需要将内容渲染到来自同一源数据的多个相关纹理时,例如渲染环境立方体贴图或虚拟现实立体图像时,层选择非常有用。
有关演示图层选择的特定示例,请参阅使用更少的渲染通道渲染反射。
检查设备对象是否支持图层选择
macOS 系列中的所有 GPU 都支持层选择。从系列 5 开始的 Apple GPU 提供层选择支持。使用以下代码来测试是否支持图层选择:
```
- (Boolean) supportsLayerSelection
{
return
[_device supportsFamily: MTLGPUFamilyMac1 ] ||
[_device supportsFamily: MTLGPUFamilyApple5 ];
}
```
添加图层选择
要指定将图元渲染到哪个切片,需要添加具有 [[rendertargetarray_index]] 属性的顶点输出。顶点着色器必须设置此值,以便 Metal 知道要渲染到哪个切片。
下面的示例使用实例化渲染将图元渲染到多个输出切片中。需要在顶点输出阶段添加一个层字段来指定目标切片。目标被当做每个实例属性的一部分作为输入,并被复制到顶点输出中。。
``` typedef struct
{ ... uint layer [[rendertargetarray_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 渲染到多个纹理的步骤,首先使用层选择为顶点着色器中的每个图元选择目标切片,其次为渲染管道配置渲染的图元类型,最后配置渲染通道。
公众号:audio_video_render 会持续更新一些干货资源,欢迎大家关注。有想了解的技术也可以给我留言,我会尽量帮你解决。