Hologram Effect

A holgoram effect with customizability. You can grab some presets here.

Huge shoutout to tentabrobpy’s light volume shader for making this possible!

Some features include:

  • Customizable scanlines 
  • Grain
  • Noise texture based variation
  • Stepped displacement
  • flickering
  • more
Shader code
shader_type spatial;
render_mode unshaded, blend_add, cull_disabled, depth_test_disabled;

uniform sampler2D depth_texture : hint_depth_texture;
uniform vec3 primary_color : source_color = vec3(1.0, 0.0, 0.0);
uniform vec3 secondary_color : source_color = vec3(1.0, 0.0, 0.0);
uniform float density = 1.0;
uniform float effect_strength = 2.0;

group_uniforms Wipe;
uniform float wipe_scale : hint_range(0.0, 16.0, 0.01) = 3.0;
uniform float wipe_speed : hint_range(0.0, 8.0, 0.01) = 0.5;
uniform float wipe_blend : hint_range(0.0, 1.0, 0.01) = 0.7;

group_uniforms Signal;
uniform float signal_scale = 40.0;
uniform float signal_speed = 1.0;
uniform float signal_random_scale : hint_range(0.0, 1.0, 0.01) = 0.3;
uniform float signal_blend : hint_range(0.0, 1.0, 0.01) = 1.0;

group_uniforms Noise;
uniform sampler2D noise_texture;
uniform float noise_distort_amount : hint_range(0.0, 1.0, 0.01) = 0.1;
uniform float noise_amount : hint_range(0.0, 1.0, 0.01) = 1.0;

group_uniforms Grain;
uniform float grain_amount : hint_range(0.0, 1.0, 0.01) = 0.4;

group_uniforms Displacement;
uniform float displacement_amount : hint_range(0.0, 2.0, 0.01) = 1.0;

group_uniforms Flicker;
uniform float flicker_amount : hint_range(0.0, 1.0, 0.01) = 0.3;
uniform float flicker_speed : hint_range(0.0, 30.0, 0.01) = 10.0;

varying vec3 vert;

float overlay(float base, float blend){
	float limit = step(0.5, base);
	return mix(2.0 * base * blend, 1.0 - 2.0 * (1.0 - base) * (1.0 - blend), limit);
}

vec2 overlay(vec2 base, vec2 blend){
	vec2 limit = step(0.5, base);
	return mix(2.0 * base * blend, 1.0 - 2.0 * (1.0 - base) * (1.0 - blend), limit);
}

float sample_wipe(float offset){
	return 1.0 - fract(vert.y * wipe_scale + TIME * wipe_speed + offset); 
}

float random(vec2 uv){
	float value = dot(uv, vec2(127.1,311.7));
	return -1.0 + 2.0 * fract(sin(value) * 43758.5453123);
}

void vertex(){
	vert = VERTEX;
	
	float step_time = floor(TIME * 3.0) / 3.0;
	VERTEX += NORMAL * (random(vert.xz * vert.xy + (step_time))) * 0.05 * displacement_amount;
}

vec3 shift_hue(vec3 color, float shift) {
	vec3 gray = vec3(0.57735);
	vec3 projection = gray * dot(gray, color.rgb);
	vec3 U = color.rgb - projection;
	vec3 V = cross(gray, U);
	vec3 shifted = U * cos(shift * 2.0 * PI) + V * sin(shift * 2.0 * PI) + projection;
	return shifted;
}

void fragment() {
	vec3 clip_pos = vec3(SCREEN_UV * 2.0 - 1.0, texture(depth_texture, SCREEN_UV).r);
	vec4 view_pos = INV_PROJECTION_MATRIX * vec4(clip_pos, 1.0);
	view_pos.xyz /= view_pos.w;
	float view_dist = length(view_pos.xyz);
	
	float dist = length(LIGHT_VERTEX);
	
	vec3 color = primary_color;
	if (!FRONT_FACING) {
		dist = min(dist, view_dist);
	}
	else {
		dist = -dist;
		dist = max(dist, -view_dist);
	}
	
	vec3 blended_color = primary_color;
	
	float flicker_mult1 = cos(TIME * PI * 2.0);
	float flicker = sin(TIME * flicker_speed + flicker_mult1) / 2.0 + 0.5;
	flicker = floor(flicker * 4.0) / 3.0;
	flicker = (1.0 - flicker * flicker_amount);
	
	ALBEDO = (dist * color * density) * flicker * 0.6;
	
	float step_time = round(TIME * 4.0) / 4.0;
	
	float grain = fract(dot(vert.x * 234.1421, vert.z * 123.7312) * 20.0);
	
	float noise_xy = texture(noise_texture, vert.xy + step_time).r;
	float noise_zy = texture(noise_texture, vert.zy + step_time).r;
	
	vec2 checker_pos = overlay(floor(vert.xy * 2.0 + step_time) / 3.0, floor(vert.zy * 2.0 - step_time) / 3.0);
	float checker = 1.0 + (fract(dot(checker_pos, vec2(1.0))) * 2.0 - 1.0) * signal_random_scale;
	
	float noise_xyz = mix(1.0, overlay(noise_xy, noise_zy), noise_amount);
	float stepped_noise = step(noise_xyz, 0.9);
	
	float scan = sample_wipe(stepped_noise*noise_distort_amount); 
	float signal = pow(abs(fract(vert.y * (checker) * signal_scale - (TIME * signal_speed)) * 2.0 - 1.0), 0.5);
	
	float fresnel = clamp(dot(normalize(NORMAL), normalize(VIEW)), 0.0, 1.0);
	
	float highlight = pow(fresnel, 4.0);
	highlight = mix(highlight, highlight / (signal + 0.1), signal_blend);
	highlight *= (1.0 - wipe_blend) + scan * wipe_blend;
	highlight *= (1.0 - grain_amount) + grain * grain_amount;
	highlight *= noise_xyz;
	
	if(FRONT_FACING){
		ALBEDO = mix(ALBEDO, ALBEDO + secondary_color * effect_strength, highlight);
	}
}
Live Preview
Tags
displacement, fresnel, glitch, hologram, light, noise, scanlines, Volume
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 binbun

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments