Search Unity

separate alpha channel for rendering glow

Discussion in 'Shaders' started by ecolvin, Mar 9, 2010.

  1. ecolvin

    ecolvin

    Joined:
    May 6, 2009
    Posts:
    18
    In my game, I would like to have the glow be controlled by a separate alpha channel (not the main color channel's alpha). I've been trying to do this by creating a separate color channel that controls the amount of glow. However, I can't seem to get this to work. Does anyone know where in the glow code the main color's alpha channel is accessed for glow intensity? If anyone has better ideas of doing this let me know.

    Thanks!
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    The fullscreen glow effect reads alpha from the frame buffer to determine glow intensity. With most opaque materials, the alpha is written as:
    Code (csharp):
    1. baseTexture.a * mainColour.a
    Specular highlights will also contribute to alpha.

    To make a shader that uses another texture for its alpha, you would have to modify an existing shader's PixelOrNone pass to write alpha from the new texture.
     
  3. ecolvin

    ecolvin

    Joined:
    May 6, 2009
    Posts:
    18
    That makes sense, but would changing the "pixelornone" pass affect how all shaders read the alpha channel? I still want to use the alpha channel of the main texture for opacity levels and such. I just want to create a second color channel and use that color channel's alpha to solely control the glow.

    Also, would I not have to edit the glow replacement shader code? Only the shaders that I place on my object?

    I'm still learning to write shaders so thanks for your patience!
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I think you're confusing the frame buffer with source textures. The frame buffer is a chunk of memory that contains what you see on the screen (RGB) plus an alpha channel (A) that you don't see. Most shaders read from source textures and write to the frame buffer. When you render an object, you usually want to see it on the screen. The fact that the frame buffer has an alpha channel allows you to write information "to the screen" that will not be seen, but is still stored. Alpha values in the frame buffer can be used for blending (with the DstAlpha argument to Blend), but can also be used by fullscreen effects. Like I mentioned above, the default opaque materials in Unity write the alpha channel of their source textures straight into the frame buffer.

    The fullscreen glow shader, and all fullscreen effect shaders, are special in that they effectively read from the frame buffer and then write back to it. The glow shader reads the alpha channel in order to determine how strong the glow should be in various parts of the screen. If you don't use any fullscreen effects, you'll probably never have a use for the alpha channel of the frame buffer, and thus won't see any change when you adjust the alpha of an opaque material.

    In your case, however, you just want to create a shader that will use a different source for the alpha that it writes. Creating such a shader would only affect objects that use the new shader in their material. Because all you're doing is changing where you get your alpha values, the glow shader would not need to be modified.
     
  5. ecolvin

    ecolvin

    Joined:
    May 6, 2009
    Posts:
    18
    Thanks for the clarification. This seems to work for opaque shaders, but it's not really working for transparent shaders. The unity built in transparency shaders also use the frame buffer's alpha channel to figure how transparent the object should be. Is it possible for the glow shader to not read the frame buffer's alpha channel, but another channel's alpha to figure out the amount of glow?
     
  6. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Only fullscreen effects read from the frame buffer. Unity's transparent shaders read transparency from their source texture alpha channels, but do not write any alpha at all (due to the ColorMask RGB line). This means that the alpha value in the frame buffer will be that of the front-most opaque object, and won't be affected by transparent objects at all.

    The only way for an object shader to communicate with the fullscreen glow effect invisibly is to write to the alpha channel. So if you want transparent objects writing to the alpha channel, you'll have to modify one of the transparent shaders to do this. You might need two passes in order to use alpha for blending properly.
     
  7. ecolvin

    ecolvin

    Joined:
    May 6, 2009
    Posts:
    18
    I'm still confused on what exactly it means to write to the frame buffer's alpha. I'm assuming it's when the color gets returned from the fragment shader.

    In Unity's Transparent pixel pass there are these lines:

    Code (csharp):
    1. float4 frag (v2f i) : COLOR
    2. {
    3.     half4 texcol = tex2D( _MainTex, i.uv );
    4.     half4 c = DiffuseLight( i.lightDir, i.normal, texcol, LIGHT_ATTENUATION(i) );
    5.     c.a = texcol.a * _Color.a;
    6.     return c;
    7. }
    The "c.a = texcol.a * _Color.a" line seems to be writing to the frame buffer alpha. So if that's true, then the transparency shader is also writing to the frame buffer alpha.

    Can you point me to the specific lines in the glow shader where it reads and writes to the frame buffer alpha?
     
  8. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    The alpha value returned by the fragment shader is not written (due to ColorMask RGB), only used for blending (due to Blend SrcAlpha One).

    The glow effect reads from the frame buffer alpha when it is downsampling the frame buffer before the blur. This shader is invoked at line 195 of GlowEffect.cs using Graphics.Blit():
    Code (csharp):
    1. DownSample4x (source, buffer);
    The actual use of the alpha value occurs on line 68 of GlowEffectDownsample.shader:
    Code (csharp):
    1. c.rgb *= (c.a + _Color.a);
    Although the downsampling shader does write to the alpha channel of the downsampled buffer (line 69, immediately after the use of the read alpha value) :
    Code (csharp):
    1. c.a = 0;
    ...it writes zeros, so nothing happens when the buffer is added back to the frame buffer using Graphics.Blit() on line 213 or 215 of GlowEffect:
    Code (csharp):
    1. BlitGlow(buffer, destination);
    As you can see, the glow effect script is not the simplest in the world. I hope this walkthough helps you figure out where the values come from, though.
     
  9. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    Edit: Nevermind, thought I had an issue but it was just glow bleeding from the background.
     
    Last edited: Dec 2, 2010