Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Combining vertex and surface shaders

Discussion in 'Shaders' started by SpiderPork, Aug 16, 2011.

  1. SpiderPork

    SpiderPork

    Joined:
    Jan 29, 2011
    Posts:
    27
    Hey there!
    So, I've got these two shaders; one of them is a surface shader and the other one is a vertex shader. Now I need to combine the two of these and my question is how?

    This is the surface shader (actually just Transparent/Cutout/Bumped Specular) ...
    Code (csharp):
    1. Shader "Transparent/Cutout/Bumped Specular"
    2. {
    3.         Properties
    4.         {
    5.             _Color ("Main Color", Color) = (1,1,1,1)
    6.             _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    7.             _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    8.             _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    9.             _BumpMap ("Normalmap", 2D) = "bump" {}
    10.             _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    11.         }
    12.  
    13.         SubShader
    14.         {
    15.             Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    16.             LOD 400
    17.  
    18.                 CGPROGRAM
    19.                 #pragma surface surf BlinnPhong alphatest:_Cutoff
    20.  
    21.                 sampler2D _MainTex;
    22.                 sampler2D _BumpMap;
    23.                 fixed4 _Color;
    24.                 half _Shininess;
    25.  
    26.                 struct Input
    27.                 {
    28.                     float2 uv_MainTex;
    29.                     float2 uv_BumpMap;
    30.                 };
    31.  
    32.                 void surf (Input IN, inout SurfaceOutput o)
    33.                 {
    34.                     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    35.                     o.Albedo = tex.rgb * _Color.rgb;
    36.                     o.Gloss = tex.a;
    37.                     o.Alpha = tex.a * _Color.a;
    38.                     o.Specular = _Shininess;
    39.                     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    40.                 }
    41.                 ENDCG
    42.         }
    43.         FallBack "Transparent/Cutout/VertexLit"
    44. }
    45.  
    ... and this is the vertex shader:
    Code (csharp):
    1. Shader "TestShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,0.5)
    6.         _MainTex ("Base (RGB)", 2D) = "grass" {}
    7.         _LightPower ("Light Power", Float) = 0.0
    8.     }
    9.     SubShader
    10.     {
    11.         Pass
    12.         {
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.             #pragma fragmentoption ARB_fog_exp2
    17.             #include "UnityCG.cginc"
    18.  
    19.             float4 _Color;
    20.             sampler2D _MainTex;
    21.             float _LightPower;
    22.  
    23.             struct v2f
    24.             {
    25.                 float4 pos : SV_POSITION;
    26.                 float2 uv : TEXCOORD0;
    27.                 float3 color : COLOR0;
    28.             };
    29.  
    30.             struct indata
    31.             {
    32.                 float4 vertex;
    33.                 float3 normal;
    34.                 float4 texcoord;
    35.                 float4 color;
    36.             };
    37.  
    38.             v2f vert(indata v)
    39.             {
    40.                 v2f o;
    41.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    42.                 o.uv = TRANSFORM_UV(0);
    43.                 o.color = v.color;
    44.                 return o;
    45.             }
    46.  
    47.             half4 frag(v2f i) : COLOR
    48.             {
    49.                 return half4(i.color*tex2D(_MainTex, i.uv).rgb, 1);//*i.lighting;
    50.             }
    51.             ENDCG
    52.         }
    53.     }
    54. }
    Thanks a lot in advance.
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    you can define the vertex shader used in a surface shader through the #pragma vert yourvertexshaderfunctionname

    just to mention: frag is actually a pixel shader, not vertex, so if you have really these two shaders you can't merge it, you would need to use multiple passes isntead
     
  3. SpiderPork

    SpiderPork

    Joined:
    Jan 29, 2011
    Posts:
    27
    Thanks for the quick response.
    Actually, all I need for the surface shader is to take mesh colours in effect. How can I do that?
     
  4. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
  5. SpiderPork

    SpiderPork

    Joined:
    Jan 29, 2011
    Posts:
    27
    Haha, it works perfectly, thank you! :)
     
  6. Woulfe

    Woulfe

    Joined:
    Nov 14, 2011
    Posts:
    1
    Is there any chance you could post the final working shader code? im still a bit confused on what to do.
     
  7. dot_entity

    dot_entity

    Joined:
    Nov 2, 2012
    Posts:
    86
    Although it's kind of late for Woulfe to still benefit from this, I hate it, when I find hanging questions, especially if they match my inquiry criteria, in the forums and this thread was one of the first results returned for combining shaders, so I decided to deliver my test shader considering the above information. Btw, I'm able to understand only the really very basic stuff about shaders and I probably have mistakes or redundant code in the result shader, so feel free to correct me. It is always better, of course to learn things properly and then combining shaders and so on would be an easy task, but sometimes the quick solution method has its advantages. Ok, here's the code:
    The surface shader (a shader imitating a glowing effect):
    Code (CSharp):
    1. Shader "Custom/glow" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.     }
    5.     SubShader {
    6.         Tags { "Queue"="Transparent" }
    7.         LOD 200
    8.         ZTest Always
    9.         Cull Back
    10.         Blend One One
    11.         CGPROGRAM
    12.         #pragma surface surf Lambert
    13.          float4 _Color;
    14.         struct Input {
    15.             float3 viewDir;
    16.             float3 worldNormal;
    17.         };
    18.         void surf (Input IN, inout SurfaceOutput o) {
    19.             o.Alpha = _Color.a * pow(abs(dot(normalize(IN.viewDir),
    20.                 normalize(IN.worldNormal))),4.0);
    21.             o.Emission = _Color.rgb * o.Alpha;
    22.         }
    23.         ENDCG
    24.     }
    25.     FallBack "Diffuse"
    26. }
    The Vertex shader (taken from unity shader examples):
    Code (CSharp):
    1. Shader "Example/Custom Vertex Data" {
    2.     Properties {
    3.       _MainTex ("Texture", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.       Tags { "RenderType" = "Opaque" }
    7.       CGPROGRAM
    8.       #pragma surface surf Lambert vertex:vert
    9.       struct Input {
    10.           float2 uv_MainTex;
    11.           float3 customColor;
    12.       };
    13.       void vert (inout appdata_full v, out Input o) {
    14.           UNITY_INITIALIZE_OUTPUT(Input,o);
    15.           o.customColor = abs(v.normal);
    16.       }
    17.       sampler2D _MainTex;
    18.       void surf (Input IN, inout SurfaceOutput o) {
    19.           o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
    20.           o.Albedo *= IN.customColor;
    21.       }
    22.       ENDCG
    23.     }
    24.     Fallback "Diffuse"
    25.   }
    and their combination:
    Code (CSharp):
    1.   Shader "Example/Custom Vertex Data" {
    2.     Properties {
    3.       _Color ("Color", Color) = (1,1,1,1)
    4. //      _MainTex ("Texture", 2D) = "white" {}
    5.     }
    6.          
    7.     SubShader {
    8.       Tags { "RenderType" = "Transparent" }
    9.         LOD 200
    10.         ZTest Always
    11.         Cull Back
    12.         Blend One One
    13.      
    14.       CGPROGRAM
    15.       #pragma surface surf Lambert vertex:vert
    16.         float4 _Color;
    17.    
    18.         struct Input {
    19.           float2 uv_MainTex;
    20.           float3 customColor;
    21.           float3 viewDir;
    22.           float3 worldNormal;
    23.         };
    24.         void vert (inout appdata_full v, out Input o) {
    25.           UNITY_INITIALIZE_OUTPUT(Input,o);
    26.           o.customColor = v.color;
    27.         }
    28.         sampler2D _MainTex;
    29.         void surf (Input IN, inout SurfaceOutput o) {
    30.           o.Alpha = _Color.a * pow(abs(dot(normalize(IN.viewDir),
    31.           normalize(IN.worldNormal))),4.0);
    32.           o.Emission = _Color.rgb * o.Alpha * IN.customColor;
    33.         }
    34.      
    35.       ENDCG
    36.     }
    37.     Fallback "Diffuse"
    38.   }
    I have not included the texture, because I was not needing it at that time.
     
    StaffanEk and LilaQ like this.
  8. LilaQ

    LilaQ

    Joined:
    Feb 15, 2013
    Posts:
    1
    I had to login, just to thank you for this concept. Boggled my mind how to combine to shaders all the time. I will try to use this to make my Distortion Shader and my Wave Shader to a combined one, making my water look way better :)

    Thanks!
     
  9. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    entity476> Please correct me if wrong but aren't you in fact combining 2 surface shaders?
     
  10. dot_entity

    dot_entity

    Joined:
    Nov 2, 2012
    Posts:
    86
    Haha! Please You can correct me, but this has been a very polite way to tell me I was writing gibberish! Although I see the post 6 years later (I believe I was not getting email notifications for my watched threads) and haven't been much involved with Unity during this time, I need to say that I was (and still am) so naive but impulsed to post something which, although functional, I was not even comprehending!...
     
    Last edited: Oct 26, 2023