Search Unity

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.