Search Unity

How can I change this shader so the rings can be displayed on a transparent surface?

Discussion in 'Shaders' started by cakefile, Aug 23, 2019.

  1. cakefile

    cakefile

    Joined:
    Dec 12, 2018
    Posts:
    3
    I need a transparent plane, on which a sonar-like effect is displayed.

    I already tried adapting the code from the Unity shader tutorial on transparent shaders in various ways, but it didn't work out.

    Code (CSharp):
    1.  
    2. Shader "MadeByProfessorOakie/SimpleSonarShader" {
    3.     Properties{
    4.         _Color("Color", Color) = (1,1,1,1)
    5.         _MainTex("Albedo (RGB)", 2D) = "white" {}
    6.         _Glossiness("Smoothness", Range(0,1)) = 0.5
    7.         _Metallic("Metallic", Range(0,1)) = 0.0
    8.         _RingColor("Ring Color", Color) = (1,1,1,1)
    9.         _RingColorIntensity("Ring Color Intensity", float) = 2
    10.         _RingSpeed("Ring Speed", float) = 1
    11.         _RingWidth("Ring Width", float) = 0.1
    12.         _RingIntensityScale("Ring Range", float) = 1
    13.         _RingTex("Ring Texture", 2D) = "white" {}
    14.     }
    15.  
    16.     SubShader{
    17.         Tags{ "RenderType" = "Opaque" }
    18.         LOD 200
    19.  
    20.         CGPROGRAM
    21.         // Physically based Standard lighting model, and enable shadows on all light types
    22.         #pragma surface surf Standard fullforwardshadows
    23.  
    24.         // Use shader model 3.0 target, to get nicer looking lighting
    25.         #pragma target 3.0
    26.  
    27.         sampler2D _MainTex;
    28.         sampler2D _RingTex;
    29.  
    30.  
    31.         struct Input {
    32.             float2 uv_MainTex;
    33.             float3 worldPos;
    34.             float3 uv_Illum;
    35.         };
    36.  
    37.         // The size of these arrays is the number of rings that can be rendered at once.
    38.         // If you want to change this, you must also change QueueSize in SimpleSonarShader_Parent.cs
    39.         half4 _hitPts[20];
    40.         half _StartTime;
    41.         half _Intensity[20];
    42.  
    43.         half _Glossiness;
    44.         half _Metallic;
    45.         fixed4 _Color;
    46.         fixed4 _RingColor;
    47.         fixed4 _EmissionLM;
    48.         half _RingColorIntensity;
    49.         half _RingSpeed;
    50.         half _RingWidth;
    51.         half _RingIntensityScale;
    52.  
    53.  
    54.         void surf(Input IN, inout SurfaceOutputStandard o) {
    55.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    56.             o.Albedo = c.rgb;
    57.  
    58.             half DiffFromRingCol = abs(o.Albedo.r - _RingColor.r) + abs(o.Albedo.b - _RingColor.b) + abs(o.Albedo.g - _RingColor.g);
    59.  
    60.  
    61.             // Check every point in the array
    62.             // The goal is to set RGB to highest possible values based on current sonar rings
    63.             for (int i = 0; i < 20; i++) {
    64.  
    65.                 half d = distance(_hitPts[i], IN.worldPos);
    66.                 half intensity = _Intensity[i] * _RingIntensityScale;
    67.                 half val = (1 - (d / intensity));
    68.  
    69.                 if (d < (_Time.y - _hitPts[i].w) * _RingSpeed && d >(_Time.y - _hitPts[i].w) * _RingSpeed - _RingWidth && val > 0) {
    70.                     half posInRing = (d - ((_Time.y - _hitPts[i].w) * _RingSpeed - _RingWidth)) / _RingWidth;
    71.  
    72.                     // Calculate predicted RGB values sampling the texture radially
    73.                     float angle = acos(dot(normalize(IN.worldPos - _hitPts[i]), float3(1,0,0)));
    74.                     val *= tex2D(_RingTex, half2(1 - posInRing, angle));
    75.                     half3 tmp = _RingColor * val + c * (1 - val);
    76.  
    77.                     // Determine if predicted values will be closer to the Ring color
    78.                     half tempDiffFromRingCol = abs(tmp.r - _RingColor.r) + abs(tmp.b - _RingColor.b) + abs(tmp.g - _RingColor.g);
    79.                     if (tempDiffFromRingCol < DiffFromRingCol)
    80.                     {
    81.                         // Update values using our predicted ones.
    82.                         DiffFromRingCol = tempDiffFromRingCol;
    83.                         o.Albedo.r = tmp.r;
    84.                         o.Albedo.g = tmp.g;
    85.                         o.Albedo.b = tmp.b;
    86.                         o.Albedo.rgb *= _RingColorIntensity;
    87.                     }
    88.                 }
    89.             }
    90.  
    91.             o.Metallic = _Metallic;
    92.             o.Smoothness = _Glossiness;
    93.         }
    94.  
    95.         ENDCG
    96.     }
    97.     FallBack "Diffuse"
    98. }
    I guess I have to use something else than the surf method. When I change the _Color value of the corresponding Material the Shader is applied to in the editor to transparent, the plane is still visible.
    Changing
    #pragma surface surf Standard fullforwardshadows

    to
    #pragma surface surf Standard fullforwardshadows alpha:fade

    Makes the plane transparent, but the circles aren't visible either.
     
  2. Namey5

    Namey5

    Joined:
    Jul 5, 2013
    Posts:
    188
    There's a few things you need to do to make this work. The first of which is actually enabling alpha blending, which is done the way you pointed out - by adding alpha:fade to your surface declaration.

    On top of that, you will need to change your shader's tags such that the engine knows that it is going to be transparent when the object is rendered;

    Code (CSharp):
    1. Tags{ "RenderType" = "Transparent" "Queue"="Transparent" }
    Lastly, for you to be able to define the transparency, you need to output an alpha value in the surface function itself. I've highlighted some important changes and their placements here;

    Code (CSharp):
    1. ...
    2. fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    3. o.Albedo = c.rgb;
    4. o.Alpha = c.a;      //Assign the base alpha here
    5.  
    6. half DiffFromRingCol = abs(o.Albedo.r - _RingColor.r) + abs(o.Albedo.b - _RingColor.b) + abs(o.Albedo.g - _RingColor.g);
    7.  
    8. ...
    9.  
    10. if (tempDiffFromRingCol < DiffFromRingCol)
    11. {
    12.     // Update values using our predicted ones.
    13.     DiffFromRingCol = tempDiffFromRingCol;
    14.     o.Albedo.r = tmp.r;
    15.     o.Albedo.g = tmp.g;
    16.     o.Albedo.b = tmp.b;
    17.     o.Albedo.rgb *= _RingColorIntensity;
    18.     o.Alpha = _RingColor.a;         //Override with the ring's alpha here
    19. }
    20. ...