Billboard Sprite3D Hitflash (Godot 4.x)
Use with Sprite3D and AnimatedSprite3D nodes. It works best if set as the material override (under GeometryInstance3D tab).
Tips:
After setting up the shader copy the texture from the Sprite3D and set it as ‘Tex’ in the shader parameters. If you would like to use this shader with an AnimatedSprite3D set tex as the texture containing all the sprites in your sprite frames (the sprite sheet). I’m not sure if it’ll work if you aren’t using a sprite sheet.
You can set the flash colour and toggle the billboard setting in shader parameters also. Animate the hitflash with the active parameter using an animation player or do it in code with something like:
$Sprite3D.material_override.set_shader_parameter("active",true)
Note: If you don’t need any billboarding comment out the entire vertex() function in the gdshader.
Shader code
shader_type spatial;
render_mode unshaded, cull_disabled, depth_draw_opaque, depth_prepass_alpha;
// Remove unshaded if you want shading
// Replace cull_disabled if you want to only show one side (cull_front, cull_back)
// Reference for depth ::: https://docs.godotengine.org/en/stable/tutorials/shaders/shader_reference/spatial_shader.html#render-modes
uniform bool active = false; // Sets pixels to flash color when true
uniform vec4 flash_color: source_color = vec4(1.0,1.0,1.0,1.0); // The color to use when active
uniform bool y_billboard = false; // Enables Y-Billboarding when true
uniform sampler2D tex: source_color; // A copy of the texture for the Sprite3D or AnimatedSprite3D
void vertex() {
// You can comment out this function if you don't need billboarding
if (y_billboard == true) {
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);
}
else {
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);
}
MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
}
void fragment() {
vec4 col = texture(tex,UV);
vec4 set_col = col;
if(active == true) {
set_col = flash_color;
}
ALBEDO = vec3(set_col.r,set_col.g,set_col.b);
ALPHA = col.a;
}
this question cost me one day.
very very thanks for you.
If you want to use this with pixel art or if your sprite seems “fuzzy”, you should change the uniform sampler2D as such:
You can add repeat_disabled to that list too, if needed.
You’re the light at the end of a 1h tunnel of googl’ing; thank you!
the way vertex is used there just surprised me, that is genius… i’m actually trying to make a laser shader, something about how the Sprite3D is like if you want, a laser facing the upwards y direction
meditating on your code is gonna give me the answer cheers
What trickery did you do to get this to work on an animated sprite?
To anyone searching around in the future for a solution like we were, the combination of these two shaders was finally the fix for our Sprite3D clipping issues. Just do billboarding, then the depth adjustment in the vertex shader, and tune the depth amount parameter until it looks right.
You might also have to play with the Y/Z position of your sprite so that it still looks like it touches the ground, and will also probably want a script that sets the shader texture to the one set on your sprite.
Billboarding:
https://godotshaders.com/shader/billboard-sprite3d-hitflash-godot-4-x/
Depth Adjustment:
https://godotshaders.com/shader/depth-adjustment-for-clipping-protection/