Holographic Light Effect

This shader was originally designed for a holographic trading card effect, but I ended up adjusting it to be used as a pseudo-cd looking shader. Feel free to tinker around if you’re aiming for more realism on that end.

 

This shader should be used as a material for whatever object you want to apply it to. It looks best on flatter objects. Pick a good normal map for best results. 

 

At a high level, the shader does the following: calculates angle between reflected light and camera angle, and based on that angle, emits light, resulting in a spectrum of colors.

Shader code
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, diffuse_burley, specular_schlick_ggx;
uniform sampler2D texture_normal : hint_roughness_normal, filter_nearest, repeat_enable;

uniform float normal_depth = 0.25;
uniform float color_compression = 6.0;

// Function to convert HSV to RGB
// Not my creation, but slightly modified
vec3 hsv2rgb(vec3 hsv) {
    float h = hsv.x * color_compression; // 6.0 transitions the colors faster for us
    float s = hsv.y;
    float v = hsv.z;

    float c = v * s;
    float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
    vec3 rgb = vec3(0.0);

    if (0.0 <= h && h < 1.0) rgb = vec3(c, x, 0.0);
    else if (1.0 <= h && h < 2.0) rgb = vec3(x, c, 0.0);
    else if (2.0 <= h && h < 3.0) rgb = vec3(0.0, c, x);
    else if (3.0 <= h && h < 4.0) rgb = vec3(0.0, x, c);
    else if (4.0 <= h && h < 5.0) rgb = vec3(x, 0.0, c);
    else if (5.0 <= h && h < 6.0) rgb = vec3(c, 0.0, x);

    return rgb + (v - c);
}

/*
Converts a value in range [istart, istop] to a value in range [ostart, ostop].
*/
float range_lerp(float value, float istart, float istop, float ostart, float ostop) {
         return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

void fragment() {
    // Set basic material properties
    ALBEDO = vec3(0.5); // Gray seems to give a nice color mix
	NORMAL_MAP = texture(texture_normal, UV * 2.0).rgb;
	NORMAL_MAP_DEPTH = normal_depth;
    METALLIC = 1.0;
    ROUGHNESS = 0.0;
	EMISSION = vec3(0.125); // Used for that faint glow
}

void light() {
    vec3 normal_dir = normalize(NORMAL); // Direction of surface normal
    vec3 light_dir = normalize(LIGHT); // Direction of light
	vec3 view_dir = normalize(VIEW); // Direction of camera

	vec3 reflection = reflect(light_dir, view_dir); // Get reflected light

    // Calculate the angle between the light direction and the normal
    float angle = dot(reflection, normal_dir);
    vec3 color = hsv2rgb((vec3(angle, 1.0, 1.0))); // Use hsv to rgb to turn angle into a color

	// Bound checking
	if (angle > 0.6) {
		angle = range_lerp(angle, 0.6, 0.65, 1.0, 0.0);
		angle = clamp(angle, 0.0, 1.0);
	}

	// Apply that light!
    SPECULAR_LIGHT += color * LIGHT_COLOR * ATTENUATION * angle;
	SPECULAR_LIGHT += color * color;
}
Live Preview
Tags
cd, holo, holographic, prism, rainbow
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.

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments