zoukankan      html  css  js  c++  java
  • [UnityShader基础]03.透明度混合

    如果要渲染半透明物体,那么就需要用到透明度混合。

    需要注意的有这几点:

    1.设置标签:Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}

    将物体放在合适的渲染队列中

    2.关闭深度写入:ZWrite Off

    具体原因见下面

    3.Blend混合命令:Blend SrcAlpha OneMinusSrcAlpha

    意思是:最终颜色 = 源颜色(该像素颜色) * SrcAlpha + 目标颜色(颜色缓冲中的颜色) * (1 - SrcAlpha)

    AlphaBlend.shader

     1 Shader "Custom/AlphaBlend"
     2 {
     3     Properties
     4     {
     5         _MainTex ("Texture", 2D) = "white" {}
     6         _AlphaScale ("Alpha Scale", Range(0, 1)) = 1
     7     }
     8     SubShader
     9     {
    10         Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    11         
    12         Pass
    13         {
    14             ZWrite Off
    15             Blend SrcAlpha OneMinusSrcAlpha
    16 
    17             CGPROGRAM
    18             #pragma vertex vert
    19             #pragma fragment frag
    20             
    21             #include "UnityCG.cginc"
    22 
    23             struct appdata
    24             {
    25                 float4 vertex : POSITION;
    26                 float2 uv : TEXCOORD0;
    27             };
    28 
    29             struct v2f
    30             {
    31                 float2 uv : TEXCOORD0;
    32                 float4 vertex : SV_POSITION;
    33             };
    34 
    35             sampler2D _MainTex;
    36             float4 _MainTex_ST;
    37             fixed _AlphaScale;            
    38 
    39             v2f vert (appdata v)
    40             {
    41                 v2f o;
    42                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    43                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    44                 return o;
    45             }
    46             
    47             fixed4 frag (v2f i) : SV_Target
    48             {
    49                 fixed4 col = tex2D(_MainTex, i.uv);
    50                 col.a = col.a * _AlphaScale;
    51                 return col;
    52             }
    53             ENDCG
    54         }
    55     }
    56 }

    效果如下:

    那么,回到问题,为什么进行透明度混合时要关闭深度写入呢?

    可以做些测试:

    1.在上图的基础上,白色物体开启深度写入,会发现没任何变化。因为红色物体先渲染,白色物体后渲染,即使开启深度写入,由于后面没有其他物体要渲染了,也就不会影响后面的深度测试

    2.在白色物体和红色物体之间放一个灰色物体,其shader复制上面的,然后修改渲染队列为"Transparent+1",白色物体关闭深度写入。可以看到,效果还是正常的

    3.白色物体开启深度写入,如下图,这时效果就不对了。渲染顺序为:红色->白色->灰色,当渲染灰色物体时,不能通过深度测试,导致重叠的那部分像素被舍弃掉

    因此,进行透明度混合时要关闭深度写入,从而让比半透明物体还要后渲染的物体能正确地显示出来。不过因为关闭深度写入,会破坏深度缓冲的工作机制,在某些十分特殊的情况(如自身重叠交叉的半透明物体)下会出现遮挡错误的问题

  • 相关阅读:
    索尼MT27i Android2.3.7 线刷Android4.04
    如何在三分钟内要到陌生女孩的电话
    闲情逸致小说嫉妒
    LINQ查询返回DataTable类型
    30个Oracle语句优化规则详解(1)
    .net session超时设置 sessionState的相关属性
    Socket请求和Http请求的各自特点、区别及适用场景
    在Oracle触发器中调用webService 或者java程序
    vs2010中使用log4net的方法
    Oracle 记录操作时长
  • 原文地址:https://www.cnblogs.com/lyh916/p/10544944.html
Copyright © 2011-2022 走看看