【发布时间】:2021-08-28 20:07:56
【问题描述】:
我在我的 Metal 渲染器中启用了深度测试,创建了一个 MTLPixelFormatDepth32Float_Stencil8 格式的 MTLTexture。
然后我为我的渲染通道创建一个深度附件:
renderPassDescriptor.depthAttachment.texture = textureDepth;
renderPassDescriptor.depthAttachment.clearDepth = 1.0;
renderPassDescriptor.depthAttachment.loadAction = MTLLoadActionLoad;
renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionDontCare;
最后,我像往常一样设置编码器的深度模板状态:
[renderEncoder setDepthStencilState:depthStencilState];
配置如下:
MTLDepthStencilDescriptor *depthStencilDescriptor = [MTLDepthStencilDescriptor new];
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionLess;
depthStencilDescriptor.depthWriteEnabled = YES;
depthStencilState = [gpu newDepthStencilStateWithDescriptor:depthStencilDescriptor];
我还确保使用正确的深度像素格式配置我的管道状态描述符:
pipelineStateDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
这足以让深度测试适用于单次绘制调用。所有顶点都以正确的顺序呈现。
奇怪的是,如果我在单独的绘制调用中绘制多个对象,它们仍然表现得好像没有启用深度测试一样。它们可以很好地渲染自己,但它们的深度仍然取决于绘制调用顺序,而不是它们的实际深度值。
在 OpenGL 中一切正常,正确的输出如下所示:
然而,在 Metal 中,我得到以下输出(注意右侧的框重叠):
首先渲染左边的盒子,然后是右边的两个盒子。
我还在 GPU 帧捕获中查看了深度缓冲区,粗略一看,它似乎是正确的:
我还需要启用/配置什么以允许根据框的深度对框进行正确排序吗?
对于我的投影矩阵,我将它与模型矩阵一起创建(使用 AAPLMathUtilities 进行矩阵函数):
vector_float3 translate = {mesh->x, mesh->y, mesh->z};
vector_float3 scale = {mesh->sx, mesh->sy, mesh->sz};
matrix_float4x4 modelMatrix = matrix_multiply(matrix4x4_translation(translate), matrix4x4_scale(scale));
vector_float3 eye = { item->camera_position.x, item->camera_position.y, item->camera_position.z };
vector_float3 target = {
item->camera_position.x + item->camera_front.x,
item->camera_position.y + item->camera_front.y,
item->camera_position.z + item->camera_front.z
};
vector_float3 up = { item->camera_up.x, item->camera_up.y, item->camera_up.z };
matrix_float4x4 viewMatrix = matrix_look_at_right_hand(eye, target, up);
auto modelViewMatrix = matrix_multiply(viewMatrix, modelMatrix);
auto projectionMatrix = matrix_perspective_right_hand(radians_from_degrees(45.0f), screenWidth / screenHeight, 0.1f, 100.0f);
着色器计算顶点位置如下:
float4 position = float4(in.data.xyz, 1.0);
out.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * position;
【问题讨论】:
-
您为金属输出的深度范围是多少?你如何创建投影矩阵?我问的原因是因为在 OpenGL 中深度将从 -1 变为 1,但在 Metal 中它从 0 变为 1
-
@JustSomeGuy 我已经用关于投影矩阵的更多细节更新了这个问题。我使用的深度范围是 0.1f 到 100.0f。
-
我尝试切换到像在我的 OpenGL 渲染器中那样使用 GLM,并且使用我在 OpenGL 中使用的完全相同的投影矩阵代码,我仍然遇到问题,所以我认为这与投影无关矩阵。
标签: metal