1

I have a lot of transparent nodes in the scene. And if scene rotates in some orientations entire object blink and not rendering

  1. some suggest to adjust rendering order but this solving issue partially and visual bug eventually appears

  2. it's possible to uncheck "read depth" but it cause blinking and I am almost sure that this is not solution

Question:

is there is some correct shader that is using correct depth buffer so that transparent nodes not hiding randomly

or is there is another proper way to solve this issue?

PS: used Metal rendering, so in case you mention to advise some technics from OpenGL, just leave it

thanks

Here is sample screenshots:

In this example to make it simple used 3 flat double sided planes with opacity 0.5, transparency can also be set with alpha Chanel of the texture. In the real project objects may have any shape, can be transparent or not, placed inside of each other or not

crossing planes visibility issue 1:

crossing planes visibility issue 2:

Ok, looks like "Order Independent Transparency", A-buffer and changing fragments count per pixel should fix this but common, how this can be achieved? we are ok with GLSL shader until it works with SceneKit and Metal rendering

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

  • you can try this approach: [OpenGL - How to create Order Independent transparency?](https://stackoverflow.com/a/37783085/2521214) or [OpenGL: Rendering a model with a lot of texture transparency, without draw ordering?](https://stackoverflow.com/a/24586538/2521214) but from your description it sounds more like Z fighting then incorrect order. In such case either offset conflicting polygons or increase depth precision ... – Spektre Aug 24 '17 at 05:44
  • I'll remind that i am using SceneKit and OpenGL is not really relevant, especially if i am using Metal rendering – Андрей Первушин Aug 24 '17 at 17:36
  • The technique is the same no matter the gfx api you just find functions that do the same in your environment. – Spektre Aug 24 '17 at 17:39
  • Great, If somebody ask you how to draw image on iOS will you give an answer for Android? "you just find functions that do the same in your environment" – Андрей Первушин Aug 25 '17 at 07:04
  • You did not read the technique then ... you saw just gl calls instead. The idea of first link is to use polygon winding to fake the Z-Sorting on its own without actually sorting anything. first you render backside , then front side (by switching polygon winding rule) . so you have 2 rendering "passes" per each transparent layer of object. `GL_CW` means clockwise and `GL_CCW` means counter clockwise. The second link uses pre-ordered parts of meshes on top of the first approach. – Spektre Aug 25 '17 at 07:10
  • And how should it help me with SceneKit? – Андрей Первушин Aug 25 '17 at 08:02
  • without any specs we can only guess ... do you got 2D or 3D ... do you got meshesh, planes, do you mix transparent and solids together ... etc add at least a screenshot of what you got – Spektre Aug 25 '17 at 08:07
  • So you got planar objects ... are all of them transparent? do they use alpha channel blending or their transparency is constant? what blending equation you use? From the images I assume all faces are transparent with constant transparency. The lower middle artifact at first image looks weird. What rendering techniques you use (Back face culling, Depth buffer, are the faces rendered just once? Can your transparency saturate (more transparent faces overlapped become solid)?) – Spektre Aug 28 '17 at 07:54
  • Are you familiar with SceneKit? If you are not, then most likely you are not the one who can help. In this example to make it simple used 3 flat double sided planes with opacity 0.5, transparency can also be set with alpha Chanel of the texture. In the real project objects may have any shape, can be transparent or not, placed inside of each other or not – Андрей Первушин Aug 28 '17 at 09:32
  • Yes you're correctly assuming I am not familiar with **SceneKit**. But I am familiar with transparency rendering both low level and rendering libs based. You should add the info from your last comment into your question as it is crucial info on which possible answer will depend. However its last part implies arbitrary mix of alpha-transparency and solids which can not be faked. So your only options are **Z-sorting** (which is really complex operation as you have intersecting polygons) and is most likelly done in custom code on CPU side instead in the **SceneKit** or use **ray-tracing** instead – Spektre Aug 28 '17 at 10:38
  • Well I don't really understand how can I perform Z-sorting (playing around with rendering order right? ) because my planes are crossing, how shouldI know what is closer if GPU don't know... I really frustrated on this as I thought it's quite common situation – Андрей Первушин Aug 28 '17 at 13:03
  • There are geometry libs for such things out there (the intersecting polygon primitives are split) you Z-sort in camera space. But for complex mixed solid/transparent scenes is ray tracing the best option but slow of coarse unless shortcuts are used at cost of quality or realism. – Spektre Aug 28 '17 at 14:02
  • I think split is not the case as objects are moving unless it can be done on a fly with GPU and Metal shaders will try to look what is raytracing and is it possible to use it somehow with SceneKit – Андрей Первушин Aug 28 '17 at 15:38

1 Answers1

0

For Metal rendering there is possible way to render the scene and I succeeded.

I suppose you have reference to id <MTLRenderPipelineState>, so what I did is I've created another and disabled writing into the color buffer (added setup for writeMask to none).

After that I call the renderer to render the model twice (first time with the secondly created id <MTLRenderPipelineState> where writing to color buffer is disabled) per one pass.

First pipeline:

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);
}

Second pipeline:

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);
}

Depth state:

MTLDepthStencilDescriptor *volumetricDepthStateDescriptor = [MTLDepthStencilDescriptor new];
volumetricDepthStateDescriptor.depthCompareFunction = MTLCompareFunctionLessEqual;
volumetricDepthStateDescriptor.depthWriteEnabled = YES;
_volumetricDepthState = [_device newDepthStencilStateWithDescriptor:volumetricDepthStateDescriptor];
DZoki019
  • 382
  • 2
  • 13