Обводка объекта. Необходимо подкорректировать код.

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

Обводка объекта. Необходимо подкорректировать код.

Сообщение Xtir 18 фев 2017, 00:20

Пошарив по интернету, наткнулся вот на такую статью, там внизу есть ссылка на готовый проект. И у меня есть одна проблема, никак не могу запилить что бы одновременно разные объекты можно было подсветить разными цветами. Кто-нибудь шарит в этом? Может помочь?
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections.Generic;

using UnityStandardAssets.ImageEffects;
using UnityEngine.Rendering;

[RequireComponent(typeof(Camera))]
public class HighlightsFX : MonoBehaviour
{
        #region enums
        public enum HighlightType
        {
                Glow = 0,
                Solid = 1
        }
        public enum SortingType
        {
                Overlay = 3,
                DepthFilter = 4
        }
        public enum FillType
        {
                Fill,
                Outline
        }
        public enum RTResolution
        {
                Quarter = 4,
                Half = 2,
                Full = 1
        }
        #endregion

        #region public vars

    public Renderer objectRenderer;

        public HighlightType m_selectionType = HighlightType.Glow;
        public SortingType m_sortingType = SortingType.DepthFilter;    
        public FillType m_fillType = FillType.Outline;
        public RTResolution m_resolution = RTResolution.Full;

        public string m_occludersTag = "Occluder";
        public Color m_highlightColor;

        #endregion

        #region private field

        private BlurOptimized m_blur;

        private Renderer[] m_occluders = null;

    private Material m_highlightMaterial;
       
        private CommandBuffer m_renderBuffer;

        private int m_RTWidth = 512;
        private int m_RTHeight = 512;

        #endregion

        private void Awake()
        {
                CreateBuffers();
                CreateMaterials();
                SetOccluderObjects();
               
                m_blur = gameObject.AddComponent<BlurOptimized>();
                m_blur.blurShader = Shader.Find("Hidden/FastBlur");
                m_blur.enabled = false;

                m_RTWidth = (int) (Screen.width / (float) m_resolution);
                m_RTHeight = (int) (Screen.height / (float) m_resolution);
        }

        private void CreateBuffers()
        {
                m_renderBuffer = new CommandBuffer();
        }

        private void ClearCommandBuffers()
        {
                m_renderBuffer.Clear();
        }
       
        private void CreateMaterials()
        {
        m_highlightMaterial = new Material(Shader.Find("Custom/Highlight"));
        }

        private void SetOccluderObjects()
        {
                if( string.IsNullOrEmpty(m_occludersTag) )
                        return;
               
                GameObject[] occluderGOs = GameObject.FindGameObjectsWithTag(m_occludersTag);
               
                List<Renderer> occluders = new List<Renderer>();
                foreach( GameObject go in occluderGOs )
                {
                        Renderer renderer = go.GetComponent<Renderer>();
                        if( renderer != null )
                                occluders.Add( renderer );
                }
               
                m_occluders = occluders.ToArray();
        }
       
        private void RenderHighlights( RenderTexture rt)
        {
                RenderTargetIdentifier rtid = new RenderTargetIdentifier(rt);
                m_renderBuffer.SetRenderTarget( rtid );
                       
        m_renderBuffer.DrawRenderer( objectRenderer, m_highlightMaterial, 0, (int) m_sortingType );

                RenderTexture.active = rt;
                Graphics.ExecuteCommandBuffer(m_renderBuffer);
                RenderTexture.active = null;
        }
       
        private void RenderOccluders( RenderTexture rt)
        {
                if( m_occluders == null )
                        return;

                RenderTargetIdentifier rtid = new RenderTargetIdentifier(rt);
                m_renderBuffer.SetRenderTarget( rtid );

                m_renderBuffer.Clear();
               
                foreach(Renderer renderer in m_occluders)
                {      
                        m_renderBuffer.DrawRenderer( renderer, m_highlightMaterial, 0, (int) m_sortingType );
                }

                RenderTexture.active = rt;
                Graphics.ExecuteCommandBuffer(m_renderBuffer);
                RenderTexture.active = null;
        }

        /// Final image composing.
        /// 1. Renders all the highlight objects either with Overlay shader or DepthFilter
        /// 2. Downsamples and blurs the result image using standard BlurOptimized image effect
        /// 3. Renders occluders to the same render texture
        /// 4. Substracts the occlusion map from the blurred image, leaving the highlight area
        /// 5. Renders the result image over the main camera's G-Buffer
        private void OnRenderImage( RenderTexture source, RenderTexture destination )
        {
                RenderTexture highlightRT;

        #if UNITY_ANDROID
        RenderTexture.active = highlightRT = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.ARGB32 );
        #else
        RenderTexture.active = highlightRT = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8);
        #endif
                GL.Clear(true, true, Color.clear);
                RenderTexture.active = null;

                ClearCommandBuffers();

                RenderHighlights(highlightRT);

        #if UNITY_ANDROID
        RenderTexture.active = highlightRT = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.ARGB32 );
        #else
                RenderTexture blurred = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8 );
        #endif

                m_blur.OnRenderImage( highlightRT, blurred );

       
                RenderOccluders(highlightRT);

                if( m_fillType == FillType.Outline )
                {
            #if UNITY_ANDROID
            RenderTexture.active = highlightRT = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.ARGB32 );
            #else
                        RenderTexture occluded = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8);
            #endif

                        // Excluding the original image from the blurred image, leaving out the areal alone
                        m_highlightMaterial.SetTexture("_OccludeMap", highlightRT);
                        Graphics.Blit( blurred, occluded, m_highlightMaterial, 2 );
                        m_highlightMaterial.SetTexture("_OccludeMap", occluded);
                        RenderTexture.ReleaseTemporary(occluded);
                }
                else
                {
                        m_highlightMaterial.SetTexture("_OccludeMap", blurred);
                }

        m_highlightMaterial.SetColor("_Color", m_highlightColor);
        Graphics.Blit(source, destination, m_highlightMaterial, (int)m_selectionType);

                RenderTexture.ReleaseTemporary(blurred);
                RenderTexture.ReleaseTemporary(highlightRT);
        }
}
 
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37

Re: Обводка объекта. Необходимо подкорректировать код.

Сообщение LemanRass 18 фев 2017, 12:15

Просто напиши свой шейдер который будет принимать в качестве параметра главную текстуру персонажа и цвет подсветки.
Применение материала с этим шейдером к конкретному объекту будет заставлять его обводится заданным цветом. Изменение цвета в настройках шейдера даст возможность менять цвет обводки "на лету". Вдобавок если ты освоишь шейдеры, ты еще и сможешь добавить кастомные параметры которые не были задуманы изначально но существенно улучшающие вид. Например толщину обводки и прочее.
И еще один плюс это то, что на уровне шейдера такая задумка будет работать намного быстрее твоих вычислений на С#.
Разработчик SpaceBall
Скрытый текст:
LemanRass
UNIверсал
 
Сообщения: 385
Зарегистрирован: 23 фев 2014, 12:00
Skype: coder.dev

Re: Обводка объекта. Необходимо подкорректировать код.

Сообщение Xtir 18 фев 2017, 12:25

Я в шейдерах вообще полный нуль )))
Там в проекте есть вот такой шейдер
Синтаксис:
Используется csharp
Shader "Custom/Highlight" {
        Properties {
                _Color ("Color", Color) = (1,1,1,1)
                _MainTex ("Main Texture", 2D) = "black" {}
                _OccludeMap ("Occlusion Map", 2D) = "black" {}
        }
       
        SubShader {

                ZTest Always Cull Off ZWrite Off Fog { Mode Off }
                       
                // OVERLAY GLOW        
                Pass {
                        CGPROGRAM
                                #pragma vertex vert_img
                                #pragma fragment frag
                                #pragma fragmentoption ARB_precision_hint_fastest
                                #include "UnityCG.cginc"
                       
                                sampler2D _MainTex;
                                sampler2D _OccludeMap;
                               
                                fixed4 _Color;
                       
                                fixed4 frag(v2f_img IN) : COLOR
                                {
                                        fixed4 mCol = tex2D (_MainTex, IN.uv);

                                        // invert for OPENGL
                                        #if UNITY_UV_STARTS_AT_TOP
                                        IN.uv.y = 1.0 - IN.uv.y;
                                        #endif

                                        fixed3 overCol = tex2D(_OccludeMap, IN.uv).r * _Color.rgb * _Color.a;
                                        return mCol + fixed4(overCol, 1.0);
                                }
                        ENDCG
                }
               
                // OVERLAY SOLID
                Pass {
                        CGPROGRAM
                                #pragma vertex vert_img
                                #pragma fragment frag
                                #pragma fragmentoption ARB_precision_hint_fastest
                                #include "UnityCG.cginc"
                       
                                sampler2D _MainTex;
                                sampler2D _OccludeMap;
                               
                                fixed4 _Color;
                       
                                fixed4 frag(v2f_img IN) : COLOR
                                {
                                        fixed4 mCol = tex2D (_MainTex, IN.uv);

                                        // invert for OPENGL
                                        #if UNITY_UV_STARTS_AT_TOP
                                        IN.uv.y = 1.0 - IN.uv.y;
                                        #endif

                                        fixed oCol = tex2D (_OccludeMap, IN.uv).r;
                                       
                                        fixed solid = step (1.0 - _Color.a, oCol);
                                        return mCol + solid * fixed4(_Color.rgb, 1.0);
                                }
                        ENDCG
                }
       
               
                // OCCLUSION   
                Pass {
                                CGPROGRAM
                                #pragma vertex vert_img
                                #pragma fragment frag
                                #pragma fragmentoption ARB_precision_hint_fastest
                                #include "UnityCG.cginc"
                       
                                sampler2D _MainTex;
                                sampler2D _OccludeMap;

                                // Note: Android platforms do not support "fixed", has to be fixed4
                                #if (SHADER_API_GLES | SHADER_API_GLES3)

                                fixed4 frag(v2f_img IN) : COLOR
                                {
                                        return tex2D (_MainTex, IN.uv) - tex2D(_OccludeMap, IN.uv);
                                }

                                #else

                                fixed frag(v2f_img IN) : COLOR
                                {
                                        return tex2D (_MainTex, IN.uv).r - tex2D(_OccludeMap, IN.uv).r;
                                }

                                #endif
                        ENDCG
                }

                // Draw to render texture
                Pass {
       
                Tags {"RenderType"="Opaque"}
                ZWrite On
                ZTest LEqual
                Fog { Mode Off }
       
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float4 v:POSITION) : POSITION {
                return mul (UNITY_MATRIX_MVP, v);
            }

            // Note: Android platforms do not support "fixed", has to be fixed4
            #if (SHADER_API_GLES | SHADER_API_GLES3)

                fixed4 frag() : COLOR {
                return 1.0;
            }

            #else

            fixed frag() : COLOR {
                return 1.0;
            }

            #endif
            ENDCG
        }      

        // Depth sort and draw to render texture
        Pass {         
                Tags {"Queue"="Transparent"}
            Cull Back
            Lighting Off
            ZWrite Off
            ZTest LEqual
            ColorMask RGBA
            Blend OneMinusDstColor One

       
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
           
            sampler2D _CameraDepthTexture;
           
            struct v2f {
                float4 vertex : POSITION;
                float4 projPos : TEXCOORD1;
            };
     
            v2f vert( float4 v : POSITION ) {        
                v2f o;
                o.vertex = mul( UNITY_MATRIX_MVP, v );
                o.projPos = ComputeScreenPos(o.vertex);            
                return o;
            }

            // Note: Android platforms do not support "fixed", has to be fixed4
            #if (SHADER_API_GLES | SHADER_API_GLES3)

            fixed4 frag( v2f i ) : COLOR {          
                float depthVal = LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r);
                float zPos = i.projPos.z;
               
                return step( zPos, depthVal );        
            }

            #else

            fixed frag( v2f i ) : COLOR {          
                float depthVal = LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r);
                float zPos = i.projPos.z;
               
                return step( zPos, depthVal );        
            }

            #endif
            ENDCG
        }
        }
}
 

Меня всё устраивает, вот только не понятно как можно в OnRenderImage, не знаю как правильно сказать, что бы не на одну текстуру "делалась" картинка, а на несколько. Пробовал создать массив из объектов, текстур и материалов, но рендерится только последняя в цикле, в чём подвох мне не понятно...
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37

Re: Обводка объекта. Необходимо подкорректировать код.

Сообщение Xtir 18 фев 2017, 12:58

OnRenderImage у меня выглядит вот так:
Синтаксис:
Используется csharp
    private void OnRenderImage( RenderTexture source, RenderTexture destination )
    {
        RenderTexture[] highlightRT = new RenderTexture[objectRenderer.Length];

        for(int i = 0; i < objectRenderer.Length; ++i)
        {
            RenderTexture.active = highlightRT[i] = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8 );
            GL.Clear(true, true, Color.clear);
            RenderTexture.active = null;

            ClearCommandBuffers();

            RenderHighlights(highlightRT[i], objectRenderer[i], m_HighlightMaterial[i]);

            RenderTexture blurred = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8 );

            m_blur.OnRenderImage( highlightRT[i], blurred );


      //      RenderOccluders(highlightRT);

            if( m_fillType == FillType.Outline )
            {
                RenderTexture occluded = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8);

                // Excluding the original image from the blurred image, leaving out the areal alone
                m_HighlightMaterial[i].SetTexture("_OccludeMap", highlightRT[i]);
                Graphics.Blit( blurred, occluded, m_HighlightMaterial[i], 2 );

                m_HighlightMaterial[i].SetTexture("_OccludeMap", occluded);

                RenderTexture.ReleaseTemporary(occluded);

            }
            else
            {
                m_HighlightMaterial[i].SetTexture("_OccludeMap", blurred);
            }

            m_HighlightMaterial[i].SetColor("_Color", m_HighlightColor[i]);
            Graphics.Blit (source, destination, m_HighlightMaterial[i], (int) m_selectionType);


 //           RenderTexture.ReleaseTemporary(blurred);
  //          RenderTexture.ReleaseTemporary(highlightRT[i]);
        }
    }


я не совсем всё понимаю, но мне кажется GL.CLear не должен быть в цикле, потом RenderTexture.ReleaseTemporary не понятно для чего нужен, что с ним, что без него, никаких изменений не видно
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37

Re: Обводка объекта. Необходимо подкорректировать код.

Сообщение LemanRass 18 фев 2017, 13:05

Синтаксис:
Используется csharp
public Renderer[] rendererObjs;
public Color[] colors;

private void Start()
{
    for(int i = 0; i < rendererObjs.Length; i++)
    {
        var material = new Material(Shader.Find("Custom/Highlight"));
        material.SetColor("_Color", colors[Random.Range(0, colors.Length - 1)]);
        rendererObjs[i].sharedMaterial = material;
    }
}


Забей на C# код. Ищи решение чисто через шейдер. С# должен использоваться только для подстановки шейдера к материалу и в следствии к правильной модели. Пример выше.
Разработчик SpaceBall
Скрытый текст:
LemanRass
UNIверсал
 
Сообщения: 385
Зарегистрирован: 23 фев 2014, 12:00
Skype: coder.dev

Re: Обводка объекта. Необходимо подкорректировать код.

Сообщение Xtir 18 фев 2017, 14:28

Есть ещё вот такой шейдер http://wiki.unity3d.com/index.php/Silho ... ed_Diffuse но это же бред Изображение да, может быть на персонаже с маленькими полигонами не будет этого заметно, но всё равно в итоге картинку он выдают не такую, какую хотелось бы. Так что считаю, что без дополнительного рендеринга не обойтись
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37


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

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10