90 lines
3.6 KiB
GLSL
90 lines
3.6 KiB
GLSL
Shader "Custom/HexGridSimple"
|
|
{
|
|
Properties
|
|
{
|
|
_BaseColor ("Base Color (alpha 0 = прозрачный)", Color) = (0,0,0,0)
|
|
_LineColor ("Line Color", Color) = (1,1,1,1)
|
|
_CellSize ("Cell Size (радиус шестигранника)", Float) = 1
|
|
_LineWidth ("Line Width (доля от размера клетки)", Range(0.001, 0.5)) = 0.05
|
|
_GridOrigin ("Grid Origin (XZ)", Vector) = (0,0,0,0)
|
|
}
|
|
SubShader
|
|
{
|
|
Tags { "RenderType"="Transparent" "Queue"="Transparent" "RenderPipeline"="UniversalPipeline" }
|
|
|
|
Pass
|
|
{
|
|
Name "HexGrid"
|
|
Tags { "LightMode"="UniversalForward" }
|
|
Blend One OneMinusSrcAlpha // premultiplied alpha
|
|
ZWrite Off
|
|
Cull Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
half4 _BaseColor;
|
|
half4 _LineColor;
|
|
float _CellSize;
|
|
float _LineWidth;
|
|
float4 _GridOrigin;
|
|
CBUFFER_END
|
|
|
|
struct Attributes { float4 positionOS : POSITION; };
|
|
struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; };
|
|
|
|
Varyings vert(Attributes IN)
|
|
{
|
|
Varyings OUT;
|
|
OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
|
|
OUT.positionCS = TransformWorldToHClip(OUT.positionWS);
|
|
return OUT;
|
|
}
|
|
|
|
static const float SQRT3 = 1.7320508;
|
|
static const float HALF_SQRT3 = 0.8660254;
|
|
|
|
// Центр шестигранника, содержащего точку p (pointy-top, R = радиус описанной окружности)
|
|
float2 HexCenter(float2 p, float R)
|
|
{
|
|
float q = (SQRT3 / 3.0 * p.x - 1.0 / 3.0 * p.y) / R;
|
|
float r = (2.0 / 3.0 * p.y) / R;
|
|
float3 c = float3(q, -q - r, r); // cube
|
|
float3 rc = round(c);
|
|
float3 d = abs(rc - c);
|
|
if (d.x > d.y && d.x > d.z) rc.x = -rc.y - rc.z;
|
|
else if (d.y > d.z) rc.y = -rc.x - rc.z;
|
|
else rc.z = -rc.x - rc.y;
|
|
return float2(R * SQRT3 * (rc.x + rc.z * 0.5), R * 1.5 * rc.z);
|
|
}
|
|
|
|
// Расстояние от точки (относительно центра) до ближайшего ребра
|
|
float HexEdgeDist(float2 d, float R)
|
|
{
|
|
float h = max(abs(d.x),
|
|
max(abs( 0.5 * d.x + HALF_SQRT3 * d.y),
|
|
abs(-0.5 * d.x + HALF_SQRT3 * d.y)));
|
|
return HALF_SQRT3 * R - h;
|
|
}
|
|
|
|
half4 frag(Varyings IN) : SV_Target
|
|
{
|
|
float2 p = IN.positionWS.xz - _GridOrigin.xy;
|
|
float2 c = HexCenter(p, _CellSize);
|
|
float e = HexEdgeDist(p - c, _CellSize);
|
|
|
|
float t = 0.5 * _LineWidth * _CellSize; // половина толщины линии
|
|
float aa = fwidth(e);
|
|
float lineMask = 1.0 - smoothstep(t - aa, t + aa, e);
|
|
|
|
half4 b = half4(_BaseColor.rgb * _BaseColor.a, _BaseColor.a);
|
|
half4 l = half4(_LineColor.rgb * _LineColor.a, _LineColor.a);
|
|
return lerp(b, l, lineMask);
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
} |