Colorized Depth Reflection / Zoom Mirror

The Tripping Balls shader.

Inspired by Nested Tinted Zooms by coprsinhere.

Usage:

The shader can be applied to a ColorRect node covering the intended effect area. Alternatively, the screen_texture uniform can have the hint_screen_texture hint removed, and be manually set to a viewport. Doing so requires the shader material be local to the scene.

The shader takes several arguments:

transparent_color is an optional color that should be treated as transparent.

transparent_color_threshold adjusts the threshold for detecting the transparent_color.

zoom_center is the point from which the zoom effect should originate.

layers adjusts the number of times the texture should get mirrored.

opacity adjusts the alpha/transparency of each layer relative to the last.

original_opacity_mod adjusts the boost given to the source/input texture.

zoom adjusts the magnification of each layer relative to the last.

normalization is a range between 0 and 1 of how much to use a normalized vector from the zoom origin.

normalized_scale is a range between -1 and 1 of how much to zoom the normalized vector relative to the screen size.

color_cycle_time is the time it should take to cycle between all 6 colors.

colors is an array of 6 colors to cycle through.

color_layer_gap adjusts the difference of colors between each reflection layer.

Shader code
shader_type canvas_item;

// The texture to receive the effect.
uniform sampler2D screen_texture: hint_screen_texture, filter_linear_mipmap, repeat_enable;
// Defines an additional color that should be turned transparent.
uniform vec4 transparent_color: source_color = vec4(0.0);
// Defines the distance theshold for the transparent color.
uniform float transparent_color_threshold: hint_range(0.0, 1.0) = 0.0;
// Defines the origin point of the zoom effect relative to the texture size.
uniform vec2 zoom_center = vec2(0.5, 0.5);
// Adjusts the number of times the texture should get mirrored.
uniform int layers = 5;
// Adjusts the alpha/transparency of each layer relative to the last.
uniform float opacity = 0.5;
// Adjusts the boost given to the colors of the input texture.
uniform float original_opacity_mod: hint_range(0.0, 1.0) = 0.0;
// Adjusts the magnification of each layer relative to the last.
uniform float zoom = 0.25;
// Range between 0 and 1 of how much to use a normalized vector from the zoom origin.
uniform float normalization: hint_range(0.0, 1.0) = 1.0;
// Range between -1 and 1 of how much to zoom the normalized vector relative to the texture size.
uniform float normalized_scale: hint_range(-1.0, 1.0) = 0.01;

uniform float color_cycle_time = 6.0;
uniform lowp vec4 colors[6]: source_color;
uniform float color_layer_gap: hint_range(0.0, 1.0) = 0.0;

// Adjust UV per new scale and pivot
vec2 adj_uv(vec2 a_uv, float a_scale, vec2 a_pivot){
	return a_pivot + (a_uv - a_pivot) * pow(a_scale, -1.0);
}

void fragment() {
	vec4 original_color = texture(screen_texture, UV);
	float transparent_color_distance = distance(original_color, transparent_color) / 2.0;
	original_color.a = mix(0.0, original_color.a, float(transparent_color_distance > transparent_color_threshold));
	COLOR = original_color;
	float time = mod(TIME, color_cycle_time);
	float time_ratio = time / color_cycle_time;
	float color_ratio = 1.0 / float(colors.length());
	for (int iter = 1; iter < layers + 1; iter++){
		float f_index = mod(time_ratio - (color_layer_gap * float(iter)), 1.0) / color_ratio;
		float f_remainder = mod(f_index, 1.0);
		vec4 prior_color = colors[int(floor(f_index))];
		vec4 next_color;
		next_color = colors[int(ceil(f_index))];
		if (int(ceil(f_index)) < colors.length()){
			next_color = colors[int(ceil(f_index))];
		} else {
			next_color = colors[0];
		}
		vec2 adjusted_uv = adj_uv(UV, 1.0 + (zoom * float(iter)), zoom_center);
		vec2 adjusted_vector = adjusted_uv - UV;
		vec2 zoom_vector = (zoom_center - UV);
		vec2 normalized_vector = normalize(zoom_vector) * float(iter) * normalized_scale;
		zoom_vector = mix(adjusted_vector, normalized_vector, normalization);
		vec4 sample_color = texture(screen_texture, zoom_vector + UV);
		float transparent_color_distance = distance(sample_color, transparent_color) / 2.0;
		sample_color.a = mix(0.0, sample_color.a, float(transparent_color_distance > transparent_color_threshold));
		sample_color = sample_color * mix(prior_color, next_color, f_remainder);
		float opacity_mod = 1.0 - (original_color.a * original_opacity_mod);
		COLOR = mix(COLOR, sample_color, sample_color.a * pow(opacity, float(iter)) * opacity_mod);
	}
}
Live Preview
Tags
colorized, depth, mirror, rainbow, reflection, zoom
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Maaack

Related shaders

guest

0 Comments
Oldest
Newest Most Voted