
There were 3 things:
1) Your particle system must emit in local space. blastoff's Local Coords checkbox must be ON.
2) Fix occasional problem when normal aligns with up axis (happens only with vertical walls in your case). When orienting the decal via look_at() check if normal and up coincide and simply pick another up:
impact.global_transform.origin = p
var up = Vector3.UP
if up.is_equal_approx(n):
up = Vector3.RIGHT
impact.look_at_from_position(p, p - n, up)
impact.forward = Vector3(0.0, 0.0, 1.0)
impact.cam = maincam
3) And this is the main culprit. Your spatial material assigned to particles had its Billboard Mode set to Particle Billboard. This forced the particle to face the camera, effectively nullifying all the work we did in the particle process shader to orient the particle. So if you set material's Billboard Mode to Dsiabled the particle will retain proper orientation we calculated in the particle shader.
However when you do so you lose frame animation setup. Don't know how to fix this via gui. The quick way it can be fixed is:
- keep the Billboard Mode set to Particle Billboarad
- convert spatial material to shader material
- open the shader source and in vertex() function comment out matrix manipulation lines but keep the frame animation part intact:
void vertex() {
UV=UV*uv1_scale.xy+uv1_offset.xy;
//mat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);
//mat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0, 1.0));
//MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;
float h_frames = float(particles_anim_h_frames);
float v_frames = float(particles_anim_v_frames);
float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);
float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));
if (!particles_anim_loop) {
particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);
} else {
particle_frame = mod(particle_frame, particle_total_frames);
} UV /= vec2(h_frames, v_frames);
UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);
}