<?xml version="1.0" encoding="UTF-8"?>
<!--
    NTSC encoding artifact shader

    This shader renders the input image with added NTSC artifacts, by
    transforming the input into an NTSC signal, then decoding it again.
    It was originally developed in this forum thread:

	http://board.byuu.org/viewtopic.php?f=10&t=1494

    Copyright (C) 2010-2012 cgwg and Themaister

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.
    -->
<shader language="GLSL">
   <fragment filter="nearest" size_x="256"><![CDATA[#version 120

      uniform sampler2D     rubyTexture;
      uniform vec2          rubyTextureSize;
      uniform vec2          rubyInputSize;
      uniform int rubyFrameCount;

      #define TEX2D(c) texture2D(rubyTexture,(c))

      #define PI 3.14159265

      void main()
      {
        vec2 xy = gl_TexCoord[0].st;

        vec2 xyp = xy * rubyTextureSize * 4.0 * PI / 3.0;
        xyp.y = xyp.y / 2.0 + 2.0 * PI / 3.0 * mod(rubyFrameCount,2);

        vec4 rgb = TEX2D(xy);

        mat3x3 rgb2yuv = mat3x3(0.299,-0.14713, 0.615,
                 0.587,-0.28886,-0.51499,
                 0.114, 0.436  ,-0.10001);

        vec3 yuv;
        yuv = rgb2yuv * rgb.rgb;

        float dx = PI/3.0;
        xyp.x = xyp.x * rubyInputSize.x/256.0;
        float c0 = yuv.x + yuv.y * sin(xyp.x+xyp.y) + yuv.z*cos(xyp.x+xyp.y);
        float c1 = yuv.x + yuv.y * sin(xyp.x+xyp.y+dx) + yuv.z * cos(xyp.x+xyp.y+dx);
        rgb = TEX2D(xy + vec2(1.0/rubyTextureSize.x * rubyInputSize.x / 512.0, 0.0));
        yuv = rgb2yuv * rgb.rgb;
        float c2 = yuv.x + yuv.y * sin(xyp.x+xyp.y+2.0*dx) + yuv.z * cos(xyp.x+xyp.y+2.0*dx);
        float c3 = yuv.x + yuv.y * sin(xyp.x+xyp.y+3.0*dx) + yuv.z * cos(xyp.x+xyp.y+3.0*dx);

        gl_FragColor = (vec4(c0,c1,c2,c3)+0.65)/2.3;
      }
   ]]></fragment>

   <fragment filter="nearest" size_x="1024" scale_y="4.0"><![CDATA[#version 120

      uniform sampler2D     rubyTexture;
      uniform vec2          rubyTextureSize;
      uniform vec2          rubyOutputSize;
      uniform int rubyFrameCount;

      #define TEX2D(c) texture2D(rubyTexture,(c))

      #define PI 3.14159265

      void main()
      {
        vec2 xy = gl_TexCoord[0].st;

        vec2 xyf = fract(xy * rubyTextureSize);
        vec2 xyp = floor(xy * rubyTextureSize)+vec2(0.5);
        xy = xyp / rubyTextureSize;
        float offs = mod(rubyFrameCount,2)/2.0;
        vec4 phases = (vec4(0.0,0.25,0.5,0.75) + vec4(xyp.x+xyp.y/2.0+offs)) *4.0*PI/3.0;
        vec4 phasesl = (vec4(0.0,0.25,0.5,0.75) + vec4(-1.0+xyp.x+xyp.y/2.0+offs)) *4.0*PI/3.0;
        vec4 phasesr = (vec4(0.0,0.25,0.5,0.75) + vec4( 1.0+xyp.x+xyp.y/2.0+offs)) *4.0*PI/3.0;
        vec4 phsin = sin(phases);
        vec4 phcos = cos(phases);
        vec4 phsinl= sin(phasesl);
        vec4 phcosl= cos(phasesl);
        vec4 phsinr= sin(phasesr);
        vec4 phcosr= cos(phasesr);
        vec4 phone = vec4(1.0);

        vec2 one = 1.0/rubyTextureSize;

        vec4 c = TEX2D(xy)*2.3-0.65;
        vec4 cl= TEX2D(xy + vec2(-one.x,0.0))*2.3-0.65;
        vec4 cr= TEX2D(xy + vec2( one.x,0.0))*2.3-0.65;

        vec3 yuva = vec3((dot(cl.zw,phone.zw)+dot(c.xyz,phone.xyz)+0.5*(cl.y+c.w))/6.0, (dot(cl.zw,phsinl.zw)+dot(c.xyz,phsin.xyz)+0.5*(cl.y*phsinl.y+c.w*phsin.w))/3.0, (dot(cl.zw,phcosl.zw)+dot(c.xyz,phcos.xyz)+0.5*(cl.y*phcosl.y+c.w*phcos.w))/3.0);

        vec3 yuvb = vec3((cl.w*phone.w+dot(c.xyzw,phone.xyzw)+0.5*(cl.z+cr.x))/6.0, (cl.w*phsinl.w+dot(c.xyzw,phsin.xyzw)+0.5*(cl.z*phsinl.z+cr.x*phsinr.x))/3.0, (cl.w*phcosl.w+dot(c.xyzw,phcos.xyzw)+0.5*(cl.z*phcosl.z+cr.x*phcosr.x))/3.0);

        vec3 yuvc = vec3((cr.x*phone.x+dot(c.xyzw,phone.xyzw)+0.5*(cl.w+cr.y))/6.0, (cr.x*phsinr.x+dot(c.xyzw,phsin.xyzw)+0.5*(cl.w*phsinl.w+cr.y*phsinr.y))/3.0, (cr.x*phcosr.x+dot(c.xyzw,phcos.xyzw)+0.5*(cl.w*phcosl.w+cr.y*phcosr.y))/3.0);

        vec3 yuvd = vec3((dot(cr.xy,phone.xy)+dot(c.yzw,phone.yzw)+0.5*(c.x+cr.z))/6.0, (dot(cr.xy,phsinr.xy)+dot(c.yzw,phsin.yzw)+0.5*(c.x*phsin.x+cr.z*phsinr.z))/3.0, (dot(cr.xy,phcosr.xy)+dot(c.yzw,phcos.yzw)+0.5*(c.x*phcos.x+cr.z*phcosr.z))/3.0);

        mat3x3 yuv2rgb = mat3x3(1.0, 1.0, 1.0,
                 0.0,-0.39465,2.03211,
                 1.13983,-0.58060,0.0);


        if (xyf.x < 0.25)
          gl_FragColor = vec4(yuv2rgb*yuva, 0.0);
        else if (xyf.x < 0.5)
          gl_FragColor = vec4(yuv2rgb*yuvb, 0.0);
        else if (xyf.x < 0.75)
          gl_FragColor = vec4(yuv2rgb*yuvc, 0.0);
        else
          gl_FragColor = vec4(yuv2rgb*yuvd, 0.0);
      }
   ]]></fragment>
   
   <fragment filter="nearest" scale="1.0"><![CDATA[#version 120

      uniform sampler2D rubyTexture;
      uniform vec2      rubyInputSize;
      uniform vec2      rubyTextureSize;
      uniform vec2      rubyOutputSize;

      #define TEX2D(v) texture2D(rubyTexture, (v))

      void main()
      {
        mat3x3 rgb2yuv = mat3x3(0.299,-0.14713, 0.615,
                 0.587,-0.28886,-0.51499,
                 0.114, 0.436  ,-0.10001);
        mat3x3 yuv2rgb = mat3x3(1.0, 1.0, 1.0,
                 0.0,-0.39465,2.03211,
                 1.13983,-0.58060,0.0);


        vec4 sum   = vec4(0.0);

        float wid = 3.0;
        vec4 c1 = vec4(exp(-1.0/wid/wid));
        vec4 c2 = vec4(exp(-4.0/wid/wid));
        vec4 c3 = vec4(exp(-9.0/wid/wid));
        vec4 c4 = vec4(exp(-16.0/wid/wid));
        vec4 norm = 1.0 / (vec4(1.0) + vec4(2.0)*(c1+c2+c3+c4));

        vec2 xy = gl_TexCoord[0].st;
        float onex = 1.0 / rubyTextureSize.x;

        sum += TEX2D(xy + vec2(-4.0 * onex,  0.0)) * c4;
        sum += TEX2D(xy + vec2(-3.0 * onex,  0.0)) * c3;
        sum += TEX2D(xy + vec2(-2.0 * onex,  0.0)) * c2;
        sum += TEX2D(xy + vec2(-1.0 * onex,  0.0)) * c1;
        sum += TEX2D(xy);
        sum += TEX2D(xy + vec2(+1.0 * onex,  0.0)) * c1;
        sum += TEX2D(xy + vec2(+2.0 * onex,  0.0)) * c2;
        sum += TEX2D(xy + vec2(+3.0 * onex,  0.0)) * c3;
        sum += TEX2D(xy + vec2(+4.0 * onex,  0.0)) * c4;

        float y = (rgb2yuv * TEX2D(xy).rgb).x;
        vec2 uv = (rgb2yuv * (sum.rgb * norm.rgb)).yz;

        gl_FragColor = vec4(yuv2rgb * vec3(y, uv), 0.0);
      }
   ]]></fragment>
</shader>
