Обводка объекта, полученного комбинированием

Общие вопросы о Unity3D

Обводка объекта, полученного комбинированием

Сообщение Friend123 16 фев 2017, 17:01

Коллеги, добрый день.
Вот уже N-ую неделю бьюсь над решением поставленной задачи, создал несколько тем (например тут: http://unity3d.ru/distribution/viewtopic.php?f=35&t=41637), но безрезультатно.

А цель вроде бы простая: необходимо обвести объект по границе, например черными линиями (например как в цивилизации или европе). Объект собирается из нескольких единиц/десятков гексагонов с помощью функции CombineMesh. Пробовал что-то подобное для решения сделать шейдером, но не получилось. Максимум, что помогло - это использование эффекта на камеру из нативного пакета эффектов - Edge Detection - он обводит объекты нормально, но если у соседних объектов одинаковый материал, то граница между ними не рисуется (а рисовать ее нужно).

Возможно, не стоит совсем использовать эти шейдеры. Возможно есть более простое решение.

Буду весьма благодарен за помощь!!!
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ

Re: Обводка объекта, полученного комбинированием

Сообщение Paul Siberdt 16 фев 2017, 17:30

А дефолтовая обводка от ShaderForge не работает?

Синтаксис:
Используется glsl
// Shader created with Shader Forge v1.34
// Shader Forge (c) Neat Corporation / Joachim Holmer - http://www.acegikmo.com/shaderforge/
// Note: Manually altering this data may prevent you from opening it in Shader Forge
/*SF_DATA;ver:1.34;sub:START;pass:START;ps:flbk:,iptp:0,cusa:False,bamd:0,lico:1,lgpr:1,limd:1,spmd:1,trmd:0,grmd:0,uamb:True,mssp:True,bkdf:False,hqlp:False,rprd:False,enco:False,rmgx:True,rpth:0,vtps:0,hqsc:True,nrmq:1,nrsp:0,vomd:0,spxs:False,tesm:0,olmd:1,culm:0,bsrc:0,bdst:1,dpts:2,wrdp:True,dith:0,atcv:False,rfrpo:True,rfrpn:Refraction,coma:15,ufog:True,aust:True,igpj:False,qofs:0,qpre:1,rntp:1,fgom:False,fgoc:False,fgod:False,fgor:False,fgmd:0,fgcr:0.5,fgcg:0.5,fgcb:0.5,fgca:1,fgde:0.01,fgrn:0,fgrf:300,stcl:False,stva:128,stmr:255,stmw:255,stcp:6,stps:0,stfa:0,stfz:0,ofsf:0,ofsu:0,f2p0:False,fnsp:False,fnfb:False;n:type:ShaderForge.SFN_Final,id:4013,x:33043,y:32745,varname:node_4013,prsc:2|diff-1304-RGB,olwid-6213-OUT,olcol-1026-RGB;n:type:ShaderForge.SFN_Color,id:1304,x:32443,y:32712,ptovrint:False,ptlb:Color,ptin:_Color,varname:node_1304,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,c1:1,c2:1,c3:1,c4:1;n:type:ShaderForge.SFN_Color,id:1026,x:32443,y:33031,ptovrint:False,ptlb:node_1026,ptin:_node_1026,varname:node_1026,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,c1:1,c2:0.007352948,c3:0.007352948,c4:1;n:type:ShaderForge.SFN_ValueProperty,id:6213,x:32443,y:32925,ptovrint:False,ptlb:node_6213,ptin:_node_6213,varname:node_6213,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,v1:0.2;proporder:1304-1026-6213;pass:END;sub:END;*/

Shader "Shader Forge/testShader" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _node_1026 ("node_1026", Color) = (1,0.007352948,0.007352948,1)
        _node_6213 ("node_6213", Float ) = 0.2
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "Outline"
            Tags {
            }
            Cull Front
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_shadowcaster
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0
            uniform float4 _node_1026;
            uniform float _node_6213;
            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                UNITY_FOG_COORDS(0)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.pos = mul(UNITY_MATRIX_MVP, float4(v.vertex.xyz + v.normal*_node_6213,1) );
                UNITY_TRANSFER_FOG(o,o.pos);
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
                return fixed4(_node_1026.rgb,0);
            }
            ENDCG
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0
            uniform float4 _LightColor0;
            uniform float4 _Color;
            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float4 posWorld : TEXCOORD0;
                float3 normalDir : TEXCOORD1;
                LIGHTING_COORDS(2,3)
                UNITY_FOG_COORDS(4)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                float3 lightColor = _LightColor0.rgb;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
                i.normalDir = normalize(i.normalDir);
                float3 normalDirection = i.normalDir;
                float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
                float3 lightColor = _LightColor0.rgb;
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
/////// Diffuse:
                float NdotL = max(0.0,dot( normalDirection, lightDirection ));
                float3 directDiffuse = max( 0.0, NdotL) * attenColor;
                float3 indirectDiffuse = float3(0,0,0);
                indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light
                float3 diffuseColor = _Color.rgb;
                float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;
/// Final Color:
                float3 finalColor = diffuse;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
        Pass {
            Name "FORWARD_DELTA"
            Tags {
                "LightMode"="ForwardAdd"
            }
            Blend One One
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDADD
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdadd_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0
            uniform float4 _LightColor0;
            uniform float4 _Color;
            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float4 posWorld : TEXCOORD0;
                float3 normalDir : TEXCOORD1;
                LIGHTING_COORDS(2,3)
                UNITY_FOG_COORDS(4)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                float3 lightColor = _LightColor0.rgb;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
                i.normalDir = normalize(i.normalDir);
                float3 normalDirection = i.normalDir;
                float3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,_WorldSpaceLightPos0.w));
                float3 lightColor = _LightColor0.rgb;
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
/////// Diffuse:
                float NdotL = max(0.0,dot( normalDirection, lightDirection ));
                float3 directDiffuse = max( 0.0, NdotL) * attenColor;
                float3 diffuseColor = _Color.rgb;
                float3 diffuse = directDiffuse * diffuseColor;
/// Final Color:
                float3 finalColor = diffuse;
                fixed4 finalRGBA = fixed4(finalColor * 1,0);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
    CustomEditor "ShaderForgeMaterialInspector"
}

 
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Обводка объекта, полученного комбинированием

Сообщение waruiyume 16 фев 2017, 17:39

Она вроде вдоль нормалей распердоливает вершины, а у него плоскость.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Обводка объекта, полученного комбинированием

Сообщение Paul Siberdt 16 фев 2017, 17:43

а.. те самые гесагоны... нууу.. у меня пока мысли не родилось, как и чем их обыграть, разве что строить поверх еще одну карту из граничных гексагонов-обводок.
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Обводка объекта, полученного комбинированием

Сообщение waruiyume 16 фев 2017, 17:49

https://drive.google.com/file/d/0B0dncz ... 4170146208
Взято отсюда(https://www.youtube.com/watch?v=_IwlpwEJ3lE)
нужна та часть которая делает Reject. Не знаю получится ли что-то или нет но это единственное что пришло в голову, кроме рендера в текстуру Id объекта с последующей обрисовкой в постэффекте.
----
Можно попробовать запхнуть координаты центров ячеек в дополнительный UV канал, а потом просто вытолкнуть вершины из центра(в шереных вершинах может получиться (полная Ж) а на границе может и прохляет)
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Обводка объекта, полученного комбинированием

Сообщение bojlahg 16 фев 2017, 20:19

сгенерируй меш с обводкой вот и все дела. и рендерь ее потом хоть в хвост хоть в гриву.
Мои проекты: MahJah Star Factory Cop Car Swash! Spline Editor
Аватара пользователя
bojlahg
UNIверсал
 
Сообщения: 392
Зарегистрирован: 13 авг 2011, 10:57
Откуда: Сатка
Skype: bojlahg
  • Сайт

Re: Обводка объекта, полученного комбинированием

Сообщение Friend123 17 фев 2017, 10:12

Paul Siberdt писал(а):А дефолтовая обводка от ShaderForge не работает?

Попробовал ее, фигня получается какая-то, не четко обводит и совсем не разделяет границы
Изображение

bojlahg писал(а):сгенерируй меш с обводкой вот и все дела. и рендерь ее потом хоть в хвост хоть в гриву.

У меня сначала генерируются гексы, а потом они комбинируются в меш (разной формы).

Код генерации меша (на вход подается объект, дочками которого и являются гексы):
Синтаксис:
Используется csharp
    private void CombineSectorsInRegions(Transform region) {
        MeshFilter[] meshFilters  = region.GetComponentsInChildren<MeshFilter>();
        CombineInstance[] combine = new CombineInstance[meshFilters.Length];

        int n = 0;
        while(n < meshFilters.Length) {
            combine[n].mesh      = meshFilters[n].sharedMesh;
            combine[n].transform = meshFilters[n].transform.localToWorldMatrix;
            meshFilters[n].gameObject.SetActive(false);
            n++;
        }

        region.gameObject.AddComponent<MeshFilter>();
        region.gameObject.AddComponent<MeshRenderer>();        
        region.gameObject.AddComponent<MeshCollider>();

        region.GetComponent<MeshFilter>().mesh = new Mesh();
        region.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
        region.GetComponent<MeshFilter>().mesh.RecalculateNormals();
        region.GetComponent<MeshFilter>().mesh.RecalculateBounds();
        region.GetComponent<MeshCollider>().sharedMesh = region.GetComponent<MeshFilter>().mesh;
       
        region.gameObject.SetActive(true);        
    }
 
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ

Re: Обводка объекта, полученного комбинированием

Сообщение Friend123 21 фев 2017, 11:35

Совершенно случайно нашел в сети шейдер, который практически решает задачу. Границы появились (не смотря на гигантское значение outline width), даже между одинаковыми материалами, но какие-то они нереалистичные.
Изображение

Сам шейдер:
Синтаксис:
Используется csharp
Shader "Outlined/Silhouetted Bumped Mobile" {
     Properties {
         _Color ("Main Color", Color) = (.5,.5,.5,1)
         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
         _Outline ("Outline width", Float) = 4
         _MainTex ("Base (RGB)", 2D) = "white" { }
         _BumpMap ("Bumpmap", 2D) = "bump" {}
     }
 
 CGINCLUDE
 #include "UnityCG.cginc"
 
 struct appdata {
     float4 vertex : POSITION;
     float3 normal : NORMAL;
 };
 
 struct v2f {
     float4 pos : POSITION;
     float4 color : COLOR;
 };
 
 uniform float _Outline;
 uniform float4 _OutlineColor;
 
 v2f vert(appdata v) {
 ////////////////////////////////REPLACE THIS SECTION WITH.../////////////////////////////
 //    // just make a copy of incoming vertex data but scaled according to normal direction
 //    v2f o;
 //    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
 //
 //     float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
 //    float2 offset = TransformViewToProjection(norm.xy);
 //
 //    o.pos.xy += offset * o.pos.z * _Outline;
 
 /////////////////////////////////////////////...THIS PART///////////////////////////
     v2f o;
     o.pos = v.vertex;
     o.pos.xyz += v.normal.xyz *_Outline*0.01;
     o.pos = mul(UNITY_MATRIX_MVP, o.pos);
 
     o.color = _OutlineColor;
     return o;
 }
 ENDCG
 
     SubShader {
         Tags { "Queue" = "Transparent" }
 
         // note that a vertex shader is specified here but its using the one above
         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Off
             ZWrite Off
             //ZTest Always //This is what allows the outline to be seen through other objects
 
             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative
 
 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag
 
 half4 frag(v2f i) : COLOR {
     return i.color;
 }
 ENDCG
         }
 
 
 CGPROGRAM
 #pragma surface surf Lambert
 struct Input {
     float2 uv_MainTex;
     float2 uv_BumpMap;
 };
 sampler2D _MainTex;
 sampler2D _BumpMap;
 uniform float3 _Color;
 void surf(Input IN, inout SurfaceOutput o) {
     o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color;
     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
 }
 ENDCG
 
     }
 
     SubShader {
         Tags { "Queue" = "Transparent" }
 
         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Front
             ZWrite Off
             //ZTest Always
             Offset 15,15
 
             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative
 
             CGPROGRAM
             #pragma vertex vert
             #pragma exclude_renderers gles xbox360 ps3
             ENDCG
             SetTexture [_MainTex] { combine primary }
         }
 
 CGPROGRAM
 #pragma surface surf Lambert
 struct Input {
     float2 uv_MainTex;
     float2 uv_BumpMap;
 };
 sampler2D _MainTex;
 sampler2D _BumpMap;
 uniform float3 _Color;
 void surf(Input IN, inout SurfaceOutput o) {
     o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color;
     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
 }
 ENDCG
 
     }
 
     Fallback "Outlined/Silhouetted Diffuse"
 }
 


Подскажите, кто знаком с шейдерами - какие параметры нужно покрутить или поменять что-то где-то чтобы привести в нормальный человеческий вид границы?
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ

Re: Обводка объекта, полученного комбинированием

Сообщение Tolking 21 фев 2017, 12:49

За это время уже раз 10 можно было было сделать чтобы по краям ставились гексагоны с текстурой нужной обводки...
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2715
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Re: Обводка объекта, полученного комбинированием

Сообщение Friend123 21 фев 2017, 13:18

Tolking писал(а):За это время уже раз 10 можно было было сделать чтобы по краям ставились гексагоны с текстурой нужной обводки...

Хм, интересный вариант. Спасибо за наводку.
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ


Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 10