Diamond-based Screen Transition

A transition shader drawn from this article by Timm[ie] Wong @DDRKirbyISQ. Permission was given by this individual for this post. The article explains more in depth and similar versions of this shader. Animating the shader parameter “progress” creates the transition effect. I have found that a tween using trans_cubic and ease_out looks pretty nice. Changing the final line from > to < will reverse the transition effect.

tween.interpolate_property(mymaterial, “shader_param/progress”, 1, 0, 1.5, Tween.TRANS_CUBIC, Tween.EASE_OUT) 

Shader code
shader_type canvas_item;

// Ranges from 0 to 1 over the course of the transition.
// We use this to actually animate the shader.
uniform float progress : hint_range(0, 1);

// Size of each diamond, in pixels.
uniform float diamondPixelSize = 10f;

void fragment() {
	float xFraction = fract(FRAGCOORD.x / diamondPixelSize);
	float yFraction = fract(FRAGCOORD.y / diamondPixelSize);
	float xDistance = abs(xFraction - 0.5);
	float yDistance = abs(yFraction - 0.5);
	if (xDistance + yDistance + UV.x + UV.y > progress * 4f) {
		discard;
	}
}
Tags
blend, transition
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from mackatap

Fade by distance to character

Related shaders

Lines Screen Transition

Saw Transition Shader

Glitch Transition

Subscribe
Notify of
guest

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Pixelneed
Pixelneed
3 years ago

Does anyone know how to make it look pixelized?

ttyyyyy
2 years ago
Reply to  Pixelneed

you can just put it behind a low-res viewport

Shady
Shady
2 years ago

A slightly more optimized version (avoiding shader-unfriendly if statement):
See https://godotshaders.com/shader/optimize-your-shaders/

shader_type canvas_item;


// Ranges from 0 to 1 over the course of the transition.
// We use this to actually animate the shader.
uniform float progress : hint_range(0, 1);


// Size of each diamond, in pixels.
uniform float diamondPixelSize = 10f;


float when_lt(float x, float y) {
  return max(sign(y - x), 0.0);
}

void fragment() {
	float xFraction = fract(FRAGCOORD.x / diamondPixelSize);
	float yFraction = fract(FRAGCOORD.y / diamondPixelSize);
	float xDistance = abs(xFraction - 0.5);
	float yDistance = abs(yFraction - 0.5);
	COLOR.a *=  when_lt(xDistance + yDistance + UV.x + UV.y, progress * 4f);
}
Nzr
Nzr
2 years ago

how to make it square not diamond?

DriftWare.exe
DriftWare.exe
2 years ago

Heck yeah! Fancy screen transition! super easy to use and animate, too!

MatiasVME
1 year ago

For Godot 4

transition.gdshader

shader_type canvas_item;




// Ranges from 0 to 1 over the course of the transition.
// We use this to actually animate the shader.
uniform float progress : hint_range(0, 1);




// Size of each diamond, in pixels.
uniform float diamondPixelSize = 10.0;




float when_lt(float x, float y) {
  return max(sign(y - x), 0.0);
}


void fragment() {
	float xFraction = fract(FRAGCOORD.x / diamondPixelSize);
	float yFraction = fract(FRAGCOORD.y / diamondPixelSize);
	float xDistance = abs(xFraction - 0.5);
	float yDistance = abs(yFraction - 0.5);
	COLOR.a *=  when_lt(xDistance + yDistance + UV.x + UV.y, progress * 4.0);
}

and de transition scene with a ColorRect

extends Node2D


func change_scene_to_file(path):
	%Background.material["shader_parameter/progress"] = 1.0
	
	var tween = create_tween()
	tween.tween_property(
		%Background.material, 
		"shader_parameter/progress", 
		1.0, 
		1
	).from(0.0).set_trans(Tween.TRANS_SINE)
	
	await tween.finished
	
	tween = create_tween()
	tween.tween_property(
		%Background.material, 
		"shader_parameter/progress", 
		0, 
		1
	).from(1.0).set_trans(Tween.TRANS_SINE)
	
	get_tree().change_scene_to_file(path)
sidpoke
1 year ago

Hi! I added parameters to allow changing the angle & anchor point of the transition.
Uses the Godot 4.0 version that has the optimizations in it.

Note: probably not 100% accurate but it works.

Have fun!

shader_type canvas_item;

// Ranges from 0 to 1 over the course of the transition.
// We use this to actually animate the shader.
uniform float progress : hint_range(0, 1);
uniform float multiplier : hint_range(1, 10) = 3;
uniform float angle : hint_range(0, 360) = 0.0;

// anchor point of the transition (best anchor point result is 0.5, 0.5)
uniform vec2 anchor = vec2(0.5, 0.5);
// use this to increase the distance from the anchor point
uniform float anchorOffset = 1.0;

// Size of each diamond, in pixels.
uniform float diamondPixelSize = 10.0;

float when_lt(float x, float y) {
  return max(sign(y - x), 0.0);
}

void fragment() {
    float xFraction = fract(FRAGCOORD.x / diamondPixelSize);
    float yFraction = fract(FRAGCOORD.y / diamondPixelSize);
    float xDistance = abs(xFraction - 0.5);
    float yDistance = abs(yFraction - 0.5);

    COLOR.a *= when_lt(xDistance + yDistance + cos(radians(angle)) * (UV.x - anchor.x) + sin(radians(angle)) * (UV.y - anchor.y), (-anchorOffset + progress * multiplier));
}
Cidwel
Cidwel
1 month ago

This is a version that will work in old android phones

shader_type canvas_item;

uniform float uv1_progress : hint_range(0, 1);

uniform float diamondPixelSize = 60.0f;
uniform bool fadeOut = false;

void fragment() {
    float xFraction = fract(FRAGCOORD.x / diamondPixelSize);
    float yFraction = fract(FRAGCOORD.y / diamondPixelSize);
    float xDistance = abs(xFraction - 0.5);
    float yDistance = abs(yFraction - 0.5);

    float alpha = 1.0;

    if (fadeOut) {
        if (xDistance + yDistance + UV.x + UV.y < uv1_progress * 4.0f) {
            alpha = 0.0;
        }
    } else {
        if (xDistance + yDistance + UV.x + UV.y > uv1_progress * 4.0f) {
            alpha = 0.0;
        }
    }

    COLOR = texture(TEXTURE, UV) * vec4(0.0, 0.0, 0.0, alpha);
}