本文实例为大家分享了unity实现玻璃效果的具体代码,供大家参考,具体内容如下
一、使用cubemap,做一个假反射
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
|
shader "custom/glassshader" { properties { _maincolor( "main color" ,color)=(1,1,1,1) _maintex ( "base (rgb)" , 2d) = "white" {} _cube( "cube" ,cube)= "" {} } subshader { tags { "rendertype" = "opaque" } lod 200 //cull off cgprogram #pragma surface surf lambert alpha fixed4 _maincolor; sampler2d _maintex; samplercube _cube; struct input { float2 uv_maintex; float3 worldrefl; }; void surf (input in , inout surfaceoutput o) { half4 c = tex2d (_maintex, in .uv_maintex); o.albedo = c.rgb*_maincolor.rgb; o.emission=texcube(_cube, in .worldrefl).rgb; o.alpha = c.a*_maincolor.a; } endcg } fallback "diffuse" } |
二、使用grabpass,抓取屏幕纹理,实现实时反射
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
|
shader "unlit/grabglass" { properties { _color( "main color" ,color)=(1,1,1,1) _maintex ( "texture" , 2d) = "white" {} } subshader { tags { "queue" = "transparent" "rendertype" = "opaque" } //opaque lod 100 //绘制半透明物体 关闭深度缓存 zwrite off //透明混合 blend srcalpha oneminussrcalpha //如果没有命名,则可以用_grabtexture来读取,不过开销很大,应用到特殊效果时才去应用 grabpass { "_grabtex" } pass { cgprogram #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "unitycg.cginc" struct appdata { float4 vertex : position; float2 uv : texcoord0; }; struct v2f { float2 uv : texcoord0; unity_fog_coords(1) float4 vertex : sv_position; }; sampler2d _maintex; float4 _maintex_st; fixed4 _color; sampler2d _grabtex; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.uv = transform_tex(v.uv, _maintex); unity_transfer_fog(o,o.vertex); return o; } fixed4 frag (v2f i) : sv_target { // sample the texture fixed4 col = tex2d(_maintex, i.uv)*_color; // apply fog unity_apply_fog(i.fogcoord, col); //调整一下uv float2 uv=i.uv; uv.x=1-uv.x; return col*tex2d(_grabtex,uv); } endcg } } } |
效果如下:
三、使用摄像机实现实时反射
因为grabpass,相对来说消耗较大,只建议用于一些特殊效果,于是这里就借助辅助摄像机,来实现实时反射效果,当然这需要多写一个脚本,同时需要在辅助摄像机中屏蔽玻璃本身
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
|
shader "unlit/cameraglass" { properties { _maintex ( "texture" , 2d) = "white" {} } subshader { tags { "rendertype" = "opaque" } lod 100 pass { cgprogram #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "unitycg.cginc" struct appdata { float4 vertex : position; float2 uv : texcoord0; }; struct v2f { float2 uv : texcoord0; unity_fog_coords(1) float4 vertex : sv_position; }; sampler2d _maintex; float4 _maintex_st; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.uv = transform_tex(v.uv, _maintex); unity_transfer_fog(o,o.vertex); return o; } fixed4 frag (v2f i) : sv_target { // sample the texture 需要调整一下uv fixed4 col = tex2d(_maintex, 1-i.uv); // apply fog unity_apply_fog(i.fogcoord, col); return col; } endcg } } } |
脚本代码如下:
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
|
using unityengine; using system.collections; public class renderglasstexture : monobehaviour { /// <summary> /// 辅助摄像机 /// 原理:就是将辅助摄像机所看到的内容渲染到玻璃物体上,所以就实现了实时反射的镜面效果 /// 因为玻璃也是场景中的物体,所以辅助摄像机也会看见他 /// 所以最好能将玻璃物体单独放在一个层级中,让辅助摄像机不去渲染他 /// </summary> public camera cam; private rendertexture rendertex; /// <summary> /// 玻璃shader /// </summary> public shader glassshader; /// <summary> /// 玻璃材质 /// </summary> private material m_glassmaterial; protected material glassmaterial { get { if (m_glassmaterial == null ) { m_glassmaterial = new material(glassshader); } return m_glassmaterial; } } // use this for initialization void start () { rendertex = new rendertexture(screen.width, screen.height, 16); cam.targettexture = rendertex; } //在摄像机开始裁剪场景之前调用 void onprecull() { glassmaterial.settexture( "_maintex" , rendertex); } //在相机完成场景渲染后调用 void onpostrender() { glassmaterial.settexture( "_maintex" , null ); } } |
效果如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/qq992817263/article/details/50773052