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

Edge Detection (Sobel)

СообщениеДобавлено: 22 окт 2010, 07:06
gnoblin
Шейдер, который выделяет края на текстуре объекта используя фильтр Собеля.

Я кривовато скопипастил шейдер, поэтому он не скомпилился для sm2.0 (т.е. работает только с shader model 3.0) - юнити написало что-то про 5 texture indirections.
Будет неплохо, если кто-то со мной подискутирует на тему как это можно оптимизнуть.

Синтаксис:
Используется glsl
Shader "ImageProc EdgeDetectionSobel" {
 Properties {
      _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
          #pragma target 3.0
               
      struct Input {
          float2 uv_MainTex;
      };
     
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o)
      {
         
          float off = 1.0/1024;
          // Sample the neighbor pixels
                        float s00 = tex2D(_MainTex, IN.uv_MainTex + float2(-off, -off));
                        float s01 = tex2D(_MainTex, IN.uv_MainTex + float2( 0, -off));
                        float s02 = tex2D(_MainTex, IN.uv_MainTex + float2( off, -off));
                        float s10 = tex2D(_MainTex, IN.uv_MainTex + float2(-off, 0));
                        float s12 = tex2D(_MainTex, IN.uv_MainTex + float2( off, 0));
                        float s20 = tex2D(_MainTex, IN.uv_MainTex + float2(-off, off));
                        float s21 = tex2D(_MainTex, IN.uv_MainTex + float2( 0, off));
                        float s22 = tex2D(_MainTex, IN.uv_MainTex + float2( off, off));
                        // Sobel filter in X and Y direction
                        float sobelX = s00 + 2 * s10 + s20 - s02 - 2 * s12 - s22;
                        float sobelY = s00 + 2 * s01 + s02 - s20 - 2 * s21 - s22;
                        // Find edge using a threshold of 0.07 which works generally
                        // well for general edge detection.
                        float edgeSqr = (sobelX * sobelX + sobelY * sobelY);
                       
                        float threshold = 0.0049;//0.07*0.07;
                       
                        half3 tmp = half3(0,0,0);
                        half3 one = half3(1,1,1);
                        if(edgeSqr > threshold)
                        {
                                tmp = one;
                        }
                                                                       
                        o.Albedo = one-tmp;    
      }
      ENDCG
    }
    Fallback "Diffuse"
  }

Re: Edge Detection (Sobel)

СообщениеДобавлено: 22 окт 2010, 07:56
Battle Angel Alita
texture indirections - это когда текстуры читаются не по текстурным координатам пришедшим из вершинного шейдера, а по вычисленным координатам. В данном случае это
IN.uv_MainTex + float2(-off, -off)
и т.д.

Re: Edge Detection (Sobel)

СообщениеДобавлено: 22 окт 2010, 14:06
gnoblin
Ясненько, спасибо.

Re: Edge Detection (Sobel)

СообщениеДобавлено: 30 окт 2010, 01:30
gnoblin
Пару улучшений к похожему шейдеру здесь: viewtopic.php?f=35&t=2757&p=23795#p23795

Re: Edge Detection (Sobel)

СообщениеДобавлено: 11 ноя 2010, 10:39
PAX
А если попробовать в вершинном шейдере рассчитать массив UV и его использовать для выборок? Только надо не сурфеейсный шейдер.
Примерно как тут:
Синтаксис:
Используется glsl
struct v2f {
        float4 pos : POSITION;
        float4 uv[4] : TEXCOORD0;
};