Search Unity

[SOVLED] Draw a transparent halo with GL functions over a GameObject

Discussion in 'Shaders' started by PMerlaud, Oct 20, 2014.

  1. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    Hi everyone,

    Here's what I'm trying to do.

    I have a 3D mesh that I can color using this shader :

    Code (CSharp):
    1. Shader "Custom/Unlit Colored"
    2. {
    3.      Properties
    4.      {
    5.          _Color ("Color Tint", Color) = (1,1,1,1)  
    6.          _MainTex ("Base (RGB) Alpha (A)", 2D) = "white"
    7.      }
    8.        
    9.      Category
    10.      {
    11.          Lighting Off
    12.          ZWrite Off
    13.                  //ZWrite On  // uncomment if you have problems like the sprite disappear in some rotations.
    14.          Cull back
    15.          Blend SrcAlpha OneMinusSrcAlpha
    16.                  //AlphaTest Greater 0.001  // uncomment if you have problems like the sprites or 3d text have white quads instead of alpha pixels.
    17.          Tags {Queue=Transparent}
    18.          SubShader
    19.          {
    20.               Pass
    21.               {
    22.                          SetTexture [_MainTex]
    23.                          {
    24.                      ConstantColor [_Color]
    25.                     Combine Texture * constant
    26.                  }
    27.              }
    28.          }
    29.      }
    30. }
    I'm drawing a halo around the gameobject with GL functions (GL.Lines), rendered with this shader :

    Code (CSharp):
    1. Shader "Lines/Colored Blended" {
    2.  
    3.     SubShader {
    4.         Tags { "Queue" = "Transparent+100" }
    5.         Pass {
    6.             BindChannels { Bind "Color",color }    
    7.        
    8.             Blend SrcAlpha OneMinusSrcAlpha
    9.             ZWrite On
    10.             ZTest LEqual
    11.             Cull Off
    12.             Fog { Mode Off }
    13.        }
    14.     }
    15. }
    When the mesh is not colored, it looks like this :
    Capture d’écran 2014-10-20 à 20.42.08 (2).png

    When the mesh is colored and the halo isn't drawn, it loos like this :
    Capture d’écran 2014-10-20 à 20.43.33 (2).png

    But when the mesh is colored and the halo is rendered, the halo is "cropping" the mesh and hides every part of the mesh behind it :
    Capture d’écran 2014-10-20 à 20.45.43 (2).png

    Is there a way to render both of them at the same time without the halo hiding the mesh ? :)
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Turn ZWrite off. It is most likely causing your halo (drawn first) to obscure the mesh behind it.
     
  3. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    Thanks for the reply.

    I turned ZWrite off and this is the result :
    Capture d’écran 2014-10-20 à 21.18.37 (2).png

    The halo is now rendered behind the GameObject, but we can barely see it now.
    What should I do to render it on top of the mesh ?

    I'd like to have something like this (it's a montage, I didn't really manage to do it) :
    Capture d’écran 2014-10-20 à 21.22.57 (2).png
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Right, so it looks like your halo is being drawn before the mesh. I'm pretty sure the GL functions ignore render queue order. Are you letting the mesh render normally and then drawing your halo in OnPostRender()?
     
  5. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    I didn't say it but the mesh is renderer by another camera (not the main). Could it have any influence ? And yep, all GL functions are processed in OnPostRender().
     
  6. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    My guess is your current render order is:
    1. Main camera
    2. OnPostRender() with your halo
    3. Another camera rendering your mesh
    And instead you want it to be:
    1. Main camera
    2. Another camera rendering your mesh
    3. OnPostRender() with your halo
    Which means (if I understand your setup) that you need to move your halo script from the main camera to the other one, ensuring that it renders last.
     
  7. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    My setup is :
    1. Main camera with halo script attached
    2. Several cameras rendering meshes (one per mesh)
    But the thing is, I can't move the script rendering the halo on the mesh cameras, it has to stay on the main.
     
  8. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Why is that?
     
  9. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    I managed to do what you suggested.

    I moved the OnPostRender() part in a MonoBehaviour that I attached to another camera, which has a larger depth than all the others (the main and the mesh cameras), but it doesn't seem to work.

    The setup is :
    1. Main camera
    2. Meshes cameras
    3. Halo camera
    If the halo camera has a lower depth than the meshes', the halo is behind the mesh :
    1.png

    And when the halo camera has a higher depth, we can't see the mesh anymore :
    Capture d’écran 2014-10-24 à 16.16.14 (2).png

    The shaders I use were updated like that :

    1. Halo shader

    Code (CSharp):
    1. Shader "Lines/Colored Blended" {
    2.  
    3.     SubShader {
    4.         Pass {
    5.             BindChannels { Bind "Color",color }    
    6.        
    7.             Blend SrcAlpha OneMinusSrcAlpha
    8.             ZWrite Off
    9.             //ZTest LEqual
    10.             Cull Off
    11.             Fog { Mode Off }
    12.        }
    13.     }
    14. }
    2. Mesh shader

    Code (CSharp):
    1. Shader "Custom/Unlit Colored"
    2. {
    3.    Properties {
    4.            _Color ("Color Tint", Color) = (1,1,1,1)
    5.            _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    6.     }
    7. SubShader {
    8.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    9.     LOD 100
    10.  
    11.     ZWrite Off
    12.     Blend SrcAlpha OneMinusSrcAlpha
    13.  
    14.     Pass {
    15.         CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.          
    19.             #include "UnityCG.cginc"
    20.          
    21.             struct appdata_t {
    22.                 float4 vertex : POSITION;
    23.                 float2 texcoord : TEXCOORD0;
    24.             };
    25.             struct v2f {
    26.                 float4 vertex : SV_POSITION;
    27.                 half2 texcoord : TEXCOORD0;
    28.             };
    29.             sampler2D _MainTex;
    30.             float4 _MainTex_ST;
    31.             fixed4 _Color;
    32.          
    33.             v2f vert (appdata_t v)
    34.             {
    35.                 v2f o;
    36.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    37.                 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
    38.                 return o;
    39.             }
    40.          
    41.             fixed4 frag (v2f i) : SV_Target
    42.             {
    43.                 fixed4 col = tex2D(_MainTex, i.texcoord) * _Color;
    44.                 return col;
    45.             }
    46.         ENDCG
    47.     }
    48. }
    49. }
    50.  
     
  10. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    I finally got it working.

    I kept the setup :
    1. Main camera (Depth 1)
    2. Mesh cameras (1 < Depth < 100)
    3. Halo camera (Depth 100)
    I just had to set the right culling mask of the halo camera (Nothing in my case) and it worked.