問題背景
在做地形模塊時,需要根據實際地形高度畫出世界相應的等高線,以及根據高度做顏色漸變,以及剖切功能。
解決方法
通過像素點在世界坐標系下的真實高度值來判斷計算繪制等高線,剖切功能以及顏色漸變均有世界坐標實際高度值來判斷,具體邏輯在代碼中,這些均 在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:剖切功能:在於實際坐標點與剖切面的夾角選擇性剔除。漸變功能:根據高度區間變換做的混合,等高線:高度值根據設定參數計算,插值出等高線。
這里是我功能源代碼,這里做了剖切和顏色漸變和光照,提供給大家做個參考吧。
效果如下: