particle occluder testing
This commit is contained in:
parent
463e142727
commit
a4bb13d59d
@ -398,6 +398,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
G_ResourceHandle gpu_ground_densities_res = Zi;
|
||||
G_ResourceHandle gpu_air_densities_res = Zi;
|
||||
G_ResourceHandle gpu_drynesses_res = Zi;
|
||||
G_ResourceHandle gpu_occluders_res = Zi;
|
||||
|
||||
G_Texture2DRef gpu_tiles = Zi;
|
||||
G_RWStructuredBufferRef gpu_particles = Zi;
|
||||
@ -407,6 +408,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
G_RWTexture2DRef gpu_ground_densities = Zi;
|
||||
G_RWTexture2DRef gpu_air_densities = Zi;
|
||||
G_RWTexture2DRef gpu_drynesses = Zi;
|
||||
G_RWTexture2DRef gpu_occluders = Zi;
|
||||
{
|
||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||
{
|
||||
@ -505,6 +507,18 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
|
||||
}
|
||||
// Init occluders texture
|
||||
{
|
||||
gpu_occluders_res = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
G_Format_R32_Uint,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||
.name = Lit("Occluders cells")
|
||||
);
|
||||
gpu_occluders = G_PushRWTexture2DRef(gpu_perm, gpu_occluders_res);
|
||||
}
|
||||
}
|
||||
G_CommitCommandList(cl);
|
||||
}
|
||||
@ -629,6 +643,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->ground_densities = gpu_ground_densities;
|
||||
frame->air_densities = gpu_air_densities;
|
||||
frame->drynesses = gpu_drynesses;
|
||||
frame->occluders = gpu_occluders;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -2158,7 +2173,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect));
|
||||
|
||||
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
|
||||
quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, wep_uv_to_world_af);
|
||||
quad->quad_uv_to_world_af = wep_uv_to_world_af;
|
||||
quad->tex = wep.tex;
|
||||
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
|
||||
}
|
||||
@ -2169,7 +2184,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Affine body_uv_to_world_af = ScaleAffine(body_pix_to_world_af, DimsFromRng2(body.tex_rect));
|
||||
|
||||
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
|
||||
quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, body_uv_to_world_af);
|
||||
quad->quad_uv_to_world_af = body_uv_to_world_af;
|
||||
quad->tex = body.tex;
|
||||
quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims);
|
||||
}
|
||||
@ -2527,19 +2542,56 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test explosion
|
||||
//- Push test emitter
|
||||
|
||||
if (frame->held_buttons[Button_F])
|
||||
// if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F])
|
||||
// {
|
||||
// }
|
||||
{
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
|
||||
emitter.kind = V_ParticleKind_Test;
|
||||
|
||||
f32 angle = AngleFromVec2(frame->look);
|
||||
// f32 angle = 0;
|
||||
// f32 angle_spread = Tau * 0.25;
|
||||
f32 angle_spread = Tau;
|
||||
// f32 angle_spread = 0;
|
||||
|
||||
// f32 speed = 25;
|
||||
// f32 speed = 50;
|
||||
f32 speed = 100;
|
||||
f32 speed_spread = speed * 2;
|
||||
|
||||
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
||||
emitter.speed.min = speed - speed_spread * 0.5;
|
||||
emitter.speed.max = speed + speed_spread * 0.5;
|
||||
emitter.angle.min = angle - angle_spread * 0.5;
|
||||
emitter.angle.max = angle + angle_spread * 0.5;
|
||||
|
||||
// emitter.falloff.min = emitter.falloff.max = 0;
|
||||
|
||||
// emitter.count = CeilF32(Kibi(64) * frame->dt);
|
||||
// emitter.count = Mebi(16);
|
||||
// emitter.count = Mebi(2);
|
||||
// emitter.count = Kibi(32);
|
||||
// emitter.count = Kibi(8);
|
||||
emitter.count = 128;
|
||||
// emitter.count = 128;
|
||||
// emitter.count = 32;
|
||||
// emitter.count = 1;
|
||||
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test emitter
|
||||
//- Push test explosion
|
||||
|
||||
// if (frame->held_buttons[Button_G])
|
||||
if (frame->held_buttons[Button_G] && !prev_frame->held_buttons[Button_G])
|
||||
if (frame->held_buttons[Button_G])
|
||||
// if (frame->held_buttons[Button_G] && !prev_frame->held_buttons[Button_G])
|
||||
{
|
||||
// Debris
|
||||
{
|
||||
@ -2554,8 +2606,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// f32 angle_spread = 0;
|
||||
|
||||
// f32 speed = 25;
|
||||
f32 speed = 50;
|
||||
// f32 speed = 100;
|
||||
// f32 speed = 50;
|
||||
f32 speed = 100;
|
||||
f32 speed_spread = speed * 2;
|
||||
|
||||
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
||||
|
||||
@ -36,38 +36,52 @@ ComputeShader2D(V_PrepareShadeCS, 8, 8)
|
||||
ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
||||
{
|
||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
||||
RWTexture2D<u32> air_cells = G_Dereference<u32>(frame.air_cells);
|
||||
RWTexture2D<u32> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
||||
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_densities);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
||||
|
||||
Vec2 cells_pos = SV_DispatchThreadID + 0.5;
|
||||
if (all(cells_pos < countof(air_cells)))
|
||||
Vec2 cell_pos = SV_DispatchThreadID + 0.5;
|
||||
if (all(cell_pos < countof(air_cells)))
|
||||
{
|
||||
Vec2 world_pos = mul(frame.af.cell_to_world, Vec3(cell_pos, 1));
|
||||
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
|
||||
P_TileKind tile = tiles[tile_pos];
|
||||
|
||||
// Clear cells
|
||||
ground_cells[cells_pos] = 0;
|
||||
air_cells[cells_pos] = 0;
|
||||
ground_cells[cell_pos] = 0;
|
||||
air_cells[cell_pos] = 0;
|
||||
|
||||
// Clear densities
|
||||
ground_densities[cells_pos] = 0;
|
||||
air_densities[cells_pos] = 0;
|
||||
ground_densities[cell_pos] = 0;
|
||||
air_densities[cell_pos] = 0;
|
||||
|
||||
// Increase dryness
|
||||
// TODO: Use simulation dt
|
||||
f32 dry_rate = frame.dt * 0.1;
|
||||
{
|
||||
f32 old_dryness = drynesses[cells_pos];
|
||||
f32 old_dryness = drynesses[cell_pos];
|
||||
f32 new_dryness = lerp(old_dryness, 1, dry_rate);
|
||||
drynesses[cells_pos] = new_dryness;
|
||||
drynesses[cell_pos] = new_dryness;
|
||||
}
|
||||
|
||||
// Reset occluders
|
||||
P_OccluderKind occluder = P_OccluderKind_None;
|
||||
if (tile == P_TileKind_Wall)
|
||||
{
|
||||
occluder = P_OccluderKind_Wall;
|
||||
}
|
||||
occluders[cell_pos] = occluder;
|
||||
|
||||
// Clear stain
|
||||
if (frame.should_clear_particles)
|
||||
{
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||
stains[cells_pos] = 0;
|
||||
drynesses[cells_pos] = 0;
|
||||
stains[cell_pos] = 0;
|
||||
drynesses[cell_pos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,7 +112,8 @@ VertexShader(V_QuadVS, V_QuadPSInput)
|
||||
V_Quad quad = quads[SV_InstanceID];
|
||||
|
||||
Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
|
||||
Vec2 screen_pos = mul(quad.quad_uv_to_screen_af, Vec3(rect_uv, 1));
|
||||
Vec2 world_pos = mul(quad.quad_uv_to_world_af, Vec3(rect_uv, 1));
|
||||
Vec2 screen_pos = mul(frame.af.world_to_screen, Vec3(world_pos, 1));
|
||||
|
||||
Vec2 samp_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv);
|
||||
|
||||
@ -163,6 +178,7 @@ ComputeShader(V_EmitParticlesCS, 64)
|
||||
ComputeShader(V_SimParticlesCS, 64)
|
||||
{
|
||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
||||
@ -170,7 +186,7 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
RWTexture2D<u32> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
||||
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_densities);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
||||
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
@ -205,28 +221,15 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
particle.velocity = Vec2(cos(initial_angle), sin(initial_angle)) * initial_speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
||||
{
|
||||
//////////////////////////////
|
||||
//- Velocity effects
|
||||
|
||||
{
|
||||
// TODO: Separate particle basis for whisp effects
|
||||
u64 seed1 = MixU64(seed0);
|
||||
f32 rand_whisp = Norm16(seed1 >> 0);
|
||||
|
||||
b32 is_whispy = particle.kind == V_ParticleKind_Smoke;
|
||||
if (is_whispy)
|
||||
{
|
||||
f32 whisp = lerp(-1, 1, rand_whisp);
|
||||
particle.velocity.x += whisp * cos(particle.life * 10);
|
||||
particle.velocity.y += whisp * sin(particle.life * 10);
|
||||
|
||||
// f32 whisp = lerp(0, Tau, rand_whisp) * frame.dt;
|
||||
// particle.velocity = RotateVec2Angle(particle.velocity, whisp);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Move
|
||||
|
||||
@ -239,16 +242,16 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
Vec2 p1 = particle.pos + particle.velocity * frame.dt;
|
||||
f32 t = 1;
|
||||
{
|
||||
Vec2 tile_p0 = mul(frame.af.world_to_tile, Vec3(p0, 1));
|
||||
Vec2 tile_p1 = mul(frame.af.world_to_tile, Vec3(p1, 1));
|
||||
Vec2I32 dda_p0 = floor(tile_p0);
|
||||
Vec2I32 dda_p1 = floor(tile_p1);
|
||||
Vec2 occluder_p0 = mul(frame.af.world_to_cell, Vec3(p0, 1));
|
||||
Vec2 occluder_p1 = mul(frame.af.world_to_cell, Vec3(p1, 1));
|
||||
Vec2I32 cell_p0 = floor(occluder_p0);
|
||||
Vec2I32 cell_p1 = floor(occluder_p1);
|
||||
|
||||
Vec2 delta = tile_p1 - tile_p0;
|
||||
Vec2 delta = occluder_p1 - occluder_p0;
|
||||
Vec2 inv_delta = 1.0 / delta;
|
||||
Vec2 dda_step_dir = Vec2((delta.x > 0) - (delta.x < 0), (delta.y > 0) - (delta.y < 0));
|
||||
Vec2 t_delta = abs(inv_delta);
|
||||
Vec2 t_max = dda_p0 - tile_p0;
|
||||
Vec2 t_max = cell_p0 - occluder_p0;
|
||||
t_max.x += dda_step_dir.x > 0;
|
||||
t_max.y += dda_step_dir.y > 0;
|
||||
t_max *= inv_delta;
|
||||
@ -256,22 +259,23 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
|
||||
f32 t_hit = 1;
|
||||
|
||||
Vec2I32 dda_pos = dda_p0;
|
||||
Vec2I32 cell_pos = cell_p0;
|
||||
|
||||
b32 stepped_x = 0;
|
||||
b32 stepped_y = 0;
|
||||
|
||||
u32 max_iterations = 32;
|
||||
// u32 max_iterations = 32;
|
||||
u32 max_iterations = 128;
|
||||
b32 done = 0;
|
||||
for (u32 iteration_idx = 0; iteration_idx < max_iterations && !done; ++iteration_idx)
|
||||
{
|
||||
if (dda_pos.x == dda_p1.x && dda_pos.y == dda_p1.y)
|
||||
if (cell_pos.x == cell_p1.x && cell_pos.y == cell_p1.y)
|
||||
{
|
||||
done = 1;
|
||||
}
|
||||
else if (t_max.x < t_max.y)
|
||||
{
|
||||
dda_pos.x += dda_step_dir.x;
|
||||
cell_pos.x += dda_step_dir.x;
|
||||
t_hit = t_max.x - t_delta.x * 0.01;
|
||||
t_max.x += t_delta.x;
|
||||
stepped_x = 1;
|
||||
@ -279,21 +283,27 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
}
|
||||
else
|
||||
{
|
||||
dda_pos.y += dda_step_dir.y;
|
||||
cell_pos.y += dda_step_dir.y;
|
||||
t_hit = t_max.y - t_delta.y * 0.01;
|
||||
t_max.y += t_delta.y;
|
||||
stepped_x = 0;
|
||||
stepped_y = 1;
|
||||
}
|
||||
|
||||
if (all(dda_pos >= 0) && all(dda_pos < countof(tiles)))
|
||||
if (all(cell_pos >= 0) && all(cell_pos < countof(occluders)))
|
||||
{
|
||||
P_TileKind tile = tiles[dda_pos];
|
||||
if (tile == P_TileKind_Wall)
|
||||
P_OccluderKind occluder = (P_OccluderKind)occluders[cell_pos];
|
||||
if (occluder != P_OccluderKind_None)
|
||||
{
|
||||
done = 1;
|
||||
collision = 1;
|
||||
particle.velocity *= 0.5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
stains[cell_pos] = Color_Black;
|
||||
// ground_cells[cell_pos] = Color_White;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -337,6 +347,7 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
//////////////////////////////
|
||||
//- Commit
|
||||
|
||||
{
|
||||
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
|
||||
Vec2 cell_screen_pos_p0 = mul(frame.af.world_to_screen, Vec3(mul(frame.af.cell_to_world, Vec3(floor(cell_pos), 1)), 1));
|
||||
Vec2 cell_screen_pos_p1 = mul(frame.af.world_to_screen, Vec3(mul(frame.af.cell_to_world, Vec3(ceil(cell_pos), 1)), 1));
|
||||
@ -346,39 +357,14 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||
|
||||
// TODO: Particle based flags
|
||||
b32 is_stain_particle = particle.kind == V_ParticleKind_Debris;
|
||||
b32 is_ground_particle = particle.kind == V_ParticleKind_Debris;
|
||||
b32 is_stain_particle = particle.kind == V_ParticleKind_Debris || particle.kind == V_ParticleKind_Test;
|
||||
b32 is_ground_particle = particle.kind == V_ParticleKind_Debris || particle.kind == V_ParticleKind_Test;
|
||||
b32 is_air_particle = particle.kind == V_ParticleKind_Smoke;
|
||||
|
||||
b32 should_stain = is_stain_particle && is_in_world;
|
||||
b32 should_draw_ground = is_ground_particle && is_in_world && (is_visible || should_stain);
|
||||
b32 should_draw_air = is_air_particle && is_in_world && is_visible;
|
||||
|
||||
// // Stain
|
||||
// if (is_in_world)
|
||||
// {
|
||||
// b32 should_stain = (
|
||||
// AnyBit(particle.flags, V_ParticleFlag_StainTrail) ||
|
||||
// (AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0)
|
||||
// );
|
||||
|
||||
// if (should_stain)
|
||||
// {
|
||||
// f32 old_dryness = drynesses[cell_pos];
|
||||
// Vec4 old_stain = stains[cell_pos];
|
||||
// // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5);
|
||||
// // old_stain = V_DryColor(old_stain, old_dryness);
|
||||
// Vec4 new_stain = 0;
|
||||
// new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a));
|
||||
// new_stain.a = color.a + (old_stain.a * (1.0 - color.a));
|
||||
// // new_stain = V_DryColor(new_stain, old_dryness * 0.1);
|
||||
// // new_stain = V_DryColor(new_stain, old_dryness * 0.5);
|
||||
|
||||
// stains[cell_pos] = new_stain;
|
||||
// drynesses[cell_pos] = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Draw
|
||||
if (should_draw_ground || should_draw_air)
|
||||
{
|
||||
@ -401,64 +387,217 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
|
||||
// Vec2 screen_pos = mul(frame.af.world_to_screen, Vec3(particle.pos, 1));
|
||||
// b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells));
|
||||
// b32 is_visible = all(screen_pos >= 0) && all(screen_pos < frame.screen_dims);
|
||||
|
||||
// Vec4 color = particle.color;
|
||||
// color.a *= prev_exists;
|
||||
|
||||
// // Stain
|
||||
// if (is_in_world)
|
||||
// {
|
||||
// b32 should_stain = (
|
||||
// AnyBit(particle.flags, V_ParticleFlag_StainTrail) ||
|
||||
// (AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0)
|
||||
// );
|
||||
|
||||
// if (should_stain)
|
||||
// {
|
||||
// f32 old_dryness = drynesses[cell_pos];
|
||||
// Vec4 old_stain = stains[cell_pos];
|
||||
// // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5);
|
||||
// // old_stain = V_DryColor(old_stain, old_dryness);
|
||||
// Vec4 new_stain = 0;
|
||||
// new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a));
|
||||
// new_stain.a = color.a + (old_stain.a * (1.0 - color.a));
|
||||
// // new_stain = V_DryColor(new_stain, old_dryness * 0.1);
|
||||
// // new_stain = V_DryColor(new_stain, old_dryness * 0.5);
|
||||
|
||||
// stains[cell_pos] = new_stain;
|
||||
// drynesses[cell_pos] = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Draw
|
||||
// {
|
||||
// b32 should_draw = is_in_world;
|
||||
|
||||
// if (should_draw)
|
||||
// {
|
||||
// cells[cell_pos] = color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Increment life
|
||||
particle.life += frame.dt;
|
||||
|
||||
// Prune
|
||||
if (!is_in_world)
|
||||
{
|
||||
particle.kind = V_ParticleKind_None;
|
||||
}
|
||||
|
||||
// Increment life
|
||||
particle.life += frame.dt;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.kind = V_ParticleKind_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
||||
// {
|
||||
// //////////////////////////////
|
||||
// //- Move
|
||||
|
||||
// b32 collision = 0;
|
||||
|
||||
// // TODO: Use simulation dt
|
||||
// // TODO: Clip to avoid unnecessary iterations outside of world bounds
|
||||
// {
|
||||
// Vec2 p0 = particle.pos;
|
||||
// Vec2 p1 = particle.pos + particle.velocity * frame.dt;
|
||||
// f32 t = 1;
|
||||
// {
|
||||
// Vec2 occluder_p0 = mul(frame.af.world_to_cell, Vec3(p0, 1));
|
||||
// Vec2 occluder_p1 = mul(frame.af.world_to_cell, Vec3(p1, 1));
|
||||
// Vec2I32 dda_p0 = floor(occluder_p0);
|
||||
// Vec2I32 dda_p1 = floor(occluder_p1);
|
||||
|
||||
// Vec2 delta = occluder_p1 - occluder_p0;
|
||||
// Vec2 inv_delta = 1.0 / delta;
|
||||
// Vec2 dda_step_dir = Vec2((delta.x > 0) - (delta.x < 0), (delta.y > 0) - (delta.y < 0));
|
||||
// Vec2 t_delta = abs(inv_delta);
|
||||
// Vec2 t_max = dda_p0 - occluder_p0;
|
||||
// t_max.x += dda_step_dir.x > 0;
|
||||
// t_max.y += dda_step_dir.y > 0;
|
||||
// t_max *= inv_delta;
|
||||
// t_max = abs(t_max);
|
||||
|
||||
// f32 t_hit = 1;
|
||||
|
||||
// Vec2I32 dda_pos = dda_p0;
|
||||
|
||||
// b32 stepped_x = 0;
|
||||
// b32 stepped_y = 0;
|
||||
|
||||
// // u32 max_iterations = 32;
|
||||
// u32 max_iterations = 128;
|
||||
// b32 done = 0;
|
||||
// for (u32 iteration_idx = 0; iteration_idx < max_iterations && !done; ++iteration_idx)
|
||||
// {
|
||||
// if (dda_pos.x == dda_p1.x && dda_pos.y == dda_p1.y)
|
||||
// {
|
||||
// done = 1;
|
||||
// }
|
||||
// else if (t_max.x < t_max.y)
|
||||
// {
|
||||
// dda_pos.x += dda_step_dir.x;
|
||||
// t_hit = t_max.x - t_delta.x * 0.01;
|
||||
// t_max.x += t_delta.x;
|
||||
// stepped_x = 1;
|
||||
// stepped_y = 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dda_pos.y += dda_step_dir.y;
|
||||
// t_hit = t_max.y - t_delta.y * 0.01;
|
||||
// t_max.y += t_delta.y;
|
||||
// stepped_x = 0;
|
||||
// stepped_y = 1;
|
||||
// }
|
||||
|
||||
// if (all(dda_pos >= 0) && all(dda_pos < countof(occluders)))
|
||||
// {
|
||||
// P_OccluderKind occluder = (P_OccluderKind)occluders[dda_pos];
|
||||
// if (occluder == P_OccluderKind_Wall)
|
||||
// {
|
||||
// done = 1;
|
||||
// collision = 1;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// done = 1;
|
||||
// }
|
||||
// iteration_idx += 1;
|
||||
// }
|
||||
|
||||
// if (collision)
|
||||
// {
|
||||
// t = saturate(t_hit);
|
||||
// if (stepped_x)
|
||||
// {
|
||||
// particle.velocity.x *= -1;
|
||||
// }
|
||||
// else if (stepped_y)
|
||||
// {
|
||||
// particle.velocity.y *= -1;
|
||||
// }
|
||||
// {
|
||||
// u64 collision_seed = MixU64s(seed0, particle.collisions_count);
|
||||
// f32 rand_collision_angle = Norm16(collision_seed >> 0);
|
||||
// f32 rand_collision_velocity = Norm16(collision_seed >> 16);
|
||||
// f32 collision_angle = lerp(-0.05 * Tau, 0.05 * Tau, rand_collision_angle);
|
||||
// // f32 collision_velocity_falloff = lerp(0, 1, rand_collision_velocity);
|
||||
// f32 collision_velocity_falloff = 0;
|
||||
// particle.velocity = RotateVec2Angle(particle.velocity, collision_angle);
|
||||
// particle.velocity *= 1.0f - collision_velocity_falloff;
|
||||
// }
|
||||
// ++particle.collisions_count;
|
||||
// }
|
||||
// }
|
||||
|
||||
// f32 falloff = saturate(lerp(10, 20, rand_falloff) * frame.dt);
|
||||
// // f32 falloff = saturate(lerp(1, 2, rand_falloff) * frame.dt);
|
||||
// particle.velocity *= 1.0f - falloff;
|
||||
|
||||
// particle.pos = p0 + (p1 - p0) * t;
|
||||
// }
|
||||
|
||||
// //////////////////////////////
|
||||
// //- Commit
|
||||
|
||||
// Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
|
||||
// Vec2 cell_screen_pos_p0 = mul(frame.af.world_to_screen, Vec3(mul(frame.af.cell_to_world, Vec3(floor(cell_pos), 1)), 1));
|
||||
// Vec2 cell_screen_pos_p1 = mul(frame.af.world_to_screen, Vec3(mul(frame.af.cell_to_world, Vec3(ceil(cell_pos), 1)), 1));
|
||||
// cell_screen_pos_p1 = max(cell_screen_pos_p1, cell_screen_pos_p0 + 1);
|
||||
|
||||
// b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(air_cells));
|
||||
// b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||
|
||||
// // TODO: Particle based flags
|
||||
// b32 is_stain_particle = particle.kind == V_ParticleKind_Debris || particle.kind == V_ParticleKind_Test;
|
||||
// b32 is_ground_particle = particle.kind == V_ParticleKind_Debris || particle.kind == V_ParticleKind_Test;
|
||||
// b32 is_air_particle = particle.kind == V_ParticleKind_Smoke;
|
||||
|
||||
// b32 should_stain = is_stain_particle && is_in_world;
|
||||
// b32 should_draw_ground = is_ground_particle && is_in_world && (is_visible || should_stain);
|
||||
// b32 should_draw_air = is_air_particle && is_in_world && is_visible;
|
||||
|
||||
// // Draw
|
||||
// if (should_draw_ground || should_draw_air)
|
||||
// {
|
||||
// u32 packed = 0;
|
||||
// packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
||||
// packed |= (particle.kind & 0xFF) << 24;
|
||||
// StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
||||
// StaticAssert(V_ParticleKind_COUNT <= 0xFF); // particle kind must fit in 8 bits
|
||||
|
||||
// if (should_draw_ground)
|
||||
// {
|
||||
// InterlockedMax(ground_cells[cell_pos], packed);
|
||||
// InterlockedAdd(ground_densities[cell_pos], 1);
|
||||
// }
|
||||
|
||||
// if (should_draw_air)
|
||||
// {
|
||||
// InterlockedMax(air_cells[cell_pos], packed);
|
||||
// InterlockedAdd(air_densities[cell_pos], 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Increment life
|
||||
// particle.life += frame.dt;
|
||||
|
||||
// // Prune
|
||||
// if (!is_in_world)
|
||||
// {
|
||||
// particle.kind = V_ParticleKind_None;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// particle.kind = V_ParticleKind_None;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
particles[particle_idx] = particle;
|
||||
}
|
||||
}
|
||||
@ -692,7 +831,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
{
|
||||
u64 seed = MixU64(P_ParticleCompositeBasis ^ particle_idx);
|
||||
f32 rand_color = Norm16(seed >> 0);
|
||||
if (kind == V_ParticleKind_Debris)
|
||||
if (kind == V_ParticleKind_Debris || kind == V_ParticleKind_Test)
|
||||
{
|
||||
color.rgb = Color_Orange.rgb;
|
||||
}
|
||||
@ -732,7 +871,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
{
|
||||
u64 seed = MixU64(P_ParticleCompositeBasis ^ particle_idx);
|
||||
f32 rand_color = Norm16(seed >> 0);
|
||||
if (kind == V_ParticleKind_Debris)
|
||||
if (kind == V_ParticleKind_Debris || kind == V_ParticleKind_Test)
|
||||
{
|
||||
color.rgb = Color_Orange.rgb;
|
||||
}
|
||||
|
||||
@ -152,11 +152,21 @@ Struct(V_SharedFrame)
|
||||
G_RWTexture2DRef ground_densities;
|
||||
G_RWTexture2DRef air_densities;
|
||||
G_RWTexture2DRef drynesses;
|
||||
G_RWTexture2DRef occluders;
|
||||
|
||||
G_StructuredBufferRef dverts;
|
||||
G_StructuredBufferRef quads;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Occluder types
|
||||
|
||||
Enum(P_OccluderKind)
|
||||
{
|
||||
P_OccluderKind_None,
|
||||
P_OccluderKind_Wall,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Particle types
|
||||
|
||||
@ -223,7 +233,7 @@ Enum(V_QuadFlag)
|
||||
Struct(V_Quad)
|
||||
{
|
||||
V_QuadFlag flags;
|
||||
Affine quad_uv_to_screen_af;
|
||||
Affine quad_uv_to_world_af;
|
||||
G_Texture2DRef tex;
|
||||
Rng2 tex_slice_uv;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user