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

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

СообщениеДобавлено: 27 апр 2016, 20:45
lichnost3d
Доброго времени суток!
Передо мной встала задачка, реализовать в 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" которая отображается позади первой,
а мне она не нужна, мне нужно чтобы на месте зелёного фона первой была прозрачность позволяющая видеть сквозь полигон на который наложена текстура.
Есть ли здесь люди добрые, которые могут если не исправить то хотя бы подсказать в какую сторону рыть?
Сам я уже что только не пробовал, понятное дело что нужно читать маны, но ради одного единственного шейдера вникать нужно глубоко в эту тему.

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

СообщениеДобавлено: 27 апр 2016, 21:20
Cr0c
Прозрачную текстуру поставить на фон не пробовали?

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

СообщениеДобавлено: 30 апр 2016, 00:51
seaman
Разобраться в шейдере правильнее. Я в шейдерах не очень, но что-то типа:
Синтаксис:
Используется 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));

Во всяком случае смысл ясен - вместо альфы в выходном значении использовать рассчитанное значение. Т.е. чем ближе к нужному цвету, тем прозрачнее пиксель.