服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - Unity Shader模拟玻璃效果

Unity Shader模拟玻璃效果

2022-09-06 11:34Zok93 C#

这篇文章主要为大家详细介绍了Unity Shader模拟玻璃效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Unity Shader实现玻璃效果的具体代码,供大家参考,具体内容如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
Shader "Glass Refraction" {
  Properties {
    _MainTex ("Main Tex", 2D) = "white" {}
    _BumpMap ("Normal Map", 2D) = "bump" {}
    _Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
    _Distortion ("Distortion", Range(0, 100)) = 10
    _RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 1.0
  }
  SubShader {
    // 1.队列设置成透明的可以保证渲染该物体的时候,其他所有不透明的物体都已经被渲染到屏幕上了
    //  这样GrabPass保存屏幕图像的时候才能完整
    // 2.渲染类型设置为不透明是为了使用着色器替换的时候,物体可以在被需要时正确的渲染
    Tags { "Queue"="Transparent" "RenderType"="Opaque" }
 
    // 抓取屏幕图像并保存到纹理 _RefractionTex 中
    GrabPass { "_RefractionTex" }
 
    Pass {  
      CGPROGRAM
 
      #pragma vertex vert
      #pragma fragment frag
 
      #include "UnityCG.cginc"
 
      sampler2D _MainTex;
      float4 _MainTex_ST;
      sampler2D _BumpMap;
      float4 _BumpMap_ST;
      samplerCUBE _Cubemap;
      float _Distortion;
      fixed _RefractAmount;
      sampler2D _RefractionTex;
      // 可以得到系统保存的纹素的尺寸大小 1/256,1/512
      // 对屏幕图像坐标采样进行偏移的时候需要使用该变量
      float4 _RefractionTex_TexelSize;
 
      struct a2v {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
        float4 tangent : TANGENT;
        float2 texcoord: TEXCOORD0;
      };
 
      struct v2f {
        float4 pos : SV_POSITION;
        float4 scrPos : TEXCOORD0;
        float4 uv : TEXCOORD1;
        float4 TtoW0 : TEXCOORD2;
        float4 TtoW1 : TEXCOORD3;
        float4 TtoW2 : TEXCOORD4;
      };
 
      v2f vert (a2v v) {
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
 
        // 得到对应被抓取的屏幕图像的采样坐标
        o.scrPos = ComputeGrabScreenPos(o.pos);
 
        // 原图和法线贴图公用同一套UV坐标,进行纹理偏移缩放设置
        o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
        o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
 
        // 世界方向
        float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
 
        // 法线世界方向
        fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
 
        // 切线世界方向
        fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
 
        // 世界副切线方向
        fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
 
        // 定义:切线空间到世界空间的变换矩阵
        // 所有的TBN都从切线空间转换到了世界空间
        o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
        o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
        o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
 
        return o;
      }
 
      fixed4 frag (v2f i) : SV_Target {   
        // 世界空间
        float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
 
        // 世界空间下的观察方向
        fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
 
        // 对法线贴图进行采样,并使用UnpackNormal解压*2-1,但实际上法线贴图在切线空间下
        // 所以需要将bump从切线空间转换到世界空间
        fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
 
        // 对采样坐标进行偏移
        float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
        i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
 
        // 对屏幕纹理进行采样
        fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
 
        // 将bump从切线空间转换到世界空间
        // TtoW0的xyz:T的X,B的X,N的X
        // 用点积得到一个常量
        bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
 
        // 用法线贴图求反射方向
        fixed3 reflDir = reflect(-worldViewDir, bump);
 
        // 主纹理采样
        fixed4 texColor = tex2D(_MainTex, i.uv.xy);
 
        // 对_Cubemap进行纹理采样,使用反射方向
        fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb;
 
        // 反射颜色+折射颜色
        fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;
 
        return fixed4(finalColor, 1);
      }
 
      ENDCG
    }
  }
 
  FallBack "Diffuse"
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/sinat_20559947/article/details/79236820

延伸 · 阅读

精彩推荐
  • C#Windows系统中使用C#读取文本文件内容的小示例

    Windows系统中使用C#读取文本文件内容的小示例

    这篇文章主要介绍了Windows系统中使用C#读取文本文件内容的小示例,包括一次一行地读取文本文件的方法,需要的朋友可以参考下...

    C#教程网10762021-11-11
  • C#详解C#的设计模式编程之抽象工厂模式的应用

    详解C#的设计模式编程之抽象工厂模式的应用

    这篇文章主要介绍了C#的设计模式编程之抽象工厂模式的应用,注意区分一下简单工厂模式、工厂方法模式和抽象工厂模式概念之间的区别,需要的朋友可以参...

    张龙豪6522021-11-12
  • C#在Winform框架界面中改变并存储界面皮肤样式的方法

    在Winform框架界面中改变并存储界面皮肤样式的方法

    下面小编就为大家分享一篇在Winform框架界面中改变并存储界面皮肤样式的方法,具有很好的参考价值,希望对大家有所帮助...

    伍华聪6302022-02-13
  • C#C#基础知识之this关键字介绍

    C#基础知识之this关键字介绍

    本文主要介绍this关键字的几种使用方法,this可以代表当前实例,可以调用其他构造函数,还可以用来构建索引器,这里都有一一举例说明。...

    Swich3722021-11-19
  • C#C#编程实现连接ACCESS数据库实例详解

    C#编程实现连接ACCESS数据库实例详解

    这篇文章主要介绍了C#编程实现连接ACCESS数据库的方法,以实例形式较为详细的分析了C#连接access数据库的具体步骤与相关技巧,具有一定参考借鉴价值,需要的...

    期待秋天的叶6972021-11-05
  • C#C# Redis学习系列(二)Redis基本设置

    C# Redis学习系列(二)Redis基本设置

    这篇文章主要为大家分享了C# Redis学习系列教程第二篇, Redis基本设置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    change_4_now5332022-01-04
  • C#C#停止线程的方法

    C#停止线程的方法

    这篇文章主要介绍了C#停止线程的方法,实例分析了C#正确停止线程的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    我心依旧12142021-10-20
  • C#WinForm IP地址输入框控件实现

    WinForm IP地址输入框控件实现

    这篇文章主要为大家详细介绍了WinForm IP地址输入框控件的实现代码,基于VS2010模拟windows系统自带IP输入框,具有一定的参考价值,感兴趣的小伙伴们可以参...

    zf152568888396302022-02-23