1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| Shader "Custom/URP/HexagonMap" { Properties { // 六边形参数 _HexScale ("六边形缩放", Float) = 5.0 _BorderWidth ("边界线宽度", Range(0, 0.1)) = 0.03 _BorderColor ("边界线颜色", Color) = (0.2, 0.2, 0.2, 1.0)
// 悬停效果 _HoveredCellID ("悬停格 ID(XY)", Vector) = (-1, -1, 0, 0) _HoverColor ("悬停颜色", Color) = (1.0, 0.8, 0.2, 0.5) _HoverPulseSpeed ("高亮脉冲速度", Float) = 2.0
// 地图数据纹理(R=地形类型, G=单位标记, B=选中状态) _MapDataTex ("地图数据纹理", 2D) = "black" {}
// 地形颜色 _GrassColor ("草原色", Color) = (0.3, 0.6, 0.2, 1) _DesertColor ("沙漠色", Color) = (0.8, 0.7, 0.3, 1) _WaterColor ("水域色", Color) = (0.1, 0.3, 0.7, 1) _MountainColor ("山脉色", Color) = (0.5, 0.4, 0.35, 1) }
SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
Pass { Tags { "LightMode" = "UniversalForward" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
TEXTURE2D(_MapDataTex); SAMPLER(sampler_MapDataTex);
CBUFFER_START(UnityPerMaterial) float _HexScale; float _BorderWidth; float4 _BorderColor; float4 _HoveredCellID; float4 _HoverColor; float _HoverPulseSpeed; float4 _GrassColor, _DesertColor, _WaterColor, _MountainColor; CBUFFER_END
struct Attributes { float4 posOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 posCS : SV_POSITION; float2 uv : TEXCOORD0; };
Varyings vert(Attributes IN) { Varyings OUT; OUT.posCS = TransformObjectToHClip(IN.posOS.xyz); OUT.uv = IN.uv; return OUT; }
// 六边形网格核心函数 // 返回:xy = 格子内局部坐标([-0.5, 0.5]),zw = 格子 ID(整数坐标) float4 HexGrid(float2 p) { // 使用轴坐标系(Axial Coordinates)计算六边形格子 // 尖顶朝上的六边形 float2 q = float2(p.x * 1.1547005, p.y + p.x * 0.5773503); // 转换到倾斜坐标 float2 pi = floor(q); float2 pf = frac(q);
float v = fmod(pi.x + pi.y, 3.0); // 确定三角形类型
float ca = step(1.0, v); float cb = step(2.0, v);
// 候选格子中心 float2 ma = step(pf.xy, pf.yx);
// 选择最近的六边形中心 float2 cellID; float2 localPos;
if (ca < 0.5) { cellID = pi + float2(1.0 - ma.x, 1.0 - ma.y); localPos = pf - float2(1.0 - ma.x, 1.0 - ma.y); } else if (cb < 0.5) { cellID = pi + float2(ma.x, 1.0 - ma.y); localPos = pf - float2(ma.x, 1.0 - ma.y); } else { cellID = pi + float2(1.0 - ma.x, ma.y); localPos = pf - float2(1.0 - ma.x, ma.y); }
return float4(localPos, cellID); }
// 六边形 SDF(正六边形) float HexSDF(float2 p) { p = abs(p); return max(dot(p, float2(0.866025, 0.5)), p.y); }
// 简单哈希(格子 ID → 颜色) float Hash21(float2 p) { return frac(sin(dot(p, float2(127.1, 311.7))) * 43758.5453); }
half4 frag(Varyings IN) : SV_Target { float2 uv = (IN.uv * 2.0 - 1.0) * _HexScale;
// 获取六边形格子信息 float4 hexInfo = HexGrid(uv); float2 localPos = hexInfo.xy; float2 cellID = hexInfo.zw;
// 六边形 SDF(用于边界线) float hexDist = HexSDF(localPos); float border = smoothstep(0.5 - _BorderWidth, 0.5, hexDist);
// 从地图数据纹理读取格子类型 // 将 cellID 映射到纹理 UV float2 mapUV = (cellID + float2(_HexScale, _HexScale)) / (float2(_HexScale, _HexScale) * 2.0); float4 mapData = SAMPLE_TEXTURE2D(_MapDataTex, sampler_MapDataTex, mapUV); float terrainType = mapData.r; // [0,1] 映射到 4 种地形
// 根据地形类型选择颜色 half3 terrainColor; if (terrainType < 0.25) terrainColor = _GrassColor.rgb; else if (terrainType < 0.5) terrainColor = _DesertColor.rgb; else if (terrainType < 0.75) terrainColor = _WaterColor.rgb; else terrainColor = _MountainColor.rgb;
// 也可以用随机颜色(测试用) // float hue = Hash21(cellID); // terrainColor = 0.5 + 0.5 * cos(float3(0, 2.094, 4.189) + hue * 6.28);
// 悬停高亮效果 float2 hoveredID = _HoveredCellID.xy; bool isHovered = (abs(cellID.x - hoveredID.x) < 0.5) && (abs(cellID.y - hoveredID.y) < 0.5); float pulse = 0.5 + 0.5 * sin(_Time.y * _HoverPulseSpeed); float hoverStrength = isHovered ? (_HoverColor.a * pulse) : 0.0; terrainColor = lerp(terrainColor, _HoverColor.rgb, hoverStrength);
// 单位标记(地图数据 G 通道) if (mapData.g > 0.5) { // 在格子中心绘制小圆点表示单位 float unitDot = smoothstep(0.15, 0.1, length(localPos)); terrainColor = lerp(terrainColor, float3(1, 0.2, 0.2), unitDot); }
// 混合边界线 half3 finalColor = lerp(terrainColor, _BorderColor.rgb, border);
return half4(finalColor, 1.0); } ENDHLSL } } }
|