Skip to content

Instantly share code, notes, and snippets.

@partybusiness
Last active April 15, 2024 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save partybusiness/792fd481205646e436b98477f9d30f37 to your computer and use it in GitHub Desktop.
Save partybusiness/792fd481205646e436b98477f9d30f37 to your computer and use it in GitHub Desktop.
Demon particles
shader_type particles;
void start() {
if (RESTART_POSITION) {
TRANSFORM[3].xyz = EMISSION_TRANSFORM[3].xyz; //sets to emitter position
float _time = TIME * 200.0;
VELOCITY = vec3(1.*cos(_time),0.,1.*sin(_time)); //sets angle based on time
}
}
void process() {
CUSTOM.x = atan(VELOCITY.x,VELOCITY.z)/ (PI * 2.0); //uses forward vector to get a rotation offset from -0.5 to 0.5 which can be rounded off for a UV offset
CUSTOM.y = float(INDEX % 10u)*0.1 + USERDATA1.x / LIFETIME; //
USERDATA1.x = USERDATA1.x + DELTA;
}
shader_type spatial;
render_mode fog_disabled, unshaded, blend_mix;
uniform sampler2D sprites:source_color, filter_nearest;
uniform uint numColumns = 8;
uniform uint numRows = 8;
uniform float rotationOffset = 0.438; // an arbitray offset to get it to work with the given texture
void vertex() {
float _rotation = INSTANCE_CUSTOM.x;
// CAMERA_DIRECTION_WORLD was wrong ?? it didn't correctly account for world direction
// I think once this is merged we can go use CAMERA_DIRECTION_WORLD:
// https://github.com/godotengine/godot/pull/86516
vec2 viewDir = normalize(vec2(INV_VIEW_MATRIX[2].x,INV_VIEW_MATRIX[2].z));
float viewRot = atan(viewDir.x,viewDir.y) / (PI * 2.0); //uv offset of range -0.5 to 0.5
float columnFloat = float(numColumns);
float rotationOff = floor((viewRot - _rotation + rotationOffset) * columnFloat) / columnFloat;
float colourOff = floor(INSTANCE_CUSTOM.y * float(numRows)) / float(numRows); //offsets to a given row
vec2 offset = vec2(rotationOff, colourOff);
UV = vec2(UV.x / columnFloat,UV.y / float(numRows)) + offset;
}
void fragment() {
vec4 col = texture(sprites, UV);
ALBEDO = col.rgb;
ALPHA = col.a;
}
@partybusiness
Copy link
Author

This is a spatial shader and particle process shader for use in Godot with the GPUParticles3D node.

It's partly based on a Unity shader I did before: https://github.com/partybusiness/DemonRender

It selects a tile to render based on the velocity of the particle and the direction of the camera that's viewing it. So, assuming a Doom style graphic where you have the same monster or item rendered from different angles, it can pick a tile based on the direction you would see it.

The row is called colour in my examples, but a more useful point would be animation.

https://mastodon.gamedev.place/@flinflonimation/112277406828720292

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment