Shader that draws alpha independent of transparency?

Hi there.

Is it possible to write a shader that does not render its own transparency into the alpha channel of the camera image, but some custom value?

I'm using the glow post processing effect that adds a glow based on the alpha channel that is rendered in the scene (The value that can be seen if you switch the view port in Unity from RGB to Alpha in the top left dropdown list). I also use semi-transparent objects who's glow behavior is hard to control: They can not carry a complete glow when they are semi transparent, because alpha 1 = full glow but also full opacity.

Maybe someone can also shed some light into the relation between the rendered image's alpha channel ("alpha-buffer"?) and alpha value of a shader?

Thank you!


Take this simple vertex lit transparent ShaderLab code for instance:

Shader "Transparent/Vertex Lit Alpha" {
Properties {
    _Color ("Color", Color) = (1,1,1,1)
    _Emissive ("Emissive", Color) = (0,0,0,0)
    _MainTex ("Texture", 2D) = "white" {}
}
SubShader {
    Tags { "RenderType"="Transparent" "Queue"="Transparent" }
    Blend SrcAlpha OneMinusSrcAlpha
    Pass {
        Lighting Off
        Material {
            Diffuse [_Color]
            Ambient (1,1,1,1)
            Emission [_Emissive]
        }
        Lighting On
        SeparateSpecular On
        SetTexture [_MainTex] {
            Combine texture * primary DOUBLE, texture * primary
        }
    }
}
}

If I understand correctly, the statements

Diffuse [_Color]

and

Combine texture * primary DOUBLE, texture * primary

together define the transparency as well as the rendered alpha of the object. If I wanted an additional property like

_RenderedAlpha ("RenderedAlpha", Range(0,1)) = 0.5

that should not influence the object's transparency, but only the level of gray that is visible if I switch from RGB to alpha view... how could I go about doing that?

Yes. Every single shader explicitly states what you're rendering into the alpha channel. You can then see what that is, if you switch the Scene view mode to Alpha instead of RGB.

If you have a specific shader you need edited, post it here. I'll see if I can do anything with it. If it's a surface shader, I'll have no idea, though.

Edit: There's no way to do exactly what you're saying, with a shader that alpha blends. I'll show you what options you have.

First, some tips as to why this base looks different than yours: The alpha component of light isn't passed into a fixed function shader - it's always one. Don't bother multiplying by one. Also, don't bother turning lighting off before turning it on - this has no effect. You have no specular component to your lighting, so don't bother using SeparateSpecular.

SubShader {
    Tags {"RenderType"="Transparent" Queue = Transparent}
    Blend SrcAlpha OneMinusSrcAlpha

    Lighting On
    Material {
        Diffuse[_Color]
        Ambient (1,1,1,1)
        Emission[_Emissive]
    }

    Pass {
        SetTexture [_MainTex] {Combine texture * primary Double, texture}
    }
}

So, the first thing you can do, is use ColorMask RGB, in which case you rely on what has already been rendered, for alpha. Unity's built-in opaque shaders render 1, for alpha, so this seems like it will get you the effect you want. Unity's built-in transparent shaders take this approach. (This method is slow on POWERVR hardware and the following technique is better there.)

The other thing you can do, is blend the alpha you're rendering, with the alpha in the color buffer, as described here. That doesn't allow for much control, but it's more than than the equivalent Blend SrcColor OneMinusSrcColor of ColorMask RGBA or Blend Zero One of ColorMask RGB.

If neither of these things gets you what you need, then your only option is to use two passes, with ColorMask A in the first one, and mangle the alpha channel as you see fit, now having explicit control of what DstAlpha is.

I came across this thread (and others) in search of a solution. An example of how to use ColorMask and Blend as @Jessy suggested can be found in this answer I posted here.