Unity3D Shader教程六 Basic Transparency

除了向屏幕上绘制简单的颜色,我们还可以保留前面渲染的颜色,然后使当前的物体能透过去。我们通过一个简单的无光照Shader来实现下。效果如下:

Unity3D Shader教程六 Basic Transparency_第1张图片
Result

为了使透明物体能被正确渲染,我们需要告诉unity它是透明的。为此我们修改渲染类型 和 渲染顺序。通过修改渲染顺序,我们确保透明物体在不透明物体之后渲染,否则不透明物体将完全遮盖住透明物体。

Tags{ "RenderType"="Transparent" "Queue"="Transparent"}

接下来我们定义融合模式"blending mode",它定义了已经存在的颜色和新的颜色如何融合。blend mode 有两个关键值,第一个定义了新颜色需要乘以的系数,第二个定义了已经存在的颜色需要乘以的系数。当他们与颜色相乘后,再相加到一起的结果就是最终被渲染效果。

当渲染不透明物体时,blend mode 的两个值分别是 1 和 0,因为我们完全使用新颜色,不使用已经存在的颜色。在透明材质中,我们通过alpha值来进行融合。所以我们设置第一个值为当前材质的alpha值,第二个参值为1减去当前材质的alpha值。

blending mode 可以在subshader 中或者 pass中声明,但是需要在HLSL代码块外面。

Blend SrcAlpha OneMinusSrcAlpha

你可以从官方文档来查看融合参数的不同
https://docs.unity3d.com/Manual/SL-Blend.html

这里我演示两个小的示例,以便能更好的展示它是如何工作的。

当fragment shader返回 的alpha值为0.5的时候,融合将使用当前颜色的0.5 以及已有颜色的 1-0.5 (当在黑色上面 渲染白色,结果将是灰色)。

当fragment shader 返回的alpha值为 0.9 ,融合将使用当前颜色的90% 加上 已有颜色的10%,使得已有颜色几乎看不到。

通过这些改变,我们的shader已经可以被用在透明材质上了。因为我们在fragment shader中保留了alpha通道,所以我们可以使用 tint color 的alpha作为材质的透明通道(假设我们使用了一张没有透明通道的贴图)

Unity3D Shader教程六 Basic Transparency_第2张图片
Change Tint

我们另外要做的一件事是把 z writing 关闭。通常当一个物体被渲染时,它将距离相机的距离写入到深度缓存中,在它后面渲染的物体进行 z test 而不会 不该覆盖的时候覆盖掉它。但是这对透明物体来说是没有用的,因为透明物体不会全部遮挡在它后面的物体。是否写入z buffer,可以在 subshader 或者 pass中进行定义。

Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off

当我们使用的贴图有alpha通道时,shader 将使用它,使得aplha值越小的地方看上去越透。

Unity3D Shader教程六 Basic Transparency_第3张图片
Result
Shader "Tutorial/006_Basic_Transparency"{
    Properties{
        _Color ("Tint", Color) = (0, 0, 0, 1)
        _MainTex ("Texture", 2D) = "white" {}
    }

    SubShader{
        Tags{ "RenderType"="Transparent" "Queue"="Transparent"}

        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off

        Pass{
            CGPROGRAM

            #include "UnityCG.cginc"

            #pragma vertex vert
            #pragma fragment frag

            sampler2D _MainTex;
            float4 _MainTex_ST;

            fixed4 _Color;

            struct appdata{
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f{
                float4 position : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert(appdata v){
                v2f o;
                o.position = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET{
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= _Color;
                return col;
            }

            ENDCG
        }
    }
}

Unity技术交流 微信公众号 UnityAsk,QQ群:891920228


你可能感兴趣的:(Unity3D Shader教程六 Basic Transparency)