Skip to content

Instantly share code, notes, and snippets.

@PixHammer
Last active February 22, 2024 18:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PixHammer/b3b29dfd5f25a1378f0f814e9ce5772f to your computer and use it in GitHub Desktop.
Save PixHammer/b3b29dfd5f25a1378f0f814e9ce5772f to your computer and use it in GitHub Desktop.
Local Y Space Billboard Shader - Godot 4.2
// By default Godot does not include a local y space billboard option within the StandardMaterial3D, and only includes a world up.
// This is annoying, as for a lot of effects you need the billboard to align with an axis that isn't world up.
// For example bullet tracers, or muzzle flashes shown from the side, or grass aligned with a slopes normal.
// This shader adds this feature.
// To use it, simply add this as the shader on a quad's material.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,unshaded;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float point_size : hint_range(0,128);
// you can just steal this vertex code if you want to inject this behaviour into another shader of your own
void vertex() {
// direction from mesh to camera (world space)
// we use this instead of view direction, as view direction is wrong lol
vec3 direction_to_camera = INV_VIEW_MATRIX[3].xyz - MODEL_MATRIX[3].xyz;
// model matrix [1] = direction of local y axis in world space
vec3 local_x = MODEL_MATRIX[0].xyz;
vec3 local_y = MODEL_MATRIX[1].xyz;
vec3 local_z = MODEL_MATRIX[2].xyz;
//use cross products to find world space axis for the billboard
// local_y cross direction_to_camera = right
vec3 billboard_x = normalize(cross(local_y, direction_to_camera));
// billboard_x cross local_y = forward
vec3 billboard_z = normalize(cross(billboard_x, local_y));
// override the model view matrix, this mat4 shenanigan is setting the X, Y, and Z axis of the matrix, to the axis we just made (keeping local y)
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(billboard_x * length(local_x), 0.0), vec4(local_y, 0.0), vec4(billboard_z * length(local_z), 0.0), MODEL_MATRIX[3]);
// and then remmake the normal matrix
MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
}
void fragment() {
vec4 albedo_tex = texture(texture_albedo,UV);
ALBEDO = albedo.rgb * albedo_tex.rgb;
ALPHA *= albedo.a * albedo_tex.a;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment