Страница 1 из 1

Шейдер обводки гексагонов

СообщениеДобавлено: 30 дек 2016, 13:36
Friend123
Коллеги, всех с наступающим новым годом!
Под закат года столкнулся с задачей, решения которой пока не нашел.
Задача - сделать обводку (по границе) у группы объединенных гексагонов. Логично, что это делается шейдером, но в написании такого знаний нет, поэтому был взят нужный с просторов сети.
Но на выходе он не отрисовывает обводку объекта, получается, что сверху объект белый (основной цвет материала), снизу черный (цвет обводки). Возможно это связано с тем, что объект-гексагон строится программно, код ниже.

Шейдер:
Синтаксис:
Используется 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"
 }
 


Создание гексагона:
Синтаксис:
Используется 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;
        }
 


Результат:
Изображение

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 16 янв 2017, 13:01
Bill Gates
Проблема в том, что он плоский

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 16 янв 2017, 16:34
Friend123
Bill Gates писал(а):Проблема в том, что он плоский

Я тут кучу времени потратил на это дело, почти получилось что надо. Импортировал нативный пакет с имейдж эффектами юнити, там есть такой эффект Edge Detection (вешается на камеру), настройкой Mode = Triangle Luminance получается очень близкое к нужному результату (скрин ниже) - границы появились, но если соседние объекты используют одинаковый материал, то границы (внутренние) между ними не рисуются. Возможно что-то надо в шейдере изменить, только не знаю что.
Изображение

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 17 янв 2017, 07:43
Bill Gates
Пост-эффект использовать не очень хорошо, т.к. придется делать две камеры. Первая рендерит гексагоны с обводкой, а вторая все остальное, — это бьет по производительности.

границы появились, но если соседние объекты используют одинаковый материал, то границы (внутренние) между ними не рисуются


Делайте инстанс материала.

У вас гексагональные области являются одним объектом или состоят из множество отдельных мешей-гексагонов?

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 17 янв 2017, 10:11
Friend123
Bill Gates писал(а):Пост-эффект использовать не очень хорошо, т.к. придется делать две камеры. Первая рендерит гексагоны с обводкой, а вторая все остальное, — это бьет по производительности.

Соглашусь, но пока это единственной работающий вариант. Вариант с использованием шейдера обводки на материале - не получилось ничего сделать.

границы появились, но если соседние объекты используют одинаковый материал, то границы (внутренние) между ними не рисуются


Делайте инстанс материала.

У вас гексагональные области являются одним объектом или состоят из множество отдельных мешей-гексагонов?


Область является одним объектом.

Более того, в этой версии юнити когда в редакторе выделяешь объект - он обводится оранжевым цветом. На офф форуме в теме https://forum.unity3d.com/threads/selection-outline.429292/#post-2776318 объясняется как юнитеки это сделали. Я попробовал их шейдер обводки, но тоже эффекта ноль (нет никаких оранжевых обводок). Может че-то не так делаю. Не могу никак понять.

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 17 янв 2017, 10:51
Bill Gates
Киньте куда-нибудь unity package с парой гексагональных мешей и дайте ссылку. Я помучаю.

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 18 янв 2017, 11:00
Friend123
Bill Gates писал(а):Киньте куда-нибудь unity package с парой гексагональных мешей и дайте ссылку. Я помучаю.

Выложил сюда: http://my-files.ru/uhuf9w

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 18 янв 2017, 14:40
kripto289
Bill Gates писал(а):Пост-эффект использовать не очень хорошо, т.к. придется делать две камеры. Первая рендерит гексагоны с обводкой, а вторая все остальное, — это бьет по производительности.

Это ваши предположения или есть тесты?
Если мне надо отрендерить 200 объектов и наложить постэффект, то разницы между 1 камера = 200 объектов и 2 камеры = 100 быть не должно.

Re: Шейдер обводки гексагонов

СообщениеДобавлено: 31 янв 2017, 14:39
Friend123
Коллеги, помогите кто разбирается в шейдерах.
Что в этом нативном шейдере нужно исправить, чтобы границы рисовались не только внешние, но и внутренние между одинаковыми материалами (между разными материалами рисуется все границы - и внутренние, и внешние)?