unity中Shader实现地形中根据实际高度绘制等高线,剖切功能,颜色渐变等功能

问题背景

在做地形模块时,需要根据实际地形高度画出世界相应的等高线,以及根据高度做颜色渐变,以及剖切功能。

解决方法

通过像素点在世界坐标系下的真实高度值来判断计算绘制等高线,剖切功能以及颜色渐变均有世界坐标实际高度值来判断,具体逻辑在代码中,这些均 在shder 中为的fragment阶段进行,

Shader代码

 1 Shader "Custom/StratumFrontShader" {
 2     Properties{
 3         _FristColir("MainColor", color) = (0,1,0,1)           //第一种颜色:绿
 4         _SecondColor("SecondColor", color) = (1,0,0,1)       //第二种颜色:红
 5         _Diffuse("Diffuse", Color) = (1,1,1,1)
 6 
 7         _K("K", float) = 0.8
 8         _P("P", float) = 0.8
 9     }
10     SubShader {
11         pass {
12             CGPROGRAM
13             #pragma vertex vert
14             #pragma fragment frag
15             #include "unitycg.cginc"
16             #include "Lighting.cginc"
17 
18             fixed4 _Diffuse;
19             uniform half _K;
20             uniform half _P;
21 
22             //高低点颜色
23             fixed4 _FristColir;
24             fixed4 _SecondColor;
25             
26             //高低点值
27             float _HighValue;
28             float _LowValue;
29              
30             //是否显示等高线
31             float _IsShowContour=0;
32 
33             //等高线密集比例
34             float _ContourScale=0.12;
35 
36             //是否是同一颜色
37             float _IsSameColor=0;
38 
39              //是否开启剖切
40              float clipping;
41              float3 clipPlanePosition;
42              float3 clipPlaneNormal;
43 
44 
45             struct v2f {
46                 float4 pos:POSITION;
47                 float y : TEXCOORD1;
48                 fixed3 worldNormal: TEXCOORD2;
49                 fixed3 worldPos: TEXCOORD3;
50             };
51 
52             v2f vert(appdata_base v)
53             {
54                 v2f o;
55                 o.pos = UnityObjectToClipPos(v.vertex);
56                 o.worldNormal = UnityObjectToWorldNormal(v.normal);
57                 o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
58                 o.y = v.vertex.y;
59                 return o;
60             }
61             fixed4 frag(v2f IN):COLOR
62             {
63                float y = IN.y;
64     
65              //剖切逻辑
66               if ( clipping > 0.0 ) {
67                 float  r = dot( normalize( IN.worldPos - clipPlanePosition ), clipPlaneNormal );
68                  if ( r > 0.0 ) {
69                     discard;
70                  }
71                }
72 
73                //等高线
74                float f = abs( frac( y * _ContourScale ) - 0.5 );  
75                float df = fwidth( y * _ContourScale );             
76                float g = smoothstep( -df * 2, df * 2, f );
77                float3 lineCol = float3( 0.0, 0.0, 0.0 );
78 
79                //颜色随高度渐变
80                float h=saturate((_HighValue-y)/(_HighValue-_LowValue));
81                h = _IsSameColor == 0 ? h : 0;//同一种颜色时为第一默认色
82                fixed3 col = lerp( _FristColir, _SecondColor, h );
83                g = _IsShowContour == 0 ? g : 1;
84                col = lerp( lineCol, col, g );
85 
86                //光照
87                float3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
88                float lightDot = clamp(dot(IN.worldNormal, worldLightDir), -1, 1);
89                lightDot = exp(-pow(_K* (1 - lightDot), _P));
90                float3 diffuse = _LightColor0.rgb * col * lightDot;
91                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
92                fixed3 color0=ambient + diffuse;
93 
94               return (fixed4(color0,1));
95             }
96             ENDCG
97         }
98     }
99 }

ps:剖切功能:在于实际坐标点与剖切面的夹角选择性剔除。渐变功能:根据高度区间变换做的混合,等高线:高度值根据设定参数计算,插值出等高线。

这里是我功能源代码,这里做了剖切和颜色渐变和光照,提供给大家做个参考吧。

效果如下:

 

posted @ 2020-03-20 18:25  望景思心  阅读(3166)  评论(3编辑  收藏  举报