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

Simple shader / Diffuse with separate mask texture

Discussion in 'Shaders' started by 3DJayC, Apr 24, 2015.

  1. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    Hello !

    I'm trying to achieve a simple material, a classic diffuse texture combine with another texture mask.

    I tried some shaders that I found on forums but it doesn't work correctly.
    Sometime there no shadows or sometime there is no mask...

    I need the mask to be a separate texture in order to manage differents UVs...

    Finally, I need this shader to be affected by lights but not in the masked part.

    Could you help me please?

    Many thanks

    JC
     
  2. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Try this:
    Code (CSharp):
    1. Shader "Custom/MaskedDiffuse" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _MaskTex ("Lighting Mask (RGB)", 2D) = "black" {}
    6.     }
    7.     SubShader {
    8.         Tags { "RenderType"="Opaque" }
    9.         LOD 200
    10.      
    11.         CGPROGRAM
    12.      
    13.         #pragma surface surf DiffuseMask fullforwardshadows
    14.  
    15.         #pragma target 3.0
    16.  
    17.         sampler2D _MainTex;
    18.         sampler2D _MaskTex;
    19.  
    20.         struct Input {
    21.             float2 uv_MainTex;
    22.             float2 uv_MaskTex;
    23.         };
    24.  
    25.         struct SurfaceOutputMask
    26.         {
    27.             fixed3 Albedo;
    28.             fixed3 Normal;
    29.             fixed3 Emission;
    30.             half Specular;
    31.             fixed Gloss;
    32.             fixed Alpha;
    33.             fixed Mask;
    34.  
    35.         };
    36.  
    37.         half4 LightingDiffuseMask (SurfaceOutputMask s, half3 lightDir,  half3 viewDir, half atten) {
    38.             half NdotL = saturate(dot (s.Normal, lightDir));
    39.             half4 c;
    40.             c.rgb = lerp(s.Albedo * _LightColor0.rgb * (NdotL * atten * 2),s.Albedo,s.Mask);
    41.             //c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
    42.             c.a = s.Alpha;
    43.             return c;
    44.         }      
    45.  
    46.         fixed4 _Color;
    47.  
    48.         void surf (Input IN, inout SurfaceOutputMask o) {
    49.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    50.             fixed m = tex2D(_MaskTex,IN.uv_MaskTex).g;
    51.             o.Albedo = c.rgb;
    52.             o.Mask = m;
    53.             o.Alpha = c.a;
    54.         }
    55.         ENDCG
    56.     }
    57.     FallBack "Diffuse"
    58. }
    59.  
    White on the mask gets no lighting, and black gets lighting. that can be reversed if needed,
     
  3. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33


    Hi Echo4papa!

    Thanks for your reply but I don't understand the result... o_O

    In fact, my mesh need a ground texture ( the diffuse), this same mesh's got some holes but I need to attenuate the border like the image below via another texture mask.


     
  4. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Hmmmmm, interesting.
     
  5. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Maybe I didn't understand how you were going to use it. Here are my results:

    Lightingmask.PNG

    You can see that the mask uses the white part to ignore the lighting calculation Here's the mask and UV grid:
    happymask.png UVGrid.png
     
  6. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    Indeed,

    I try to get a standard diffuse material with another slot for texture mask map (In order to tweak the tiling independently)

    I found some shader but they are Unlit.
     
  7. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    In fact I just need a diffuse material with a primary diffuse map and an opacity map in a second texture slot with different UVs
     
  8. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Oh, that's a bit different. Here:

    Code (CSharp):
    1. Shader "Custom/DiffuseAlpha" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _OpacityTex("Opacity (A)", 2D) = "white" {}
    6.     }
    7.     SubShader {
    8.         Tags { "RenderType"="Transparent" "Queue"="Transparent" }
    9.         LOD 200
    10.  
    11.         Blend SrcAlpha OneMinusSrcAlpha
    12.  
    13.         CGPROGRAM
    14.         #pragma surface surf Lambert fullforwardshadows alpha
    15.  
    16.         #pragma target 3.0
    17.  
    18.         sampler2D _MainTex;
    19.         sampler2D _OpacityTex;
    20.  
    21.         struct Input {
    22.             float2 uv_MainTex;
    23.             float2 uv_OpacityTex;
    24.         };
    25.  
    26.         fixed4 _Color;
    27.  
    28.         void surf (Input IN, inout SurfaceOutput o) {
    29.  
    30.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    31.             o.Albedo = c.rgb;
    32.  
    33.             half opacity = tex2D(_OpacityTex, IN.uv_OpacityTex).a;
    34.             o.Alpha = opacity;
    35.         }
    36.         ENDCG
    37.     }
    38.     FallBack "Diffuse"
    39. }
    40.  
     
    deepportion likes this.
  9. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33


    Hi!

    That works, but I get no shadows

    :(
     
  10. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Oops, here:

    Code (CSharp):
    1. Shader "Custom/DiffuseAlpha" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _OpacityTex("Opacity (A)", 2D) = "white" {}
    6.     }
    7.     SubShader {
    8.         Tags { "RenderType"="Transparent" "Queue"="Transparent" }
    9.         LOD 200
    10.         Blend SrcAlpha OneMinusSrcAlpha
    11.         CGPROGRAM
    12.         #pragma surface surf Lambert fullforwardshadows addshadow alpha
    13.         #pragma target 3.0
    14.         sampler2D _MainTex;
    15.         sampler2D _OpacityTex;
    16.         struct Input {
    17.             float2 uv_MainTex;
    18.             float2 uv_OpacityTex;
    19.         };
    20.         fixed4 _Color;
    21.         void surf (Input IN, inout SurfaceOutput o) {
    22.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    23.             o.Albedo = c.rgb;
    24.             half opacity = tex2D(_OpacityTex, IN.uv_OpacityTex).a;
    25.             o.Alpha = opacity;
    26.         }
    27.         ENDCG
    28.     }
    29.     FallBack "Diffuse"
    30. }
     
  11. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    I appreciate your help but the cubes don't cast shadows on the grass
     
  12. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    May be the result is impossible?
     
  13. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Perhaps the direction of the light doesn't make the shadows actually fall on GRASS?
     
  14. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    ...really? Don't worry, the lighting direction should cast shadow on the grass ;)
     
  15. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Have you checked that the plane below is set as a shadow receiver? And has a shader that would actually receive shadows? (I'm thinking that if the ground plane is some type of unlit shader it would not receive shadows ofc. And even if it is, do transparent objects receive shadows with unity 5?)

    Also, now that I look at the image again I guess the cubes are NOT high over the ground, but the lower one actually clipping the ground >.<.

    The reason shadows are a must have. Or at the very least a SSAO effect...
     
  16. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    May be I forgot to mention that I'm working with unity 4.6
    But I don't think it's about editor version.

    May be the shader is not correct to receive shadow?
    I know that I must take time to study writing shaders...

    Do you have any idea about this shader and why it doesn't work?

    JC
     
  17. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Try using a standard diffuse shader, (for the grass plane), and make sure the mesh renderer is set to receive shadows.
     
  18. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    Everything is checked and correct
     
  19. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Umm just realized something, is it the plane or the cube(s) that have this shader on them? (I was up until now assuming that you had the custom shader on the cubes, not the plane, stupid me)
     
  20. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    Lol, the shader is on the plane with grass texture, the cubes were there only to show shadow casting :p
    They cast shadows on themselves but not on the grass... :(
     
  21. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Ok, I'm getting there :D!
    Tho most likely your materials will case shadows were they are semitransparent, but I think that tradeoff is reasonable?
    I recieve shadows, but not sure if my shadows I cast are properly cutout or not
     
  22. 3DJayC

    3DJayC

    Joined:
    Jul 29, 2014
    Posts:
    33
    You get shadows with the same shader?
     
  23. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    I receive shadows yes, but currently not casting them >.<
    (I do both cast and receive if I'm using cutout ofc)
     
  24. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Ok I got it working!
    (And have had it working for a while),
    BUT there are a couple of bugs I don't seem able to get rid of. BugNotAsObvious.PNG

    First image is with clear: Color (black in this case). Works great!

    Skybox bug.png
    However if I clear with skybox I run into problems due to the skybox being rendered after opaque objects to get a nice performance boost.

    CastingAndRecieving.png
    Now here you see the material, you also notice that the red creeps into the blend of the ghost, even tho there is a shadow below! (Where he blends against). Correct blending for that is below. WithoutRecievingShadows.PNG

    Due to max attachments continuing in next post! (With why/how this happens!)
     
  25. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Here is the collected shadowmap, and then 2 images showing what goes wrong!
    View attachment 136748

    At this image everything BUT objects with your shader have been drawn. (And ofc all other semi-transparent stuff is also missing!)
    BeforeRendered.jpg

    As you can see where our transparent object WILL BE, there are no shadows...
    AfterRendered.jpg

    And the end result once again!

    To make this problem less visible:
    Use "harsher" alpha edges and not much semi-transparent areas, as those will NOT work properly without a much more complex solution.

    A "real" cutout shader would ofc not have this problem.

    I'll give the code in a min, had forgotten you needed different tilings, so gonna go and modify the shader for that :)
     
  26. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    The code I ended up with, same errors.
    The main "trick" I used to get this work EASILY was that I use the _MainTex as your opacity texture, as that's the texture used for cutout shadows...
    Then I use the new texture as the color one, reorder them so it's the order your used to.

    HOWEVER for a game where you use this more then on small stuff, I would suggest only having 1 texture but 2 set's of tiling coordinates. Don't think it'd be reasonable to assume using surface shaders however.

    Code (CSharp):
    1. Shader "Custom/DiffuseAlpha" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _ColorTex("Albedo (RGB)", 2D) = "white" {}
    5.         _MainTex("Opacity (A)", 2D) = "white" {}
    6.         _Cutoff ("Alpha cutoff (For shadows?!)", Range(0,1)) = 0.5
    7.     }
    8.     SubShader {
    9.         Tags { "Queue"="AlphaTest+50" "IgnoreProjector"="True" "RenderType"="TransparentCutout" }
    10.         LOD 200
    11.         Blend SrcAlpha OneMinusSrcAlpha
    12.        
    13.         CGPROGRAM
    14.         #pragma surface surf Lambert fullforwardshadows keepalpha
    15.         #pragma target 3.0
    16.        
    17.         sampler2D _ColorTex;
    18.         sampler2D _MainTex;
    19.        
    20.         struct Input {
    21.             float2 uv_MainTex;
    22.             float2 uv_ColorTex;
    23.         };
    24.        
    25.         fixed4 _Color;
    26.        
    27.         void surf (Input IN, inout SurfaceOutput o) {
    28.             fixed4 c = tex2D (_ColorTex, IN.uv_ColorTex) * _Color;
    29.             o.Albedo = c.rgb;
    30.             half opacity = tex2D(_MainTex, IN.uv_MainTex).a;
    31.             o.Alpha = opacity;
    32.         }
    33.         ENDCG
    34.     }
    35. Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
    36. }
     
    antislash likes this.
  27. AndroidMusic

    AndroidMusic

    Joined:
    Jan 1, 2015
    Posts:
    4
    Hey I really like the first shader! Is it possible to change it to transparent/fade instead of cutout though?