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

Projector Multiply With Alpha

Discussion in 'Shaders' started by padishar, Jun 18, 2009.

  1. padishar

    padishar

    Joined:
    May 14, 2009
    Posts:
    5
    Hello everyone,

    Firstly, I'd like to say a big hello to the community. I've been lurking around for quite a while now, but was too shy to post :roll:

    Ok, now that we've got that out of the way, my problem is as follows:

    I'm designing a decal system for my game, and I am using projectors to achieve that. I would also like the decals to nicely fade out after a certain time, and then self destruct. The only problem is that the Projector Multiply shader doesn't allow alpha blending. So I went ahead and tried to write my own shader. Here's the code(Btw I am a complete noob and this is my first shader):

    Code (csharp):
    1.  
    2. Shader "FX/Projector Multiply Color" {
    3. Properties {
    4.     _Color ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    5.     _MainTex ("Cookie", 2D) = "" { TexGen ObjectLinear }
    6.     _FalloffTex ("FallOff", 2D) = "" { TexGen ObjectLinear  }
    7. }
    8.  
    9. Category {
    10.     Tags { "Queue" = "Transparent" }
    11.     Offset -1, -1
    12.     Blend SrcAlpha OneMinusSrcAlpha
    13.    
    14.     AlphaTest Greater .01
    15.     ColorMask RGB
    16.     Lighting Off ZWrite Off Fog { Color (0,0,0,0) }
    17.     BindChannels {
    18.         Bind "Color", color
    19.         Bind "Vertex", vertex
    20.         Bind "TexCoord", texcoord
    21.     }
    22.    
    23.     // ---- Dual texture cards
    24.     SubShader {
    25.         Pass {
    26.             SetTexture [_MainTex] {
    27.                 constantColor [_Color]
    28.                 combine constant * primary
    29.                 Matrix [_Projector]
    30.             }
    31.             SetTexture [_MainTex] {
    32.                 combine texture * previous DOUBLE
    33.             }
    34.             SetTexture [_FalloffTex] {
    35.                 constantColor (1,1,1,0)
    36.                 combine previous lerp (texture) constant
    37.                 Matrix [_ProjectorClip]
    38.             }
    39.         }
    40.     }
    41.    
    42.     // ---- Single texture cards (does not do color tint)
    43.     SubShader {
    44.         Pass {
    45.             SetTexture [_MainTex] {
    46.                 combine texture * primary
    47.             }
    48.             SetTexture [_FalloffTex] {
    49.                 constantColor (1,1,1,0)
    50.                 combine previous lerp (texture) constant
    51.                 Matrix [_ProjectorClip]
    52.             }
    53.         }
    54.     }
    55. }
    56. }
    57.  
    This shader works fine for the nice fading bit, but I can't get the decal to look "multiplied" on the background. If I use "Blend DstColor Zero" it looks fine, but the alpha fading stops working :(

    Any kind of help is welcome,
    Padi.
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Unfortunately, you can't do multiplicative blending and alpha blending at the same time. To learn why, I recommend reading the section on blending in chapter 6 of the Red Book.

    However, if you want your shader to have a controllable effect, remember that multiplying by 1 has no effect. The closer the output of your shader is to white, the less effect it will have on the final image. Since the final fragment value of a shader is always clamped to [0,1], you don't have to worry about going over, and you can just add an offset (starting at black, going to white) to reduce and eventually entirely remove the effect of the multiplication:

    Code (csharp):
    1. Shader "FX/Projector Multiply Offset" {
    2.     Properties {
    3.         _ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
    4.         _FalloffTex ("FallOff", 2D) = "white" { TexGen ObjectLinear }
    5.         _Tint ("Offset", Color) = (0,0,0,0)
    6.     }
    7.  
    8.     Subshader {
    9.         Pass {
    10.             ZWrite Off
    11.             Offset -1, -1
    12.  
    13.             Fog { Color (1, 1, 1) }
    14.             AlphaTest Greater 0
    15.             ColorMask RGB
    16.             Blend DstColor Zero
    17.             SetTexture [_ShadowTex] {
    18.                 combine texture, ONE - texture
    19.                 Matrix [_Projector]
    20.             }
    21.             SetTexture [_FalloffTex] {
    22.                 constantColor (1,1,1,0)
    23.                 combine previous lerp (texture) constant
    24.                 Matrix [_ProjectorClip]
    25.             }
    26.             SetTexture [_FalloffTex] { // add offset
    27.                 constantColor [_Tint]
    28.                 combine previous + constant
    29.             }
    30.         }
    31.     }
    32. }
     
  3. padishar

    padishar

    Joined:
    May 14, 2009
    Posts:
    5
    Whoa thanx a lot! I'll be sure to check this out when I get the chance and post a reply to tell you how it worked.

    Lol fun times I remember reading that book about 7 years ago. I obviously don't remember anything now.

    Cheers,
    Padi
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    It's a good read. If you take the twenty minutes or so, you'll go from wondering what the hell a blending function is doing to wondering which order the damn coefficients are in again.
     
  5. padishar

    padishar

    Joined:
    May 14, 2009
    Posts:
    5
    Man I tried your shader and it's friggin' sweet! You cannot imagine how helpful that was, thank you so much!
    I am working on placing the projectors properly in 3D space now. It works for most parts, just need to fix the spot where 2 or 3 surfaces intersect, i.e. a corner in a room.
    I'm thinking of some raycasts in a 45 degree angle, 2 on x and 2 on y. I'll get on with it and let you know of my progress.

    Thank you again,
    Padi.