Effects/Gradient and Edges

From LIV Wiki
Jump to: navigation, search


More effects here!


What To Edit

Everything you can change is at the bottom of the file, in the vec4 chroma_key(in vec2 coords) function!


Gradient

This is a simple two-point linear gradient, you can adjust both the color of each point, and the direction.

To change the color, find the two SRGB functions:

  • These are simple RGB colors, so for red, you'd do this:
    SRGB(255, 0, 0)
  • Just like Beat Saber custom colors, these can be "overdriven":
    SRGB(1000, 500, 50)
  • Use this link for as a color picker!


To change the direction of the gradient, find the two vec2 functions:

  • These are X/Y positions, with the bottom left corner as the "origin".
  • You can put these coordinates outside the screen if you want!
  • For top left: vec2(0.0f, 1.0f)
  • For top right: vec2(1.0f, 1.0f)
  • For bottom left: vec2(0.0f, 0.0f)
  • For bottom right: vec2(1.0f, 0.0f)


Edges

To change the color of the edges, you'll need to find the line that starts: color.rgb += SRGB(


Shader Code

%INPUT_FUNCTION%

uniform vec3 key_color;
uniform float threshold;
uniform float smoothness;

////////////////////////////////////////////////////////////////////////////////////// CHROMA

vec2 rgb_to_cbcr(in vec3 rgb)
{
	float Y = 0.2989 * rgb.r + 0.5866 * rgb.g + 0.1145 * rgb.b;
	float Cb = 0.5647 * (rgb.b - Y);
	float Cr = 0.7132 * (rgb.r - Y);
	return vec2(Cb, Cr);
}

float chroma_dist(in vec4 color)
{
	return distance(rgb_to_cbcr(color.rgb), rgb_to_cbcr(key_color));
}

float filtered_chroma_dist(in vec4 color, in vec2 coords)
{
	float dist = chroma_dist(color);

	dist += chroma_dist(%INPUT0%(coords + vec2(-pixel_size.x, -pixel_size.y)));
	dist += chroma_dist(%INPUT0%(coords + vec2(-pixel_size.x,  pixel_size.y)));
	dist += chroma_dist(%INPUT0%(coords + vec2( pixel_size.x, -pixel_size.y)));
	dist += chroma_dist(%INPUT0%(coords + vec2( pixel_size.x,  pixel_size.y)));

	dist += chroma_dist(%INPUT0%(coords + vec2(-pixel_size.x, 0.0f)));
	dist += chroma_dist(%INPUT0%(coords + vec2( pixel_size.x, 0.0f)));
	dist += chroma_dist(%INPUT0%(coords + vec2(0.0f, -pixel_size.y)));
	dist += chroma_dist(%INPUT0%(coords + vec2(0.0f,  pixel_size.y)));

	return dist / 9.0f;
}

vec4 chroma(in vec2 coords)
{
	vec4 color = %INPUT0%(coords);

	float mask = smoothstep(threshold, threshold + smoothness, filtered_chroma_dist(color, coords));

	color.rgb *= vec3(1.0f) - (1.0f - mask) * key_color;
	color.a *= mask;

	return color;
}


////////////////////////////////////////////////////////////////////////////////////// GRADIENT

// Adapted from: https://www.shadertoy.com/view/lscGDr by tsone

#define SRGB_TO_LINEAR(c) pow((c), vec3(2.2f))
#define LINEAR_TO_SRGB(c) pow((c), vec3(1.0f / 2.2f))
#define SRGB(r, g, b) SRGB_TO_LINEAR(vec3(float(r), float(g), float(b)) / 255.0f)

const vec3 COLOR0 = SRGB(0, 0, 0);
const vec3 COLOR1 = SRGB(0, 100, 220);

const vec2 GRADIENT1 = vec2(0.5f, 0.0f);
const vec2 GRADIENT2 = vec2(1.0f, 1.0f);

float gradientNoise(in vec2 uv)
{
	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
	return fract(magic.z * fract(dot(uv, magic.xy)));
}

vec3 gradient(in vec2 coords, in vec2 g1p, in vec3 g1c, in vec2 g2p, in vec3 g2c)
{
	// Calculate interpolation factor with vector projection.
	vec2 ba = g2p - g1p;
	float t = dot(coords - g1p, ba) / dot(ba, ba);
	// Saturate and apply smoothstep to the factor.
	t = smoothstep(0.0f, 1.0f, clamp(t, 0.0f, 1.0f));
	// Interpolate.
	vec3 color = mix(g1c, g2c, t);

	// Convert color from linear to sRGB color space (=gamma encode).
	color = LINEAR_TO_SRGB(color);

	// Add gradient noise to reduce banding.
	color += (1.0f / 255.0f) * gradientNoise(coords) - (0.5f / 255.0f);

	return color;
}


////////////////////////////////////////////////////////////////////////////////////// SOBEL

// Adapted from https://www.shadertoy.com/view/Mdf3zr by jmk

const float SOBEL_KERNEL = 1.5f;
const vec2 INPUT_RESOLUTION = vec2(1920.0, 1080.0);

float sobel_lookup(in vec2 p, in float dx, in float dy)
{
	vec2 uv = (p + vec2(dx * SOBEL_KERNEL, dy * SOBEL_KERNEL)) / INPUT_RESOLUTION;
	vec4 c = %INPUT0%(uv);

	// return as luma
	return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;
}

float sobel(in vec2 p)
{
	p *= INPUT_RESOLUTION;

	float gx = 0.0f;
	gx += -1.0f * sobel_lookup(p, -1.0f, -1.0f);
	gx += -2.0f * sobel_lookup(p, -1.0f,  0.0f);
	gx += -1.0f * sobel_lookup(p, -1.0f,  1.0f);
	gx +=  1.0f * sobel_lookup(p,  1.0f, -1.0f);
	gx +=  2.0f * sobel_lookup(p,  1.0f,  0.0f);
	gx +=  1.0f * sobel_lookup(p,  1.0f,  1.0f);

	float gy = 0.0f;
	gy += -1.0f * sobel_lookup(p, -1.0f, -1.0f);
	gy += -2.0f * sobel_lookup(p,  0.0f, -1.0f);
	gy += -1.0f * sobel_lookup(p,  1.0f, -1.0f);
	gy +=  1.0f * sobel_lookup(p, -1.0f,  1.0f);
	gy +=  2.0f * sobel_lookup(p,  0.0f,  1.0f);
	gy +=  1.0f * sobel_lookup(p,  1.0f,  1.0f);

	return gx * gx + gy * gy;
}



vec4 chroma_key(in vec2 coords)
{
	vec4 color = chroma(coords);

	//return color; // Remove the first two slashes to disable the effect.

	color.rgb = gradient(
		coords,
		vec2(0.5f, 0.0f), SRGB(0, 0, 0),
		vec2(1.0f, 1.0f), SRGB(0, 100, 220)
	);

	float sobel_result = sobel(coords);

	color.rgb += SRGB(120, 0, 120) * sobel_result;

	return color;
}