Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question GPU Instancing and depth problem

Discussion in 'Shaders' started by BigPipi666, Feb 17, 2023.

  1. BigPipi666

    BigPipi666

    Joined:
    Aug 3, 2021
    Posts:
    3
    Hi! I am trying to create GPU instanced particles (no unity particle system involved). Currently I just have a bunch of quads with a texture and I move around in a compute shader. The problem is with transparency. It seems to me that some instances are rendered in wrong order and I think the issue might be in z depth. I tried to play around with writing to depth buffer in frag shader, but it didn't really help. Below are the screenshots of what is happening and the shader code. If anyone has any idea what is the problem and how to fix it, I would really appreciate it. Thanks!

    CODE:

    StructuredBuffer<ParticleData> _ParticlesData;
    StructuredBuffer<float3> _VertexPositions;
    StructuredBuffer<int> _Triangles;
    StructuredBuffer<float2> _UV;

    v2f vert (uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID)
    {
    int realVertexId = _Triangles[vertex_id];
    float4 worldCoord = float4(_ParticlesData[instance_id].Position, 1);
    float4 position = float4(_VertexPositions[realVertexId] + _ParticlesData[instance_id].Position, 1);
    float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(_VertexPositions[realVertexId], 0);
    float4 outPos = mul(UNITY_MATRIX_P, viewPos);

    v2f o;
    o.ClipSpacePosition = outPos;
    o.data.x = length(position) / 10;
    o.uv = _UV[realVertexId];
    return o;
    }

    fixed4 frag (v2f result) : SV_Target
    {
    float alpha = tex2D(_MainTex, result.uv).a;
    float4 color = float4(_Color.rgb, alpha);
    return color;
    }



    upload_2023-2-17_13-18-13.png


    upload_2023-2-17_13-18-37.png
    upload_2023-2-17_13-18-13.png
     
  2. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Most particles use additive blending, so it does not matter what order they are rendered in. In the
    Pass {}
    block, of your vertex/fragment shader, put
    Blend One One
    .

    For certain types of particles, you may need to use different blend modes (eg alpha testing might be appropriate for falling leaves).
     
    BigPipi666 likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    If it is not specified, Unity shaders default to
    ZWrite On
    . For transparent materials, usually you want
    ZWrite Off
    .
    ZWrite
    along with
    ZTest
    is used for depth sorting of opaque objects, but it is only really useful for opaque objects because the depth buffer can only store one depth value per pixel. For transparent objects you want set turn
    ZWrite Off
    and then you'll either need to use a blend mode that doesn't care about the render order, like additive (though I'd recommend
    Blend SrcAlpha One
    instead of
    Blend One One
    ), or you'll need to manually sort the particles in back to front order in the structured buffers.
     
    BigPipi666 likes this.
  4. BigPipi666

    BigPipi666

    Joined:
    Aug 3, 2021
    Posts:
    3
    Yeah, z testing was on, and after I disabled it things changed but not much better. Now, if I look at the particles with cameraZ being negative I - they render properly. But, when cameraZ is positive at certain distances I get the black square artifacts again.
    upload_2023-2-18_1-0-5.png
    This is a screenshot with cameraZ positive at distance when rendering is ok.

    upload_2023-2-18_1-0-52.png
    And this same position, but a little further away from the center - artifacts appear again. Plus, particles behind the blue plane are now occluded by it - which is what I expect always, but it only happens when the artifacts appear.

    In my shader code I have:
    Tags{ "RenderType" = "Transparent"
    "Queue" = "Transparent"}
    LOD 200

    Blend SrcAlpha One
    ZTest Off
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    You do not want
    ZTest Off
    , you want that on, or more specifically
    ZWrite GEqual
    , which is the default if you don't include it.. You want
    ZWrite Off
    .

    ZTest Off
    will mean it will render on top of opaque objects, even if they're behind those surfaces.

    ZWrite Off
    means it won't write to the depth buffer (aka z buffer), which is still what's causing your issue

    The behavior of the black squares showing or not is due to the render order changing. In the first image the walls are rendering first, and then the particles. In the second image the particles were rendering first, and then the walls. Because
    ZWrite
    was still enabled, in the second image the walls aren't rendering anywhere they're behind the particles because that's what the depth buffer along with
    ZWrite
    and
    ZTest
    are supposed to do to ensure depth sorting.

    However the fact the order between the walls and the particles isn't consistent makes me think the Render Queue on the material itself is overriding the shader (make sure it's set to 3000 or Use Shader and not 2000 or some other number), or you're manually rendering the mesh during the opaque queue.