着色器实现纪念碑谷中的几何体消失效果 VR资源

492899250 2017-11-10 16:42:48
这是我的第一篇文章,一个很容易理解的着色器。
 
 
 
为了PegJam2017,我决定做一个游戏,灵感来自于纪念碑谷。我想在我的jam游戏中,营造一些类似于下图关卡的气氛。这个jam游戏叫“Isolation”,可以从这里下载。
 
 
 
 
想要实现这种几何体消失在雾/背景中的效果,最简单的方法就是我要在文中分享的着色器。这个着色器所做的就是,根据几何体顶点和y轴0点之间的距离,将顶点逐渐变为一个新的颜色。
 
 
步骤1:声明2个颜色变量。
 
 
[C#] 纯文本查看 复制代码
 
1
fixed4 _Color;
fixed4 _FogColor;
 
_Color是几何体的颜色,_FogColor是最终需要渐变成的背景颜色。
 
步骤2:声明2个新变量,用于对每个对象定义,渐变开始和渐变结束的y坐标。这样可以控制场景中每个物体的最终效果。
 
[C#] 纯文本查看 复制代码
 
1
half _FogStart;
half _FogEnd;
 
步骤3:把顶点的输出坐标转换为游戏的世界坐标,以便计算特效的开始坐标和结束的y坐标。
 
 
[C#] 纯文本查看 复制代码
 
float4 pos = mul(unity_ObjectToWorld, v.vertex).xyzw;
 
 
步骤4:需要计算一下这个效果的而影响范围,它基于顶点的y坐标,然后用saturate函数将结果限制在0到1之间。
 
 
[C#] 纯文本查看 复制代码
 
data.fog = saturate((_FogStart - pos.y) / (_FogStart - _FogEnd));
 
 
步骤5:计算最终颜色,利用步骤4中计算的data.fog的强度,在_Color和_FogColor之间进行差值。color.rgb是由unity标准着色器计算的输出颜色,把它和_Color相乘。如果不这样做,会遗漏场景中的阴影和光照信息。
 
 
[C#] 纯文本查看 复制代码
 
color.rgb = lerp(color.rgb * _Color , _FogColor, IN.fog);
 
 
最后,将它嵌入到unity中。需要创建一个新的材质,使用这个着色器,然后将它应用到所有的3d资源。使背景色和雾的颜色相同,同时还需要将相机的Background属性设置为雾的颜色。
 
 
 
这样就完成了一个简单的着色器,它的效果和纪念碑谷的很相似,而且不需要为任何模型创建自定义纹理。这个着色器可用于任何颜色、光照和阴影,据我实践,对模型上的纹理也有效。因为这个效果是用着色器创建的,当物体从地面向上移动时,会有一个很酷的渐显效果。
 
 
 
 
通过调整开始和结束位置,可以改变效果的影响范围,甚至可以让它渐隐到天空中而不是地面。
 
 
 
感谢阅读!
 
[C#] 纯文本查看 复制代码
 
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Shader "Custom/Fog"
 
{
 
Properties
 
{
 
_Color("Color", Color) = (1,1,1,1)
 
_MainTex("Texture", 2D) = "white" {}
 
_FogColor("Fog Color", Color) = (0.3, 0.4, 0.7, 1.0)
 
_FogStart("Fog Start", float) = 0
 
_FogEnd("Fog End", float) = 0
 
}
 
  
 
SubShader
 
{
 
Tags{ "RenderType" = "Opaque" }
 
  
 
CGPROGRAM
 
  
 
#pragma surface surf Lambert finalcolor:mycolor vertex:myvert
 
  
 
struct Input
 
{
 
float2 uv_MainTex;
 
half fog;
 
};
 
  
 
fixed4 _Color;
 
fixed4 _FogColor;
 
half _FogStart;
 
half _FogEnd;
 
sampler2D _MainTex;
 
  
 
void myvert(inout appdata_full v, out Input data)
 
{
 
UNITY_INITIALIZE_OUTPUT(Input,data);
 
float4 pos = mul(unity_ObjectToWorld, v.vertex).xyzw;
 
data.fog = saturate((_FogStart - pos.y) / (_FogStart - _FogEnd));
 
}
 
  
 
void mycolor(Input IN, SurfaceOutput o, inout fixed4 color)
 
{
 
fixed3 fogColor = _FogColor.rgb;
 
fixed3 tintColor = _Color.rgb;
 
#ifdef UNITY_PASS_FORWARDADD
 
fogColor = 0;
 
#endif
 
color.rgb = lerp(color.rgb * tintColor, fogColor, IN.fog);
 
}
 
  
 
void surf(Input IN, inout SurfaceOutput o)
 
{
 
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
 
}
 
  
 
ENDCG
 
}
 
  
 
Fallback "Diffuse"
 
}
 
99VR视界二维码
热门推荐
Hot Recommended
在线客服