Borderlands (EdgeDetection поверх текстуры)

Для экспериментальных разработок и тем "я нашел чужой исходник, почему он не работает?"

Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 27 окт 2010, 18:32

Чуть улучшенный EdgeDetect, теперь накладывается поверх основной текстуры объекта и получается что-то типа эффекта Borderlands (хотя не уверен как конкретно это реализовано в самой игре).
Конечно же, намного оптимальнее сделать текстуру сразу с таким эффектом :D.

При удалении от объекта смотрится намного хуже, интересно какими способами можно это бороть :-w.

Синтаксис:
Используется glsl
Shader "ImageProc EdgeDetectionSobel_BorderLands" {
 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;    
                        half4 color = tex2D(_MainTex, IN.uv_MainTex);
                       
                        if(o.Albedo.r > 0.2)
                        {
                                                        o.Albedo = color;
                        }
      }
      ENDCG
    }
    Fallback "Diffuse"
  }
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение antonio 27 окт 2010, 18:45

В Borderlands текстуры рисованные - разбирал.
Аватара пользователя
antonio
UNIт
 
Сообщения: 132
Зарегистрирован: 03 ноя 2009, 15:42
Откуда: Смоленск

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 27 окт 2010, 20:03

Ок).

Типа такого, только без обводки по контурам объекта.
Ещё скрины из игры тут:
http://games.1c.ru/borderlands/?type=gallery
У вас нет доступа для просмотра вложений в этом сообщении.
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение Neodrop 27 окт 2010, 20:07

(3A4OT)
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение antonio 28 окт 2010, 15:59

Покрутил.
Да зд`орово.
Может сэмплер не дефолтовый использовать sampler2D, а покрутить самому.
Синтаксис:
Используется glsl
sampler Samp = sampler_state
{
    Texture   = (_MainTex);
    MipFilter = none;
    MinFilter = point;
    MagFilter = point;
    AddressU  = CLAMP;
    AddressV = CLAMP;
};

(popcorn1)
Аватара пользователя
antonio
UNIт
 
Сообщения: 132
Зарегистрирован: 03 ноя 2009, 15:42
Откуда: Смоленск

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 28 окт 2010, 18:38

А можно чуть подробнее про семплеры и чем вот этот приведенный лучше?

Я думал в юнити нельзя пользоваться "нестандартными".
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение Neodrop 28 окт 2010, 18:42

А я бы и полный код шейдера попросил :ymdaydream:
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение Battle Angel Alita 28 окт 2010, 19:32

1. Строчка float s00 = tex2D(_MainTex, IN.uv_MainTex + float2(-off, -off)); возвращает красный канал текстуры. Т.е ты детектируешь грань по красному каналу, а было-бы правильней допустим по яркости.
2. Просто собель на текстуре это не так интересно, его можно и в фотошопе наложить. Гораздо интереснее завязать его на яркость освещения и/или на NdotV(фреснель).
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 28 окт 2010, 21:03

Две отличные идеи!

Сделаю, только без понятия как завязать на освещение.

Ещё была мысль детектить маской 2x2 в надежде, что это всё станет работать на sm 2.0
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение antonio 29 окт 2010, 08:49

да с сэмплером я не туда завернул.
Может threshold = 0.0049 сделать не статичным а привязать к COMPUTE_EYEDEPTH(o.threshold) и умножать на thresholdCustom вынесеный в интерфейс для доводки. Примерно как реализован аутлайн в тун шейдере. Я попытался расcчитать COMPUTE_EYEDEPTH в вертексном шейдере, а потом отправить threshold в пиксел шейдер. Но пока что-то не очень смотриться (Видимо надо еще подрезать минимумом и максимумом) и потерял заливку светом. Не думаю что стоит выставлять итак сочинение написал(. С шейдерами только стал разбираться вдохновился творческим порывом gnoblina.
Аватара пользователя
antonio
UNIт
 
Сообщения: 132
Зарегистрирован: 03 ноя 2009, 15:42
Откуда: Смоленск

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 30 окт 2010, 01:04

Ещё можно результат edge detect'а использовать как маску для спекуляра\отражений (наверное) :D
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 30 окт 2010, 01:27

Свежий вариант шейдера.
Края считаются по яркости изображения, плюс вместо костыля 1.0/1024.0 используется _MainTex_TexelSize :).

Синтаксис:
Используется glsl
Shader "BorderLands2" {
 Properties {
      _MainTex ("Texture", 2D) = "white" {}
      //_FPOW("FPOW", Float) = 5.0
      //_R0("R0", Float) = 0.05
    }
    SubShader {
         
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #include "UnityCG.cginc"
      #pragma surface surf Lambert
      #pragma target 3.0
         
      struct Input {
          float2 uv_MainTex;
          float3 viewDir;
      };
     
      sampler2D _MainTex;
      float2 _MainTex_TexelSize;
         // float _FPOW;
         // float _R0;
         
          float Brightness(half3 color)
          {
             return 0.299*color.r + 0.587*color.g + 0.184*color.b;
          }
         
      void surf (Input IN, inout SurfaceOutput o)
      {
                        //dot(o.Normal, normalize(IN.viewDir)
         
                        //half fresnel = saturate(1.0 - dot(o.Normal, normalize(IN.viewDir)));
                        //fresnel = pow(fresnel, _FPOW);
                        //fresnel = _R0 + (1.0 - _R0) * fresnel;
                        //reflcol = lerp(c, reflcol, fresnel);
         
                        float2 off = _MainTex_TexelSize;
         
                        // Sample the neighbor pixels
                        float s00 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, -off.y)).rgb);
                        float s01 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( 0, -off.y)).rgb);
                        float s02 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, -off.y)).rgb);
                        float s10 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, 0)).rgb);
                        float s12 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, 0)).rgb);
                        float s20 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, off.y)).rgb);
                        float s21 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( 0, off.y)).rgb);
                        float s22 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, off.y)).rgb);
                        // 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;    
                        half4 color = tex2D(_MainTex, IN.uv_MainTex);
                       
                        float brightness = Brightness(o.Albedo.rgb);
                       
                        //if(o.Albedo.r > 0.2)
                        if(brightness > 0.2)
                        {
                                o.Albedo = color;
                        }
      }
      ENDCG
    }
    Fallback "Diffuse"
  }
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение gnoblin 30 окт 2010, 01:45

Вариант с френелем, но здесь я похоже перемудрил :-\

Синтаксис:
Используется glsl
Shader "BorderLands2" {
 Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _FPOW("FPOW", Float) = 5.0
      _R0("R0", Float) = 0.05
    }
    SubShader {
         
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #include "UnityCG.cginc"
      #pragma surface surf Lambert
      #pragma target 3.0
         
      struct Input {
          float2 uv_MainTex;
          float3 viewDir;
      };
     
      sampler2D _MainTex;
      float2 _MainTex_TexelSize;
          float _FPOW;
          float _R0;
         
          float Brightness(half3 color)
          {
             return 0.299*color.r + 0.587*color.g + 0.184*color.b;
          }
         
      void surf (Input IN, inout SurfaceOutput o)
      {
                        float2 off = _MainTex_TexelSize;
         
                        // Sample the neighbor pixels
                        float s00 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, -off.y)).rgb);
                        float s01 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( 0, -off.y)).rgb);
                        float s02 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, -off.y)).rgb);
                        float s10 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, 0)).rgb);
                        float s12 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, 0)).rgb);
                        float s20 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, off.y)).rgb);
                        float s21 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( 0, off.y)).rgb);
                        float s22 = Brightness(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, off.y)).rgb);
                        // 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;    
                        half4 color = tex2D(_MainTex, IN.uv_MainTex);
                       
                        float brightness = Brightness(o.Albedo.rgb);
                       
                        float NdotV = dot(o.Normal, normalize(IN.viewDir));
                        half fresnel = saturate(1.0 - NdotV);
                        fresnel = pow(fresnel, _FPOW);
                        fresnel = _R0 + (1.0 - _R0) * fresnel;
                               
                        o.Albedo = lerp(o.Albedo, color, fresnel);
                       
                        if(brightness > 0.2)
                                o.Albedo = color;
      }
      ENDCG
    }
    Fallback "Diffuse"
  }
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение Battle Angel Alita 30 окт 2010, 09:29

gnoblin
Синтаксис:
Используется glsl
Shader "BorderLands2+"
{
        Properties
        {
                _MainTex ("Texture", 2D) = "white" {}
                _thr("threshold", Float) = 0.15
                _tweak("???", Float) = -20.0
        }
        SubShader
        {
                Tags { "RenderType" = "Opaque" }
CGPROGRAM
#include "UnityCG.cginc"
#pragma surface surf Lambert
#pragma target 3.0

sampler2D _MainTex;
float2 _MainTex_TexelSize;
float _thr;
float _tweak;

struct Input
{
        float2 uv_MainTex;
        float3 viewDir;
};

void surf (Input IN, inout SurfaceOutput o)
{
        float2 off = _MainTex_TexelSize;
       
        // Sample the neighbor pixels
        float s00 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, -off.y)).rgb);
        float s01 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2( 0, -off.y)).rgb);
        float s02 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, -off.y)).rgb);
        float s10 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, 0)).rgb);
        float s12 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, 0)).rgb);
        float s20 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2(-off.x, off.y)).rgb);
        float s21 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2( 0, off.y)).rgb);
        float s22 = Luminance(tex2D(_MainTex, IN.uv_MainTex + float2( off.x, off.y)).rgb);
        // 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);
       
        edgeSqr = (edgeSqr - _thr) * _tweak;
        edgeSqr = saturate(edgeSqr);
       
        o.Emission = tex2D(_MainTex, IN.uv_MainTex);
        o.Emission = o.Emission * edgeSqr;

        /*
        o.Normal = half3(0.0, 0.0, 1.0);
        float NdotV = dot(o.Normal, normalize(IN.viewDir));
        //mad with NdotV
        NdotV = saturate(NdotV * 1.5);
        NdotV = pow(NdotV, 2.0);
        NdotV = clamp(NdotV, 0.0, 0.9);
       
        o.Emission = lerp(o.Emission * edgeSqr, o.Emission, NdotV);
        */

}
ENDCG

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

Re: Borderlands (EdgeDetection поверх текстуры)

Сообщение Battle Angel Alita 30 окт 2010, 09:59

Вот такая зависимость хорошо смотрится

Синтаксис:
Используется glsl
        o.Normal = half3(0.0, 0.0, 1.0);
        float NdotV = dot(o.Normal, normalize(IN.viewDir));
       
        edgeSqr = (edgeSqr - _thr * NdotV) * _tweak;
        edgeSqr = saturate(edgeSqr);
 
Мозг рака
Изображение
Аватара пользователя
Battle Angel Alita
UNIверсал
 
Сообщения: 476
Зарегистрирован: 25 ноя 2009, 14:52

След.

Вернуться в Шейдерная кузня

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

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