Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question "Tile" transparency overlapping

Discussion in 'Shaders' started by P_e_t_a_c_h_e_k, Aug 26, 2023.

  1. P_e_t_a_c_h_e_k

    P_e_t_a_c_h_e_k

    Joined:
    Dec 26, 2017
    Posts:
    25
    Hi, I'm facing an issue with the transparency of the tiles. I create a procedural mesh, it looks something like this:
    upload_2023-8-26_12-57-24.png

    upload_2023-8-26_12-57-35.png
    That is, the higher the "tile", the further it is from the orthographic camera. The point is that since one tile of the mesh has a height of 2 and a width of 1 (since the image is 256x384), this causes the tiles to overlap one another, but there is a problem of transparency, I need the images to overlap one another correctly. I read about "Alpha Clip Threshold", it works, but it produces strange "artifacts" at the edges of the image when the camera zooms in or out. Especially as far as I understand it won't work with semi-transparent sprites. Here is the shader graph:
    upload_2023-8-26_12-55-53.png
    I thought maybe I need to align the mesh and use ZWrite Off, but I don't quite understand how to solve this, any help would be appreciated!

    Here is the shader:
    Code (CSharp):
    1. Shader "Unlit/Tiles"
    2. {
    3.      Properties
    4.     {
    5.         _MainTexArr ("Main Tex Array", 2DArray) = "white" {}
    6.     }
    7.     SubShader
    8.     {
    9.         Tags { "RenderType"="TransparentCutout" "Queue"="AlphaTest" }
    10.  
    11.         Cull Off
    12.         Lighting Off
    13.         ZWrite Off
    14.         Blend One OneMinusSrcAlpha
    15.  
    16.      
    17.      
    18.         Pass
    19.         {
    20.        
    21.        
    22.           //AlphaToMask On
    23.             CGPROGRAM
    24.             #pragma vertex vert
    25.             #pragma fragment frag
    26.             #include "UnityCG.cginc"
    27.             struct appdata {
    28.                 float4 vertex : POSITION;
    29.                 float3 uv : TEXCOORD0;
    30.             };
    31.             struct v2f {
    32.                 float4 pos : SV_POSITION;
    33.                 float2 uv : TEXCOORD0;
    34.                 nointerpolation int index : TEXCOORD1;
    35.             };
    36.             v2f vert(appdata v)
    37.             {
    38.                 v2f o;
    39.                 o.pos = UnityObjectToClipPos(v.vertex);
    40.                 o.uv = v.uv.xy;
    41.                 o.index = v.uv.z;
    42.                 return o;
    43.             }
    44.             UNITY_DECLARE_TEX2DARRAY(_MainTexArr);
    45.             fixed4 frag(v2f i) : SV_Target
    46.             {
    47.                 fixed4 col  =   UNITY_SAMPLE_TEX2DARRAY(_MainTexArr, float3(i.uv.xy, i.index));
    48.                 // UNITY_OPAQUE_ALPHA(col.a);
    49.                 return col;
    50.             }
    51.             ENDCG
    52.         }
    53.     }
    54. }
    55.  
    Here's how it is at the moment:
    upload_2023-8-26_13-4-23.png
    This is what it should look like:
    upload_2023-8-26_13-4-35.png
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,497
    If you're generating it as one combined mesh, then the rendering can't be pre-sorted. With AlphaClip, you can allow the depth of the geometry to take care of that, but then you're giving up semi-transparency for smoother edges (though there are some tricks for that like Alpha to Coverage).

    Here's a couple solutions for semi transparency

    1. If you're generating the mesh on C# side as a mesh object, then split the tiles up into separate meshes and sort by height + depth and then render them in that order.

    2. Instead of generating a mesh asset, use something like RenderMeshInstanced and have your matrix buffer sorted in the order your tiles should draw so they overlap how you want, and an instance data buffer that you can add information to for determining a texture to sample from and other info.
     
  3. P_e_t_a_c_h_e_k

    P_e_t_a_c_h_e_k

    Joined:
    Dec 26, 2017
    Posts:
    25
    Hi, it's an interesting idea to use Graphics.RenderMeshInstanced, but it doesn't work for me for some reason (not sure why) even though Graphics.RenderMesh works as expected.

    In any case, it works better than the built-in unity tile system, I tweaked the grids a bit, and I get ~30 draw calls (I don't think it's too low) compared to 120 with the tile system.

    I also had an idea that maybe I should use a submesh for chunks, but I'm not sure if it's a good idea, for example, to use 10 submesh with 10 identical materials.