Стандартный шейдер блюра + маска (РЕШЕНО)

Шейдеры и все-все-все.

Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение RefractoR 14 янв 2012, 20:34

Доброго времени суток!
Помогите пожалуйтса дописать стандартный пост-процесс шейдер блюра, чтобы можно было использовать маску для его интенсивности.
Картинка для наглядности
Скрытый текст:
Изображение

Код эффекта:
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[AddComponentMenu("Image Effects/Blur")]
public class BlurEffect : MonoBehaviour
{      
        /// Blur iterations - larger number means more blur.
        public int iterations = 3;
       
        /// Blur spread for each iteration. Lower values
        /// give better looking blur, but require more iterations to
        /// get large blurs. Value is usually between 0.5 and 1.0.
        public float blurSpread = 0.6f;
       
       
        // --------------------------------------------------------
        // The blur iteration shader.
        // Basically it just takes 4 texture samples and averages them.
        // By applying it repeatedly and spreading out sample locations
        // we get a Gaussian blur approximation.
       
        private static string blurMatString =
@"Shader ""BlurConeTap"" {
        Properties { _MainTex ("
""", any) = """" {} }
        SubShader {
                Pass {
                        ZTest Always Cull Off ZWrite Off Fog { Mode Off }
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant alpha}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                }
        }
        Fallback off
}"
;

        static Material m_Material = null;
        protected static Material material {
                get {
                        if (m_Material == null) {
                                m_Material = new Material( blurMatString );
                                m_Material.hideFlags = HideFlags.HideAndDontSave;
                                m_Material.shader.hideFlags = HideFlags.HideAndDontSave;
                        }
                        return m_Material;
                }
        }
       
        protected void OnDisable() {
                if( m_Material ) {
                        DestroyImmediate( m_Material.shader );
                        DestroyImmediate( m_Material );
                }
        }      
       
        // --------------------------------------------------------
       
        protected void Start()
        {
                // Disable if we don't support image effects
                if (!SystemInfo.supportsImageEffects) {
                        enabled = false;
                        return;
                }
                // Disable if the shader can't run on the users graphics card
                if (!material.shader.isSupported) {
                        enabled = false;
                        return;
                }
        }
       
        // Performs one blur iteration.
        public void FourTapCone (RenderTexture source, RenderTexture dest, int iteration)
        {
                float off = 0.5f + iteration*blurSpread;
                Graphics.BlitMultiTap (source, dest, material,
                        new Vector2(-off, -off),
                        new Vector2(-off,  off),
                        new Vector2( off,  off),
                        new Vector2( off, -off)
                );
        }
       
        // Downsamples the texture to a quarter resolution.
        private void DownSample4x (RenderTexture source, RenderTexture dest)
        {
                float off = 1.0f;
                Graphics.BlitMultiTap (source, dest, material,
                        new Vector2(-off, -off),
                        new Vector2(-off,  off),
                        new Vector2( off,  off),
                        new Vector2( off, -off)
                );
        }
       
        // Called by the camera to apply the image effect
        void OnRenderImage (RenderTexture source, RenderTexture destination) {         
                RenderTexture buffer = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
                RenderTexture buffer2 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
               
                // Copy source to the 4x4 smaller texture.
                DownSample4x (source, buffer);
               
                // Blur the small texture
                bool oddEven = true;
                               
                for(int i = 0; i < iterations; i++)
                {
                        if( oddEven )
                                FourTapCone (buffer, buffer2, i);
                        else
                                FourTapCone (buffer2, buffer, i);
                        oddEven = !oddEven;
                }
               
                if( oddEven ) Graphics.Blit(buffer, destination);
                else Graphics.Blit(buffer2, destination);
               
                RenderTexture.ReleaseTemporary(buffer);
                RenderTexture.ReleaseTemporary(buffer2);
        }      
}
 
Последний раз редактировалось RefractoR 15 янв 2012, 19:28, всего редактировалось 2 раз(а).
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска

Сообщение RefractoR 15 янв 2012, 18:11

Алгоритм и шейдер описаны в самом скрипте. Шейдер для отрисовки элементарный (см. стринговую переменную blurMatString).
Насколько я понимаю, нужно описать еще один шейдер, который будет комбинировать заблюренное изображение и исходное (например, если исходное RenderTexture src = RenderTexture.GetTemporary(source.width, source.height, 0))
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска

Сообщение Battle Angel Alita 15 янв 2012, 18:51

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[AddComponentMenu("Image Effects/Blur")]
public class BlurEffect : MonoBehaviour
{      
        /// Blur iterations - larger number means more blur.
        public int iterations = 3;
       
        /// Blur spread for each iteration. Lower values
        /// give better looking blur, but require more iterations to
        /// get large blurs. Value is usually between 0.5 and 1.0.
        public float blurSpread = 0.6f;
       
                public Texture maskTexture;
       
       
        // --------------------------------------------------------
        // The blur iteration shader.
        // Basically it just takes 4 texture samples and averages them.
        // By applying it repeatedly and spreading out sample locations
        // we get a Gaussian blur approximation.
       
        private static string blurMatString =
@"Shader ""BlurConeTap"" {
        Properties { _MainTex ("
""", any) = """" {} }
        SubShader {
                Pass {
                        ZTest Always Cull Off ZWrite Off Fog { Mode Off }
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant alpha}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                }
        }
        Fallback off
}"
;

        static Material m_Material = null;
        protected static Material material {
                get {
                        if (m_Material == null) {
                                m_Material = new Material( blurMatString );
                                m_Material.hideFlags = HideFlags.HideAndDontSave;
                                m_Material.shader.hideFlags = HideFlags.HideAndDontSave;
                        }
                        return m_Material;
                }
        }
               
                private static string combineMatString =
@"Shader ""Combine"" {
        Properties { _MainTex ("
""", any) = """" {}
                                         _BlurTex ("
""", any) = ""black"" {}
                                         _MaskTex ("
""", any) = """" {}
                }
        SubShader {
                Pass {
                        ZTest Always Cull Off ZWrite Off Fog { Mode Off }
                        SetTexture [_BlurTex] {combine texture}
                                SetTexture [_MaskTex] {combine previous, texture}
                        SetTexture [_MainTex] {combine texture lerp(previous) previous, texture}
                }
        }
        Fallback off
}"
;

        static Material c_Material = null;
        protected static Material cmaterial {
                get {
                        if (c_Material == null) {
                                c_Material = new Material( combineMatString );
                                c_Material.hideFlags = HideFlags.HideAndDontSave;
                                c_Material.shader.hideFlags = HideFlags.HideAndDontSave;
                        }
                        return c_Material;
                }
        }
       
        protected void OnDisable() {
                if( m_Material ) {
                        DestroyImmediate( m_Material.shader );
                        DestroyImmediate( m_Material );
                }
                                if( c_Material ) {
                        DestroyImmediate( c_Material.shader );
                        DestroyImmediate( c_Material );
                }
        }      
       
        // --------------------------------------------------------
       
        protected void Start()
        {
                // Disable if we don't support image effects
                if (!SystemInfo.supportsImageEffects) {
                        enabled = false;
                        return;
                }
                // Disable if the shader can't run on the users graphics card
                if (!material.shader.isSupported) {
                        enabled = false;
                        return;
                }
        }
       
        // Performs one blur iteration.
        public void FourTapCone (RenderTexture source, RenderTexture dest, int iteration)
        {
                float off = 0.5f + iteration*blurSpread;
                Graphics.BlitMultiTap (source, dest, material,
                        new Vector2(-off, -off),
                        new Vector2(-off,  off),
                        new Vector2( off,  off),
                        new Vector2( off, -off)
                );
        }
       
        // Downsamples the texture to a quarter resolution.
        private void DownSample4x (RenderTexture source, RenderTexture dest)
        {
                float off = 1.0f;
                Graphics.BlitMultiTap (source, dest, material,
                        new Vector2(-off, -off),
                        new Vector2(-off,  off),
                        new Vector2( off,  off),
                        new Vector2( off, -off)
                );
        }
       
        // Called by the camera to apply the image effect
        void OnRenderImage (RenderTexture source, RenderTexture destination) {        
                RenderTexture buffer = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
                RenderTexture buffer2 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
               
                // Copy source to the 4x4 smaller texture.
                DownSample4x (source, buffer);
               
                // Blur the small texture
                bool oddEven = true;
                               
                for(int i = 0; i < iterations; i++)
                {
                        if( oddEven )
                                FourTapCone (buffer, buffer2, i);
                        else
                                FourTapCone (buffer2, buffer, i);
                        oddEven = !oddEven;
                }
               
                if( oddEven ){
                                        cmaterial.SetTexture("_BlurTex", buffer);
                                        cmaterial.SetTexture("_MaskTex", maskTexture);
                                        Graphics.Blit(source, destination, cmaterial);
                                }else{
                                        cmaterial.SetTexture("_BlurTex", buffer2);
                                        cmaterial.SetTexture("_MaskTex", maskTexture);
                                        Graphics.Blit(source, destination, cmaterial);
                                }
               
                RenderTexture.ReleaseTemporary(buffer);
                RenderTexture.ReleaseTemporary(buffer2);
        }      
}
 


Кто-нибудь может сказать, как сделать материал в скрипте без этих дурацких

static Material m_Material = null;
protected static Material material {
get {
if (m_Material == null) {
m_Material = new Material( blurMatString );
m_Material.hideFlags = HideFlags.HideAndDontSave;
m_Material.shader.hideFlags = HideFlags.HideAndDontSave;
}
return m_Material;
}
}

???
Хочу чтоб просто Material myMat = new Material(blurMatString);
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Стандартный шейдер блюра + маска

Сообщение RefractoR 15 янв 2012, 19:23

Battle Angel Alita, спасибо огромное! Работает)
Так первый же конструктор позволяет по коду шейдера создавать материал http://unity3d.com/support/documentatio ... erial.html
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска

Сообщение Battle Angel Alita 15 янв 2012, 19:36

>Так первый же конструктор позволяет по коду шейдера создавать материал http://unity3d.com/support/documentatio ... erial.html
А вот нифига! Попробуйте сами закоментить эту фигню с сделать просто

private Material c_Material;
...
protected void Start()
{
c_Material = new Material( combineMatString );
...

сразу заругается.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение RefractoR 15 янв 2012, 19:37

оу...тупость написал. Там же и так конструктор по стрингу юзается.
Наверное только такой вариант (через property)
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение RefractoR 15 янв 2012, 19:40

заругается потому что обращение к материалу идет в OnRenderImage.
Да, все же как property тут оптимально) а чем не нравится такая конструкция?)
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение Battle Angel Alita 15 янв 2012, 19:42

Да, все же как property тут оптимально) а чем не нравится такая конструкция?)
Лень писать, да и выглядит это угрёбищно. Вообще, считаю что чем меньше кода тем эффективней человек пишет.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение RefractoR 15 янв 2012, 19:49

Battle Angel Alita писал(а):Вообще, считаю что чем меньше кода тем эффективней человек пишет.

В данном случае это заблуждение. Но в общем случае да)
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение Battle Angel Alita 15 янв 2012, 19:53

И вообще, я ни шарп ни ООП не знаю, и как эта конструкция работает не понимаю.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение seaman 15 янв 2012, 20:28

Ну вообще-то у меня почему-то не ругается:
Синтаксис:
Используется csharp
using UnityEngine;

[ExecuteInEditMode]
[AddComponentMenu("Image Effects/Blur")]
public class BlurEffect : MonoBehaviour
{
    /// Blur iterations - larger number means more blur.
    public int iterations = 3;

    /// Blur spread for each iteration. Lower values
    /// give better looking blur, but require more iterations to
    /// get large blurs. Value is usually between 0.5 and 1.0.
    public float blurSpread = 0.6f;


    // --------------------------------------------------------
    // The blur iteration shader.
    // Basically it just takes 4 texture samples and averages them.
    // By applying it repeatedly and spreading out sample locations
    // we get a Gaussian blur approximation.

    private const string _BLUR_MAT_STRING =
@"Shader ""BlurConeTap"" {
        Properties { _MainTex ("
""", any) = """" {} }
        SubShader {
                Pass {
                        ZTest Always Cull Off ZWrite Off Fog { Mode Off }
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant alpha}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                        SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
                }
        }
        Fallback off
}"
;

    private static Material _material;

    protected void OnDisable()
    {
        if (!_material) return;
        DestroyImmediate(_material.shader);
        DestroyImmediate(_material);
    }

    // --------------------------------------------------------

    protected void Start()
    {
        _material = new Material(_BLUR_MAT_STRING) { hideFlags = HideFlags.HideAndDontSave, shader = {hideFlags = HideFlags.HideAndDontSave} };

        // Disable if we don't support image effects if the shader can't run on the users graphics card
        if (SystemInfo.supportsImageEffects && _material.shader.isSupported) return;
        enabled = false;
    }

    // Performs one blur iteration.
    public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
    {
        float off = 0.5f + iteration * blurSpread;
        Graphics.BlitMultiTap(source, dest, _material, new Vector2(-off, -off), new Vector2(-off, off), new Vector2(off, off), new Vector2(off, -off) );
    }

    // Downsamples the texture to a quarter resolution.
    private static void _DownSample4X(RenderTexture source, RenderTexture dest)
    {
        const float off = 1.0f;
        Graphics.BlitMultiTap(source, dest, _material, new Vector2(-off, -off), new Vector2(-off, off), new Vector2(off, off), new Vector2(off, -off) );
    }

    // Called by the camera to apply the image effect
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        RenderTexture buffer = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0);
        RenderTexture buffer2 = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0);

        // Copy source to the 4x4 smaller texture.
        _DownSample4X(source, buffer);

        // Blur the small texture
        bool oddEven = true;

        for (int i = 0; i < iterations; i++)
        {
            if (oddEven)
                FourTapCone(buffer, buffer2, i);
            else
                FourTapCone(buffer2, buffer, i);
            oddEven = !oddEven;
        }

        Graphics.Blit(oddEven ? buffer : buffer2, destination);

        RenderTexture.ReleaseTemporary(buffer);
        RenderTexture.ReleaseTemporary(buffer2);
    }
}
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение RefractoR 15 янв 2012, 20:36

seaman писал(а):Ну вообще-то у меня почему-то не ругается

Даже когда в редакторе на окно Game переключаетесь?
RefractoR
UNIт
 
Сообщения: 50
Зарегистрирован: 05 ноя 2009, 16:31
Откуда: Краснодар
  • ICQ

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение seaman 15 янв 2012, 20:40

Изображение
А с чего вдруг ругаться то будет? Вы мой код со своим сравните.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение Battle Angel Alita 15 янв 2012, 20:51

_material = new Material(_BLUR_MAT_STRING) { hideFlags = HideFlags.HideAndDontSave, shader = {hideFlags = HideFlags.HideAndDontSave} };
Я понимаю, сказывается конечно незнание шарпа, но WTF?
jackiechanface.jpg
У вас нет доступа для просмотра вложений в этом сообщении.
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Стандартный шейдер блюра + маска (РЕШЕНО)

Сообщение seaman 15 янв 2012, 20:58

Я понимаю, сказывается конечно незнание шарпа, но WTF?

new - создает экземпляр класса Material с помощью конструктора класса, в который передается параметр - текст шейдера. Далее в { } можно установить поля этого класса в нужные значения.
Строка
Синтаксис:
Используется csharp
_material = new Material(_BLUR_MAT_STRING) { hideFlags = HideFlags.HideAndDontSave, shader = {hideFlags = HideFlags.HideAndDontSave} };

Эквивалентна строкам:
Синтаксис:
Используется csharp
        _material = new Material(blurMatString);
        material .hideFlags = HideFlags.HideAndDontSave;
        material .shader.hideFlags = HideFlags.HideAndDontSave;

Все это просто для укорочения текста и соответственно лучшей обозримости программы.
PS^ любите Джеки? Или случайно картинка попалась?
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

След.

Вернуться в Shader Lab

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

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


cron