2.5d sprite shader
Reproduces the behaviour of 2.5D/Doom-style sprites inside a shader.
The shader is designed to minimise the work done in scripting that’s usually required with this sort of thing in godot.
The other benefit is you can see the effect in-editor.
The shader is set up so the angular sprites are stacked horizontally, with the animation frames stacked vertically
The “frame” instance uniform can be used to change the animation from by offsetting the UV Y coordinate. Because you can animate everything in godot, you can animate your sprite by changing the frame value.
Shader code
//By Kyra July 2023
//Tested in Godot 4.1
//Made with help from Blackle Mori at suricrasia.online
shader_type spatial;
uniform sampler2D albedo;
uniform int directions = 8; //The number of direction frames on the sheet
uniform int frame_count = 1; //The number of animation frames on the sheet
instance uniform int frame = 0; //The animation frame to display
void vertex() {
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);
vec3 direction_to_camera = normalize(CAMERA_POSITION_WORLD-NODE_POSITION_WORLD);
float angle_to_camera_y = atan(direction_to_camera.x,direction_to_camera.z);
vec4 model_direction = MODEL_MATRIX*vec4(1.0,0.0,0.0,0.0);
float y_angle = atan(model_direction.x,model_direction.z)-PI;
float final_angle_y = angle_to_camera_y-y_angle;
float int_y_angle = float(2+int(((final_angle_y)/TAU)*9.0))/8.0;
float final_frame = float( frame ) / float( frame_count );
UV /= vec2( float( directions ), float( frame_count ) );
UV += vec2( int_y_angle, final_frame );
}
void fragment() {
vec4 albedo_tex = texture(albedo,UV);
ALPHA_SCISSOR_THRESHOLD = 0.5;
ALPHA = albedo_tex.a;
ALBEDO = albedo_tex.rgb;
}
I had problems with it working correctly on a different amount of directions than 8
I think changing this line:
to this fixes it:
If you want the billboarding to be constrained to the Y axis, you can replace these lines:
With these (copied from Godot’s StandardMaterial converted to ShaderMaterial):
is there a way to chnage the size?