上一篇 绘制一个正六边形的shader 中实现了在面片上绘制单一的六边形。结合上上篇的六边形网格向量工具,可以创建大量的六边形来实现绘制一个六边形网格。
然而这样的绘制问题很明显,顶点数较多,每一个六边形用掉4个顶点。。。那我为什么不去直接用6个顶点的mesh呢?(手动滑稽)。
试想一下如果我有10000个格子,就要为了它绘制40000个顶点。。。
还有一种很常用的方式,画出一张六边形的贴图,然后用平铺的方式铺出六边形的网格,然而这样的方式六边形位置精度又很难保证,而且很容易变形。入下图中就有变形,注意材质的tiling。
综合这些因素,最终决定在上一张的shader基础上扩展出一个shader来实现这种网格的绘制。(网上其他人写了一堆if else的shader 我直接跳过了。。。)。最终实现效果如下图:
下面是shader的最终实现。
其中EdgeColor为边框的颜色,Color为背景的颜色,Column为横排格子数量,Edge为边框宽度占格子宽度(不是半径)占比,Center的xy为0,0坐标格子所在的UV位置,zw为格子整体便宜的格子百分比。
Shader "Unlit/Hex2" {
Properties {
_EdgeColor ("Edge Color", Color) = (1,1,1,1)
_Color ("BG Color", Color) = (1,1,1,1)
_Colmun ("Colmun", float) = 1
_Edge ("Edge Width", Range(0,1)) = 0
_Center ("Center(xy) OffsetX(zw)", Vector) = (0,0,0,0)
_Target ("A(xy)", Vector) = (0,0,0,0)
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(0)
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
fixed4 _EdgeColor;
fixed _Colmun;
fixed _Edge;
fixed4 _Target;
fixed4 _Center;
v2f vert (appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f input) : COLOR
{
//fixed4 col = _EdgeColor;
fixed size = 0.5 / (_Colmun * 0.86602540378445);
fixed2 pixel = input.uv.xy + fixed2( 2 * size * _Center.z - _Center.x, 2 * size * _Center.w - _Center.y);
fixed q = (pixel.x * 0.57735026918963 - pixel.y *0.33333333333) / size;
fixed r = pixel.y * 0.66666666666 / size;
fixed rx = round(q);
fixed ry = round(-q - r);
fixed rz = round(r);
fixed yx = step(abs(ry + q + r),abs(rx - q));
fixed zx = step(abs(rz - r),abs(rx - q));
fixed zy = step(abs(rz - r),abs(ry + q + r));
rx = (yx * zx) * (-ry - rz) + (1-yx * zx ) * rx;
ry = (zy- yx*zx*zy) * (-rx - rz) + (1- zy+yx*zx*zy) *ry;
rz = (1- zy+yx*zx*zy) * (-rx - ry) + (zy-yx * zx* zy) * rz;
fixed3 n[6] = {
fixed3(0, 1, -1),
fixed3(1, 0, -1),
fixed3(-1, 1, 0),
fixed3(1, -1, 0),
fixed3(-1, 0, 1),
fixed3(0, -1, 1),
};
fixed mindis = 2;
for(int i=0; i<6; i++){
fixed2 pos = fixed2(size * 1.73205080756887 * ((rx+n[i].x) + (rz+n[i].z) * 0.5),size * 1.5 *(rz+ n[i].z));
fixed a = distance(pixel.xy,pos);
mindis = min(mindis,a);
}
fixed isEdge = step(abs(distance(pixel.xy,fixed2(size * 1.73205080756887 * (rx + rz * 0.5) ,size * 1.5 * rz))-mindis),size*_Edge);
/*
//目标位置
zx = (_Target.x<0)*ceil(_Target.x) + (_Target.x>0)*floor(_Target.x);
zy = (_Target.y<0)*ceil(_Target.y) + (_Target.y>0)*floor(_Target.y);
fixed hx = zx - (zy - fmod(zy,2)) *0.5;
hx = step(hx,0) * ceil(hx) + step(0,hx) * floor(hx);
fixed hz = zy;
fixed hy = -hx - hz;
fixed isTarget= distance(fixed3(hx,hy,hz), fixed3(rx,ry,rz)) == 0;
fixed4 col = isEdge * _EdgeColor +
(1 - isEdge)*(1-isTarget) * _Color +
(1 - isEdge)* isTarget* fixed4(1,0,0,1);
*/
fixed4 col = isEdge * _EdgeColor +
(1 - isEdge)* _Color;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
注释掉的代码可以在网格中红色填充显示制定坐标的格子,打开注释后如图。
效果很不错,可以试着放到立方体或者球上看看。