zoukankan      html  css  js  c++  java
  • 透明度混合

    透明度混合:这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是透明度混合需要关闭深度写入。

    这使得我们要非常小心物体的渲染顺序。

    为了进行混合,我们需要使用Unity提供的混合命令——Blend。

    我们这里使用 Blend SrcAlpha OneMinusSrcAlpha

    内部公式为:DstColor(new)=SrcAlpha*SrcColor+(1-SrcAlpha)*DstColor(old);

    首先是关闭深度写入的代码:

     1 Shader "Custom/AlphaBlend" {
     2     Properties {
     3         _Color ("Main Tint", Color) = (1,1,1,1)
     4         _MainTex ("Albedo (RGB)", 2D) = "white" {}
     5         _AlphaScale("Alpha Scale",Range(0,1))=1
     6     }
     7     SubShader {
     8     /*
     9     "Queue"="Transparent":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列
    10     "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响
    11     RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是Transparent组)
    12     */
    13     Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="Transparent"}
    14         Pass
    15         {
    16         Tags{"LightMode"="ForwardBase"}
    17         ZWrite Off//关闭深度写入
    18         Blend SrcAlpha OneMinusSrcAlpha
    19         CGPROGRAM
    20         #pragma vertex vert
    21         #pragma fragment frag
    22         #include"Lighting.cginc"
    23 
    24         fixed4 _Color;
    25         sampler2D _MainTex;
    26         float4 _MainTex_ST;
    27         fixed _AlphaScale;
    28 
    29         struct a2v
    30         {
    31         float4 vertex:POSITION;
    32         float3 normal:NORMAL;
    33         float4 texcoord:TEXCOORD0;
    34         };
    35         struct v2f
    36         {
    37         float4 pos:SV_POSITION;
    38         float3 worldNormal:TEXCOORD0;
    39         float3 worldPos:TEXCOORD1;
    40         float2 uv:TEXCOORD2;
    41         };
    42         v2f vert(a2v v)
    43         {
    44         v2f o;
    45         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
    46         o.worldNormal=UnityObjectToWorldNormal(v.normal);
    47         o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
    48         o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
    49         return o;
    50         }
    51 
    52         fixed4 frag(v2f i):SV_Target
    53         {
    54         fixed3 worldNormal=normalize(i.worldNormal);
    55         fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
    56         fixed4 texColor=tex2D(_MainTex,i.uv);
    57         fixed3 albedo=texColor.rgb*_Color.rgb;
    58         fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
    59         fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
    60         return fixed4(ambient+diffuse,texColor.a*_AlphaScale);//颜色乘以透明程度
    61         }
    62 
    63         ENDCG
    64         }
    65     }
    66     FallBack "Transparent/Cutout/VertexLit"
    67 }
    透明度混合(关闭深度写入)

    我们可以调节材质面板上的Alpha Scale参数,以控制整体透明度。

    当然,关闭深度写入有时候会带来因为排序错误而产生的错误的透明效果(模型本身有复杂的遮挡关系)。

    所以我们可以采用开启深度写入进行透明度混合。原理是开启2个Pass来渲染模型。第一个Pass开启深度写入,但是不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中。第二个Pass进行透明度混合。(多使用一个Pass会对性能造成一定的影响)。在之前的代码中原有的Pass前面添加以下代码即可:

    Pass
    {
        ZWrite On
        ColorMask 0
    }

    完整代码:

     1 Shader "Custom/AlphaBlend" {
     2     Properties {
     3         _Color ("Main Tint", Color) = (1,1,1,1)
     4         _MainTex ("Albedo (RGB)", 2D) = "white" {}
     5         _AlphaScale("Alpha Scale",Range(0,1))=1
     6     }
     7     SubShader {
     8     /*
     9     "Queue"="Transparent":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列
    10     "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响
    11     RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是Transparent组)
    12     */
    13     Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="Transparent"}
    14         Pass
    15         {
    16         Tags{"LightMode"="ForwardBase"}
    17         Cull Front
    18         ZWrite On//开启深度写入
    19         ColorMask 0//当ColorMask设为0时,意味着该pass不写任何颜色通道,即不会输出任何颜色。这正是我们需要的-该Pass只需要写入深度缓冲即可
    20         
    21         }
    22         Pass
    23         {
    24         Tags{"LightMode"="ForwardBase"}
    25         Cull Back
    26         ZWrite Off//关闭深度写入
    27         Blend  SrcAlpha OneMinusSrcAlpha
    28         
    29         CGPROGRAM
    30         #pragma vertex vert
    31         #pragma fragment frag
    32         #include"Lighting.cginc"
    33 
    34         fixed4 _Color;
    35         sampler2D _MainTex;
    36         float4 _MainTex_ST;
    37         fixed _AlphaScale;
    38 
    39         struct a2v
    40         {
    41         float4 vertex:POSITION;
    42         float3 normal:NORMAL;
    43         float4 texcoord:TEXCOORD0;
    44         };
    45         struct v2f
    46         {
    47         float4 pos:SV_POSITION;
    48         float3 worldNormal:TEXCOORD0;
    49         float3 worldPos:TEXCOORD1;
    50         float2 uv:TEXCOORD2;
    51         };
    52         v2f vert(a2v v)
    53         {
    54         v2f o;
    55         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
    56         o.worldNormal=UnityObjectToWorldNormal(v.normal);
    57         o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
    58         o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
    59         return o;
    60         }
    61 
    62         fixed4 frag(v2f i):SV_Target
    63         {
    64         fixed3 worldNormal=normalize(i.worldNormal);
    65         fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
    66         fixed4 texColor=tex2D(_MainTex,i.uv);
    67         fixed3 albedo=texColor.rgb*_Color.rgb;
    68         fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
    69         fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
    70         return fixed4(ambient+diffuse,texColor.a*_AlphaScale);//颜色乘以透明程度
    71         }
    72 
    73         ENDCG
    74         }
    75     }
    76     FallBack "Transparent/Cutout/VertexLit"
    77 }
    透明度混合(开启深度写入)

    双面渲染的透明效果建立在关闭深度写入的状态下。

     1 Shader "Custom/AlphaBlend With Both Side" {
     2     Properties {
     3         _Color ("Main Tint", Color) = (1,1,1,1)
     4         _MainTex ("Albedo (RGB)", 2D) = "white" {}
     5         _AlphaScale("Alpha Scale",Range(0,1))=1
     6     }
     7     SubShader {
     8     Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="Transparent"}
     9         Pass
    10         {
    11         Tags{"LightMode"="ForwardBase"}
    12         Cull Front
    13                 //和之前一样的代码
    14         }
    15         Pass
    16         {
    17         Tags{"LightMode"="ForwardBase"}
    18         Cull Back
    19             //和之前一样的代码
    20         }
    21     }
    22     FallBack "Transparent/Cutout/VertexLit"
    23 }
    24         
    伪代码
      1 Shader "Custom/AlphaBlend With Both Side" {
      2     Properties {
      3         _Color ("Main Tint", Color) = (1,1,1,1)
      4         _MainTex ("Albedo (RGB)", 2D) = "white" {}
      5         _AlphaScale("Alpha Scale",Range(0,1))=1
      6     }
      7     SubShader {
      8     /*
      9     "Queue"="Transparent":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列
     10     "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响
     11     RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是Transparent组)
     12     */
     13     Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="Transparent"}
     14         Pass
     15         {
     16         Tags{"LightMode"="ForwardBase"}
     17         Cull Front
     18         ZWrite Off//关闭深度写入
     19         Blend SrcAlpha OneMinusSrcAlpha
     20         CGPROGRAM
     21         #pragma vertex vert
     22         #pragma fragment frag
     23         #include"Lighting.cginc"
     24 
     25         fixed4 _Color;
     26         sampler2D _MainTex;
     27         float4 _MainTex_ST;
     28         fixed _AlphaScale;
     29 
     30         struct a2v
     31         {
     32         float4 vertex:POSITION;
     33         float3 normal:NORMAL;
     34         float4 texcoord:TEXCOORD0;
     35         };
     36         struct v2f
     37         {
     38         float4 pos:SV_POSITION;
     39         float3 worldNormal:TEXCOORD0;
     40         float3 worldPos:TEXCOORD1;
     41         float2 uv:TEXCOORD2;
     42         };
     43         v2f vert(a2v v)
     44         {
     45         v2f o;
     46         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
     47         o.worldNormal=UnityObjectToWorldNormal(v.normal);
     48         o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
     49         o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
     50         return o;
     51         }
     52 
     53         fixed4 frag(v2f i):SV_Target
     54         {
     55         fixed3 worldNormal=normalize(i.worldNormal);
     56         fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
     57         fixed4 texColor=tex2D(_MainTex,i.uv);
     58         fixed3 albedo=texColor.rgb*_Color.rgb;
     59         fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
     60         fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
     61         return fixed4(ambient+diffuse,texColor.a*_AlphaScale);//颜色乘以透明程度
     62         }
     63         ENDCG
     64         }
     65         Pass
     66         {
     67         Tags{"LightMode"="ForwardBase"}
     68         Cull Back
     69         ZWrite Off//关闭深度写入
     70         Blend SrcAlpha OneMinusSrcAlpha
     71         CGPROGRAM
     72         #pragma vertex vert
     73         #pragma fragment frag
     74         #include"Lighting.cginc"
     75 
     76         fixed4 _Color;
     77         sampler2D _MainTex;
     78         float4 _MainTex_ST;
     79         fixed _AlphaScale;
     80 
     81         struct a2v
     82         {
     83         float4 vertex:POSITION;
     84         float3 normal:NORMAL;
     85         float4 texcoord:TEXCOORD0;
     86         };
     87         struct v2f
     88         {
     89         float4 pos:SV_POSITION;
     90         float3 worldNormal:TEXCOORD0;
     91         float3 worldPos:TEXCOORD1;
     92         float2 uv:TEXCOORD2;
     93         };
     94         v2f vert(a2v v)
     95         {
     96         v2f o;
     97         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
     98         o.worldNormal=UnityObjectToWorldNormal(v.normal);
     99         o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
    100         o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
    101         return o;
    102         }
    103 
    104         fixed4 frag(v2f i):SV_Target
    105         {
    106         fixed3 worldNormal=normalize(i.worldNormal);
    107         fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
    108         fixed4 texColor=tex2D(_MainTex,i.uv);
    109         fixed3 albedo=texColor.rgb*_Color.rgb;
    110         fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
    111         fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
    112         return fixed4(ambient+diffuse,texColor.a*_AlphaScale);//颜色乘以透明程度
    113         }
    114 
    115         ENDCG
    116         }
    117     }
    118     FallBack "Transparent/Cutout/VertexLit"
    119 }
    完整代码(建立在上面关闭深度写入的透明度混合代码基础上)

     效果:

  • 相关阅读:
    网络--会话层、表示层、应用层
    Unix C
    操作系统原理
    TCP/UDP
    config OSX firewall programmatically
    Objective-C 浅谈
    OS X background process
    CreateProcessWithToken 1058 error
    WebBrowser keystroke
    MFC加载PNG图片并实现双缓冲
  • 原文地址:https://www.cnblogs.com/luxishi/p/6484586.html
Copyright © 2011-2022 走看看