Бесплатный шейдер с хромокеем (видео на зелёном фоне)

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

Бесплатный шейдер с хромокеем (видео на зелёном фоне)

Сообщение lichnost3d 27 апр 2016, 20:45

Доброго времени суток!
Передо мной встала задачка, реализовать в Unity3d просмотр видеопотока с веб камеры с отсечением зелёного фона.
С начало было подумал сделать это с помощью библиотек Aforge на c#, но потом увидел что можно сделать и с помощью шейдеров, при чём есть как платные реализации так и бесплатные чужие наработки. На платные само собой денег нет, а вот среди бесплатных был выбран наиболее гибкий
Синтаксис:
Используется csharp
Shader "Shader Forge/ChromakeyHSV" {
    Properties {
        _MainTex ("MainTex", 2D) = "white" {}
        _MaxHue ("MaxHue", Range(0, 1)) = 0
        _MinHue ("MinHue", Range(0, 1)) = 0
        _MaxSaturation ("MaxSaturation", Range(0, 1)) = 0
        _MinSaturation ("MinSaturation", Range(0, 1)) = 0
        _MaxBrightness ("MaxBrightness", Range(0, 1)) = 0
        _MinBrightness ("MinBrightness", Range(0, 1)) = 0
        _Cutout ("Cutout", Range(0, 1)) = 0
        _Background ("Background", 2D) = "transparent" {}
    }
    SubShader {
        Tags {
        //    "RenderType"="Opaque"
                "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" //L3D
        }
                Lighting Off //L3D
                ZWrite Off //L3D
                AlphaTest Off //L3D
                Blend SrcAlpha OneMinusSrcAlpha //L3D
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma exclude_renderers gles3 metal d3d11_9x xbox360 xboxone ps3 ps4 psp2
            #pragma target 3.0
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform float _MaxHue;
            uniform float _MinHue;
            uniform float _MaxSaturation;
            uniform float _MinSaturation;
            uniform float _MaxBrightness;
            uniform float _MinBrightness;
            float3 RGBtoHSV( float3 RGB ){
            float4 k = float4(0.0, -1.0/3.0, 2.0/3.0, -1.0);
            float4 p = RGB.g < RGB.b ? float4(RGB.b, RGB.g, k.w, k.z) : float4(RGB.gb, k.xy);
            float4 q = RGB.r < p.x   ? float4(p.x, p.y, p.w, RGB.r) : float4(RGB.r, p.yzx);
            float d = q.x - min(q.w, q.y);
            float e = 1.0e-10;
            return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
            }
           
            float CheckHSV( float3 HSV , float MXH , float MNH , float MXS , float MNS , float MXV , float MNV ){
            if (HSV.r >= MNH && HSV.r <= MXH) {
                    if (HSV.g >= MNS && HSV.g <= MXS) {
                        if (HSV.b >= MNV && HSV.b <= MXV) {
                            return MXV - HSV.b;
                        }
                    }
                }
           
            return 1.0;
            }
           
            uniform float _Cutout;
            uniform sampler2D _Background; uniform float4 _Background_ST;
            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
/////// Vectors:
////// Lighting:
////// Emissive:
                float4 _Background_var = tex2D(_Background,TRANSFORM_TEX(i.uv0, _Background));
                float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
                float node_7320 = CheckHSV( RGBtoHSV( normalize(_MainTex_var.rgb) ) , _MaxHue , _MinHue , _MaxSaturation , _MinSaturation , _MaxBrightness , _MinBrightness );
                float node_6804_if_leA = step(node_7320,_Cutout);
                float node_6804_if_leB = step(_Cutout,node_7320);
                float3 emissive = lerp(_Background_var.rgb,_MainTex_var.rgb,lerp((node_6804_if_leA*0.0)+(node_6804_if_leB*node_7320),node_7320,node_6804_if_leA*node_6804_if_leB));
                float3 finalColor = emissive;
                return fixed4(finalColor,1);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
    CustomEditor "ShaderForgeMaterialInspector"
}

Одна беда, в этом шейдере есть вторая текстура "background" которая отображается позади первой,
а мне она не нужна, мне нужно чтобы на месте зелёного фона первой была прозрачность позволяющая видеть сквозь полигон на который наложена текстура.
Есть ли здесь люди добрые, которые могут если не исправить то хотя бы подсказать в какую сторону рыть?
Сам я уже что только не пробовал, понятное дело что нужно читать маны, но ради одного единственного шейдера вникать нужно глубоко в эту тему.
lichnost3d
UNец
 
Сообщения: 5
Зарегистрирован: 17 окт 2013, 00:49

Re: Бесплатный шейдер с хромокеем (видео на зелёном фоне)

Сообщение Cr0c 27 апр 2016, 21:20

Прозрачную текстуру поставить на фон не пробовали?
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Бесплатный шейдер с хромокеем (видео на зелёном фоне)

Сообщение seaman 30 апр 2016, 00:51

Разобраться в шейдере правильнее. Я в шейдерах не очень, но что-то типа:
Синтаксис:
Используется csharp
                float node_6804_if_leA = step(node_7320,_Cutout);
                float node_6804_if_leB = step(_Cutout,node_7320);
                float3 finalColor = emissive;
                return fixed4(_MainTex_var.rgb,lerp((node_6804_if_leA*0.0)+(node_6804_if_leB*node_7320),node_7320,node_6804_if_leA*node_6804_if_leB));

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


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

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

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