Cyberpunk scanner

A pixelated 3D scanner effect, heavily inspired by Cyberpunk 2077. It uses a separate camera and additional visibility / render layers to create an overlay. There are 2 MeshInstance3D nodes in the scene, to show the difference between scannable and non-scannable objects.

The cryopod model was created for the game Intrepid and is in public domain.

 

Shader code
shader_type canvas_item;

// These params create the dynamic scanner effect
group_uniforms DynamicParams;
// Scanning progress influences the pixelization, transparency, and outline size
uniform float scanning_progress = 0.0;
// Visibility allows to hide the shader without changing the scanning progress
uniform float visibility : hint_range(0.0, 1.0, 0.01) = 1.0;

// These params are likely to be set only once.
group_uniforms FixedParams;
uniform vec4 color: source_color;
uniform float initial_outline_pixel_size = 32.0;
uniform float final_outline_pixel_size = 2.0;
uniform float initial_fill_transparency = 2.0;
uniform float final_fill_transparency = 0.15;
uniform float initial_pixelize_power = 9.0;
uniform float final_pixelize_power = 1.0;

// Returns the strength of the scanner's color
// * 1 for the outline
// * 0 - 1 for the filling (depends on fill transparency)
// * 0 for pixels outside of the scanned area
float get_scanner_alpha(sampler2D tex, vec2 pixel_size, vec2 uv) {
	vec4 pixel = texture(tex, uv);
	// If a pixel is transparent, it might be a part of the outline
	if (pixel.a < 0.5) {
		vec2 outline_size = pixel_size * mix(
			initial_outline_pixel_size, final_outline_pixel_size, scanning_progress
		);
		for (float x = -outline_size.x; x <= outline_size.x; x += pixel_size.x) {
			for (float y = -outline_size.y; y <= outline_size.y; y += pixel_size.y) {
				vec4 surrounding_pixel = texture(tex, uv + vec2(x, y));
				// If one of the surrounding pixels is visible: draw an outline (opaque color)
				if (surrounding_pixel.a > 0.5) {
					return 1.0;
				}
			}
		}
		// If none of the surrounding pixels is visible: draw transparency
		return 0.0;
	}
	// If a pixel is visible: draw filling (partially transparent color)
	float fill_transparency = mix(
		initial_fill_transparency, final_fill_transparency, scanning_progress
	);
	return fill_transparency;
}

void fragment() {
	// Scale the UV (using powers of 2) to obtain the effect of pixelization
	vec2 pixelized_texture_size = vec2(textureSize(TEXTURE, 0)) / pow(
		2.0, floor(mix(initial_pixelize_power, final_pixelize_power, scanning_progress))
	);
	vec2 pixelized_uv = (
		floor(UV * pixelized_texture_size) + ceil(UV * pixelized_texture_size)
	) * 0.5 / pixelized_texture_size;
	COLOR = color;
	COLOR.a *= visibility * scanning_progress * get_scanner_alpha(
		TEXTURE, TEXTURE_PIXEL_SIZE, pixelized_uv
	);
}
Tags
3d, cyberpunk, overlay, pixelization, scanner, sci-fi
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 miskatonicstudio

Burning paper

Engine flame

Aurora Borealis

Related shaders

Radar Scanner

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Danikakes
Danikakes
13 days ago

This is game changing, thank you you beautiful beautiful soul