Dithering / Screen Door Transparency

An alternative to alpha transparency using order dithering / screen-door technique

Uniforms:
Player Position: The (normalized) position of the player – from (0,0) to (1,0)
Player Influence: How strong the player affects the transparency (higher = more transparent)
Radius: How far the player’s influence goes

Intensity: How transparent the image is (higher = more transparent)

Note:
This shader includes commented-out code for a “player position” parameter. To activate this functionality, uncomment the code in the uniform secion, and in the fragment function.

Shader code
shader_type canvas_item;

// --- Uniforms --- //
//global uniform vec2 player_position;

uniform float intensity: hint_range(0.0, 1.0, 0.05) = 0.0;

//group_uniforms player;
//uniform float player_influence: hint_range(0.0, 1.0, 0.05) = 0.60;
//uniform float radius: hint_range(0.0, 1.0, 0.05) = 0.05;

// --- Constants --- //
const mat4 THRESHOLD_MATRIX = mat4(
		vec4(1.0 / 17.0,  9.0 / 17.0,  3.0 / 17.0, 11.0 / 17.0),
		vec4(13.0 / 17.0,  5.0 / 17.0, 15.0 / 17.0,  7.0 / 17.0),
		vec4(4.0 / 17.0, 12.0 / 17.0,  2.0 / 17.0, 10.0 / 17.0),
		vec4(16.0 / 17.0,  8.0 / 17.0, 14.0 / 17.0,  6.0 / 17.0));

// --- Functions --- //
void fragment() {
	vec2 uv = UV / TEXTURE_PIXEL_SIZE;
	//float player_dist = (clamp(1.0 - distance(SCREEN_UV / SCREEN_PIXEL_SIZE, player_position / SCREEN_PIXEL_SIZE) * SCREEN_PIXEL_SIZE.x / radius, 0.0, 1.0)) * player_influence * step(0.01, intensity);
	//COLOR.a *= step(0.0, THRESHOLD_MATRIX[int(uv.x) % 4][int(uv.y) % 4] - intensity - player_dist);
	COLOR.a *= step(0.0, THRESHOLD_MATRIX[int(uv.x) % 4][int(uv.y) % 4] - intensity);
}
Live Preview
Tags
dither, dithering, screen door, Transparency
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 KingToot

Related shaders

guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
SagiriHimoto
11 months ago

amazing shader!!! Works great for my pixel art game!!
I had a bit of an issue with it, specifically, the dithering effect was done in 2×2 portions, instead of affecting single pixels, but I figured out that this can be fixed by adding “/ vec2(0.5, 0.5)” at the end of the first line in fragment() function:

vec2 uv = UV / TEXTURE_PIXEL_SIZE / vec2(0.5, 0.5);
SagiriHimoto
11 months ago
Reply to  SagiriHimoto

you could probably include variables to increase and decrease pixel size, if that’s an effect people might want