How to "copy-paste" a Cg shader found on the internet in Unity

Hello everyone, this is an extremely newbie question about shaders.
I need to make a post-processing shader for my camera that scales up the rendered game image using an xBR algorithm. I found a Cg shader on the internet that does just that, but since I’m a complete beginner in the field of shader programming, I just couldn’t write it properly in a Unity-compatible way.
Here is the Cg shader :

Here is what the output should look like ( this was achieved by feeding a screenshot of my game to a scaling software that uses the xBR method), click to enlarge :

Note that I know how to attach a post-processing shader to a camera, I just couldn’t figure out where to copy-paste the Cg code so that it works properly.
Any clarifications on how you achieved so would appreciated.
Also note that the effect only works when you’re displaying the game x2 its native resolution ( in the case of my game the native res is 512x300)

Make a new shader. I assume you’re using Unity 5 so it defaults to a surface shader. Delete everything between the lines “CGPROGRAM” and “ENDCG”. Just above “CGPROGRAM”, add a bracket “{” and just below “ENDCG”, add a closing bracket “}”. Then copy everything in the .cg file you have and paste in the space between CGPROGRAM and ENDCG. Then go back up, to the line containing “CGPROGRAM” and paste this:
#include "UnityCG.cginc" . After this line, add these too:

#pragma vertex [name of vertex shader]
#pragma fragment [name of fragment shader]

which in your case will be “main_vertex” for your vertex shader and “main_fragment” for your fragment shader.

After these, tell me what errors you encounter and we’ll go from there.

Hey there! Thanks for the help.
I followed what you said and I got this error :

I’ve seen some shaders adding a “Pass” before the brackets you told me to add, so I thought you forgot to mention that.
Now it’s not displaying any errors thankfully ( except that warning) :

So I guess I need to add the shader to a material? and then use Graphics.Blit?
I’ll try and let you know.

I added the shader to a material, now the console gives me this :

EDIT 1 : I’ve just solved the warning, but those bunch of errors still persist.
EDIT 2 : I’ve solved those errors, seems like a bug in Unity when drag&dropping a shader to a material, I’ve selected the shader from the the dropbox.

I have no idea what’s going on, any help guys ?

My shader so far looks like this : http://pastebin.com/raw.php?i=2tqZtPth

It’s definitely not working. We’ll need to adjust the shader to fit Unity. This is what I have so far but it throws out an error: “half4x3 not supported in pre-GLSL1.20 line x”

Shader "Custom/2xBR" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1) //You should set this field in Unity scripting, material.SetColor
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        decal ("decal (RGB)", 2D) = "white" {} //you should also set this in scripting with material.SetTexture ("decal", yourDecalTexture)
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        ///////////////////////////////////
        Pass {
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex main_vertex
            #pragma fragment main_fragment
           
            uniform half4 _Color;
            uniform sampler2D decal : TEXUNIT0;
            uniform half2 video_size; //You should set this in Unity (your script) using material.SetVector("video_size", outputSize float); //note that the vector you set must be a vector4, smae as the remaining two below
            uniform float2 texture_size; //You should set this in Unity (your script) using material.SetVector("texture_size", outputSize float);
            uniform half2 output_size; //You should set this in Unity (your script) using material.SetVector("output_size", outputSize float);
           
            const static float coef = 2.0;
            const static float3 dtt = float3(65536,255,1);
            const static half y_weight = 48.0;
            const static half u_weight = 7.0;
            const static half v_weight = 6.0;
            const static half3x3 yuv = half3x3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
            const static half3x3 yuv_weighted = half3x3(y_weight*yuv[0], u_weight*yuv[1], v_weight*yuv[2]);

            //const static half3x3 yuv_weighted = half3x3(14.352, 28.176, 5.472, -1.183, -2.317, 3.5, 3.0, -2.514, -0.486);

            float4 RGBtoYUV(half4x3 mat_color) {
                float a = abs(mul(yuv_weighted, mat_color[0]));
                float b = abs(mul(yuv_weighted, mat_color[1]));
                float c = abs(mul(yuv_weighted, mat_color[2]));
                float d = abs(mul(yuv_weighted, mat_color[3]));

                return float4(a, b, c, d);
            }

            float4 df(float4 A, float4 B) {
                return float4(abs(A - B));
            }


            float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h) {
                return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
            }

            struct out_vertex {
                half4 position : POSITION;
                half4 color    : COLOR;
                float2 texCoord : TEXCOORD0;
                half4 t1 : TEXCOORD1;
            };

            //    VERTEX_SHADER
            out_vertex main_vertex ( appdata_base v ) {
                out_vertex OUT;

                OUT.position = mul(UNITY_MATRIX_MVP, v.vertex);
                OUT.color = _Color;

                half2 ps = half2(1.0 / texture_size.x, 1.0 / texture_size.y);
                half dx = ps.x;
                half dy = ps.y;

                OUT.texCoord = v.texcoord;
                OUT.t1.xy = half2(dx,  0); // F
                OUT.t1.zw = half2(0, dy); // H

                return OUT;
            }

            //   FRAGMENT SHADER
            half4 main_fragment( out_vertex VAR ) : COLOR {
                bool4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
                bool4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;

                float2 fp = frac(VAR.texCoord*texture_size);

                half2 dx = VAR.t1.xy;
                half2 dy = VAR.t1.zw;

                half3 A = tex2D(decal, VAR.texCoord - dx - dy).xyz;
                half3 B = tex2D(decal, VAR.texCoord - dy).xyz;
                half3 C = tex2D(decal, VAR.texCoord + dx - dy).xyz;
                half3 D = tex2D(decal, VAR.texCoord - dx).xyz;
                half3 E = tex2D(decal, VAR.texCoord).xyz;
                half3 F = tex2D(decal, VAR.texCoord + dx).xyz;
                half3 G = tex2D(decal, VAR.texCoord - dx + dy).xyz;
                half3 H = tex2D(decal, VAR.texCoord + dy).xyz;
                half3 I = tex2D(decal, VAR.texCoord + dx + dy).xyz;

                half3  A1 = tex2D(decal, VAR.texCoord - dx - 2.0*dy).xyz;
                half3  C1 = tex2D(decal, VAR.texCoord + dx - 2.0*dy).xyz;
                half3  A0 = tex2D(decal, VAR.texCoord - 2.0*dx - dy).xyz;
                half3  G0 = tex2D(decal, VAR.texCoord - 2.0*dx + dy).xyz;
                half3  C4 = tex2D(decal, VAR.texCoord + 2.0*dx - dy).xyz;
                half3  I4 = tex2D(decal, VAR.texCoord + 2.0*dx + dy).xyz;
                half3  G5 = tex2D(decal, VAR.texCoord - dx + 2.0*dy).xyz;
                half3  I5 = tex2D(decal, VAR.texCoord + dx + 2.0*dy).xyz;
                half3  B1 = tex2D(decal, VAR.texCoord - 2.0*dy).xyz;
                half3  D0 = tex2D(decal, VAR.texCoord - 2.0*dx).xyz;
                half3  H5 = tex2D(decal, VAR.texCoord + 2.0*dy).xyz;
                half3  F4 = tex2D(decal, VAR.texCoord + 2.0*dx).xyz;

                float4 a = RGBtoYUV(half4x3(A, G, I, C));
                float4 b = RGBtoYUV(half4x3(B, D, H, F));
                float4 c = RGBtoYUV(half4x3(C, A, G, I));
                float4 d = RGBtoYUV(half4x3(D, H, F, B));
                float4 e = RGBtoYUV(half4x3(E, E, E, E));
                float4 f = RGBtoYUV(half4x3(F, B, D, H));
                float4 g = RGBtoYUV(half4x3(G, I, C, A));
                float4 h = RGBtoYUV(half4x3(H, F, B, D));
                float4 i = RGBtoYUV(half4x3(I, C, A, G));

                float4 a1 = RGBtoYUV(half4x3(A1, G0, I5, C4));
                float4 c1 = RGBtoYUV(half4x3(C1, A0, G5, I4));
                float4 a0 = RGBtoYUV(half4x3(A0, G5, I4, C1));
                float4 g0 = RGBtoYUV(half4x3(G0, I5, C4, A1));
                float4 c4 = RGBtoYUV(half4x3(C4, A1, G0, I5));
                float4 i4 = RGBtoYUV(half4x3(I4, C1, A0, G5));
                float4 g5 = RGBtoYUV(half4x3(G5, I4, C1, A0));
                float4 i5 = RGBtoYUV(half4x3(I5, C4, A1, G0));
                float4 b1 = RGBtoYUV(half4x3(B1, D0, H5, F4));
                float4 d0 = RGBtoYUV(half4x3(D0, H5, F4, B1));
                float4 h5 = RGBtoYUV(half4x3(H5, F4, B1, D0));
                float4 f4 = RGBtoYUV(half4x3(F4, B1, D0, H5));

                interp_restriction_lv1 = ((e != f) && (e != h));
                interp_restriction_lv2_left = ((e != g) && (d != g));
                interp_restriction_lv2_up = ((e != c) && (b != c));

                edr = (weighted_distance(e, c, g, i, h5, f4, h, f) < weighted_distance(h, d, i5, f, i4, b, e, i)) && interp_restriction_lv1;
                edr_left = ((coef*df(f,g)) <= df(h,c)) && interp_restriction_lv2_left;
                edr_up = (df(f,g) >= (coef*df(h,c))) && interp_restriction_lv2_up;

                half3 E0 = E;
                half3 E1 = E;
                half3 E2 = E;
                half3 E3 = E;

                px = (df(e,f) <= df(e,h));

                half3 P[4];

                P[0] = px.x ? F : H;
                P[1] = px.y ? B : F;
                P[2] = px.z ? D : B;
                P[3] = px.w ? H : D;


                if (edr.x)
                {
                    if (edr_left.x && edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.833333);
                        E2 = lerp(E2 , P[0],  0.25);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else if (edr_left.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E2 = lerp(E2 , P[0],  0.25);
                    }
                    else if (edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else
                    {
                        E3 = lerp(E3 , P[0],  0.5);
                    }
                }

                if (edr.y)
                {
                    if (edr_left.y && edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.833333);
                        E3 = lerp(E3 , P[1],  0.25);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else if (edr_left.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E3 = lerp(E3 , P[1],  0.25);
                    }
                    else if (edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else
                    {
                        E1 = lerp(E1 , P[1],  0.5);
                    }
                }

                if (edr.z)
                {
                    if (edr_left.z && edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.833333);
                        E1 = lerp(E1 , P[2],  0.25);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else if (edr_left.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E1 = lerp(E1 , P[2],  0.25);
                    }
                    else if (edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else
                    {
                        E0 = lerp(E0 , P[2],  0.5);
                    }
                }

                if (edr.w)
                {
                    if (edr_left.w && edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.833333);
                        E0 = lerp(E0 , P[3],  0.25);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else if (edr_left.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E0 = lerp(E0 , P[3],  0.25);
                    }
                    else if (edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else
                    {
                        E2 = lerp(E2 , P[3],  0.5);
                    }
                }

                half3 res = (fp.x < 0.50) ? (fp.y < 0.50 ? E0 : E2) : (fp.y < 0.50 ? E1 : E3);

                return half4(res, 1.0);
            }
            ENDCG
        }
        ///////////////////////////////////
    }
    FallBack "Diffuse"
}

Gotten rid of the half4x3 issue, now facing this comparison issues “&&”.

Shader "Custom/2xBR" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1) //You should set this field in Unity scripting, material.SetColor
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        decal ("decal (RGB)", 2D) = "white" {} //you should also set this in scripting with material.SetTexture ("decal", yourDecalTexture)
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        ///////////////////////////////////
        Pass {
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex main_vertex
            #pragma fragment main_fragment
           
            uniform half4 _Color;
            uniform sampler2D decal : TEXUNIT0;
            uniform half2 video_size; //You should set this in Unity (your script) using material.SetVector("video_size", outputSize float); //note that the vector you set must be a vector4, smae as the remaining two below
            uniform float2 texture_size; //You should set this in Unity (your script) using material.SetVector("texture_size", outputSize float);
            uniform half2 output_size; //You should set this in Unity (your script) using material.SetVector("output_size", outputSize float);
           
            const static float coef = 2.0;
            const static float3 dtt = float3(65536,255,1);
            const static half y_weight = 48.0;
            const static half u_weight = 7.0;
            const static half v_weight = 6.0;
            const static half3x3 yuv = half3x3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
            const static half3x3 yuv_weighted = half3x3(y_weight*yuv[0], u_weight*yuv[1], v_weight*yuv[2]);

            //const static half3x3 yuv_weighted = half3x3(14.352, 28.176, 5.472, -1.183, -2.317, 3.5, 3.0, -2.514, -0.486);

            float4 RGBtoYUV(half4x4 mat_color) {
                float a = abs(mul(yuv_weighted, mat_color[0].xyz));
                float b = abs(mul(yuv_weighted, mat_color[1].xyz));
                float c = abs(mul(yuv_weighted, mat_color[2].xyz));
                float d = abs(mul(yuv_weighted, mat_color[3].xyz));

                return float4(a, b, c, d);
            }

            float4 df(float4 A, float4 B) {
                return float4(abs(A - B));
            }


            float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h) {
                return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
            }

            struct out_vertex {
                half4 position : POSITION;
                half4 color    : COLOR;
                float2 texCoord : TEXCOORD0;
                half4 t1 : TEXCOORD1;
            };

            //    VERTEX_SHADER
            out_vertex main_vertex ( appdata_base v ) {
                out_vertex OUT;

                OUT.position = mul(UNITY_MATRIX_MVP, v.vertex);
                OUT.color = _Color;

                half2 ps = half2(1.0 / texture_size.x, 1.0 / texture_size.y);
                half dx = ps.x;
                half dy = ps.y;

                OUT.texCoord = v.texcoord;
                OUT.t1.xy = half2(dx,  0); // F
                OUT.t1.zw = half2(0, dy); // H

                return OUT;
            }

            //   FRAGMENT SHADER
            half4 main_fragment( out_vertex VAR ) : COLOR {
                bool4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
                bool4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;

                float2 fp = frac(VAR.texCoord*texture_size);

                half2 dx = VAR.t1.xy;
                half2 dy = VAR.t1.zw;

                half3 A = tex2D(decal, VAR.texCoord - dx - dy).xyz;
                half3 B = tex2D(decal, VAR.texCoord - dy).xyz;
                half3 C = tex2D(decal, VAR.texCoord + dx - dy).xyz;
                half3 D = tex2D(decal, VAR.texCoord - dx).xyz;
                half3 E = tex2D(decal, VAR.texCoord).xyz;
                half3 F = tex2D(decal, VAR.texCoord + dx).xyz;
                half3 G = tex2D(decal, VAR.texCoord - dx + dy).xyz;
                half3 H = tex2D(decal, VAR.texCoord + dy).xyz;
                half3 I = tex2D(decal, VAR.texCoord + dx + dy).xyz;

                half3  A1 = tex2D(decal, VAR.texCoord - dx - 2.0*dy).xyz;
                half3  C1 = tex2D(decal, VAR.texCoord + dx - 2.0*dy).xyz;
                half3  A0 = tex2D(decal, VAR.texCoord - 2.0*dx - dy).xyz;
                half3  G0 = tex2D(decal, VAR.texCoord - 2.0*dx + dy).xyz;
                half3  C4 = tex2D(decal, VAR.texCoord + 2.0*dx - dy).xyz;
                half3  I4 = tex2D(decal, VAR.texCoord + 2.0*dx + dy).xyz;
                half3  G5 = tex2D(decal, VAR.texCoord - dx + 2.0*dy).xyz;
                half3  I5 = tex2D(decal, VAR.texCoord + dx + 2.0*dy).xyz;
                half3  B1 = tex2D(decal, VAR.texCoord - 2.0*dy).xyz;
                half3  D0 = tex2D(decal, VAR.texCoord - 2.0*dx).xyz;
                half3  H5 = tex2D(decal, VAR.texCoord + 2.0*dy).xyz;
                half3  F4 = tex2D(decal, VAR.texCoord + 2.0*dx).xyz;

                float4 a = RGBtoYUV(half4x4(half4(A,1), half4(G,1), half4(I,1), half4(C,1)));
                float4 b = RGBtoYUV(half4x4(half4(B,1), half4(D,1), half4(H,1), half4(F,1)));
                float4 c = RGBtoYUV(half4x4(half4(C,1), half4(A,1), half4(G,1), half4(I,1)));
                float4 d = RGBtoYUV(half4x4(half4(D,1), half4(H,1), half4(F,1), half4(B,1)));
                float4 e = RGBtoYUV(half4x4(half4(E,1), half4(E,1), half4(E,1), half4(E,1)));
                float4 f = RGBtoYUV(half4x4(half4(F,1), half4(B,1), half4(D,1), half4(H,1)));
                float4 g = RGBtoYUV(half4x4(half4(G,1), half4(I,1), half4(C,1), half4(A,1)));
                float4 h = RGBtoYUV(half4x4(half4(H,1), half4(F,1), half4(B,1), half4(D,1)));
                float4 i = RGBtoYUV(half4x4(half4(I,1), half4(C,1), half4(A,1), half4(G,1)));

                float4 a1 = RGBtoYUV(half4x4(half4(A1,1), half4(G0,1), half4(I5,1), half4(C4,1)));
                float4 c1 = RGBtoYUV(half4x4(half4(C1,1), half4(A0,1), half4(G5,1), half4(I4,1)));
                float4 a0 = RGBtoYUV(half4x4(half4(A0,1), half4(G5,1), half4(I4,1), half4(C1,1)));
                float4 g0 = RGBtoYUV(half4x4(half4(G0,1), half4(I5,1), half4(C4,1), half4(A1,1)));
                float4 c4 = RGBtoYUV(half4x4(half4(C4,1), half4(A1,1), half4(G0,1), half4(I5,1)));
                float4 i4 = RGBtoYUV(half4x4(half4(I4,1), half4(C1,1), half4(A0,1), half4(G5,1)));
                float4 g5 = RGBtoYUV(half4x4(half4(G5,1), half4(I4,1), half4(C1,1), half4(A0,1)));
                float4 i5 = RGBtoYUV(half4x4(half4(I5,1), half4(C4,1), half4(A1,1), half4(G0,1)));
                float4 b1 = RGBtoYUV(half4x4(half4(B1,1), half4(D0,1), half4(H5,1), half4(F4,1)));
                float4 d0 = RGBtoYUV(half4x4(half4(D0,1), half4(H5,1), half4(F4,1), half4(B1,1)));
                float4 h5 = RGBtoYUV(half4x4(half4(H5,1), half4(F4,1), half4(B1,1), half4(D0,1)));
                float4 f4 = RGBtoYUV(half4x4(half4(F4,1), half4(B1,1), half4(D0,1), half4(H5,1)));
               
                interp_restriction_lv1 = ((e != f) && (e != h));
                interp_restriction_lv2_left = ((e != g) && (d != g));
                interp_restriction_lv2_up = ((e != c) && (b != c));

                edr = (weighted_distance(e, c, g, i, h5, f4, h, f) < weighted_distance(h, d, i5, f, i4, b, e, i)) && interp_restriction_lv1;
                edr_left = ((coef*df(f,g)) <= df(h,c)) && interp_restriction_lv2_left;
                edr_up = (df(f,g) >= (coef*df(h,c))) && interp_restriction_lv2_up;

                half3 E0 = E;
                half3 E1 = E;
                half3 E2 = E;
                half3 E3 = E;

                px = (df(e,f) <= df(e,h));

                half3 P[4];

                P[0] = px.x ? F : H;
                P[1] = px.y ? B : F;
                P[2] = px.z ? D : B;
                P[3] = px.w ? H : D;


                if (edr.x)
                {
                    if (edr_left.x && edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.833333);
                        E2 = lerp(E2 , P[0],  0.25);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else if (edr_left.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E2 = lerp(E2 , P[0],  0.25);
                    }
                    else if (edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else
                    {
                        E3 = lerp(E3 , P[0],  0.5);
                    }
                }

                if (edr.y)
                {
                    if (edr_left.y && edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.833333);
                        E3 = lerp(E3 , P[1],  0.25);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else if (edr_left.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E3 = lerp(E3 , P[1],  0.25);
                    }
                    else if (edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else
                    {
                        E1 = lerp(E1 , P[1],  0.5);
                    }
                }

                if (edr.z)
                {
                    if (edr_left.z && edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.833333);
                        E1 = lerp(E1 , P[2],  0.25);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else if (edr_left.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E1 = lerp(E1 , P[2],  0.25);
                    }
                    else if (edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else
                    {
                        E0 = lerp(E0 , P[2],  0.5);
                    }
                }

                if (edr.w)
                {
                    if (edr_left.w && edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.833333);
                        E0 = lerp(E0 , P[3],  0.25);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else if (edr_left.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E0 = lerp(E0 , P[3],  0.25);
                    }
                    else if (edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else
                    {
                        E2 = lerp(E2 , P[3],  0.5);
                    }
                }

                half3 res = (fp.x < 0.50) ? (fp.y < 0.50 ? E0 : E2) : (fp.y < 0.50 ? E1 : E3);

                return half4(res, 1.0);
            }
            ENDCG
        }
        ///////////////////////////////////
    }
    FallBack "Diffuse"
}

Hey there, I’m back.
I’ve previously sent a message to Chman the guy behind the Colorful asset about this. The response included other topics but here is what he said about the implementation of the shader :

Not sure if this would help now that you’re this far into porting the shader.

Yes I did what he was saying. The vertex shader was the easiest in fact. Copy and paste what I have and tell me what errors you get. I know what he’s talking about.

After compiling the shader you wrote I get the following errors ( I guess the same as you) :

The screen is now white, if that helps in any way :

For the temp register issue, add this line under the #pragma fragment line:
#pragma profileoption NumTemps=64 .Keep increasing the number till the temp register errors go away. I have a question that might solve the ‘&&’ problem: what platform are you targeting?

Hmmm particularly desktop ( priority for Windows, not sure if I’d include Linux and Mac). No chance for mobile, the screen would get all flooded by the controls.

Okay. Did the temp registers error go away after adding that line? If no, quit Unity, and start it with the -force-opengl argument. The error should go away then (I use openGL [Mac] and don’t encounter that problem). The && problem is a tricky one. I managed to fix it by breaking the statement into individual booleans. Here, the shader throws no more errors on my system. Note that I haven’t tested it, so that’s up to you.

Shader "Custom/2xBR" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1) //You should set this field in Unity scripting, material.SetColor
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        decal ("decal (RGB)", 2D) = "white" {} //you should also set this in scripting with material.SetTexture ("decal", yourDecalTexture)
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        ///////////////////////////////////
        Pass {
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex main_vertex
            #pragma fragment main_fragment
           
            uniform half4 _Color;
            uniform sampler2D decal : TEXUNIT0;
            uniform half2 video_size; //You should set this in Unity (your script) using material.SetVector("video_size", outputSize float); //note that the vector you set must be a vector4, smae as the remaining two below
            uniform float2 texture_size; //You should set this in Unity (your script) using material.SetVector("texture_size", outputSize float);
            uniform half2 output_size; //You should set this in Unity (your script) using material.SetVector("output_size", outputSize float);
           
            const static float coef = 2.0;
            const static float3 dtt = float3(65536,255,1);
            const static half y_weight = 48.0;
            const static half u_weight = 7.0;
            const static half v_weight = 6.0;
            const static half3x3 yuv = half3x3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
            const static half3x3 yuv_weighted = half3x3(y_weight*yuv[0], u_weight*yuv[1], v_weight*yuv[2]);

            //const static half3x3 yuv_weighted = half3x3(14.352, 28.176, 5.472, -1.183, -2.317, 3.5, 3.0, -2.514, -0.486);

            float4 RGBtoYUV(half4x4 mat_color) {
                float a = abs(mul(yuv_weighted, mat_color[0].xyz));
                float b = abs(mul(yuv_weighted, mat_color[1].xyz));
                float c = abs(mul(yuv_weighted, mat_color[2].xyz));
                float d = abs(mul(yuv_weighted, mat_color[3].xyz));

                return float4(a, b, c, d);
            }

            float4 df(float4 A, float4 B) {
                return float4(abs(A - B));
            }


            float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h) {
                return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
            }

            struct out_vertex {
                half4 position : POSITION;
                half4 color    : COLOR;
                float2 texCoord : TEXCOORD0;
                half4 t1 : TEXCOORD1;
            };

            //    VERTEX_SHADER
            out_vertex main_vertex ( appdata_base v ) {
                out_vertex OUT;

                OUT.position = mul(UNITY_MATRIX_MVP, v.vertex);
                OUT.color = _Color;

                half2 ps = half2(1.0 / texture_size.x, 1.0 / texture_size.y);
                half dx = ps.x;
                half dy = ps.y;

                OUT.texCoord = v.texcoord;
                OUT.t1.xy = half2(dx,  0); // F
                OUT.t1.zw = half2(0, dy); // H

                return OUT;
            }

            //   FRAGMENT SHADER
            half4 main_fragment( out_vertex VAR ) : COLOR {
                bool4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
                bool4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;

                float2 fp = frac(VAR.texCoord*texture_size);

                half2 dx = VAR.t1.xy;
                half2 dy = VAR.t1.zw;

                half3 A = tex2D(decal, VAR.texCoord - dx - dy).xyz;
                half3 B = tex2D(decal, VAR.texCoord - dy).xyz;
                half3 C = tex2D(decal, VAR.texCoord + dx - dy).xyz;
                half3 D = tex2D(decal, VAR.texCoord - dx).xyz;
                half3 E = tex2D(decal, VAR.texCoord).xyz;
                half3 F = tex2D(decal, VAR.texCoord + dx).xyz;
                half3 G = tex2D(decal, VAR.texCoord - dx + dy).xyz;
                half3 H = tex2D(decal, VAR.texCoord + dy).xyz;
                half3 I = tex2D(decal, VAR.texCoord + dx + dy).xyz;

                half3  A1 = tex2D(decal, VAR.texCoord - dx - 2.0*dy).xyz;
                half3  C1 = tex2D(decal, VAR.texCoord + dx - 2.0*dy).xyz;
                half3  A0 = tex2D(decal, VAR.texCoord - 2.0*dx - dy).xyz;
                half3  G0 = tex2D(decal, VAR.texCoord - 2.0*dx + dy).xyz;
                half3  C4 = tex2D(decal, VAR.texCoord + 2.0*dx - dy).xyz;
                half3  I4 = tex2D(decal, VAR.texCoord + 2.0*dx + dy).xyz;
                half3  G5 = tex2D(decal, VAR.texCoord - dx + 2.0*dy).xyz;
                half3  I5 = tex2D(decal, VAR.texCoord + dx + 2.0*dy).xyz;
                half3  B1 = tex2D(decal, VAR.texCoord - 2.0*dy).xyz;
                half3  D0 = tex2D(decal, VAR.texCoord - 2.0*dx).xyz;
                half3  H5 = tex2D(decal, VAR.texCoord + 2.0*dy).xyz;
                half3  F4 = tex2D(decal, VAR.texCoord + 2.0*dx).xyz;

                float4 a = RGBtoYUV(half4x4(half4(A,1), half4(G,1), half4(I,1), half4(C,1)));
                float4 b = RGBtoYUV(half4x4(half4(B,1), half4(D,1), half4(H,1), half4(F,1)));
                float4 c = RGBtoYUV(half4x4(half4(C,1), half4(A,1), half4(G,1), half4(I,1)));
                float4 d = RGBtoYUV(half4x4(half4(D,1), half4(H,1), half4(F,1), half4(B,1)));
                float4 e = RGBtoYUV(half4x4(half4(E,1), half4(E,1), half4(E,1), half4(E,1)));
                float4 f = RGBtoYUV(half4x4(half4(F,1), half4(B,1), half4(D,1), half4(H,1)));
                float4 g = RGBtoYUV(half4x4(half4(G,1), half4(I,1), half4(C,1), half4(A,1)));
                float4 h = RGBtoYUV(half4x4(half4(H,1), half4(F,1), half4(B,1), half4(D,1)));
                float4 i = RGBtoYUV(half4x4(half4(I,1), half4(C,1), half4(A,1), half4(G,1)));

                float4 a1 = RGBtoYUV(half4x4(half4(A1,1), half4(G0,1), half4(I5,1), half4(C4,1)));
                float4 c1 = RGBtoYUV(half4x4(half4(C1,1), half4(A0,1), half4(G5,1), half4(I4,1)));
                float4 a0 = RGBtoYUV(half4x4(half4(A0,1), half4(G5,1), half4(I4,1), half4(C1,1)));
                float4 g0 = RGBtoYUV(half4x4(half4(G0,1), half4(I5,1), half4(C4,1), half4(A1,1)));
                float4 c4 = RGBtoYUV(half4x4(half4(C4,1), half4(A1,1), half4(G0,1), half4(I5,1)));
                float4 i4 = RGBtoYUV(half4x4(half4(I4,1), half4(C1,1), half4(A0,1), half4(G5,1)));
                float4 g5 = RGBtoYUV(half4x4(half4(G5,1), half4(I4,1), half4(C1,1), half4(A0,1)));
                float4 i5 = RGBtoYUV(half4x4(half4(I5,1), half4(C4,1), half4(A1,1), half4(G0,1)));
                float4 b1 = RGBtoYUV(half4x4(half4(B1,1), half4(D0,1), half4(H5,1), half4(F4,1)));
                float4 d0 = RGBtoYUV(half4x4(half4(D0,1), half4(H5,1), half4(F4,1), half4(B1,1)));
                float4 h5 = RGBtoYUV(half4x4(half4(H5,1), half4(F4,1), half4(B1,1), half4(D0,1)));
                float4 f4 = RGBtoYUV(half4x4(half4(F4,1), half4(B1,1), half4(D0,1), half4(H5,1)));
               
                //interp_restriction_lv1 = ((e != f) && (e != h)); //must break up into seperate conditions
                bool iop1 = (e != f);
                bool iop2 = (e != h);
                interp_restriction_lv1 = iop1 && iop2;
               
                //interp_restriction_lv2_left = ((e != g) && (d != g));
                bool irp1 = (e != g);
                bool irp2 = (d != g);
                interp_restriction_lv2_left = irp1 && irp2;
               
                //interp_restriction_lv2_up = ((e != c) && (b != c));
                bool iru1 = (e != c);
                bool iru2 = (b != c);
                interp_restriction_lv2_up = iru1 && iru2;

                //edr = (weighted_distance(e, c, g, i, h5, f4, h, f) < weighted_distance(h, d, i5, f, i4, b, e, i)) && interp_restriction_lv1;
                bool ed1 = (weighted_distance(e, c, g, i, h5, f4, h, f) < weighted_distance(h, d, i5, f, i4, b, e, i));
                edr = ed1 && (iop1 && iop2); //interp_restriction_lv1 here throws error, so I replaced it with it's assignment
               
                //edr_left = ((coef*df(f,g)) <= df(h,c)) && interp_restriction_lv2_left;
                bool edl1 = ((coef*df(f,g)) <= df(h,c));
                edr_left = edl1 && (irp1 && irp2);
               
                //edr_up = (df(f,g) >= (coef*df(h,c))) && interp_restriction_lv2_up;
                bool edu1 = (df(f,g) >= (coef*df(h,c)));
                edr_up = edu1 && (iru1 && iru2);


                half3 E0 = E;
                half3 E1 = E;
                half3 E2 = E;
                half3 E3 = E;

                px = (df(e,f) <= df(e,h));

                half3 P[4];

                P[0] = px.x ? F : H;
                P[1] = px.y ? B : F;
                P[2] = px.z ? D : B;
                P[3] = px.w ? H : D;


                if (edr.x)
                {
                    if (edr_left.x && edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.833333);
                        E2 = lerp(E2 , P[0],  0.25);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else if (edr_left.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E2 = lerp(E2 , P[0],  0.25);
                    }
                    else if (edr_up.x)
                    {
                        E3 = lerp(E3 , P[0],  0.75);
                        E1 = lerp(E1 , P[0],  0.25);
                    }
                    else
                    {
                        E3 = lerp(E3 , P[0],  0.5);
                    }
                }

                if (edr.y)
                {
                    if (edr_left.y && edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.833333);
                        E3 = lerp(E3 , P[1],  0.25);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else if (edr_left.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E3 = lerp(E3 , P[1],  0.25);
                    }
                    else if (edr_up.y)
                    {
                        E1 = lerp(E1 , P[1],  0.75);
                        E0 = lerp(E0 , P[1],  0.25);
                    }
                    else
                    {
                        E1 = lerp(E1 , P[1],  0.5);
                    }
                }

                if (edr.z)
                {
                    if (edr_left.z && edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.833333);
                        E1 = lerp(E1 , P[2],  0.25);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else if (edr_left.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E1 = lerp(E1 , P[2],  0.25);
                    }
                    else if (edr_up.z)
                    {
                        E0 = lerp(E0 , P[2],  0.75);
                        E2 = lerp(E2 , P[2],  0.25);
                    }
                    else
                    {
                        E0 = lerp(E0 , P[2],  0.5);
                    }
                }

                if (edr.w)
                {
                    if (edr_left.w && edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.833333);
                        E0 = lerp(E0 , P[3],  0.25);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else if (edr_left.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E0 = lerp(E0 , P[3],  0.25);
                    }
                    else if (edr_up.w)
                    {
                        E2 = lerp(E2 , P[3],  0.75);
                        E3 = lerp(E3 , P[3],  0.25);
                    }
                    else
                    {
                        E2 = lerp(E2 , P[3],  0.5);
                    }
                }

                half3 res = (fp.x < 0.50) ? (fp.y < 0.50 ? E0 : E2) : (fp.y < 0.50 ? E1 : E3);

                return half4(res, 1.0);
            }
            ENDCG
        }
        ///////////////////////////////////
    }
    FallBack "Diffuse"
}

I added the " #pragma profileoption NumTemps=64 " line after/before the frag pragma but the errors are still persistent even after increasing/decreasing the value ( same errors number regardless of the NumTemps value).
Also tried the -force-opengl, but Unity turns extremely slow and sick :

No text, some buttons are semi-transparent, fails at rendering the game ( I barely got my mouse moving to the Play button), etc …

You know what, I guess I’ll leave this for later, for the moment I’ll try experimenting with Post FX Studio. Have you tried it before? If so how well would you recommend it?

Sorry for the trouble and thanks for the effort!

Hey man. I don’t have any experience with PostFX Studio so I cannot say for sure, but if this is the only effect you’re aiming for, I won’t advise it. I generally don’t advise it because you have little to no control over the code; this is always a downside to advanced devs. But back on this issue, the problem seems to be your GPU. suggests that your GPU is old-ish. I also believe you’re running Unity 5. Replace the "#pragma profileoption NumTemps=64 " with this:
#pragma target 3.0 . This forces shader model 3 which means more features. I ran this on my surface pro (DX9 GPU) and was encountering a similar issue: too many math operations. I added that line and voila! The error disappeared. Fingers crossed it works this time.

Hey Lanre! It’s indeed throwing no more errors thanks to you.
But I have no idea what to fill the videoSize, textureSize, outputSize values with.
So I posted on the Lib Retro forums where the xBR algorithm creator seems to be active in : http://libretro.com/forums/showthread.php?t=88&page=18 ( scroll down)
As I said in the reply the screen is always white, maybe I’m not setting the three variables properly. I’m most afraid that the cg shader isn’t working properly to begin with.
In any case, many thanks to you for this much effort!!
By the way is the Z and W values of the three variables used in the shader? I’m thinking they normally should be left empty since sizes are given in two floats ( width x height)

By the way this is how the script that controls the shader looks like :

using UnityEngine;
using System.Collections;

public class CameraOutputResize : MonoBehaviour
{
    public Material mat_2xBR;

    public Vector4 videoSize;
    public Vector4 textureSize;
    public Vector4 outputSize;

    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        mat_2xBR.SetVector("video_size", videoSize);
        mat_2xBR.SetVector("texture_size", textureSize);
        mat_2xBR.SetVector("output_size", outputSize);

        Graphics.Blit(source, destination, mat_2xBR);
    }
}

By reading through the shader, it doesn’t seem that videoSize and outputSize are used anywhere, nor are textureSize’s Z and W.
I’ve found an HLSL implementation of the shader in XNA ( 2d - How do I perform an xBR or hqx filter in XNA? - Game Development Stack Exchange) and from what I understood the outputSize is the native resolution of the game ( 512x300 in my case), already tried it ( both (512,300,0,0) and (0,0,512,300)) but it doesn’t seem to work. Argggh

BTW I already have Post FX Studio, so I’ll experiment with it to get familiar with fragment shaders, I also have a set of effects other than the xBR scaling that I want to implement in the game ( like water, shockwave, and fire distortions)

I think I see the problem. The shader samples from the “decal” texture. But when you do a Graphics.Blit(), you’re effectively setting the source texture as the “_MainTex” field in the shader; in our case, this should be the decal field. Renaming every instance of ‘decal’ to ‘_MainTex’ would be too cumbersome. And I notice you use OnRenderImage. For optimization purposes, use OnPostRender instead because OnRenderImage makes the camera render twice: first for the view, then to make the source texture.

Replace the OnRenderImage with these:

private RenderTexture reTex;

void OnPreRender () {
if (reTex == null) {
reTex = new RenderTexture(Screen.width, Screen.height, 0);
reTex.antiAliasing = QualitySettings.antiAliasing;
reTex.Create();
}
GetComponent<Camera>().targetTexture = reTex;
}

void OnPostRender () {
//set the material attributes here
mat_2xBR.SetTexture("decal", reTex);
Graphics.Blit((RenderTexture)null, (RenderTexture)null, mat_2xBR);
GetFomponent<Camera>().targetTexture = null;
reTex.DiscardContents();
}

And everything should be good to go.

If you wanna see if those variables are useless, comment them out (the uniform lines inside CGPROGRAM). If you encounter no errors, then they are indeed useless; you might then erase them from your code.