particle collison testing

This commit is contained in:
jacob 2026-01-06 07:03:11 -06:00
parent 65d34d49af
commit 87a624eaeb
3 changed files with 155 additions and 38 deletions

View File

@ -894,12 +894,17 @@ void V_TickForever(WaveLaneCtx *lane)
frame->draw_cursor = MulXformV2(frame->xf.ui_to_draw, frame->ui_cursor);
frame->world_cursor = MulXformV2(frame->xf.ui_to_world, frame->ui_cursor);
b32 show_editor_ui = TweakBool("Show editor UI", 0);
frame->world_selection_start = frame->world_cursor;
if (frame->is_editing)
{
b32 m1_held = frame->held_buttons[Button_M1];
b32 m2_held = frame->held_buttons[Button_M2];
// frame->selection_mode = V_SelectionMode_Tile;
if (show_editor_ui)
{
frame->selection_mode = V_SelectionMode_Tile;
}
if (m1_held)
{
frame->is_selecting = 1;
@ -1073,7 +1078,7 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Build panels
if (TweakBool("Show editor UI", 0) && frame->is_editing)
if (show_editor_ui && frame->is_editing)
{
Struct(PanelDfsNode) { PanelDfsNode *next; b32 visited; V_Panel *panel; UI_Checkpoint cp; };
PanelDfsNode *first_panel_dfs = PushStruct(frame->arena, PanelDfsNode);
@ -2682,12 +2687,14 @@ void V_TickForever(WaveLaneCtx *lane)
emitter->pos = frame->world_cursor;
emitter->angle = AngleFromVec2(dir);
emitter->count = 1000;
emitter->count = 100;
emitter->speed = 10;
emitter->seed = RandU64FromState(&frame->rand);
emitter->speed_spread = 1;
emitter->angle_spread = 1;
// emitter->angle_spread = 1;
// emitter->angle_spread = 0.5;
emitter->angle_spread = Tau / 4;
}
// Flatten emitters list
@ -2736,7 +2743,6 @@ void V_TickForever(WaveLaneCtx *lane)
params.target_rw = draw_target_rw;
params.xf = frame->xf;
params.seed = RandU64FromState(&frame->rand);
params.noise = G_BasicNoiseTexture();
params.selection_mode = frame->selection_mode;
params.equipped_tile = frame->equipped_tile;
@ -2770,6 +2776,7 @@ void V_TickForever(WaveLaneCtx *lane)
// Constants
G_SetConstant(frame->cl, V_ShaderConst_State, gpu_state_ref);
G_SetConstant(frame->cl, V_ShaderConst_Params, gpu_params_ref);
G_SetConstant(frame->cl, V_ShaderConst_NoiseTex, G_BasicNoiseTexture());
// Sync
G_DumbGlobalMemorySync(frame->cl);
@ -2795,6 +2802,19 @@ void V_TickForever(WaveLaneCtx *lane)
G_DiscardRenderTarget(frame->cl, draw_target);
//////////////////////////////
//- Particle simulation pass
{
// Emit particles
G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(emitters_count));
G_DumbMemorySync(frame->cl, gpu_particles);
// Simulate particles
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(max_particles));
}
//////////////////////////////
//- Backdrop pass
@ -2820,19 +2840,6 @@ void V_TickForever(WaveLaneCtx *lane)
);
}
//////////////////////////////
//- Particle simulation pass
{
// Emit particles
G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(emitters_count));
G_DumbMemorySync(frame->cl, gpu_particles);
// Simulate particles
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(max_particles));
}
//////////////////////////////
//- Overlay pass

View File

@ -144,6 +144,25 @@ ComputeShader2D(V_BackdropCS, 8, 8)
result = bounds_color;
}
}
// TODO: Remove this
// Decals test
{
RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
// Vec2 decal_uv = decal_pos / countof(decals);
V_ParticleKind decal = decals.Load(decal_pos);
if (decal == V_ParticleKind_Test)
{
result = Color_Yellow;
// result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
}
}
}
target[SV_DispatchThreadID] = result;
@ -235,6 +254,7 @@ ComputeShader(V_SimParticlesCS, 64)
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
Texture2D<S_TileKind> tiles = G_Dereference<S_TileKind>(params.tiles);
u32 particle_idx = SV_DispatchThreadID;
if (particle_idx < params.max_particles)
@ -247,17 +267,14 @@ ComputeShader(V_SimParticlesCS, 64)
{
V_Emitter emitter = G_Dereference<V_Emitter>(params.emitters)[particle.emitter_init_num - 1];
// TODO: Faster mix
u64 seed = MixU64(emitter.seed + particle.idx_in_emitter);
// TODO: Blue noise
u32 speed_noise = ((u32)seed >> 0) & 0xFFFF;
u32 angle_noise = ((u32)seed >> 16) & 0xFFFF;
f32 speed_rand = speed_noise / (f32)0xFFFF;
f32 angle_rand = angle_noise / (f32)0xFFFF;
f32 speed = emitter.speed + ((speed_rand * 2 - 1) * emitter.speed_spread);
f32 angle = emitter.angle + ((angle_rand * 2 - 1) * emitter.angle_spread);
f32 speed = emitter.speed + ((speed_rand - 0.5) * emitter.speed_spread);
f32 angle = emitter.angle + ((angle_rand - 0.5) * emitter.angle_spread);
particle.pos = emitter.pos;
particle.velocity = Vec2(cos(angle), sin(angle)) * speed;
@ -268,7 +285,100 @@ ComputeShader(V_SimParticlesCS, 64)
// Simulate
{
f32 dt = params.dt;
particle.pos += particle.velocity * dt;
Vec2 pos_a = particle.pos;
Vec2 pos_b = pos_a + particle.velocity * dt;
// TODO: Don't query tiles
Vec2I32 tile_pos_a = S_TilePosFromWorldPos(pos_a);
S_TileKind tile_a = tiles.Load(Vec3I32(tile_pos_a, 0));
b32 is_blocked_a = tile_a == S_TileKind_Wall;
Vec2 pos_a_decal = mul(params.xf.world_to_decal, Vec3(pos_a, 1));
Vec2 pos_b_decal = mul(params.xf.world_to_decal, Vec3(pos_b, 1));
Vec2 step_a = pos_a_decal;
Vec2 step_b = pos_b_decal;
Vec2 step_vab = step_b - step_a;
f32 slope = step_vab.y / step_vab.x;
i32 x_dir = (step_vab.x >= 0) - (step_vab.x < 0);
if (!is_blocked_a)
{
i32 step_x = step_a.x;
for (;;)
{
f32 step_y = step_a.y + slope * (step_x - step_a.x);
Vec2 step = Vec2(step_x, step_y);
// TODO: Don't query tiles
Vec2 world_step = mul(params.xf.decal_to_world, Vec3(step, 1));
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_step);
S_TileKind tile = tiles.Load(Vec3I32(tile_pos, 0));
b32 is_blocked = tile == S_TileKind_Wall;
if (is_blocked)
{
// particle.velocity *= -1;
particle.velocity.y *= -1;
// particle.velocity.x *= -1;
break;
}
step_x += x_dir;
if (x_dir > 0)
{
if (step_x > (step_b.x + x_dir))
{
break;
}
}
else
{
if (step_x < (step_b.x + x_dir))
{
break;
}
}
}
}
// // Line walk
// // FIXME: Real line walk, not aabb check
// b32 is_blocked = 0;
// for (u32 step_y = step_a.y; step_y <= step_b.y; ++step_y)
// {
// for (u32 step_x = step_a.x; step_x <= step_b.x; ++step_x)
// {
// // TODO: Don't query tiles
// Vec2 world_step = mul(params.xf.decal_to_world, Vec3(step_x, step_y, 1));
// Vec2I32 tile_pos = S_TilePosFromWorldPos(world_step);
// S_TileKind tile = tiles.Load(Vec3I32(tile_pos, 0));
// if (tile == S_TileKind_Wall)
// {
// if (is_blocked)
// {
// // particle.velocity *= -1;
// particle.velocity.x *= -1;
// break;
// }
// is_blocked = 1;
// }
// }
// }
// Vec2I32 tile_pos = S_TilePosFromWorldPos(pos_a);
// S_TileKind tile = tiles.Load(Vec3I32(tile_pos, 0));
particle.pos = pos_a + particle.velocity * dt;
particle.velocity = lerp(particle.velocity, 0, 4 * params.dt);
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(particle.pos, 1));
if (decal_pos.x >= 0 && decal_pos.y >= 0 && decal_pos.x < countof(decals).x && decal_pos.y < countof(decals).y)
@ -393,20 +503,20 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
}
}
// TODO: Remove this
// Decals test
{
RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
// Vec2 decal_uv = decal_pos / countof(decals);
V_ParticleKind decal = decals.Load(floor(decal_pos));
// // TODO: Remove this
// // Decals test
// {
// RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
// Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
// // Vec2 decal_uv = decal_pos / countof(decals);
// V_ParticleKind decal = decals.Load(decal_pos);
if (decal == V_ParticleKind_Test)
{
result = Color_Yellow;
// result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
}
}
// if (decal == V_ParticleKind_Test)
// {
// result = Color_Yellow;
// // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
// }
// }
V_OverlayPSOutput output;

View File

@ -6,6 +6,7 @@
G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 0);
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 1);
G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 2);
Enum(V_SelectionMode)
{
@ -48,7 +49,6 @@ Struct(V_GpuParams)
V_Xforms xf;
u64 seed;
G_Texture3DRef noise;
V_SelectionMode selection_mode;
S_TileKind equipped_tile;