Files
Noita-GPU-Vulkan/shaders/rigid_raster.comp
T
2026-10-19 20:59:15 +02:00

29 lines
1.6 KiB
Plaintext

#version 450
#extension GL_GOOGLE_include_directive : require
layout(local_size_x = 64) in;
#include "rigid_common.glsl"
// Marks the cells covered by the pixel masks of the rigid bodies (those that are solid for creatures and projectiles) in a per-cell grid, so that
// creatures and projectiles test a cell in one read instead of looping over all bodies. One workgroup per body.
layout(std430, set = 0, binding = 40) buffer BodyGrid { uint bodyGrid[]; };
void main() {
int bi = int(gl_WorkGroupID.x), t = int(gl_LocalInvocationID.x);
if (bi >= bhdr.x) return;
Body b = bodies[bi];
if ((b.i.z & 2) != 0 || b.m.y > 0.5) return; // removed, or a corpse part (passable)
int s = b.i.x;
float rad = shf(s, 9);
int n = int(2.0 * rad) + 2;
ivec2 lo = ivec2(floor(b.p.xy - vec2(rad)));
float cs = cos(b.p.z), sn = sin(b.p.z);
for (int k = t; k < n * n; k += 64) {
ivec2 w = lo + ivec2(k % n, k / n);
ivec2 q = w - ivec2(pc.view_x, pc.view_y);
if (q.x < 0 || q.y < 0 || q.x >= pc.gw || q.y >= pc.gh) continue;
vec2 dd = vec2(w) + 0.5 - b.p.xy;
vec2 im = vec2(cs * dd.x + sn * dd.y, -sn * dd.x + cs * dd.y) + vec2(shf(s, 5), shf(s, 6));
if (shape_solid(s, int(floor(im.x)), int(floor(im.y)))) bodyGrid[q.y * pc.gw + q.x] = (b.d.w > 0.5 ? uint(b.d.w + 0.5) : uint(b.i.y) + 1u) | ((b.i.z & 1024) != 0 ? 0x80000000u : 0u); // (bit 31: flag 1024, no platform: characters pass) // the entity slot + 1 (a part body of a PhysicsBody2 entity: the owner's, d.w; the engine's body user data is the entity)
}
}