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

Vertex Color + Shadows

Discussion in 'Shaders' started by Foam, Jul 19, 2013.

  1. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    Hello. I am currently using this shader to set the color of a procedural mesh. It works fine but I would like to take this and then apply real-time shadows to it (I have Pro) but I'm not sure how. Anyone have any suggestions?

    Can't I set the vertex info in "pass one" and then do the lighting calculations in "pass two"? Or something like that?

    Any suggestions?
     
  2. Gibbonator

    Gibbonator

    Joined:
    Jul 27, 2012
    Posts:
    204
    I don't think it's possible to get at the shadow map using a fixed function shader. Your best bet may be to port this to a surface shader.
     
    Last edited: Jul 19, 2013
  3. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    Do you know how I can access the shadow map in a surface shader?
     
  4. Gibbonator

    Gibbonator

    Joined:
    Jul 27, 2012
    Posts:
    204
    The code to sample it is added automatically in surface shaders.
     
  5. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    Oh, ok. I thought that was a surface shader but I see what you're saying now.

    Time to study up on my CG.
     
  6. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    After some research this is what I've come up with. It works pretty good so far. This allows me to pass in a vertex color (for some mock ambient occlusion as well as coloring an object without a texture), as well as use a directional light to alter the color, as well as applying real-time shadows in the last pass (hence the fallback to Diffuse).

    Code (csharp):
    1. Shader "Custom/VertexColorPlusDiffusePlusShadows" {
    2.     Properties {
    3.     _Color ("Diffuse Color", Color) = (1.0, 1.0, 1.0, 1.0)
    4.     }
    5.     SubShader {
    6.     Tags { "RenderType" = "Opaque" }
    7.     Pass {
    8.         Tags { "LightMode" = "ForwardBase" }
    9.  
    10.         CGPROGRAM
    11.         #pragma vertex vert
    12.         #pragma fragment frag
    13.         //#pragma multi_compile_fwdbase
    14.             #pragma multi_compile_fwdadd_fullshadows
    15.         //#pragma fragmentoption ARB_precision_hint_fastest
    16.  
    17.  
    18.         #include "UnityCG.cginc"
    19.         #include "Lighting.cginc"
    20.         #include "AutoLight.cginc"
    21.  
    22.         uniform float4 _Color;
    23.  
    24.         struct vertex_input {
    25.         float4 vertex : POSITION;
    26.         float4 color : COLOR;
    27.         float3 normal : NORMAL;
    28.         };
    29.  
    30.         struct vertex_output {
    31.         float4 pos : POSITION;
    32.         float4 color : COLOR;
    33.         //float4 _ShadowCoord : TEXCOORD3;
    34.         LIGHTING_COORDS(3, 4)
    35.         };
    36.  
    37.         struct fragment_output {
    38.         float4 color : COLOR;
    39.         };
    40.  
    41.         vertex_output vert(vertex_input v) {
    42.         vertex_output o;
    43.         // convert the local position to world position
    44.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    45.  
    46.         float4x4 model_matrix = _Object2World;
    47.         float4x4 model_matrix_inverse = _World2Object;
    48.         // calculate the diffuse lighting
    49.         float3 normal_dir = normalize(float3(mul(float4(v.normal, 0.0), model_matrix_inverse)));
    50.         float3 light_dir = normalize(float3(_WorldSpaceLightPos0));
    51.         float3 diffuse_reflection = float3(_LightColor0) * float3(_Color) * max(0.0, dot(normal_dir, light_dir));
    52.  
    53.         // combine the diffuse lighting from the light source
    54.                 // with the vertex color passed in by the mesh generator
    55.         /* OUT.color = (IN.color + float4(diffuse_reflection, 1.0)) * 0.5; */
    56.         o.color = lerp(v.color, float4(diffuse_reflection, 1.0), 0.5);
    57.         TRANSFER_VERTEX_TO_FRAGMENT(o);
    58.  
    59.         return o;
    60.         };
    61.  
    62.  
    63.         fragment_output frag(vertex_output IN) {
    64.         fragment_output OUT;
    65.  
    66.         float atten = LIGHT_ATTENUATION(IN);
    67.         OUT.color = IN.color * atten;
    68.  
    69.         return OUT;
    70.         };
    71.         ENDCG
    72.  
    73.     }
    74.     }
    75.  
    76.     Fallback "Diffuse"//, 2
    77. }
     
  7. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    This shader works fine for me in the Editor but when I try a stand-alone build (at least on OSX) any mesh with this shader doesn't show up at all. Anyone have any suggestions for how to fix this?

    I checked the quality settings on the build and it matches what I am using in the editor. The shader is in the Resources folder.
     
  8. VslPaul

    VslPaul

    Joined:
    Aug 18, 2013
    Posts:
    1
    This is one that works for me:

    Code (csharp):
    1. Shader "Custom/Vertex Colored Diffuse" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB)", 2D) = "white" {}
    5. }
    6.  
    7. SubShader {
    8.     Tags { "RenderType"="Opaque" }
    9.     LOD 150
    10.  
    11. CGPROGRAM
    12. #pragma surface surf Lambert vertex:vert
    13.  
    14. sampler2D _MainTex;
    15. fixed4 _Color;
    16.  
    17. struct Input {
    18.     float2 uv_MainTex;
    19.     float3 vertColor;
    20. };
    21.  
    22. void vert (inout appdata_full v, out Input o) {
    23.     UNITY_INITIALIZE_OUTPUT(Input, o);
    24.     o.vertColor = v.color;
    25. }
    26.  
    27. void surf (Input IN, inout SurfaceOutput o) {
    28.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    29.     o.Albedo = c.rgb * IN.vertColor;
    30.     o.Alpha = c.a;
    31. }
    32. ENDCG
    33. }
    34.  
    35. Fallback "Diffuse"
    36. }
     
    Shinigami92 and puzzlekings like this.
  9. kritchie

    kritchie

    Joined:
    Mar 17, 2013
    Posts:
    7
    VslPaul - Your shader works wonderfully. I was about to write the same thing, but you saved me several hours to piece it all together.

    Well done, thanks for sharing!
     
  10. deab

    deab

    Joined:
    Aug 11, 2013
    Posts:
    91
    VslPaul shader above is just what I was looking for, but would it be possible to add alpha/transparency to this? If so any pointers as to how to go about it?
     
  11. Phantomx

    Phantomx

    Joined:
    Oct 30, 2012
    Posts:
    202
    Just modify those lines:
    Code (CSharp):
    1.  Tags { "RenderType"="Opaque" }
    2. // TO:
    3. Tags { "Queue" = "Transparent" "RenderType"="Transparent" }
    4.  
    5. #pragma surface surf Lambert vertex:vert
    6. // TO:
    7. #pragma surface surf Lambert vertex:vert alpha
     
  12. deab

    deab

    Joined:
    Aug 11, 2013
    Posts:
    91
    Thanks Phantomx, worked a treat!
     
  13. junglemason

    junglemason

    Joined:
    Dec 30, 2010
    Posts:
    69
    Does anything about it need to be updated to work in Unity 4.5? It's not working for me, keeps falling back to Diffuse.