Под закат года столкнулся с задачей, решения которой пока не нашел.
Задача - сделать обводку (по границе) у группы объединенных гексагонов. Логично, что это делается шейдером, но в написании такого знаний нет, поэтому был взят нужный с просторов сети.
Но на выходе он не отрисовывает обводку объекта, получается, что сверху объект белый (основной цвет материала), снизу черный (цвет обводки). Возможно это связано с тем, что объект-гексагон строится программно, код ниже.
Шейдер:
Синтаксис:
Используется csharp
Shader "Self/Border Diffuse"
{
Properties
{
_Color("Main Color", Color) = (0,0,0,1)
_OutlineColor("Border Color", Color) = (0,1,0,1)
_Outline("Border width", Range(0.002, 0.1)) = 0.1
_MainTex("Base (RGB)", 2D) = "white" { }
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
UsePass "Diffuse/FORWARD"
Pass
{
Name "OUTLINE"
Tags{ "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float _Outline;
uniform float4 _OutlineColor;
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
float4 vert(appdata v) : SV_POSITION
{
float4 pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul((float3x3)UNITY_MATRIX_MV, v.normal);
norm.x *= UNITY_MATRIX_P[0][0];
norm.y *= UNITY_MATRIX_P[1][1];
pos.xy += norm.xy * pos.z * _Outline;
return pos;
}
float4 frag() : SV_TARGET
{
return _OutlineColor;
}
ENDCG
}
}
Fallback "Diffuse"
}
{
Properties
{
_Color("Main Color", Color) = (0,0,0,1)
_OutlineColor("Border Color", Color) = (0,1,0,1)
_Outline("Border width", Range(0.002, 0.1)) = 0.1
_MainTex("Base (RGB)", 2D) = "white" { }
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
UsePass "Diffuse/FORWARD"
Pass
{
Name "OUTLINE"
Tags{ "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float _Outline;
uniform float4 _OutlineColor;
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
float4 vert(appdata v) : SV_POSITION
{
float4 pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul((float3x3)UNITY_MATRIX_MV, v.normal);
norm.x *= UNITY_MATRIX_P[0][0];
norm.y *= UNITY_MATRIX_P[1][1];
pos.xy += norm.xy * pos.z * _Outline;
return pos;
}
float4 frag() : SV_TARGET
{
return _OutlineColor;
}
ENDCG
}
}
Fallback "Diffuse"
}
Создание гексагона:
Синтаксис:
Используется csharp
public GameObject MakeHex (int offset, float scale) {
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[7];
//Center
vertices[0] = Vector3.zero;
vertices[1] = GetVertexPos(0 + offset) * scale;
vertices[2] = GetVertexPos(60 + offset) * scale;
vertices[3] = GetVertexPos(120 + offset) * scale;
vertices[4] = GetVertexPos(180 + offset) * scale;
vertices[5] = GetVertexPos(240 + offset) * scale;
vertices[6] = GetVertexPos(300 + offset) * scale;
int[] triangles = new int[18];
//Top
triangles[0] = 0;
triangles[1] = 2;
triangles[2] = 1;
//Bottom
triangles[3] = 0;
triangles[4] = 3;
triangles[5] = 2;
//Bottom Left
triangles[6] = 0;
triangles[7] = 4;
triangles[8] = 3;
//Bottom Right
triangles[9] = 0;
triangles[10] = 5;
triangles[11] = 4;
//Top Right
triangles[12] = 0;
triangles[13] = 6;
triangles[14] = 5;
//Top Left
triangles[15] = 0;
triangles[16] = 1;
triangles[17] = 6;
Vector2[] uv = new Vector2[7];
// Center
uv[0] = new Vector2(.5f, .5f);
uv[1] = new Vector2(1f, .5f); // Top Left
uv[2] = new Vector2(.75f, .935f); // Top Right
uv[3] = new Vector2(.25f, 0.935f); // Bottom Right
uv[4] = new Vector2(0, 0.5f); // Bottom Left
uv[5] = new Vector2(.25f, .065f); // Center Bottom Left
uv[6] = new Vector2(.75f, .065f); // Bottom Left
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
mesh.RecalculateNormals();
GameObject o = new GameObject("New Hex");
o.AddComponent<MeshRenderer>();
o.AddComponent<MeshFilter>();
o.GetComponent<MeshFilter>().mesh = mesh;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
o.AddComponent<MeshCollider>();
return o;
}
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[7];
//Center
vertices[0] = Vector3.zero;
vertices[1] = GetVertexPos(0 + offset) * scale;
vertices[2] = GetVertexPos(60 + offset) * scale;
vertices[3] = GetVertexPos(120 + offset) * scale;
vertices[4] = GetVertexPos(180 + offset) * scale;
vertices[5] = GetVertexPos(240 + offset) * scale;
vertices[6] = GetVertexPos(300 + offset) * scale;
int[] triangles = new int[18];
//Top
triangles[0] = 0;
triangles[1] = 2;
triangles[2] = 1;
//Bottom
triangles[3] = 0;
triangles[4] = 3;
triangles[5] = 2;
//Bottom Left
triangles[6] = 0;
triangles[7] = 4;
triangles[8] = 3;
//Bottom Right
triangles[9] = 0;
triangles[10] = 5;
triangles[11] = 4;
//Top Right
triangles[12] = 0;
triangles[13] = 6;
triangles[14] = 5;
//Top Left
triangles[15] = 0;
triangles[16] = 1;
triangles[17] = 6;
Vector2[] uv = new Vector2[7];
// Center
uv[0] = new Vector2(.5f, .5f);
uv[1] = new Vector2(1f, .5f); // Top Left
uv[2] = new Vector2(.75f, .935f); // Top Right
uv[3] = new Vector2(.25f, 0.935f); // Bottom Right
uv[4] = new Vector2(0, 0.5f); // Bottom Left
uv[5] = new Vector2(.25f, .065f); // Center Bottom Left
uv[6] = new Vector2(.75f, .065f); // Bottom Left
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
mesh.RecalculateNormals();
GameObject o = new GameObject("New Hex");
o.AddComponent<MeshRenderer>();
o.AddComponent<MeshFilter>();
o.GetComponent<MeshFilter>().mesh = mesh;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
o.AddComponent<MeshCollider>();
return o;
}
Результат: