Unity中shader实现绘制六边形网格

来源:互联网 发布:centos 7如何安装rpm包 编辑:程序博客网 时间:2024/05/17 06:31

上一篇 绘制一个正六边形的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    }}}

注释掉的代码可以在网格中红色填充显示制定坐标的格子,打开注释后如图。

这里写图片描述

效果很不错,可以试着放到立方体或者球上看看。

原创粉丝点击