Energy shield with impact effect
Hi! This is my first complete shader. It is rough and it can be improved a lot, but I’m happy with the current result. It is the combination of a fresnel effect and a ripple distortion. More detail, credits and demo in the github page.
If you have any advice leave a comment 😃
Shader code
shader_type spatial;
render_mode shadows_disabled, specular_disabled, ambient_light_disabled, unshaded;
group_uniforms Shield_Color;
uniform vec3 _shield_color : source_color = vec3(0.0, 0.0, 1.0);
uniform float _shield_color_brightness : hint_range(0.25, 20.0, 0.05) = 10.0;
uniform float _shield_intensity : hint_range(0.25, 5.0, 0.05) = 2.0;
group_uniforms Shield_Transform;
uniform vec3 _rotation = vec3(0.1, 0.0, 0.0);
uniform float _shield_size : hint_range(0.0, 0.5, 0.01) = 0.0;
group_uniforms Shield_Pulse;
uniform float _shield_pulse_frequency = 1.0;
uniform float _shield_pulse_density = 1.0;
uniform float _shield_pulse_amplitude = 1.0;
uniform float _shield_pulse_blend = 1.0;
uniform float _shield_pulse_radius = 1.0;
group_uniforms Impact_Shape;
uniform vec3 _impact_origin = vec3(1.0, 0.0, 0.0);
uniform float _impact_frequency = 5.0;
uniform float _impact_density = 5.0;
uniform float _impact_amplitude = 6.0;
uniform float _impact_blend = 0;
uniform float _impact_radius = 1.1;
uniform float _impact_anim = 0.0;
// === IMPACT ===
float _GetRippleOrigin(vec3 vert, vec3 orig) {
// distance of each vertex from the origin
return length(orig - vert);
}
float _FadeRipple(float orig, float blend, float radius) {
// create a radius
float b = clamp(blend, 0.0, radius);
return smoothstep(b, -radius, orig);
}
float _ComputeRipple(vec3 vert, vec3 orig, float blend, float radius, float freq, float dens, float ampl, float anim) {
// calculate the intensity of the impact
float o = _GetRippleOrigin(vert, orig);
float i = sin(anim * freq - o * dens) / ampl;
return i * _FadeRipple(o, blend, radius);
}
// === SHIELD ===
float saturate(float x) {
return max(0, min(1, x));
}
float ComputeFresnel(vec3 norm, vec3 view_dir, float intensity) {
// dot product between mesh normals and view direction
float fresnel = saturate(1.0 - dot(norm, view_dir));
// modulate fresnel intensity
fresnel = pow(fresnel, intensity);
return fresnel;
}
vec3 Rotate(vec3 vert, vec3 speed) {
// build the 3 rotation matrices
speed = speed * TIME * 5.0;
mat4 xrot = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, cos(speed.x), -sin(speed.x), 0.0),
vec4(0.0, sin(speed.x), cos(speed.x), 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
mat4 yrot = mat4(
vec4(cos(speed.y), 0.0, -sin(speed.y), 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(sin(speed.y), 0.0, cos(speed.y), 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
mat4 zrot = mat4(
vec4(cos(speed.z), -sin(speed.z), 0.0, 0.0),
vec4(sin(speed.z), cos(speed.z), 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
return (xrot * yrot * zrot * vec4(vert, 1.0)).xyz;
}
void vertex() {
// rotate VERTICES in local space
VERTEX = Rotate(VERTEX, _rotation);
// ...and relative NORMALS for the fresnel effect to work
NORMAL = Rotate(NORMAL, _rotation);
// Local to World conversion to add impact ripple
vec3 w_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
// normalize impact origin vector
vec3 imp_or = normalize(_impact_origin);
float impact_ripple = _ComputeRipple(w_pos,
_impact_origin,
_impact_blend,
_impact_radius,
_impact_frequency,
_impact_density,
_impact_amplitude,
_impact_anim);
VERTEX += NORMAL * (impact_ripple + _shield_size);
}
void fragment() {
// add fresnel
float f = ComputeFresnel(NORMAL, VIEW, _shield_intensity);
// set color and alpha
ALBEDO = f * _shield_color_brightness * _shield_color;
ALPHA *= f;
}
This is top tier
look effect!
I had to add
NODE_POSITION_WORLD.xyz
to _origin when passed into the_ComputeRipple()
function to get this to work as expected when the mesh was anywhere but 0,0,0. alsoimp_or
is never used?Hi! Thanks for your comment! That helps me a lot in improving my work!
I tried to move the mesh around and works fine for me! Also, adding
NODE_POSITION_WORLD.xyz
makes things not work anymore. Can you explain to me a more detailed way I can reproduce this? So I’ll try to fix itFor the
imp_or
I certainly must forgot to remove it! I stopped working on this shader due to other projects so I can’t remember why I didn’t use it 😂It’s a nice shader, thanks for sharing. Highly recommend tweening instead of the way you have it in your demo project. Give something like this a try:
Thanks! That’s awesome, I didn’t think about it 🤔