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. Dismiss Notice

Surface shader with vertex color alpha blending?

Discussion in 'General Graphics' started by TabuuForteAkugun, Aug 18, 2021.

  1. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    56
    I'm very new at shaders, so I'd appreciate some help.

    I prefer to hard-code my shaders rather than use ShaderGraph and the like, so yeah.

    I have my shader mostly working the way I want. But I have an issue with vertex colors, their alpha values, to be exact. I am coding a shader that blends the materials of two overlapping meshes, and the one at the top should have a faded material via vertex alpha to get a "blending" grass effect. Let me illustrate.



    Anything I try just results in the affected mesh being a brighter hue that ignores all my other effects such as bump mapping etc, and not a properly blended effect.

    Some world textures also support texture alpha AND vertex alpha.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Can you post your shader code? There’s not much anyone can do to help without seeing that, apart from tell you it is entirely possible to do what you’re trying to do.
     
    TabuuForteAkugun likes this.
  3. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    56
    My code is a bit of a mess, but here.

    Code (CSharp):
    1. /* SUPER SMASH BROS. FEUD - COMMON FIGHTER SHADER
    2. * Is able to transition from default materials to metal or inked materials, and back. Masking transition effect adapted from code by SMG (ScandinavianMountainGoat), co-creator of open-source
    3. * SSB Ultimate render library CrossMod. Written 2018-2019 by Ploaj and SMG, implemented in Unity surface shader Cg/HLSL format by Tabuu Forte Akugun. It supports composite PRM maps
    4. *(Metallic/Roughness/Ambient Occlusion/Specularity) and composite NOR maps complete with generated Z+, noise maps and cavity textures.
    5. */
    6.  
    7. Shader "Super Smash Bros. Feud/Pseudo-HBSS Shader (For Stage Materials)"
    8. {
    9.     Properties
    10.     {
    11.         [Toggle(USE_VERT_RGB)] _UseVertRGB("Use Vertex Colors?", Float) = 0
    12.         [Toggle(USE_VERT_ALPHA)]_VertAlpha("Use vertex color alpha?", Float) = 0
    13.         _Color("Main Color", Color) = (1.0,1.0,1.0,1.0)
    14.         _RimLightColor("Rim light color", Color) = (0.6,0.6,0.6,1.0)
    15.         _MainTex("Base Color Map (RGB+A)", 2D) = "white" {}
    16.         [Toggle(USE_TEX_ALPHA)]_TexAlpha("Use *.col  alpha?", Float) = 0
    17.         [NoScaleOffset]_NormalMap("Normal Map (*_nor)", 2D) = "bump" {}
    18.         [Toggle(USE_PRM_MAP)]_UsePrm("Use a PRM Map?", Float) = 0
    19.         [NoScaleOffset]_PRMMap("PBR (PRM) Combined Map (*_prm)", 2D) = "white" {}
    20.         [Toggle(SKIN_MAT)]_SkinMat("Skin Map with SSS?", Float) = 0
    21.         _CustomVector30("Subsurface effect intensity", Vector) = (0,0,0,0)
    22.         _CustomVector11("Subsurface Scattering color for skin", Color) = (1,1,1,1)
    23.         [HideInInspector]_DefaultVertClr("", Color) = (0.5,0.5,0.5,1)
    24.  
    25.         [Toggle(USE_EMISSIVE)]_EmissionMap("Check if using Emissive Texture.", Float) = 0
    26.         [NoScaleOffset]_EmiMap("Emissive Texture (*_emi)", 2D) = "black" {}
    27.         _FlashColor("Flash Color", Color) = (0,0,0,1)
    28.         _Cutoff("Alpha Cutoff", Range(0.01,1)) = 0.5
    29.     }
    30.  
    31.     CGINCLUDE
    32.         #define UNITY_SETUP_BRDF_INPUT RoughnessSetup
    33.     ENDCG
    34.  
    35.     SubShader
    36.     {
    37.         Tags { "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" "IgnoreProjector" = "True"}
    38.         LOD 200
    39.  
    40.         Pass
    41.         {
    42.             ColorMask 0
    43.             Lighting Off
    44.             ZWrite On
    45.  
    46.             CGPROGRAM
    47.             #pragma vertex vert
    48.             #pragma fragment frag
    49.             #include "UnityCG.cginc"
    50.  
    51.             struct v2f
    52.             {
    53.                 float4 vertex : SV_POSITION;
    54.                 float2 texcoord : TEXCOORD0;
    55.             };
    56.  
    57.             sampler2D _MainTex;
    58.             fixed _Cutoff;
    59.  
    60.             v2f vert(appdata_img v)
    61.             {
    62.                 v2f o;
    63.                 o.vertex = UnityObjectToClipPos(v.vertex);
    64.                 o.texcoord = v.texcoord;
    65.                 return o;
    66.             }
    67.  
    68.             fixed4 frag(v2f i) : SV_Target
    69.             {
    70.                 fixed4 col = tex2D(_MainTex, i.texcoord);
    71.                 clip(col.a - _Cutoff);
    72.                 return 0;
    73.             }
    74.             ENDCG
    75.         }
    76.  
    77.         Pass
    78.         {
    79.             Tags {"LightMode" = "ShadowCaster"}
    80.             ColorMask 0
    81.             ZWrite On
    82.             Cull Off
    83.  
    84.             CGPROGRAM
    85.             #pragma vertex vert
    86.             #pragma fragment frag
    87.             #pragma multi_compile_shadowcaster
    88.             #include "UnityCG.cginc"
    89.  
    90.             struct v2f
    91.             {
    92.                 V2F_SHADOW_CASTER;
    93.                 float2 texcoord : TEXCOORD1;
    94.             };
    95.  
    96.             v2f vert(appdata_base v)
    97.             {
    98.                 #if defined(PIXELSNAP_ON)
    99.                     v.vertex = UnityPixelSnap(v.vertex);
    100.                 #endif
    101.  
    102.                 v2f o;
    103.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    104.                 o.texcoord = v.texcoord;
    105.                 return o;
    106.             }
    107.  
    108.             sampler2D _MainTex;
    109.             fixed _Cutoff;
    110.  
    111.             float4 frag(v2f i) : SV_Target
    112.             {
    113.                 fixed4 col = tex2D(_MainTex, i.texcoord);
    114.                 clip(col.a - _Cutoff);
    115.                 SHADOW_CASTER_FRAGMENT(i)
    116.             }
    117.             ENDCG
    118.         }
    119.  
    120.         ColorMask 0
    121.         LOD 300
    122.         ZWrite On
    123.         // paste in forward rendering passes from Transparent/Diffuse
    124.         UsePass "Transparent/Diffuse/FORWARD"
    125.  
    126.         CGPROGRAM
    127.         #include "UnityCG.cginc"
    128.         #include "UnityPBSLighting.cginc"
    129.         #pragma surface surf Standard vertex:vert fullforwardshadows decal:blend exclude_path:prepass
    130.         #pragma multi_compile _ PIXELSNAP_ON
    131.         #pragma shader_feature SKIN_MAT
    132.         #pragma shader_feature USE_VERT_RGB
    133.         #pragma shader_feature USE_TEX_ALPHA
    134.         #pragma shader_feature USE_PRM_MAP
    135.         #pragma shader_feature USE_CAV_MAP
    136.         #pragma shader_feature USE_EMISSIVE
    137.         #pragma shader_feature USE_VERT_ALPHA
    138.         #pragma target 3.0
    139.  
    140.         sampler2D _MainTex;
    141.         sampler2D _InkTex;
    142.         sampler2D _NormalMap;
    143.         sampler2D _PRMMap;
    144.         sampler2D _SplatMap;
    145.         sampler2D _EmiMap;
    146.         sampler2D _InkBump;
    147.         sampler2D _MetalMap;
    148.         float4 _InkColor;
    149.         float4 _Color;
    150.         float4 _RimLightColor;
    151.         fixed _Cutoff;
    152.  
    153.         struct Input
    154.         {
    155.             float2 uv_MainTex;
    156.             float3 worldRefl;
    157.             float3 viewDir;
    158.             float3 worldPos;
    159.             float4 vertexColor : COLOR;
    160.             INTERNAL_DATA
    161.         };
    162.  
    163.         fixed4 _CustomVector11;
    164.         fixed4 _FlashColor;
    165.         fixed4 _DefaultVertClr;
    166.         float4 _CustomVector30;
    167.  
    168.         // Generate the Z+ direction, or blue channel, of supplied normal map.
    169.         float GetNormalMapZ(float2 normalmap)
    170.         {
    171.             // Remap the 0 to 1 range of the normal map to -1 to 1.
    172.             float r = 2 * normalmap.r - 1.0;
    173.             float g = 2 * normalmap.g - 1.0;
    174.             // x*x + y*y + z*z = 1.0
    175.             float b = sqrt(1 - (r * r) + (g * g));
    176.             // Map back to 0 to 1 range to get the equivalent texture color.
    177.             return b * 0.5 + 0.5;
    178.         }
    179.  
    180.         void vert(inout appdata_full v, out Input o) {
    181.             UNITY_INITIALIZE_OUTPUT(Input, o);
    182.             o.vertexColor = v.color;
    183.         }
    184.  
    185.         void surf(Input IN, inout SurfaceOutputStandard o)
    186.         {
    187.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex);                                // Albedo comes from a texture tinted by color
    188.             fixed4 nor = tex2D(_NormalMap, IN.uv_MainTex);                            // Use the normal map as is for now.
    189.             float blend = nor.b;                                                    // Set current nor.b as blend map.
    190.             float cav = nor.a;                                                        // Set current nor.a as cavity map.
    191.             nor.b = GetNormalMapZ(nor.rg);                                            // Generate the .b, or Z+ channel, of the normal map.
    192.             nor.a = 1;                                                                // Cancel out Alpha on nor.
    193.             fixed4 prm = tex2D(_PRMMap, IN.uv_MainTex);                                // Init PRM map.
    194.             fixed3 vertRGB = IN.vertexColor.rgb;                                    // Get vertex colors.
    195.             float sssBlend = _CustomVector30.x * prm.r;                                // Shading and color.                  
    196.             fixed4 emi = tex2D(_EmiMap, IN.uv_MainTex);                                // Emissive maps.
    197.             float3 albedoFinal;                                                        // Pre-final Albedo.
    198.             half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));        // Setup rimlights.
    199.             float texAlpha;
    200.             float vertAlpha;
    201.  
    202.             #if USE_TEX_ALPHA
    203.                 texAlpha = saturate(c.a * _Cutoff);
    204.             #else
    205.                 texAlpha = 1;
    206.             #endif
    207.  
    208.             #if USE_VERT_ALPHA
    209.                 vertAlpha = IN.vertexColor.a;
    210.             #else
    211.                 vertAlpha = 1;
    212.             #endif
    213.  
    214.             o.Normal = UnpackNormal(nor);                                          
    215.             float3 worldRefl = WorldReflectionVector(IN, o.Normal);
    216.             rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));      
    217.             #ifdef USE_PRM_MAP
    218.                 #ifdef SKIN_MAT
    219.                     albedoFinal = lerp((c.rgb * _Color), (c.rgb * _Color  * _CustomVector11), sssBlend);
    220.                     o.Metallic = 0;
    221.                     o.Smoothness = 0;
    222.                 #else
    223.                     albedoFinal = c.rgb * _Color;
    224.                     o.Metallic = prm.r * c.rgb;
    225.                     o.Smoothness = 1 - prm.g;
    226.                 #endif
    227.                 o.Occlusion = prm.b;
    228.             #else
    229.                 albedoFinal = c.rgb * _Color;
    230.                 o.Metallic = 0;
    231.                 o.Smoothness = 0;
    232.             #endif
    233.             #ifdef USE_VERT_RGB
    234.                 o.Albedo = albedoFinal * IN.vertexColor.rgb;
    235.             #else
    236.                 o.Albedo = albedoFinal * _DefaultVertClr;
    237.             #endif      
    238.             #ifdef USE_EMISSIVE
    239.                 o.Emission = _FlashColor.rgb + emi.rgb + (_RimLightColor * pow(rim, 3));
    240.             #else
    241.                 o.Emission = _FlashColor.rgb + (_RimLightColor * pow(rim, 3));
    242.             #endif
    243.  
    244.             o.Alpha = texAlpha * vertAlpha;
    245.  
    246.         }
    247.         ENDCG
    248.     }
    249.     Fallback "VertexLit"
    250. }
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    What's this for? That's going to mean it's rendering the main texture twice, and without any consideration of the vertex alpha.
     
  5. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    56
    I don't know, I got some of this code from a shader that allowed alphas AND no z-fighting.

    So if I remove that?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Try it?

    Also I'm not sure Z-fighting is the term you're looking for. Z-fighting is when two surfaces are on the same plane, but not using the same vertices or math to calculate the screen space position, and causing the math to not perfectly match and you see a kind of striped noise where one surface or the other swaps back and forth.


    That's Z-fighting. You're probably thinking of depth sorting, which is where surfaces that are behind another appear "on top" when they shouldn't, which is a still unsolved problem for transparent surfaces. That first
    ColorMask 0
    pass should be a good enough workaround for that though.
     
  7. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    56
    It's okay, thanks! Removing the Forward pass thing worked. Now my alphas (texture and vertex) work flawlessly. And sorting is fine too. And I also got my shader to support Cutout and receiving shadows.

    Thanks for the help!