Merging two shaders together

I suck at shaders. There, I said it.

I don’t have any clue as to what the hell is going on inside them. That’s why I need your help.

I have two shaders. The first one is from the Mobile Movie Texture asset. This one:

Shader "Color Space/YCbCrtoRGBVHS"
{
    Properties
    {
        _YTex ("Y (RGB)", 2D) = "black" {}
        _CrTex ("Cr (RGB)", 2D) = "gray" {}
        _CbTex ("Cb (RGB)", 2D) = "gray" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            ColorMask RGB
            Lighting Off Fog { Color (0,0,0,0) }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            sampler2D _YTex;
            sampler2D _CbTex;
            sampler2D _CrTex;
           
            #include "YCbCrtoRGB.cginc"

            struct v2f
            {
                float4  pos : SV_POSITION;
                half2  uvY : TEXCOORD0;
                half2  uvCbCr : TEXCOORD1;
            };

            float4 _YTex_ST;
            float4 _CbTex_ST;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                o.uvY = TRANSFORM_TEX (v.texcoord, _YTex);
                o.uvCbCr = TRANSFORM_TEX (v.texcoord, _CbTex);
                return o;
            }

            fixed4 frag (v2f i) : COLOR
            {
                return YCbCrToRGB(SampleYCbCr( i.uvY, i.uvCbCr));
            }
            ENDCG
        }
    }
}

The second one is a shader that does some sort of chroma keying (I suppose), which removes the black background from a video. This one:

Shader "Hidden/VHSPostProcessEffect" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _VHSTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader {
        Pass {
            ZTest Always Cull Off ZWrite Off
            Fog { Mode off }
                   
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"

            uniform sampler2D _MainTex;
            uniform sampler2D _VHSTex;
           
            float _yScanline;
            float _xScanline;
           
            fixed4 frag (v2f_img i) : COLOR{   
                fixed4 vhs = tex2D (_VHSTex, i.uv);

                float dx = 1-abs(distance(i.uv.y, _xScanline));
                float dy = 1-abs(distance(i.uv.y, _yScanline));
               
                i.uv.x += dy * 0;
               
                float white = (vhs.r+vhs.g+vhs.b)/3;
                //i.uv.y += step(0.99, dx) * white * dx;
               
                if(dx > 0.99)
                    i.uv.y = _xScanline;
                //i.uv.y = step(0.99, dy) * (_yScanline) + step(dy, 0.99) * i.uv.y;
               
                fixed4 c = tex2D (_MainTex, i.uv);
               
                return c + vhs;
            }
            ENDCG
        }
    }
Fallback off
}

My question is, how can I combine the two shaders, so I get mobile playback capability of the first one, but with the cool keying of the second one?

PS: The Mobile Movie Texture asset does have some chroma keying shaders, but doesn’t work with high noise in the video.

Anyone? Could really use a hand. :slight_smile:

Copy and paste all the properties from the VHS shader to the movie player shader. Then copy all the code from the VHS shader frag function to the beginning of the movie player shader frag function.

Then you just need to replace where it’s getting the main texture here:

To instead grab the movie texture:

You will also need to see what’s in the “v2f_img” vertex data struct that is passed into the frag shader (it will be in the Unity docs or you can dig into “UnityCG.cginc” to find where it is defined), and add anything you need from it to the “v2f” struct that is defined in the first shader. You will usually use one of Unity’s default vertex structures, but you can declare your own if you need to.

Shaders aren’t too complicated. They need to small and fast (the frag function runs for each pixel every frame) so they are usually much simpler than most C# code you will work with. But they do have a lot of arcane syntax that you just need to learn by going through some examples. Go through the Unity docs, and look for a few good tutorials.

I could do it for you in about 30 seconds, but this isn’t a very difficult problem so I’m not going to simply let you off the hook with a “I suck at shaders”. :wink: