Search Unity

Question Issues with clipping in DrawMeshInstanced and shader

Discussion in 'Shaders' started by Supergeek, Mar 7, 2021.

  1. Supergeek

    Supergeek

    Joined:
    Aug 13, 2010
    Posts:
    103
    I'm very bad with shaders, and I'm using one I copied from an article I read online about DrawMeshInstanced. I'm making a 2D game and some of the meshes are clipping into some of the others. Here's an example of the bug: https://i.imgur.com/Bj1U7e0.gif

    Here's the shader I'm using:


    Shader "Custom/DMIColor2"
    {
    Properties
    {
    _MainTex("Texture", 2D) = "white" {}
    _Color("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
    Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
    LOD 100
    Cull Back
    ZWrite On
    Blend SrcAlpha OneMinusSrcAlpha
    Pass
    {
    //ZWrite Off
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma multi_compile_instancing
    #include "UnityCG.cginc"
    struct appdata
    {
    float4 vertex : POSITION;
    UNITY_VERTEX_INPUT_INSTANCE_ID
    float2 uv : TEXCOORD0;
    };
    struct v2f
    {
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    UNITY_VERTEX_INPUT_INSTANCE_ID
    };
    sampler2D _MainTex;
    //float4 _MainTex_UV;
    UNITY_INSTANCING_BUFFER_START(Props)
    UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
    UNITY_DEFINE_INSTANCED_PROP(fixed4, _MainTex_UV)
    UNITY_INSTANCING_BUFFER_END(Props)
    v2f vert(appdata v)
    {
    v2f o;
    UNITY_SETUP_INSTANCE_ID(v);
    UNITY_TRANSFER_INSTANCE_ID(v, o);
    float3 worldPosition = float3(v.vertex.x, v.vertex.y, -v.vertex.y / 100);
    o.vertex = UnityObjectToClipPos(float4(worldPosition, 1.0f));
    o.uv = (v.uv * UNITY_ACCESS_INSTANCED_PROP(Props, _MainTex_UV).xy) + UNITY_ACCESS_INSTANCED_PROP(Props, _MainTex_UV).zw;
    return o;
    }
    fixed4 frag(v2f i) : SV_Target
    {
    UNITY_SETUP_INSTANCE_ID(i);
    fixed4 col = tex2D(_MainTex, i.uv) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    clip(col.a - 30.0 / 255.0);
    col.rgba *= col.a;
    return col;
    }
    ENDCG
    }
    }
    }


    The shader is supposed to handle depth sorting using the Z coordinate, so that things with lower Y on the screen render on top of things with higher Y on the screen.
    I'm setting the Z like this in my C# code when I populate the arrays for using with DrawMeshInstanced: "position.z = -10 + position.y * 0.01f;"

    The draw portion of my code is:


    block.SetVectorArray(uvShaderId, local_uvs);
    block.SetVectorArray(colorShaderId, local_colors);
    Graphics.DrawMeshInstanced(mesh, 0, material, local_matrices, b, block);


    local_uvs, local_matrices, and local_colors are arrays with the obvious data. b is just the slice size, and block is the MaterialPropertyBlock. It all works fine for thousands of meshes, except I have this little clipping issue.
    My previous solution was one I wrote myself, using a mesh with verts and uvs generated every frame. It worked, with no objects clipping through others, but it was a little bit slower.

    I would appreciate any help. Thanks.