zoukankan      html  css  js  c++  java
  • Unity Shader 玻璃效果

    一个玻璃效果主要分为两个部分,一部分是折射效果的计算,另一部分则是反射。下面分类进行讨论:

    折射:

    1.利用Grass Pass对当前屏幕的渲染图像进行采样

    2.得到法线贴图对折射的影响

    3.对采集的屏幕图像进行关于法线方向上的扭曲和偏移,以模拟折射效果

    反射:

    主要利用环境贴图产生反射的残影,并和主贴图采样结果混合

    得到反射和折射的结果后,以一个插值变量控制最终效果(类似于玻璃的透光率);

    脚本如下:

      1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
      2 
      3 Shader "MyUnlit/GlassRefraction"
      4 {
      5     Properties
      6     {
      7         _MainTex ("Texture", 2D) = "white" {}
      8         //这里的法线贴图用于计算折射产生的扭曲
      9         _BumpMap("Normal Map",2D)="bump"{}
     10         //这里的环境贴图用于反射周围环境的部分残影
     11         _Cubemap("Environment Map",cube)="_Skybox"{}
     12         _Distortion("Distortion",range(0,100))=10
     13         //一个折射系数,用于控制折射和反射的占比
     14         _RefractAmount("Refract Amount",range(0,1))=1
     15     }
     16     SubShader
     17     {
     18         //保证该物体渲染时,其他不透明物体都已经渲染完成
     19         Tags { "RenderType"="Opaque" "Queue"="Transparent"}
     20         //抓取当前屏幕的渲染图像并存入指定纹理
     21         GrabPass{"_RefractionTex"}
     22 
     23         Pass
     24         {
     25             CGPROGRAM
     26             #pragma vertex vert
     27             #pragma fragment frag
     28 
     29             #include "UnityCG.cginc"
     30 
     31             struct appdata
     32             {
     33                 float4 vertex : POSITION;
     34                 float2 uv : TEXCOORD0;
     35                 float3 normal:NORMAL;
     36                 float4 tangent:TANGENT;
     37             };
     38 
     39             struct v2f
     40             {
     41                 float4 uv : TEXCOORD0;
     42                 float4 pos : SV_POSITION;
     43                 float4 scrPos : TEXCOORD4;
     44                 float4 TtoW0:TEXCOORD1;
     45                 float4 TtoW1:TEXCOORD2;
     46                 float4 TtoW2:TEXCOORD3;
     47             };
     48 
     49             sampler2D _MainTex;
     50             float4 _MainTex_ST;
     51             sampler2D _BumpMap;
     52             float4 _BumpMap_ST;
     53             samplerCUBE _Cubemap;
     54             float _Distortion;
     55             fixed _RefractAmount;
     56             sampler2D _RefractionTex;
     57             float4 _RefractionTex_TexelSize;
     58 
     59             v2f vert (appdata v)
     60             {
     61                 v2f o;
     62 
     63                 o.pos = UnityObjectToClipPos(v.vertex);
     64 
     65                 o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
     66                 o.uv.zw = TRANSFORM_TEX(v.uv, _BumpMap);
     67                 //得到屏幕采样坐标
     68                 o.scrPos = ComputeGrabScreenPos(o.pos);
     69 
     70                 float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
     71                 float3 worldNormal = UnityObjectToWorldNormal(v.normal);
     72                 float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
     73                 float3 worldBinormal = cross(worldTangent, worldNormal)*v.tangent.w;
     74 
     75                 o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
     76                 o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
     77                 o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
     78 
     79                 return o;
     80             }
     81 
     82             fixed4 frag (v2f i) : SV_Target
     83             {
     84                 float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
     85                 float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);
     86 
     87                 fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
     88 
     89                 fixed3 tanNormal = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
     90                 fixed3 worldNormal = mul(TtoW, tanNormal);
     91                 //对采集的屏幕图像进行关于法线方向上的扭曲和偏移,也就是模拟折射的效果
     92                 float2 offset = tanNormal.xy*_Distortion*_RefractionTex_TexelSize.xy;
     93                 i.scrPos.xy += offset;
     94                 fixed3 refractCol = tex2D(_RefractionTex, i.scrPos.xy / i.scrPos.w).xyz;
     95                 //这一块用来模拟反射的效果,反射越强,也就是透光度越低,越能看到主贴图纹理以及周围环境反射的残影
     96                 fixed3 reflectDir = reflect(-worldViewDir, worldNormal);
     97                 fixed4 mainTexCol = tex2D(_MainTex, i.uv.xy);
     98                 fixed4 cubemapCol = texCUBE(_Cubemap, reflectDir);
     99                 fixed3 reflectCol = mainTexCol.rgb*cubemapCol.rgb;
    100                 //最后将折射和反射进行一个综合叠加,_RefractAmount可以认为是透光率,当它为1时,就是全透过而没有反射,为0时就是全反射跟镜子一样
    101                 fixed3 color = refractCol * _RefractAmount + reflectCol * (1 - _RefractAmount);
    102                 return fixed4(color,1.0);
    103             }
    104             ENDCG
    105         }
    106     }
    107     fallback "Diffuse"
    108 }

    效果如下:

  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    How to check if one path is a child of another path?
    Why there is two completely different version of Reverse for List and IEnumerable?
    在Jenkins中集成Sonarqube
    如何查看sonarqube的版本 how to check the version of sonarqube
    Queue
    BFS广度优先 vs DFS深度优先 for Binary Tree
    Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
    102. Binary Tree Level Order Traversal 广度优先遍历
    How do I check if a type is a subtype OR the type of an object?
  • 原文地址:https://www.cnblogs.com/koshio0219/p/11114659.html
Copyright © 2011-2022 走看看