Search Unity

projected shadow alpha problem

Discussion in 'Shaders' started by bytescruncher, Mar 21, 2007.

  1. bytescruncher

    bytescruncher

    Joined:
    Sep 12, 2006
    Posts:
    32
    Hello,
    we've worked out a very naive polygonal shadow projection script by simply projecting the mesh on a receiving surface. We're using the following shader to render the shadow:

    Code (csharp):
    1.  
    2. Shader "MVStudios/ShadowShader" {
    3.     Properties {
    4.         _Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    5.         _MainTex ("SelfIllum Color (RGB) Alpha (A)", 2D) = "gray"
    6.     }      
    7.        
    8.     SubShader {
    9.         Material {  }
    10.            
    11.         Tags {"Queue" = "Transparent"}
    12.         Lighting Off
    13.         Cull Back
    14.  
    15.         // Rendering pass
    16.         Pass {
    17.             ZWrite Off
    18.             ZTest Less
    19.             Blend SrcAlpha OneMinusSrcAlpha
    20.             Color  [_Color]
    21.             SetTexture [_MainTex] {
    22.                 Combine texture * primary, texture
    23.             }
    24.         }
    25.     }
    26. }
    27.  
    As you may see in the picture the problem we have is on overlapping triangles, where the rendered alpha value is not correct. Any help will be appreciated.
    Thanks.

    E.
     

    Attached Files:

  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    This happens because the mesh is concave - you are blending, and when multiple triangles project to the same space, they blend multiple times.

    What to do? - I don't really know. One option would be to render into a texture and project that with Projector (just like CharacterShadow on unify wiki does). The other option would be to not use blending, but use alpha testing instead. This should solve the issue; but the shadow would not be transparent.
     
  3. polytropoi

    polytropoi

    Joined:
    Aug 16, 2006
    Posts:
    681
    So there's no way to make the CharacterShadow script semi-transparent?
     
  4. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    One workaround would be to render the character all black and then use a 2nd combiner state to fade it back up towards white.
     
  5. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Why, there is. It just renders into a texture and projects it with a custom shader - you can tweak the shader any way you like.

    The problem bytescruncher has is that he's not using CharacterShadow, he's doing some sort of "geometry based" shadows, where triangles overlap when they are flattened.
     
  6. davidpolcino

    davidpolcino

    Joined:
    Feb 2, 2006
    Posts:
    65
    You've attained the classic GameStudio look! :D
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's exactly how the shadows in Quake 2 engine games were done. And yes, they have the same problem. So it was good enough for commercial games...of course, Quake 2 is slightly outdated these days.... ;)

    --Eric
     
  8. bytescruncher

    bytescruncher

    Joined:
    Sep 12, 2006
    Posts:
    32
    Thanks everybody. :wink:

    E.
     
  9. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Hey bytescruncher,

    Just curious if you'd be willing to share the other half of this techinique with us?

    Thanks,
    Ethan
     
  10. milkytreat

    milkytreat

    Joined:
    Jan 15, 2007
    Posts:
    267
    hey.. quake 2 rocked my world :p

    actually i still love firing up quake 1 every now and then, i absolutely love the look and feel that engine has
     
  11. bytescruncher

    bytescruncher

    Joined:
    Sep 12, 2006
    Posts:
    32
    Hello Ethan,
    sorry for getting back to you so late. This technique is very straight forward.
    I enclose a very naive script that makes the trick. I wish I could upload it onto the wiki site, but was unable. Maybe some of you guys will be so kind to do that.

    1. Prepare a lower resolution mesh and skin it like your original model (the one casting the shadow).
    2. be sure your shadow mesh move along with the original one.
    3. attach the script I enclose to the original model.
    4. assign to a receiving plane a user layer (by default #8 )
    5. set the script properties (what light casts the shadow, the shadow's mesh, and the layer where the receiving objects lie).

    This technique basically projects each vertex of the shadow mesh onto a receiving mesh (ideally a plane). It has some limitation but it works nicely if you need to project the shadow on a nearly flat surface and you can live with an opaque shadow (or live with the artifacts highlithed above if semi-transparent).

    The projection is made by drawing a vector from the light to the receiving surface, through the shadow's vertex. Despite its semplicity this might come in handy if you want to cast shadows from very simple objects and don't want / can't use shadowmaps or have unity pro. Keep in mind that this might be efficient for objects with a small number of polys; if your receiving object is flat and you want to optimize you might want to use a projection matrix instead. Hope this help and comes useful.

    Take care,

    Eugenio
     

    Attached Files:

  12. bytescruncher

    bytescruncher

    Joined:
    Sep 12, 2006
    Posts:
    32
    Am I able to order the rendering (queue?)? I'm asking since if I only could render the shadows before the terrain, I could render the shadows in an opaque gray and then blend in the terrain. Any thought appreciated. Thanks,

    Eugenio
     
  13. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Thanks Eugenio,

    I appreciate you sharing that. I'm not going to use it for anything "as is", but I'm very interested in learning Unity's communication between scripts and shaders. This is a good example of using the mesh interface in conjunction with a shader. I'm very interested in learning how a process like Shadow Volume Extrusion can be implented in Unity with this combo.

    Thanks for sharing this,
    Ethan