Runtime HSV\HSL ColorPicker (2 штуки)

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

Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 21 окт 2010, 19:55

На базе HueShift шейдера сделал колорпикер как в фотошопе (даже две штуки).
Пока минус этого решения в том, что нужно shader model 3.0

Представляю немного недоработанный вариант... У меня почему-то rtt не хочет выводиться в гуи, в связи с этим не делал непосредственный пик цвета мышкой.

1) Вариант номер 1.
Используем старый добрый хуеШифт шейдер и две картинки.
Первая для ползунка,
hue_shift.png

Вторая будет меняться шейдером в зависимости от положения ползунка.
RCP2.png

Синтаксис:
Используется glsl
Shader "HSB_HSV_Colorpicker" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _HueShift("HueShift", Float) = 0
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      #pragma target 3.0
         
        float3 rgb_to_hsv_no_clip(float3 RGB)
        {
                float3 HSV;
           
         float minChannel, maxChannel;
         if (RGB.x > RGB.y) {
          maxChannel = RGB.x;
          minChannel = RGB.y;
         }
         else {
          maxChannel = RGB.y;
          minChannel = RGB.x;
         }
         
         if (RGB.z > maxChannel) maxChannel = RGB.z;
         if (RGB.z < minChannel) minChannel = RGB.z;
           
                HSV.xy = 0;
                HSV.z = maxChannel;
                float delta = maxChannel - minChannel;             //Delta RGB value
                if (delta != 0) {                    // If gray, leave H & S at zero
                   HSV.y = delta / HSV.z;
                   float3 delRGB;
                   delRGB = (HSV.zzz - RGB + 3*delta) / (6.0*delta);
                   if      ( RGB.x == HSV.z ) HSV.x = delRGB.z - delRGB.y;
                   else if ( RGB.y == HSV.z ) HSV.x = ( 1.0/3.0) + delRGB.x - delRGB.z;
                   else if ( RGB.z == HSV.z ) HSV.x = ( 2.0/3.0) + delRGB.y - delRGB.x;
                }
                return (HSV);
        }

        float3 hsv_to_rgb(float3 HSV)
        {
                float3 RGB = HSV.z;
           
                   float var_h = HSV.x * 6;
                   float var_i = floor(var_h);   // Or ... var_i = floor( var_h )
                   float var_1 = HSV.z * (1.0 - HSV.y);
                   float var_2 = HSV.z * (1.0 - HSV.y * (var_h-var_i));
                   float var_3 = HSV.z * (1.0 - HSV.y * (1-(var_h-var_i)));
                   if      (var_i == 0) { RGB = float3(HSV.z, var_3, var_1); }
                   else if (var_i == 1) { RGB = float3(var_2, HSV.z, var_1); }
                   else if (var_i == 2) { RGB = float3(var_1, HSV.z, var_3); }
                   else if (var_i == 3) { RGB = float3(var_1, var_2, HSV.z); }
                   else if (var_i == 4) { RGB = float3(var_3, var_1, HSV.z); }
                   else                 { RGB = float3(HSV.z, var_1, var_2); }
           
           return (RGB);
        }

      struct Input {
          float2 uv_MainTex;
      };
     
      sampler2D _MainTex;
      float _HueShift;
     
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
         
          float3 hsv = rgb_to_hsv_no_clip(o.Albedo.xyz);
          hsv.x+=_HueShift;
                 
          if ( hsv.x > 1.0 ) { hsv.x -= 1.0; }
          o.Albedo = half3(hsv_to_rgb(hsv));

      }
     
      ENDCG
    }
    Fallback "Diffuse"
  }


2) Вариант номер 2.
Модифицированный хуеШифт шейдер процедурно генерит градиентную картинку (к uv.x привязана s-компонента цвета, то есть saturation, к uv.y привязана v\b-компонента цвета, то есть brightness, а h-компонента, то есть hue задается ползунком). Т.е. шейдер рендерит вот точно такую картинку
RCP2.png


К сожалению тоже не влазит в sm 2.0

Синтаксис:
Используется glsl
Shader "HSB_HSV_Colorpicker_cutdown" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _HueShift("HueShift", Float) = 0
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      #pragma target 3.0        

        float3 hsv_to_rgb(float3 HSV)
        {
                float3 RGB = HSV.z;
           
                   float var_h = HSV.x * 6;
                   float var_i = floor(var_h);   // Or ... var_i = floor( var_h )
                   float var_1 = HSV.z * (1.0 - HSV.y);
                   float var_2 = HSV.z * (1.0 - HSV.y * (var_h-var_i));
                   float var_3 = HSV.z * (1.0 - HSV.y * (1-(var_h-var_i)));
                   if      (var_i == 0) { RGB = float3(HSV.z, var_3, var_1); }
                   else if (var_i == 1) { RGB = float3(var_2, HSV.z, var_1); }
                   else if (var_i == 2) { RGB = float3(var_1, HSV.z, var_3); }
                   else if (var_i == 3) { RGB = float3(var_1, var_2, HSV.z); }
                   else if (var_i == 4) { RGB = float3(var_3, var_1, HSV.z); }
                   else                 { RGB = float3(HSV.z, var_1, var_2); }
           
           return (RGB);
        }

      struct Input {
          float2 uv_MainTex;
      };
     
      float _HueShift;
     
      void surf (Input IN, inout SurfaceOutput o)
      {
          float3 hsv = float3(_HueShift, IN.uv_MainTex.x, IN.uv_MainTex.y);
          if ( hsv.x > 1.0 ) { hsv.x -= 1.0; }
          o.Albedo = half3(hsv_to_rgb(hsv));
      }
     
      ENDCG
    }
    Fallback "Diffuse"
  }


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

public class HSB_HSV_ColorPicker : MonoBehaviour
{
    public RenderTexture rtt;
    public Texture hueShiftTexture;
    public Material colorPickerMat;

    Color pickedColor;
    float hueShiftAmount;

    GUIStyle thumbStyle;
    void OnGUI()
    {
        if(thumbStyle==null)
        {
            thumbStyle = GUI.skin.FindStyle("verticalsliderthumb");
        }

        //не работает пачему-то
        GUI.Label(new Rect(100,100,256,256), rtt, GUIStyle.none);

        GUI.Label(new Rect(356, 100, 16, 256), hueShiftTexture, GUIStyle.none);
        hueShiftAmount = GUI.VerticalSlider(new Rect(356, 100-5, 16, 256+14), hueShiftAmount, 1f, 0f, GUIStyle.none, thumbStyle);
       

        colorPickerMat.SetFloat("_HueShift", hueShiftAmount);
        //осталось сделать чтобы можно было пикать
        GUI.Label(new Rect(100,356,256,256), "color: "+pickedColor.ToString());
    }
}


Вот скриншот:
cp_screen.png


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

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 21 окт 2010, 19:59

Вот тут Дымок подсказывает что есть уже колорпикер (popcorn) .
http://www.arongranberg.com/unity/unitypaint/

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

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение GrueGames 21 окт 2010, 20:42

Нужная вещь!
(3A4OT)

а круглый в рисовалке - фигня.
Аватара пользователя
GrueGames
UNITрон
 
Сообщения: 200
Зарегистрирован: 11 апр 2009, 16:42
Откуда: Samara, Russia
  • Сайт
  • ICQ

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение Neodrop 22 окт 2010, 03:23

Картинка не отображалась потому, что на RTT была 100% альфа.
Убрать её можно вот этим кодом (положить в скрипт и навесить на RTT камеру)

viewtopic.php?f=87&t=2564&st=0&sk=t&sd=a&start=60#p22352
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 22 окт 2010, 15:49

Ага, действительно помогает.
Спс.

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

public class ClearAlpha : MonoBehaviour
{

    private Material mat;

    void OnPostRender()
    {
        if (!mat)
        {
            mat = new Material("Shader \"Hidden/Alpha\" {" +
                "SubShader {" +
                "    Pass {" +
                "        ZTest Always Cull Off ZWrite Off" +
                "        ColorMask A" +
                "        Color (1,1,1,1)" +
                "    }" +
                "}" +
                "}"
            );
            mat.shader.hideFlags = HideFlags.HideAndDontSave;
            mat.hideFlags = HideFlags.HideAndDontSave;
        }
        GL.PushMatrix();
        GL.LoadOrtho();
        for (int i = 0; i < mat.passCount; ++i)
        {
            mat.SetPass(i);
            GL.Begin(GL.QUADS);
            GL.Vertex3(0, 0, 0.1f);
            GL.Vertex3(1, 0, 0.1f);
            GL.Vertex3(1, 1, 0.1f);
            GL.Vertex3(0, 1, 0.1f);
            GL.End();
        }
        GL.PopMatrix();
    }
}
 
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 22 окт 2010, 16:56

Апдейт двух скриптов, теперь колопикер работает полностью корректно, цвет пикается.
Спасибо Тутанхомону.

В принципе, можно немного оптимизнуть.
+ надо будет не забыть запостить обновленный проект целиком и вебплеерную демку.

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

//версия 2
public class ClearAlpha : MonoBehaviour
{

    private Material mat;
    public Texture2D tex;
    public RenderTexture rt;

    void OnPostRender()
    {
        if (!mat)
        {
            mat = new Material("Shader \"Hidden/Alpha\" {" +
                "SubShader {" +
                "    Pass {" +
                "        ZTest Always Cull Off ZWrite Off" +
                "        ColorMask A" +
                "        Color (1,1,1,1)" +
                "    }" +
                "}" +
                "}"
            );
            mat.shader.hideFlags = HideFlags.HideAndDontSave;
            mat.hideFlags = HideFlags.HideAndDontSave;
        }
        GL.PushMatrix();
        GL.LoadOrtho();
        for (int i = 0; i < mat.passCount; ++i)
        {
            mat.SetPass(i);
            GL.Begin(GL.QUADS);
            GL.Vertex3(0, 0, 0.1f);
            GL.Vertex3(1, 0, 0.1f);
            GL.Vertex3(1, 1, 0.1f);
            GL.Vertex3(0, 1, 0.1f);
            GL.End();
        }
        GL.PopMatrix();

       
    }

    void Start()
    {
        tex = new Texture2D(256, 256);
    }

    void Update()
    {
        RenderTexture.active = rt;
        tex.ReadPixels(new Rect(0, 0, 256, 256), 0, 0, false);
        tex.Apply();
        RenderTexture.active = null;
    }
}


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

//версия 2, помог Тутан
public class HSB_HSV_ColorPicker : MonoBehaviour
{
    public RenderTexture rtt;
    public ClearAlpha clearAlpha;

    public Texture hueShiftTexture;
    public Material colorPickerMat;
    public Color testColor;

    Color pickedColor;
    float hueShiftAmount;

    GUIStyle thumbStyle;

    Rect pickerRect;

    [HideInInspector]
    Vector2 baseOffset = new Vector2(100, 100);

    float size = 256;

    void InitColorPicker()
    {
        pickerRect = new Rect(baseOffset.x, baseOffset.y, size, size);
        pixelReader = new Texture2D(8, 8);
    }

    void ShowColorPicker()
    {
        if (thumbStyle == null)
        {
            thumbStyle = GUI.skin.FindStyle("verticalsliderthumb");
        }
       
        GUI.Label(pickerRect, rtt, GUIStyle.none);

        GUI.Label(new Rect(baseOffset.x + size + 32, baseOffset.y, 16, size), hueShiftTexture, GUIStyle.none);
        hueShiftAmount = GUI.VerticalSlider(new Rect(baseOffset.x + 256 + 32, baseOffset.y - 5, 16, size + 14), hueShiftAmount, 0.999f, 0f, GUIStyle.none, thumbStyle);
       
        colorPickerMat.SetFloat("_HueShift", hueShiftAmount);

        GUI.Label(new Rect(baseOffset.x, baseOffset.x + size, size, size), new GUIContent("color: " + pickedColor.ToString(), pixelReader));
       
    }

    //void Update()
    //{
        //GetColor(Input.mousePosition.x, Input.mousePosition.y);
    //}

    Texture2D pixelReader;
    Color[] cols = new Color[8 * 8];
    void GetColor(float x, float y)
    {
        y = Screen.height - y;

        if (pickerRect.Contains(new Vector2(x, y)))
        {
            testColor = clearAlpha.tex.GetPixel((int)(x-baseOffset.x), (int)(clearAlpha.tex.height - y + baseOffset.y));
           
        }
        else
        {
            testColor = Color.magenta;
        }
    }

    ///use like this:
    void Start()
    {
        InitColorPicker();
    }
    void OnGUI()
    {
        ShowColorPicker();
        GetColor(Input.mousePosition.x, Input.mousePosition.y);
        GUILayout.Label(Input.mousePosition.x + " " + (Screen.height - Input.mousePosition.y).ToString());
    }
}
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение Neodrop 22 окт 2010, 22:41

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

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 22 окт 2010, 23:32

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

Re: Runtime HSV\HSL ColorPicker (2 штуки)

Сообщение gnoblin 15 ноя 2010, 17:39

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


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

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

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