繁体   English   中英

[SceneKit][Metal] 是否可以根据深度缓冲而不是渲染顺序来渲染透明节点

[英][SceneKit][Metal] Is there is ability to render transparent nodes based on depth buffer and not by rendering order

我在场景中有很多透明节点。 如果场景在某些方向旋转,整个对象会闪烁而不渲染

  1. 有些人建议调整渲染顺序,但这个解决问题部分和视觉错误最终出现

  2. 可以取消选中“读取深度”,但它会导致闪烁,我几乎可以肯定这不是解决方案

问题:

是否有一些正确的着色器使用正确的深度缓冲区,以便透明节点不会随机隐藏

还是有另一种正确的方法来解决这个问题?

PS:使用了 Metal 渲染,所以如果你提到从 OpenGL 中提供一些技术建议,就留下它

谢谢

以下是示例屏幕截图:

在这个例子中,为了简单起见,使用了 3 个不透明度为 0.5 的平坦双面平面,透明度也可以用纹理的 alpha Chanel 设置。 在实际项目中对象可以是任何形状,可以是透明的,可以是不透明的,可以是相互放置的,也可以是不透明的

穿越飞机的能见度问题 1:

穿越飞机的能见度问题 2:

好的,看起来像“顺序无关透明度”,A 缓冲区和每像素更改片段数应该解决这个问题,但很常见,如何实现? 我们可以使用 GLSL 着色器,直到它适用于 SceneKit 和 Metal 渲染

http://www.openglsuperbible.com/2013/08/20/is-order-independent-transparency-really-necessary/

对于Metal渲染,有一种可能的方法来渲染场景,我成功了。

我想你引用了id <MTLRenderPipelineState> ,所以我所做的是我创建了另一个并禁用了写入颜色缓冲区(将writeMask设置添加为无)。

之后,我调用渲染器对模型进行两次渲染(第一次使用第二次创建的id <MTLRenderPipelineState> ,其中写入颜色缓冲区被禁用)每一次传递。

第一条管道:

MTLRenderPipelineDescriptor *volumetricPipelineDescriptor = [MTLRenderPipelineDescriptor new];
volumetricPipelineDescriptor.vertexFunction = vertexFunction;
volumetricPipelineDescriptor.fragmentFunction = fragmentFunction;
volumetricPipelineDescriptor.vertexDescriptor = vertexDescriptor;

volumetricPipelineDescriptor.colorAttachments[0].blendingEnabled             = YES;
volumetricPipelineDescriptor.colorAttachments[0].rgbBlendOperation           = MTLBlendOperationAdd;
volumetricPipelineDescriptor.colorAttachments[0].alphaBlendOperation         = MTLBlendOperationAdd;
volumetricPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;
volumetricPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor      = MTLBlendFactorSourceAlpha;
volumetricPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;
volumetricPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;

volumetricPipelineDescriptor.colorAttachments[0].pixelFormat = _renderDestination.colorPixelFormat;
volumetricPipelineDescriptor.depthAttachmentPixelFormat = _renderDestination.depthStencilPixelFormat;
volumetricPipelineDescriptor.stencilAttachmentPixelFormat = _renderDestination.depthStencilPixelFormat;

error = nil;
_volumetricPipelineState = [_device newRenderPipelineStateWithDescriptor:volumetricPipelineDescriptor
                                                                   error:&error];

if (!_volumetricPipelineState) {
    NSLog(@"Error occurred when creating render pipeline state: %@", error);
}

第二条流水线:

MTLRenderPipelineDescriptor *volumetricPipelineDescriptor = [MTLRenderPipelineDescriptor new];
volumetricPipelineDescriptor.vertexFunction = vertexFunction;
volumetricPipelineDescriptor.fragmentFunction = fragmentFunction;
volumetricPipelineDescriptor.vertexDescriptor = vertexDescriptor;
volumetricPipelineDescriptor.colorAttachments[0].writeMask = MTLColorWriteMaskNone;
volumetricPipelineDescriptor.colorAttachments[0].pixelFormat = _renderDestination.colorPixelFormat;
volumetricPipelineDescriptor.depthAttachmentPixelFormat = _renderDestination.depthStencilPixelFormat;
volumetricPipelineDescriptor.stencilAttachmentPixelFormat = _renderDestination.depthStencilPixelFormat;

error = nil;
_volumetricPipelineState2 = [_device newRenderPipelineStateWithDescriptor:volumetricPipelineDescriptor
                                                                   error:&error];

if (!_volumetricPipelineState2) {
    NSLog(@"Error occurred when creating render pipeline state: %@", error);
}

深度状态:

MTLDepthStencilDescriptor *volumetricDepthStateDescriptor = [MTLDepthStencilDescriptor new];
volumetricDepthStateDescriptor.depthCompareFunction = MTLCompareFunctionLessEqual;
volumetricDepthStateDescriptor.depthWriteEnabled = YES;
_volumetricDepthState = [_device newDepthStencilStateWithDescriptor:volumetricDepthStateDescriptor];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM