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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Modifying Vertex/Fragment Shader so it works with Lighting & Lightmapping

Discussion in 'Shaders' started by eco_bach, Dec 20, 2015.

  1. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    I have a custom shader for creating 2 sided textures. But I need the Materials using this shader to also react to lighting, ie be part of the PBR pipeline.

    Here is my custom shader with support for 2 textures but no lighting. Can any Shader gurus help? Note that I am using the VFACE semantic in my pixel shader to determine which side is facing the camera.
    Code (csharp):
    1.  
    2. Shader "Custom/TwoSided" {
    3. Properties {
    4. _FirstTex ("First(RGB)", 2D) = "white" {}
    5. _SecondTex ("Second(RGB)", 2D) = "white"{}
    6. }
    7.  
    8. SubShader {
    9.  
    10. Pass {
    11. Cull Off
    12. CGPROGRAM
    13. #pragma vertex vert
    14. #pragma fragment frag
    15. #include "UnityCG.cginc"
    16.  
    17.  
    18. sampler2D _FirstTex;
    19. sampler2D _SecondTex;
    20.  
    21. struct v2f {
    22. float4 pos : SV_POSITION;
    23. fixed4 color : COLOR;
    24. float4 tex : TEXCOORD0;
    25. };
    26.  
    27. v2f vert (appdata_base v)
    28. {
    29. v2f o;
    30.  
    31. o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    32.  
    33. float3 viewVector = normalize(_WorldSpaceCameraPos);
    34.  
    35.  
    36. //Converting the normal to world space as we have viewvector in world space. We need to transfer both to same space for any operations.
    37. float3 worldSpaceNormal = normalize(mul((float3x3)_World2Object,v.normal));
    38. float NdotL = dot(viewVector,v.normal);
    39.    
    40.  
    41.   o.color.w = NdotL;
    42.  
    43.  
    44. o.tex = v.texcoord;
    45.  
    46. return o;
    47. }
    48.  
    49. fixed4 frag (v2f i, fixed facing : VFACE) : COLOR0 {
    50.  
    51. if(facing > 0.0f)
    52. {
    53. i.color.xyz = tex2D(_FirstTex, float2(i.tex.xy)).xyz;
    54. }
    55. else
    56. {
    57. i.color.xyz = tex2D(_SecondTex, float2(i.tex.xy)).xyz;
    58. }
    59.  
    60. return i.color;
    61. }
    62. ENDCG
    63. }
    64. }
    65. }
    66.  
     
    Last edited: Dec 21, 2015
  2. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    Start with a surface shader and add the vertex function you want to it. There are examples of vertex programs with surface shaders in the manual.

    CGPROGRAM
    #pragma surface surf Lambert vertex:vert


    You do not need to create a million threads for every problem you have with your one shader.
     
  3. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    Thanks. Am I correct in assuming that any Surface Shader can be re written as a vertex-fragment shader? The only advantage being that Surface Shaders require less code?

    The following vertex fragment shader DOES work for lighting but just for ONE texture.
    But I can't seem to get a 2nd texture working using the same logic as in my shader above using the VFACE semantic .

    Code (csharp):
    1.  
    2. Shader "custom/one sided plus lighting"{
    3.    Properties {
    4.      _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
    5.      _MainTex ("Diffuse Texture", 2D) = "white" {}
    6.      _SpecColor ("Specular Color", Color) = (1.0,1.0,1.0,1.0)
    7.      _Shininess ("Shininess", Float) = 10
    8.    }
    9.    SubShader {
    10.      Pass {
    11.        Tags {"LightMode" = "ForwardBase"}
    12.        CGPROGRAM
    13.        #pragma vertex vert
    14.        #pragma fragment frag
    15.    
    16.        //user defined variables
    17.        uniform sampler2D _MainTex;
    18.        uniform float4 _MainTex_ST;
    19.        uniform float4 _Color;
    20.        uniform float4 _SpecColor;
    21.        uniform float _Shininess;
    22.    
    23.        //unity defined variables
    24.        uniform float4 _LightColor0;
    25.    
    26.        //base input structs
    27.        struct vertexInput{
    28.          float4 vertex : POSITION;
    29.          float3 normal : NORMAL;
    30.          float4 texcoord : TEXCOORD0;
    31.        };
    32.        struct vertexOutput{
    33.          float4 pos : SV_POSITION;
    34.          float4 tex : TEXCOORD0;
    35.          float4 posWorld : TEXCOORD1;
    36.          float3 normalDir : TEXCOORD2;
    37.        };
    38.    
    39.        //vertex Function
    40.    
    41.        vertexOutput vert(vertexInput v){
    42.          vertexOutput o;
    43.      
    44.          o.posWorld = mul(_Object2World, v.vertex);
    45.          o.normalDir = normalize( mul( float4( v.normal, 0.0 ), _World2Object ).xyz );
    46.          o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    47.          o.tex = v.texcoord;
    48.      
    49.          return o;
    50.        }
    51.    
    52.        //fragment function
    53.    
    54.        float4 frag(vertexOutput i) : COLOR
    55.        {
    56.          float3 normalDirection = i.normalDir;
    57.          float3 viewDirection = normalize( _WorldSpaceCameraPos.xyz - i.posWorld.xyz );
    58.          float3 lightDirection;
    59.          float atten;
    60.      
    61.          if(_WorldSpaceLightPos0.w == 0.0){ //directional light
    62.            atten = 1.0;
    63.            lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    64.          }
    65.          else{
    66.            float3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - i.posWorld.xyz;
    67.            float distance = length(fragmentToLightSource);
    68.            atten = 1.0/distance;
    69.            lightDirection = normalize(fragmentToLightSource);
    70.          }
    71.      
    72.          //Lighting
    73.          float3 diffuseReflection = atten * _LightColor0.xyz * saturate(dot(normalDirection, lightDirection));
    74.          float3 specularReflection = diffuseReflection * _SpecColor.xyz * pow(saturate(dot(reflect(-lightDirection, normalDirection), viewDirection)) , _Shininess);
    75.            
    76.          float3 lightFinal = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseReflection + specularReflection;// + rimLighting;
    77.      
    78.          //Texture Maps
    79.          float4 tex = tex2D(_MainTex, i.tex.xy * _MainTex_ST.xy + _MainTex_ST.zw);
    80.      
    81.          return float4(tex.xyz * lightFinal * _Color.xyz, 1.0);
    82.        }
    83.    
    84.        ENDCG
    85.    
    86.      }
    87.  
    88.  
    89.    }
    90.    //Fallback "Specular"
    91. }
    92.  
    93.  
     
    Last edited: Dec 22, 2015
  4. aaronfjerstad

    aaronfjerstad

    Joined:
    Oct 26, 2017
    Posts:
    2
    You are correct in that assumption. Create a pbr shader and click "show generated code", and you will see it.