Need help trimming a shader

Hi! I was wondering if anyone here with the proper knowledge could help me trim this shader (VHS) so the only code present is the one needed for the chroma smear effect. I see there’s a lot of references to the play timer count, and while I linked the textures to transparent ones on a custom preset file and commented out the wiggle parameter, I would like all that functions out from the shader itself for optimization sake (It runs great on my tablet, but eats battery like crazy).

The shader code:

// VHS shader
// by hunterk
// adapted from ompuco's more AVdistortion shadertoy:
// https://www.shadertoy.com/view/XlsczN

// Parameter lines go here:
//#pragma parameter wiggle "Wiggle" 0.0 0.0 10.0 1.0
#pragma parameter smear "Chroma Smear" 0.5 0.0 1.0 0.05

#if defined(VERTEX)

#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;

vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main()
{
    gl_Position = MVPMatrix * VertexCoord;
    TEX0.xy = TexCoord.xy;
}

#elif defined(FRAGMENT)

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
uniform sampler2D play;
COMPAT_VARYING vec4 TEX0;

// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float wiggle;
uniform COMPAT_PRECISION float smear;
#else
#define wiggle 3.0
#define smear 1.0
#endif

#define iTime mod(float(FrameCount), 7.0)
#define iChannel0 Texture

//YIQ/RGB shit
vec3 rgb2yiq(vec3 c){
					return vec3(
						(0.2989*c.x + 0.5959*c.y + 0.2115*c.z),
						(0.5870*c.x - 0.2744*c.y - 0.5229*c.z),
						(0.1140*c.x - 0.3216*c.y + 0.3114*c.z)
					);
				}

vec3 yiq2rgb(vec3 c){
					return vec3(
						(	 1.0*c.x +	  1.0*c.y + 	1.0*c.z),
						( 0.956*c.x - 0.2720*c.y - 1.1060*c.z),
						(0.6210*c.x - 0.6474*c.y + 1.7046*c.z)
					);
				}

vec2 Circle(float Start, float Points, float Point)
{
	float Rad = (3.141592 * 2.0 * (1.0 / Points)) * (Point + Start);
	//return vec2(sin(Rad), cos(Rad));
		return vec2(-(.3+Rad), cos(Rad));

}

vec3 Blur(vec2 uv, float d){
	float t = (sin(iTime*5.0+uv.y*5.0))/10.0;
    float b = 1.0;
    t=0.0;
    vec2 PixelOffset=vec2(d+.0005*t,0);

    float Start = 2.0 / 14.0;
    vec2 Scale = 0.66 * 4.0 * 2.0 * PixelOffset.xy;

    vec3 N0 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 0.0) * Scale).rgb;
    vec3 N1 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 1.0) * Scale).rgb;
    vec3 N2 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 2.0) * Scale).rgb;
    vec3 N3 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 3.0) * Scale).rgb;
    vec3 N4 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 4.0) * Scale).rgb;
    vec3 N5 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 5.0) * Scale).rgb;
    vec3 N6 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 6.0) * Scale).rgb;
    vec3 N7 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 7.0) * Scale).rgb;
    vec3 N8 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 8.0) * Scale).rgb;
    vec3 N9 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 9.0) * Scale).rgb;
    vec3 N10 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 10.0) * Scale).rgb;
    vec3 N11 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 11.0) * Scale).rgb;
    vec3 N12 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 12.0) * Scale).rgb;
    vec3 N13 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 14.0, 13.0) * Scale).rgb;
    vec3 N14 = COMPAT_TEXTURE(iChannel0, uv).rgb;

	vec4 clr = COMPAT_TEXTURE(iChannel0, uv);
    float W = 1.0 / 15.0;

    clr.rgb=
		(N0 * W) +
		(N1 * W) +
		(N2 * W) +
		(N3 * W) +
		(N4 * W) +
		(N5 * W) +
		(N6 * W) +
		(N7 * W) +
		(N8 * W) +
		(N9 * W) +
		(N10 * W) +
		(N11 * W) +
		(N12 * W) +
		(N13 * W) +
		(N14 * W);
    return  vec3(clr.xyz)*b;
}

float onOff(float a, float b, float c, float framecount)
{
	return step(c, sin((framecount * 0.001) + a*cos((framecount * 0.001)*b)));
}

vec2 jumpy(vec2 uv, float framecount)
{
	vec2 look = uv;
	float window = 1./(1.+80.*(look.y-mod(framecount/4.,1.))*(look.y-mod(framecount/4.,1.)));
	look.x += 0.05 * sin(look.y*10. + framecount)/20.*onOff(4.,4.,.3, framecount)*(0.5+cos(framecount*20.))*window;
	float vShift = (0.1*wiggle) * 0.4*onOff(2.,3.,.9, framecount)*(sin(framecount)*sin(framecount*20.) +
										 (0.5 + 0.1*sin(framecount*200.)*cos(framecount)));
	look.y = mod(look.y - 0.01 * vShift, 1.);
	return look;
}

void main()
{
    float timer = (float(FrameDirection) > 0.5) ? float(FrameCount) : 0.0;
	float d = 0.1 - ceil(mod(iTime/3.0,1.0) + 0.5) * 0.1;
	vec2 uv = jumpy(vTexCoord.xy, iTime);
	vec2 uv2 = uv;

    float s = 0.0001 * -d + 0.0001 * wiggle * sin(iTime);

	float e = min(.30,pow(max(0.0,cos(uv.y*4.0+.3)-.75)*(s+0.5)*1.0,3.0))*25.0;
    float r = (iTime*(2.0*s));
    uv.x+=abs(r*pow(min(.003,(-uv.y+(.01*mod(iTime, 17.0))))*3.0,2.0));

    d=.051+abs(sin(s/4.0));
    float c = max(0.0001,.002*d) * smear;
	vec2 uvo = uv;
    vec4 final;
	final.xyz =Blur(uv,c+c*(uv.x));
    float y = rgb2yiq(final.xyz).r;

	uv.x+=.01*d;
    c*=6.0;
    final.xyz =Blur(uv,c);
    float i = rgb2yiq(final.xyz).g;

    uv.x+=.005*d;

    c*=2.50;
    final.xyz =Blur(uv,c);
    float q = rgb2yiq(final.xyz).b;
	final = vec4(yiq2rgb(vec3(y,i,q))-pow(s+e*2.0,3.0), 1.0);

	vec4 play_osd = COMPAT_TEXTURE(play, uv2 * TextureSize.xy / InputSize.xy);
	float show_overlay = (mod(timer, 100.0) < 50.0) && (timer != 0.0) && (timer < 500.0) ? play_osd.a : 0.0;
	show_overlay = clamp(show_overlay, 0.0, 1.0);
	final = mix(final, play_osd, show_overlay);

    FragColor = final;
}
#endif

Can you add three of these before and after that of please? `

Done! Sorry about that.

1 Like

The blur stuff is what you need to keep, but fwiw that’s the part that’s eating your battery :frowning:

Anyway to do the blur cheaper at the cost of looks?

Use a smaller blur kernel with fewer taps.

1 Like

Kinda hacky but managed to alleviate the power usage/heat on my tablet (when I say heat I’m referring to a slight warm feeling on one corner, but I’m obsessive so there you go) by cutting and rounding up some lines from the blur code. The effect is less strong, but works for me as I only need a light color smear, and other shaders like film noise are a full color channel separation which does not look natural IMO. Thanks for the replies though!

// VHS shader
// by hunterk
// adapted from ompuco's more AVdistortion shadertoy:
// https://www.shadertoy.com/view/XlsczN

// Parameter lines go here:
//#pragma parameter wiggle "Wiggle" 0.0 0.0 10.0 1.0
#pragma parameter smear "Chroma Smear" 0.5 0.0 1.0 0.05

#if defined(VERTEX)

#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;

vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main()
{
    gl_Position = MVPMatrix * VertexCoord;
    TEX0.xy = TexCoord.xy;
}

#elif defined(FRAGMENT)

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
uniform sampler2D play;
COMPAT_VARYING vec4 TEX0;

// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float wiggle;
uniform COMPAT_PRECISION float smear;
#else
#define wiggle 3.0
#define smear 1.0
#endif

#define iTime mod(float(FrameCount), 7.0)
#define iChannel0 Texture

//YIQ/RGB shit
vec3 rgb2yiq(vec3 c){
					return vec3(
						(0.2989*c.x + 0.5959*c.y + 0.2115*c.z),
						(0.5870*c.x - 0.2744*c.y - 0.5229*c.z),
						(0.1140*c.x - 0.3216*c.y + 0.3114*c.z)
					);
				}

vec3 yiq2rgb(vec3 c){
					return vec3(
						(	 1.0*c.x +	  1.0*c.y + 	1.0*c.z),
						( 0.956*c.x - 0.2720*c.y - 1.1060*c.z),
						(0.6210*c.x - 0.6474*c.y + 1.7046*c.z)
					);
				}

vec2 Circle(float Start, float Points, float Point)
{
	float Rad = (3.141592 * 2.0 * (1.0 / Points)) * (Point + Start);
	//return vec2(sin(Rad), cos(Rad));
		return vec2(-(.3+Rad), cos(Rad));

}

vec3 Blur(vec2 uv, float d){
	float t = (sin(iTime*5.0+uv.y*5.0))/10.0;
    float b = 1.0;
    t=0.0;
    vec2 PixelOffset=vec2(d+.0005*t,0);

    float Start = 2.0 / 4.0;
    vec2 Scale = 0.66 * 4.0 * 2.0 * PixelOffset.xy;

    vec3 N0 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 4.0, 0.0) * Scale).rgb;
    vec3 N1 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 4.0, 1.0) * Scale).rgb;
    vec3 N2 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 4.0, 2.0) * Scale).rgb;
    vec3 N3 = COMPAT_TEXTURE(iChannel0, uv + Circle(Start, 4.0, 3.0) * Scale).rgb;
    vec3 N4 = COMPAT_TEXTURE(iChannel0, uv).rgb;

	vec4 clr = COMPAT_TEXTURE(iChannel0, uv);
    	float W = 1.0 / 5.0;

    clr.rgb=
		(N0 * W) +
		(N1 * W) +
		(N2 * W) +
		(N3 * W) +
		(N4 * W);
    return  vec3(clr.xyz)*b;
}

float onOff(float a, float b, float c, float framecount)
{
	return step(c, sin((framecount * 0.001) + a*cos((framecount * 0.001)*b)));
}

vec2 jumpy(vec2 uv, float framecount)
{
	vec2 look = uv;
	float window = 1./(1.+80.*(look.y-mod(framecount/4.,1.))*(look.y-mod(framecount/4.,1.)));
	look.x += 0.05 * sin(look.y*10. + framecount)/20.*onOff(4.,4.,.3, framecount)*(0.5+cos(framecount*20.))*window;
	float vShift = (0.1*wiggle) * 0.4*onOff(2.,3.,.9, framecount)*(sin(framecount)*sin(framecount*20.) +
										 (0.5 + 0.1*sin(framecount*200.)*cos(framecount)));
	look.y = mod(look.y - 0.01 * vShift, 1.);
	return look;
}

void main()
{
    float timer = (float(FrameDirection) > 0.5) ? float(FrameCount) : 0.0;
	float d = 0.1 - ceil(mod(iTime/3.0,1.0) + 0.5) * 0.1;
	vec2 uv = jumpy(vTexCoord.xy, iTime);
	vec2 uv2 = uv;

    float s = 0.0001 * -d + 0.0001 * wiggle * sin(iTime);

	float e = min(.30,pow(max(0.0,cos(uv.y*4.0+.3)-.75)*(s+0.5)*1.0,3.0))*25.0;
    float r = (iTime*(2.0*s));
    uv.x+=abs(r*pow(min(.003,(-uv.y+(.01*mod(iTime, 17.0))))*3.0,2.0));

    d=.051+abs(sin(s/4.0));
    float c = max(0.0001,.002*d) * smear;
	vec2 uvo = uv;
    vec4 final;
	final.xyz =Blur(uv,c+c*(uv.x));
    float y = rgb2yiq(final.xyz).r;

	uv.x+=.01*d;
    c*=6.0;
    final.xyz =Blur(uv,c);
    float i = rgb2yiq(final.xyz).g;

    uv.x+=.005*d;

    c*=2.50;
    final.xyz =Blur(uv,c);
    float q = rgb2yiq(final.xyz).b;
	final = vec4(yiq2rgb(vec3(y,i,q))-pow(s+e*2.0,3.0), 1.0);

	vec4 play_osd = COMPAT_TEXTURE(play, uv2 * TextureSize.xy / InputSize.xy);
	float show_overlay = (mod(timer, 100.0) < 50.0) && (timer != 0.0) && (timer < 500.0) ? play_osd.a : 0.0;
	show_overlay = clamp(show_overlay, 0.0, 1.0);
	final = mix(final, play_osd, show_overlay);

    FragColor = final;
}
#endif

2 Likes