Чернобелый пост-эффект

Программирование на Юнити.

Чернобелый пост-эффект

Сообщение Riddik 07 апр 2013, 14:52

Привет.
С шейдерами не сталкивался, так что не обессудьте)

Иногда нужно показывать всю картинку на экране в чёрно-белом цвете, кроме одного объекта на переднем плане.

Взял чёрно-белый шейдер:

Синтаксис:
Используется glsl
Shader "GrayScaleAlpha"
{
  Properties
  {
       _MainTex ("Texture", 2D) = "white" { }
  }
     SubShader
         {
       Tags { "RenderType" = "Opaque" }

       CGPROGRAM
       #pragma surface surf Lambert alpha

       struct Input
           {
           float2 uv_MainTex;
       };
     
       sampler2D _MainTex;

       void surf (Input IN, inout SurfaceOutput o)
           {
           half4 tex = tex2D(_MainTex, IN.uv_MainTex);
           
           o.Albedo = 0.299 * tex.r + 0.587 * tex.g + 0.184 * tex.b;
           o.Alpha = tex.a;                  
       }
                     
       ENDCG          
     }
         
     Fallback "Diffuse"        
}
 


В нужные моменты юзаю:
Синтаксис:
Используется csharp
Camera.mainCamera.SetReplacementShader(Shader.Find("GrayScaleAlpha"), "");


1. Первая проблема - все объекты теперь рендерятся в обратной последовательности - ближайший объект теперь позади всех, а самый далёкий - поверх всех. (камера в ортографической проекции).
2. Как применить это ко всем, кроме одного объекта? Если заюзать второй параметр (пробовал указывать тег объекта) - то вообще черный экран.

Помогите разобраться в их решении.
Аватара пользователя
Riddik
UNITрон
 
Сообщения: 160
Зарегистрирован: 18 апр 2011, 11:11

Re: Чернобелый пост-эффект

Сообщение LightWorld 08 апр 2013, 04:57

Вроде можно через слой исключить, или я что-то путаю?
Аватара пользователя
LightWorld
UNIт
 
Сообщения: 96
Зарегистрирован: 14 сен 2011, 09:21
Откуда: г. Зарафшан

Re: Чернобелый пост-эффект

Сообщение Riddik 08 апр 2013, 09:06

Каким образом?

И главная проблема - все рисуется в обратном порядке при включении чёрно-белого шейдера. Откуда такие грабли?
Аватара пользователя
Riddik
UNITрон
 
Сообщения: 160
Зарегистрирован: 18 апр 2011, 11:11

Re: Чернобелый пост-эффект

Сообщение waruiyume 08 апр 2013, 11:51

В шейдере объекта, на который не должен воздействовать эффект, нужно написать: Tags { "RenderType"="GrayscaleMask" }

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

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[AddComponentMenu("Image Effects/GrayscaleMasked")]
public class GrayscaleMasked: MonoBehaviour
{

    public Shader shader;
    private Material material;

        public Texture  textureRamp;
    //public Texture mask;
    public Shader maskShader;
        public float    rampOffset;

    private Camera maskCamera;
    private RenderTexture renderTexture;

    void Start()
    {
        shader = Shader.Find("Hidden/GrayscaleMasked Effect");
        maskShader = Shader.Find("Hidden/RenderGrayscaleMask");

        // Disable if we don't support image effects
        if (!SystemInfo.supportsImageEffects)
        {
            enabled = false;
            return;
        }

        // Disable the image effect if the shader can't
        // run on the users graphics card
        if (!shader || !shader.isSupported)
            enabled = false;
    }

        // Called by camera to apply image effect
        void OnRenderImage (RenderTexture source, RenderTexture destination)
    {
        if (material == null)
        {
            if(shader==null)return;
            material = new Material(shader);
            material.hideFlags = HideFlags.HideAndDontSave;
        }

        if (maskCamera == null)
        {
            maskCamera = new GameObject("maskCamera").AddComponent<Camera>();
            maskCamera.enabled = false;
            maskCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
        }
        maskCamera.CopyFrom(camera);
        maskCamera.clearFlags = CameraClearFlags.SolidColor;
        maskCamera.backgroundColor = new Color32(0, 0, 0, 0);

        renderTexture = RenderTexture.GetTemporary((int)maskCamera.pixelWidth, (int)maskCamera.pixelHeight, 8, RenderTextureFormat.RGB565);

            maskCamera.targetTexture = renderTexture;
        maskCamera.RenderWithShader(maskShader, "RenderType");
       
                material.SetTexture("_RampTex", textureRamp);
        material.SetTexture("_Mask", renderTexture);
                material.SetFloat("_RampOffset", rampOffset);
                Graphics.Blit (source, destination, material);

        RenderTexture.ReleaseTemporary(renderTexture);
        }

     void OnDisable()
    {
        if (material)
        {
            DestroyImmediate(material);
        }

        if (renderTexture != null)
        {
            renderTexture.Release();
            renderTexture = null;
        }

        if(maskCamera!=null)
        {
            DestroyImmediate(maskCamera.gameObject);
        }

    }
}
 


Эффект
Синтаксис:
Используется glsl
Shader "Hidden/GrayscaleMasked Effect"
{
Properties {
        _MainTex ("Base (RGB)", Rect) = "white" {}
        _Mask ("Mask (a)", Rect) = "white" {}
        _RampTex ("Base (RGB)", 2D) = "grayscaleRamp" {}
}

SubShader {
        Pass {
                ZTest Always Cull Off ZWrite Off
                Fog { Mode off }
                               
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

uniform sampler2D _MainTex;
uniform sampler2D _Mask;
uniform sampler2D _RampTex;
uniform half _RampOffset;

fixed4 frag (v2f_img i) : COLOR
{
        fixed4 original = tex2D(_MainTex, i.uv);
        fixed grayscale = Luminance(original.rgb);
        half2 remap = half2 (grayscale + _RampOffset, .5);
        fixed4 output = tex2D(_RampTex, remap);

        fixed4 maskR = tex2D(_Mask, i.uv).r;
        output = lerp(output, original, maskR);
        //output = maskA;

        output.a = original.a;
        return output;
}
ENDCG

        }
}

Fallback off

}
 


Маска.
Синтаксис:
Используется glsl
Shader "Hidden/RenderGrayscaleMask"
{
        Category
        {
                        Fog { Mode Off }

                SubShader
                {
                        Tags { "RenderType"="GrayscaleMask" }
                        Pass
                        {      
                                Color (1.0,0.0,0.0,1.0)
                        }
                }

                SubShader
                {
                        Tags { "RenderType"="Opaque" }
                        Pass
                        {
                                Fog { Mode Off }
                                Color (0.0,0.0,0.0,1.0)
                        }
                }

                SubShader
                {
                        Tags { "RenderType"="Transparent" }

                        Pass
                        {
                                        Blend SrcAlpha OneMinusSrcAlpha
                                 CGPROGRAM
 
                                 #pragma vertex vert  
                                 #pragma fragment frag
 
                                 uniform sampler2D _MainTex;
                                 uniform half4 _MainTex_ST;          
 
                                 struct vertexInput {
                                        float4 vertex : POSITION;
                                        half4 texcoord : TEXCOORD0;
                                 };
                                 struct vertexOutput {
                                        half4 pos : SV_POSITION;
                                        half4 tex : TEXCOORD0;
                                 };
 
                                 vertexOutput vert(vertexInput input)
                                 {
                                        vertexOutput output;
 
                                        output.tex = input.texcoord;
                                        output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
                                        return output;
                                 }
 
                                 float4 frag(vertexOutput input) : COLOR
                                 {
                                        fixed4 col = tex2D(_MainTex,
                                           _MainTex_ST.xy * input.tex.xy + _MainTex_ST.zw);
                                        return  fixed4(1.0-col.a, 0.0, 0.0, col.a);
                                 }
 
                                 ENDCG
                        }
                }

                SubShader
                {
                        Tags { "RenderType"="TransparentCutout" }
                        Pass
                        {
                                AlphaTest Greater [_Cutoff]
                                SetTexture[_MainTex] { constantColor(0.0,0.0,0.0,1.0) combine constant, texture }
                        }
                }

        }
}

 


Если нужно что бы работало и для земли, курите: http://u3d.as/content/unity-technologie ... cement/3zx - там много букафф копировать.
P.S. Впервые пробую, т.ч. если что через (полная Ж), я не виноват :D
Кто нибудь, может подсказать, какой формат и глубину использовать в данном случае.

Версия с фиксами для пятёрки
https://yadi.sk/d/JM9y_Jr3sAyu3
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Чернобелый пост-эффект

Сообщение Riddik 08 апр 2013, 12:39

Спасибо! Уже есть с чем работать, что пробовать и от чего отталкиваться.

С другой стороны, мне уже кажется, что проще сделать задуманное наложением текстуры поверх всех объектов (кроме того, на который эффект не должен распространяться - этот объект останется перед текстурой, остальные - позади неё). Требования не обязательно сделать чёрно-белое изображение, а сделать его просто менее заметным, серым, добавить серости, в общем как бы показать, что оно неактивно.

Может ради этого не стоит заморачиваться с шейдерами, тем более не везде гарантируется их работа?
Аватара пользователя
Riddik
UNITрон
 
Сообщения: 160
Зарегистрирован: 18 апр 2011, 11:11

Re: Чернобелый пост-эффект

Сообщение waruiyume 08 апр 2013, 13:09

ХЗ, можно нарисовать планку перед камерой, а выделенный объект, вывести второй камерой; или изменить материалы на всех объектах, коме выделенного; или не делать постэффект, а просто, отрисовать шейдерреплейсментом, и во всех тэгах, кроме нужного сделать серый цвет.
P.S. Подправил маску.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Чернобелый пост-эффект

Сообщение gturk 10 апр 2013, 19:23

Я делал так: Объект, который нужно подсветить клал в отдельный слой newLayer, создавал дополнительную камеру cam2, которая совпадает с основной, но рендерит только newLayer, основная камера показывает все, кроме newLayer. На основную камеру вешается постэффект "цветокоррекция" с выкрученным в 0 значением saturation.
cam1.Depth = 0;
cam2.Depth = 1;
cam2.clear = DepthOnly;
Аватара пользователя
gturk
UNITрон
 
Сообщения: 239
Зарегистрирован: 01 апр 2012, 18:49

Re: Чернобелый пост-эффект

Сообщение Woolf 10 апр 2013, 20:02

gturk писал(а):Я делал так: Объект, который нужно подсветить клал в отдельный слой newLayer, создавал дополнительную камеру cam2, которая совпадает с основной, но рендерит только newLayer, основная камера показывает все, кроме newLayer. На основную камеру вешается постэффект "цветокоррекция" с выкрученным в 0 значением saturation.
cam1.Depth = 0;
cam2.Depth = 1;
cam2.clear = DepthOnly;


И это и есть самое идеологически верное решение )
Разработчик theFisherOnline - там, где клюёт
Разработчик Atom Fishing II - Первая 3D MMO про рыбалку
Разработчик Atom Fishing - Рыбалка на поплавок, донку, нахлыст, блесну в постъядерный период.
Аватара пользователя
Woolf
Адепт
 
Сообщения: 7179
Зарегистрирован: 02 мар 2009, 16:59

Re: Чернобелый пост-эффект

Сообщение Riddik 12 апр 2013, 00:27

Спасибо большое!!!
Аватара пользователя
Riddik
UNITрон
 
Сообщения: 160
Зарегистрирован: 18 апр 2011, 11:11


Вернуться в Скрипты

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

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