Search Unity

Deriving transparency from alpha channel of Albedo texture in Surface shader

Discussion in 'Shaders' started by eco_bach, Aug 31, 2017.

  1. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    Hi
    Have a challenging issue for a shader novice like myself. I have an existing shader which uses vertex animation to deform a mesh at render time using previously created position and normal vertex maps.
    It works fine.
    However, since this is supposed to be an ocean surface I would like to add a little translucency, and optionally, subsurface scattering to the shader.
    The color is controlled by an additional Albedo map with alpha.

    Here is the Surface Shader and a screen grab of the actual mesh is attached. I've also included an inspector view of the mesh prefab

    (See this sidefx article for the entire workflow)


    Code (csharp):
    1.  
    2. Shader "sidefx/vertex_soft_body_shader" {
    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.         _boundingMax("Bounding Max", Float) = 1.0
    9.         _boundingMin("Bounding Min", Float) = 1.0
    10.         _numOfFrames("Number Of Frames", int) = 240
    11.         _speed("Speed", Float) = 0.33
    12.         [MaterialToggle] _pack_normal ("Pack Normal", Float) = 0
    13.         _posTex ("Position Map (RGB)", 2D) = "white" {}
    14.         _nTex ("Normal Map (RGB)", 2D) = "grey" {}
    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 addshadow vertex:vert
    23.  
    24.         // Use shader model 3.0 target, to get nicer looking lighting
    25.         #pragma target 3.0
    26.  
    27.         sampler2D _MainTex;
    28.         sampler2D _posTex;
    29.         sampler2D _nTex;
    30.         uniform float _pack_normal;
    31.         uniform float _boundingMax;
    32.         uniform float _boundingMin;
    33.         uniform float _speed;
    34.         uniform int _numOfFrames;
    35.  
    36.         struct Input {
    37.             float2 uv_MainTex;
    38.         };
    39.  
    40.         half _Glossiness;
    41.         half _Metallic;
    42.         fixed4 _Color;
    43.  
    44.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    45.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    46.         // #pragma instancing_options assumeuniformscaling
    47.         UNITY_INSTANCING_CBUFFER_START(Props)
    48.             // put more per-instance properties here
    49.         UNITY_INSTANCING_CBUFFER_END
    50.  
    51.         //vertex function
    52.         void vert(inout appdata_full v){
    53.             //calcualte uv coordinates
    54.             float timeInFrames = ((ceil(frac(-_Time.y * _speed) * _numOfFrames))/_numOfFrames) + (1.0/_numOfFrames);
    55.  
    56.             //get position and normal from textures
    57.             float4 texturePos = tex2Dlod(_posTex,float4(v.texcoord1.x, (timeInFrames + v.texcoord1.y), 0, 0));
    58.             float3 textureN = tex2Dlod(_nTex,float4(v.texcoord1.x, (timeInFrames + v.texcoord1.y), 0, 0));
    59.  
    60.             //expand normalised position texture values to world space
    61.             float expand = _boundingMax - _boundingMin;
    62.             texturePos.xyz *= expand;
    63.             texturePos.xyz += _boundingMin;
    64.             texturePos.x *= -1;  //flipped to account for right-handedness of unity
    65.             v.vertex.xyz += texturePos.xzy;  //swizzle y and z because textures are exported with z-up
    66.  
    67.             //calculate normal
    68.             if (_pack_normal){
    69.                 //decode float to float2
    70.                 float alpha = texturePos.w * 1024;
    71.                 float2 f2;
    72.                 f2.x = floor(alpha / 32.0) / 31.5;
    73.                 f2.y = (alpha - (floor(alpha / 32.0)*32.0)) / 31.5;
    74.  
    75.                 //decode float2 to float3
    76.                 float3 f3;
    77.                 f2 *= 4;
    78.                 f2 -= 2;
    79.                 float f2dot = dot(f2,f2);
    80.                 f3.xy = sqrt(1 - (f2dot/4.0)) * f2;
    81.                 f3.z = 1 - (f2dot/2.0);
    82.                 f3 = clamp(f3, -1.0, 1.0);
    83.                 f3 = f3.xzy;
    84.                 f3.x *= -1;
    85.                 v.normal = f3;
    86.             } else {
    87.                 textureN = textureN.xzy;
    88.                 textureN *= 2;
    89.                 textureN -= 1;
    90.                 textureN.x *= -1;
    91.                 v.normal = textureN;
    92.             }
    93.         }
    94.  
    95.         void surf (Input IN, inout SurfaceOutputStandard o) {
    96.             // Albedo comes from a texture tinted by color
    97.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    98.             o.Albedo = c.rgb;
    99.             // Metallic and smoothness come from slider variables
    100.             o.Metallic = _Metallic;
    101.             o.Smoothness = _Glossiness;
    102.             o.Alpha = c.a;
    103.         }
    104.         ENDCG
    105.     }
    106.     FallBack "Diffuse"
    107. }
    108.  
     

    Attached Files:

    Last edited: Aug 31, 2017
  2. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    ok so some progress!

    Am able to add global transparency following these instructions
    http://answers.unity3d.com/questions/244837/shader-help-adding-transparency-to-a-shader.html


    Edit 1
    _MainTex ("Texture", 2D) = "white" {}
    Tags { "RenderType" = "Opaque" }

    to:
    _MainTex ("Color (RGB) Alpha (A)", 2D) = "white"
    Tags { "Queue"="Transparent" "RenderType"="Transparent" }


    Edit 2
    Append "alpha":
    #pragma surface surf Lambert alpha

    Edit 3
    Added this line after o.Albedo...
    o.Alpha = tex2D (_MainTex, IN.uv_MainTex).a;

    But how would I change alpha based on the alpha channel of my Main Texture(albedo map)?
     
  3. Namey5

    Namey5

    Joined:
    Jul 5, 2013
    Posts:
    188
    Those are the steps. In fact, I would recommend that you keep the alpha as "c.a" like you had in the original, so that you can also control transparency through the main colour's alpha channel if need be.
     
  4. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    This is bad "o.Alpha = tex2D (_MainTex, IN.uv_MainTex).a;" You're re-sampling a texture you've already sampled. The shader code you started with already sets the output Alpha to your sampled MainTex's alpha channel times the tint Color's alpha.

    Adjusting the tags and adding alpha to end of the surface pragma line is all you have to do.