zoukankan      html  css  js  c++  java
  • UnityShader之遮挡透明

      好久没写博客了,最近在学shader,不得不说,shader真的非常美妙,我沉迷其中无法自拔= =

      之前做过一个遮挡透明的功能,当物体遮挡住主角时,该物体会变成半透明显示出主角。这次同样是遮挡透明的功能,不过,变透明的刚刚相反,是主角变成半透明,更严谨的说是主角被遮挡的那一部分变成半透明。

      先放出结果图:

      当被遮挡时,遮挡部分透明处理,那么需要涉及渲染深度的知识。引擎是如何判断哪个物体在前面哪个物体在后面呢?

      深度:每个像素有自己的深度值,离摄像机近的深度小,远的深度大

      深度缓冲区:存储每个像素的深度

      颜色缓冲区:存储每个像素的颜色

      过程:首先比较像素的深度与深度缓冲区同一位置的深度,如果前者小于后者,则未通过深度测试;否则,通过深度测试,将前者写入后者,将该像素的颜色写入到颜色缓冲区。将颜色缓冲区像素颜色显示到屏幕上。

      通过这个过程即可把深度小的像素剔除掉,将深度大的显示到屏幕上,从而实现物体的前后顺序。

      UnityShader提供了ZWrite 和 ZTest对应深度写入和深度测试。

      调整ZWrite可以控制是否将深度写入到深度缓冲区,当然,前提是深度测试通过,如果没通过测试,那么肯定是无法写入的

      调整ZTest可以定义上述中前者与后者的比较关系,默认为LEqual即小于等于时通过测试

       那么可以得到一种实现思路,用两个PASS:

      第一个PASS:ZTest 为 Greater,ZWrite 为 Off,当该像素被遮挡即深度大于深度缓冲区对应位置深度时执行该PASS,那么就可以在该PASS中实现被遮挡像素的效果。

      第二个PASS:ZTest为LEqual,ZWrite 为 On,这个PASS与上述PASS是互斥的,在这个PASS中实现未被遮挡像素的效果。

      设置ZWrite 是为了防止两个PASS都执行,如果第一个PASS的ZWrite为On,某一像素未被遮挡时,执行第一个PASS,将像素深度写入深度缓冲区,然后轮到第二个PASS进行深度测试时也会通过,因为小于等于嘛。

      

      被遮挡像素透明实现用了边缘光使得更炫酷。边缘光公式大概如下:

      fixed   rim=1-saturate(dot(worldNormalDir,worldViewDir));

      fixed3 finalCol=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity  

      通过第一个式子可以得到一个参数rim,顶点法线方向与视角方向契合度越高则rim越小,否则rim越大,即越靠近边缘rim越大

      第二个式子中pow是为了提高边缘光硬度

      代码:

      1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
      2 
      3 Shader "MyShader/Rim/RimShader" {
      4     Properties{
      5         _RimColor("Rim Color",Color)=(1.0,1.0,1.0,1.0)//边缘光颜色
      6         _RimPower("Rim Power",Range(0.1,10))=3.0//Pow参数
      7         _RimIntensity("Rim Intensity",Range(0,100))=10//边缘光强度
      8 
      9         _MainTex("Base (RGB)",2D)="white"{}
     10     }
     11     SubShader{
     12         //当所有不透明物体渲染后开始渲染此物体
     13         Tags{"Queue"="Geometry+50" "RenderType"="Opaque"}
     14 
     15         Pass{
     16             Blend SrcAlpha OneMinusSrcAlpha
     17             Cull Off
     18             ZWrite Off
     19             ZTest Greater
     20 
     21             CGPROGRAM
     22             #pragma vertex vert
     23             #pragma fragment frag
     24             #include "UnityCG.cginc"
     25 
     26                 fixed4 _RimColor;
     27                 float _RimPower;
     28                 float _RimIntensity;
     29 
     30                 struct a2v{
     31                     float4 vertex:POSITION;
     32                     float3 normal:NORMAL;
     33                 };
     34 
     35                 struct v2f{
     36                     float4 pos:SV_POSITION;
     37                     float4 worldPos:TEXCOORD0;
     38                     float3 worldNormal:TEXCOORD1;
     39                 };
     40 
     41                 v2f vert(a2v v){
     42                     v2f o;
     43                     o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
     44                     o.worldPos=mul(unity_ObjectToWorld,v.vertex);
     45                     o.worldNormal=UnityObjectToWorldNormal(v.normal);
     46                     return o;
     47                 }
     48 
     49                 fixed4 frag(v2f i):SV_TARGET{
     50                     fixed3 worldNormalDir=normalize(i.worldNormal);
     51                     fixed3 worldViewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
     52                     fixed rim=1-saturate(dot(worldNormalDir,worldViewDir));
     53 
     54                     fixed3 col=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity;
     55                     return fixed4(col,0.3);
     56                 }
     57             ENDCG
     58         }
     59 
     60         Pass{
     61             Tags{"LightMode"="ForwardBase"}
     62             ZWrite On
     63             ZTest LEqual
     64             CGPROGRAM
     65             #pragma vertex vert
     66             #pragma fragment frag
     67             #include "UnityCG.cginc"
     68             #include "Lighting.cginc"
     69             #include "AutoLight.cginc"
     70 
     71                 sampler2D _MainTex;
     72                 float4 _MainTex_ST;
     73 
     74 
     75                 struct a2v{
     76                     float4 vertex:POSITION;
     77                     float2 texcoord:TEXCOORD0;
     78                 };
     79 
     80                 struct v2f{
     81                     float4 pos:SV_POSITION;
     82                     float2 uv:TEXCOORD0;
     83                 };
     84 
     85                 v2f vert(a2v v){
     86                     v2f o;
     87                     o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
     88                     o.uv=v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
     89                     return o;
     90                 }
     91 
     92                 fixed4 frag(v2f i):SV_TARGET{
     93                     fixed3 col=tex2D(_MainTex,i.uv).rgb;
     94 
     95                     return fixed4(col,1);
     96                 }
     97 
     98             ENDCG
     99         }
    100 
    101 
    102     }
    103     FallBack "Diffuse"
    104 }
    View Code
  • 相关阅读:
    Visual Studio 2010使用Visual Assist X的方法
    SQL Server 2000 评估版 升级到 SQL Server 2000 零售版
    双网卡多网络单主机同时访问
    开发即过程!立此纪念一个IT新名词的诞生
    delphi dxBarManager1 目录遍历 转为RzCheckTree2树
    5320 软件集合
    delphi tree 从一个表复制到另一个表
    DELPHI 排课系统课表
    长沙金思维 出现在GOOGLE的 金思维 相关搜索里啦!!
    如何在DBGrid的每一行前加一个单选框?
  • 原文地址:https://www.cnblogs.com/McYY/p/7277401.html
Copyright © 2011-2022 走看看