UnityShader14.1:透明效果实现(下)

接上文:UnityShader14:透明效果实现(上)

四、开启深度写入的透明效果

对比下面两种渲染效果:

前面提到过,透明物体的渲染顺序非常重要,对于一个复杂的透明物体,若不进行网格分割,那么几乎不可能得到正确的渲染结果,就如图一

但是也有一个折中的方案,那就是使用两个 Pass 来渲染模型,第一个 Pass 开启深度写入,把所有被遮挡的片元剔除掉,第二个 Pass 正常渲染,这样就可以得到图二的效果,代码在下:

Shader "Jaihk662/AlphaTest1"
{
    Properties
    {
        _DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _MainTex ("MainTex", 2D) = "white" {}
        _Gloss ("Gloss", Range(8.0, 256)) = 20
        _AlphaScale ("AlphCutOff", Range(0, 1)) = 1
    }
    SubShader
    {
        LOD 200
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
        PASS
        {
            ZWrite On ColorMask 0
        }
        PASS 
        {
            //和前一章代码一摸一样
        }
    }
    FallBack "Transparent/VertexLit"
}

尽管这也不太正确,但是相对于第一个表现要好很多

  • ColorMask R|G|B|A:ColorMask 可以设置任何 RGBA 组合,目的是设置颜色通道的写掩码(write mask),当 ColorMask 设定为0时,意味着该 Pass 不写入任何颜色通道

这个 Pass 为空,同等于顶点着色器和片段着色器中不进行顶点变换外的任何运算,当然它们肯定是存在的

一些重点,可以解决一些疑惑:

  • 关于深度测试:如果开启了混合,那么深度测试通过后,当前片段相对当前深度值距离摄像机更远,就不再进行混合操作,否则进行混合
  • 未进行优化时,每个物体的每个 Pass 都会是一次 drawcall,假设当前有4个物体应用了上面的 shader,就会有8次 drawcall

五、双面渲染

对于透明的物体,理论上是可以看到它的“内部”的,或是看到反面,就像下图的对比,右边效果更真实

这里需要提前了解的是:OpenGL基础32:面剔除

想要实现右边的效果,理论只需要关闭面剔除就可以了,但是没有那么简单,因为这个时候渲染顺序就非常重要了,如果背面(内部)后渲染,那么就会出现很明显的渲染错误,所以还需要保证背面先被渲染:

Shader "Jaihk662/AlphaTest1"
{
    Properties
    {
        _DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _MainTex ("MainTex", 2D) = "white" {}
        _Gloss ("Gloss", Range(8.0, 256)) = 20
        _AlphaScale ("AlphCutOff", Range(0, 1)) = 1
    }
    SubShader
    {
        LOD 200
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
        PASS 
        {
            Tags { "LightMode" = "ForwardBase" }
            ZWrite Off Blend SrcAlpha OneMinusSrcAlpha
            Cull Front    //先进行正面剔除,渲染背面

            //…… 和之前一样的代码
        }
        PASS 
        {
            Tags { "LightMode" = "ForwardBase" }
            ZWrite Off Blend SrcAlpha OneMinusSrcAlpha
            Cull Back

            //…… 和之前一样的代码
        }
    }
    FallBack "Transparent/VertexLit"
}

六、常见混合类型

本部分完全照搬于 UnityShader 入门精要

  • Blend SrcAlpha OneMinusSrcAlpha:正常混合
  • Blend OneMinusDstColor One:柔和相加(Soft Additive)
  • Blend DstColor Zero:正片叠底(Multiply),即相乘
  • Blend DstColor SrcColor:两倍相乘(2x Multiply)
  • BlendOp Min    Blend One One:变暗(Darken)
  • BlendOp Max    Blend One One:变亮(Lighten) 
  • Blend OneMinusDstColor One:滤色(Screen)
  • Blend One One:线性减淡(Linear Dodge)

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/111911098