particle tile collisions
This commit is contained in:
parent
f3ae9674f1
commit
f16a102cfa
@ -56,7 +56,7 @@ i32 SignF64(f64 v)
|
||||
|
||||
f32 Norm8(u32 v)
|
||||
{
|
||||
return (v & 0xFF) / (f32)0x1FF;
|
||||
return (v & 0xFF) / (f32)0x100;
|
||||
}
|
||||
|
||||
f32 Norm16(u32 v)
|
||||
|
||||
@ -519,22 +519,14 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wframe-larger-than=1048575"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wmissing-prototypes"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wmissing-declarations"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-variable"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-but-set-variable"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-parameter"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wimplicit-fallthrough"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wswitch"));
|
||||
|
||||
// Disable warnings
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-initializer-overrides"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-microsoft-enum-forward-reference"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-microsoft-anon-tag"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-variable"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-but-set-variable"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-parameter"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-incompatible-function-pointer-types"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-missing-braces"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-switch"));
|
||||
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-value"));
|
||||
}
|
||||
|
||||
@ -546,7 +538,7 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
|
||||
|
||||
// Enable warnings
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wall"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-WX"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Werror"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wshadow"));
|
||||
|
||||
// Disable warnings
|
||||
|
||||
@ -2150,78 +2150,78 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
// TODO: Not like this
|
||||
|
||||
for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
{
|
||||
if (bullet->is_bullet)
|
||||
{
|
||||
Vec2 start = bullet->bullet_start;
|
||||
Vec2 end = bullet->bullet_end;
|
||||
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
// {
|
||||
// if (bullet->is_bullet)
|
||||
// {
|
||||
// Vec2 start = bullet->bullet_start;
|
||||
// Vec2 end = bullet->bullet_end;
|
||||
|
||||
b32 skip = 0;
|
||||
if (bullet->has_hit)
|
||||
{
|
||||
Vec2 hit_pos = bullet->hit_entry;
|
||||
if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
|
||||
{
|
||||
skip = 1;
|
||||
}
|
||||
// V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
|
||||
// V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
|
||||
end = hit_pos;
|
||||
}
|
||||
// b32 skip = 0;
|
||||
// if (bullet->has_hit)
|
||||
// {
|
||||
// Vec2 hit_pos = bullet->hit_entry;
|
||||
// if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
|
||||
// {
|
||||
// skip = 1;
|
||||
// }
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
|
||||
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
|
||||
// end = hit_pos;
|
||||
// }
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
f32 trail_len = Vec2Len(SubVec2(end, start));
|
||||
f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
|
||||
particles_count = MaxF32(particles_count, 1);
|
||||
// if (!skip)
|
||||
// {
|
||||
// f32 trail_len = Vec2Len(SubVec2(end, start));
|
||||
// f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
|
||||
// particles_count = MaxF32(particles_count, 1);
|
||||
|
||||
f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
// f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// // f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
// emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
// emitter.flags |= V_ParticleFlag_StainTrail;
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// // emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
// // emitter.flags |= V_ParticleFlag_StainTrail;
|
||||
|
||||
// emitter.lifetime = 1;
|
||||
// emitter.lifetime_spread = 2;
|
||||
// // emitter.lifetime = 1;
|
||||
// // emitter.lifetime_spread = 2;
|
||||
|
||||
emitter.count = particles_count;
|
||||
// emitter.count = particles_count;
|
||||
|
||||
// emitter.lifetime = 1;
|
||||
// emitter.lifetime = 0.15;
|
||||
emitter.lifetime = 0.075;
|
||||
// emitter.lifetime = 0.05;
|
||||
// emitter.lifetime = 0.04;
|
||||
emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
// // emitter.lifetime = 1;
|
||||
// // emitter.lifetime = 0.15;
|
||||
// emitter.lifetime = 0.075;
|
||||
// // emitter.lifetime = 0.05;
|
||||
// // emitter.lifetime = 0.04;
|
||||
// emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
|
||||
emitter.angle = angle;
|
||||
// emitter.angle_spread = Tau / 4;
|
||||
emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle = angle;
|
||||
// // emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle_spread = Tau / 4;
|
||||
|
||||
emitter.start = start;
|
||||
emitter.end = end;
|
||||
// emitter.start = start;
|
||||
// emitter.end = end;
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.8, 0.8, 0.25));
|
||||
emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
|
||||
// emitter.color_spread = LinearFromSrgb(VEC4(0, 0, 0, 0.2));
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.8, 0.8, 0.25));
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
|
||||
// // emitter.color_spread = LinearFromSrgb(VEC4(0, 0, 0, 0.2));
|
||||
|
||||
emitter.speed = 0;
|
||||
emitter.speed_spread = 1;
|
||||
// emitter.speed = 0;
|
||||
// emitter.speed_spread = 1;
|
||||
|
||||
// emitter.speed = 1;
|
||||
// emitter.speed_spread = 1;
|
||||
// // emitter.speed = 1;
|
||||
// // emitter.speed_spread = 1;
|
||||
|
||||
// emitter.velocity_falloff = 1;
|
||||
// emitter.velocity_falloff_spread = 0;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // emitter.velocity_falloff = 1;
|
||||
// // emitter.velocity_falloff_spread = 0;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@ -2234,156 +2234,157 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
// if (0)
|
||||
{
|
||||
for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
{
|
||||
if (bullet->is_bullet && bullet->has_hit)
|
||||
{
|
||||
P_MaterialKind material = bullet->hit_material;
|
||||
// {
|
||||
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
// {
|
||||
// if (bullet->is_bullet && bullet->has_hit)
|
||||
// {
|
||||
// P_MaterialKind material = bullet->hit_material;
|
||||
|
||||
Vec2 hit_entry = bullet->hit_entry;
|
||||
Vec2 hit_entry_normal = bullet->hit_entry_normal;
|
||||
Vec2 bullet_vel = SubVec2(bullet->bullet_end, bullet->bullet_start);
|
||||
// Vec2 hit_entry = bullet->hit_entry;
|
||||
// Vec2 hit_entry_normal = bullet->hit_entry_normal;
|
||||
// Vec2 bullet_vel = SubVec2(bullet->bullet_end, bullet->bullet_start);
|
||||
|
||||
V_DrawLine(bullet->bullet_start, bullet->bullet_end, Color_Cyan);
|
||||
// V_DrawLine(bullet->bullet_start, bullet->bullet_end, Color_Cyan);
|
||||
|
||||
//////////////////////////////
|
||||
//- Wall particles
|
||||
// //////////////////////////////
|
||||
// //- Wall particles
|
||||
|
||||
if (material != P_MaterialKind_Flesh)
|
||||
{
|
||||
//- Wall debris
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
// if (material != P_MaterialKind_Flesh)
|
||||
// {
|
||||
// //- Wall debris
|
||||
// {
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// // emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// // emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
|
||||
emitter.count = 4;
|
||||
|
||||
emitter.start = hit_entry;
|
||||
emitter.end = emitter.start;
|
||||
// emitter.count = 4;
|
||||
|
||||
emitter.color_lin = LinearFromSrgb(VEC4(0.4, 0.3, 0.2, 0.75));
|
||||
emitter.color_spread = VEC4(0, 0, 0, 0.25);
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
emitter.speed = 2;
|
||||
// emitter.speed_spread = emitter.speed * 2;
|
||||
emitter.speed_spread = emitter.speed * 2.5;
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.4, 0.3, 0.2, 0.75));
|
||||
// emitter.color_spread = VEC4(0, 0, 0, 0.25);
|
||||
|
||||
emitter.velocity_falloff = 5;
|
||||
emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
// emitter.speed = 2;
|
||||
// // emitter.speed_spread = emitter.speed * 2;
|
||||
// emitter.speed_spread = emitter.speed * 2.5;
|
||||
|
||||
Vec2 dir = hit_entry_normal;
|
||||
// emitter.velocity_falloff = 5;
|
||||
// emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
emitter.angle_spread = Tau * 0.5;
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
|
||||
// emitter.lifetime = 0.25;
|
||||
// emitter.lifetime = 0.05;
|
||||
// emitter.lifetime = 0.04;
|
||||
emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau * 0.5;
|
||||
|
||||
//- Wall dust
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
// emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// // emitter.lifetime = 0.25;
|
||||
// // emitter.lifetime = 0.05;
|
||||
// // emitter.lifetime = 0.04;
|
||||
// emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
|
||||
emitter.count = 32;
|
||||
// //- Wall dust
|
||||
// {
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// // emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
|
||||
emitter.start = hit_entry;
|
||||
emitter.end = emitter.start;
|
||||
// emitter.count = 32;
|
||||
|
||||
emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
emitter.speed = 4;
|
||||
// emitter.speed_spread = emitter.speed * 2;
|
||||
emitter.speed_spread = emitter.speed * 2;
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
|
||||
|
||||
emitter.velocity_falloff = 12;
|
||||
emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
// emitter.speed = 4;
|
||||
// // emitter.speed_spread = emitter.speed * 2;
|
||||
// emitter.speed_spread = emitter.speed * 2;
|
||||
|
||||
Vec2 dir = hit_entry_normal;
|
||||
// emitter.velocity_falloff = 12;
|
||||
// emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
emitter.angle_spread = Tau * 0.1;
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
|
||||
emitter.lifetime = 1;
|
||||
// emitter.lifetime = 0.05;
|
||||
// emitter.lifetime = 0.04;
|
||||
emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
}
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau * 0.1;
|
||||
|
||||
//////////////////////////////
|
||||
//- Blood particles
|
||||
// emitter.lifetime = 1;
|
||||
// // emitter.lifetime = 0.05;
|
||||
// // emitter.lifetime = 0.04;
|
||||
// emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (material == P_MaterialKind_Flesh)
|
||||
{
|
||||
// Vec2 bullet_start = bullet->start;
|
||||
// Vec2 bullet_end = bullet->end;
|
||||
// //////////////////////////////
|
||||
// //- Blood particles
|
||||
|
||||
V_ParticleFlag flags = 0;
|
||||
flags |= V_ParticleFlag_PruneWhenStill;
|
||||
flags |= V_ParticleFlag_StainOnPrune;
|
||||
if (TweakBool("Emitter stain trail", 1))
|
||||
{
|
||||
flags |= V_ParticleFlag_StainTrail;
|
||||
}
|
||||
// f32 count = TweakFloat("Emitter count", 50, 0, 10000);
|
||||
f32 count = TweakFloat("Emitter count", 20, 1, 1000);
|
||||
f32 speed = TweakFloat("Emitter speed", 20, 0, 100);
|
||||
f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100);
|
||||
f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||
// if (material == P_MaterialKind_Flesh)
|
||||
// {
|
||||
// // Vec2 bullet_start = bullet->start;
|
||||
// // Vec2 bullet_end = bullet->end;
|
||||
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
emitter.count = count;
|
||||
emitter.flags = flags;
|
||||
// V_ParticleFlag flags = 0;
|
||||
// flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// flags |= V_ParticleFlag_StainOnPrune;
|
||||
// if (TweakBool("Emitter stain trail", 1))
|
||||
// {
|
||||
// flags |= V_ParticleFlag_StainTrail;
|
||||
// }
|
||||
// // f32 count = TweakFloat("Emitter count", 50, 0, 10000);
|
||||
// f32 count = TweakFloat("Emitter count", 20, 1, 1000);
|
||||
// f32 speed = TweakFloat("Emitter speed", 20, 0, 100);
|
||||
// f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100);
|
||||
// f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// emitter.count = count;
|
||||
// emitter.flags = flags;
|
||||
|
||||
emitter.start = hit_entry;
|
||||
emitter.end = emitter.start;
|
||||
// // Vec2 dir = hit_entry_normal;
|
||||
// Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
|
||||
emitter.speed = speed;
|
||||
emitter.speed_spread = speed * 2;
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
emitter.velocity_falloff = falloff;
|
||||
emitter.velocity_falloff_spread = falloff * 1.5;
|
||||
// emitter.speed = speed;
|
||||
// emitter.speed_spread = speed * 2;
|
||||
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau / 4;
|
||||
emitter.angle_spread = angle_spread;
|
||||
// emitter.angle_spread = Tau / 32;
|
||||
// emitter.velocity_falloff = falloff;
|
||||
// emitter.velocity_falloff_spread = falloff * 1.5;
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 0.5));
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// // emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle_spread = angle_spread;
|
||||
// // emitter.angle_spread = Tau / 32;
|
||||
|
||||
// emitter.color_spread = VEC4(0.1, 0, 0, 0);
|
||||
emitter.color_spread = VEC4(0.1, 0, 0, 0.5);
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 0.5));
|
||||
|
||||
// emitter.color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
// // emitter.color_spread = VEC4(0.1, 0, 0, 0);
|
||||
// emitter.color_spread = VEC4(0.1, 0, 0, 0.5);
|
||||
|
||||
// emitter.angle_spread = 1;
|
||||
// emitter.angle_spread = 0.5;
|
||||
// emitter.angle_spread = Tau;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
// // emitter.color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
|
||||
// V_DrawPoint(victim_raycast.p, Color_Green);
|
||||
// V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // emitter.angle_spread = 1;
|
||||
// // emitter.angle_spread = 0.5;
|
||||
// // emitter.angle_spread = Tau;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
|
||||
// // V_DrawPoint(victim_raycast.p, Color_Green);
|
||||
// // V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@ -2499,36 +2500,49 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test emitter
|
||||
|
||||
if (frame->held_buttons[Button_G])
|
||||
// if (frame->held_buttons[Button_G])
|
||||
if (frame->held_buttons[Button_G] && !prev_frame->held_buttons[Button_G])
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
|
||||
Vec2 dir = frame->look;
|
||||
emitter.start = frame->world_cursor;
|
||||
emitter.end = emitter.start;
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
emitter.kind = V_ParticleKind_Test;
|
||||
|
||||
// emitter.flags |= V_ParticleFlag_StainTrail;
|
||||
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 = 1000;
|
||||
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 = Kibi(1);
|
||||
// emitter.count = 128;
|
||||
emitter.count = CeilF32(Kibi(16) * frame->dt);
|
||||
emitter.speed = 10;
|
||||
|
||||
emitter.color_lin = LinearFromSrgb(Color_Yellow);
|
||||
|
||||
emitter.speed_spread = 1;
|
||||
// emitter.angle_spread = 1;
|
||||
// emitter.angle_spread = 0.5;
|
||||
emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle_spread = Tau;
|
||||
// emitter.count = 32;
|
||||
// emitter.count = 1;
|
||||
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Debug draw
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ ComputeShader(V_ClearParticlesCS, 64)
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
{
|
||||
particles[particle_idx].exists = 0;
|
||||
particles[particle_idx].kind = V_ParticleKind_None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,13 +136,15 @@ ComputeShader(V_EmitParticlesCS, 64)
|
||||
if (emitter_idx < frame.emitters_count)
|
||||
{
|
||||
V_Emitter emitter = emitters[emitter_idx];
|
||||
i32 semantic_particle_kind = V_ParticleKind_None;
|
||||
if (emitter.kind > V_ParticleKind_None)
|
||||
{
|
||||
semantic_particle_kind = (i32)(emitter_idx + 1) * -1;
|
||||
}
|
||||
for (u32 emitter_particle_idx = 0; emitter_particle_idx < emitter.count; ++emitter_particle_idx)
|
||||
{
|
||||
u32 particle_seq = emitter.first_particle_seq + emitter_particle_idx;
|
||||
u32 particle_idx = particle_seq % (u32)V_ParticlesCap;
|
||||
particles[particle_idx].exists = 1;
|
||||
particles[particle_idx].emitter_init_num = emitter_idx + 1;
|
||||
particles[particle_idx].seq = particle_seq;
|
||||
u32 particle_idx = (emitter.first_particle_seq + emitter_particle_idx) % (u32)V_ParticlesCap;
|
||||
particles[particle_idx].kind = semantic_particle_kind;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,130 +159,269 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
{
|
||||
V_Particle particle = particles[particle_idx];
|
||||
if (particle.exists > 0)
|
||||
|
||||
//////////////////////////////
|
||||
//- Initialize particle
|
||||
|
||||
if (particle.kind != 0)
|
||||
{
|
||||
u64 seed0 = MixU64(particle_idx);
|
||||
f32 rand_offset = Norm16(seed0 >> 0);
|
||||
f32 rand_angle = Norm16(seed0 >> 16);
|
||||
f32 rand_speed = Norm16(seed0 >> 32);
|
||||
f32 rand_falloff = Norm16(seed0 >> 48);
|
||||
|
||||
//////////////////////////////
|
||||
//- Initialize particle
|
||||
//- Init
|
||||
|
||||
if (particle.emitter_init_num != 0)
|
||||
if (particle.kind < 0)
|
||||
{
|
||||
V_Emitter emitter = G_Dereference<V_Emitter>(frame.emitters)[particle.emitter_init_num - 1];
|
||||
u32 emitter_idx = -particle.kind - 1;
|
||||
V_Emitter emitter = G_Dereference<V_Emitter>(frame.emitters)[emitter_idx];
|
||||
|
||||
u64 seed0 = MixU64(particle.seq);
|
||||
u64 seed1 = MixU64(seed0);
|
||||
f32 initial_angle = lerp(emitter.angle.min, emitter.angle.max, rand_angle);
|
||||
f32 initial_speed = lerp(emitter.speed.min, emitter.speed.max, rand_speed);
|
||||
|
||||
f32 rand_speed = Norm16(seed0 >> 0);
|
||||
f32 rand_angle = Norm16(seed0 >> 16);
|
||||
f32 rand_offset = Norm16(seed0 >> 32);
|
||||
f32 rand_falloff = Norm16(seed0 >> 48);
|
||||
|
||||
f32 rand_r = Norm8(seed1 >> 0);
|
||||
f32 rand_g = Norm8(seed1 >> 8);
|
||||
f32 rand_b = Norm8(seed1 >> 16);
|
||||
f32 rand_a = Norm8(seed1 >> 24);
|
||||
f32 rand_lifetime = Norm16(seed1 >> 32);
|
||||
|
||||
f32 speed = emitter.speed + (rand_speed - 0.5) * emitter.speed_spread;
|
||||
f32 angle = emitter.angle + (rand_angle - 0.5) * emitter.angle_spread;
|
||||
f32 velocity_falloff = emitter.velocity_falloff + (rand_falloff - 0.5) * emitter.velocity_falloff_spread;
|
||||
f32 lifetime = emitter.lifetime + (rand_lifetime - 0.5) * emitter.lifetime_spread;
|
||||
Vec4 color = emitter.color_lin + (Vec4(rand_r, rand_g, rand_b, rand_a) - 0.5) * emitter.color_spread;
|
||||
Vec2 offset = (emitter.end - emitter.start) * rand_offset;
|
||||
|
||||
particle.flags = emitter.flags;
|
||||
particle.pos = emitter.start + offset;
|
||||
particle.velocity = Vec2(cos(angle), sin(angle)) * speed;
|
||||
particle.velocity_falloff = velocity_falloff;
|
||||
particle.color = color;
|
||||
particle.lifetime = lifetime;
|
||||
if (emitter.lifetime == 0)
|
||||
{
|
||||
particle.lifetime = Inf;
|
||||
}
|
||||
|
||||
particle.emitter_init_num = 0;
|
||||
particle.kind = emitter.kind;
|
||||
particle.life = 0;
|
||||
particle.pos = lerp(emitter.pos.p0, emitter.pos.p1, rand_offset);
|
||||
particle.velocity = Vec2(cos(initial_angle), sin(initial_angle)) * initial_speed;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Simulate particle
|
||||
|
||||
f32 prev_exists = particle.exists;
|
||||
if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
||||
{
|
||||
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
|
||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells));
|
||||
//////////////////////////////
|
||||
//- Move
|
||||
|
||||
// Simulate
|
||||
b32 collision = 0;
|
||||
|
||||
// TODO: Use simulation dt
|
||||
// TODO: Clip to avoid unnecessary iterations outside of world bounds
|
||||
{
|
||||
// TODO: Use simulation dt
|
||||
particle.pos += particle.velocity * frame.dt;
|
||||
particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * frame.dt);
|
||||
particle.exists -= frame.dt / particle.lifetime;
|
||||
if ((particle.flags & V_ParticleFlag_PruneWhenStill) && (dot(particle.velocity, particle.velocity) < (0.1 * 0.1)))
|
||||
Vec2 p0 = particle.pos;
|
||||
Vec2 p1 = particle.pos + particle.velocity * frame.dt;
|
||||
f32 t = 1;
|
||||
{
|
||||
particle.exists = 0;
|
||||
}
|
||||
if (particle.exists < 0.000001)
|
||||
{
|
||||
particle.exists = 0;
|
||||
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 grid_p0 = floor(tile_p0);
|
||||
Vec2I32 grid_p1 = floor(tile_p1);
|
||||
|
||||
Vec2 delta = tile_p1 - tile_p0;
|
||||
Vec2 inv_delta = 1.0 / delta;
|
||||
Vec2 grid_step_dir = Vec2((delta.x > 0) - (delta.x < 0), (delta.y > 0) - (delta.y < 0));
|
||||
Vec2 t_delta = abs(inv_delta);
|
||||
Vec2 t_crossover_next = grid_p0 - tile_p0;
|
||||
t_crossover_next.x += grid_step_dir.x > 0;
|
||||
t_crossover_next.y += grid_step_dir.y > 0;
|
||||
t_crossover_next *= inv_delta;
|
||||
t_crossover_next = abs(t_crossover_next);
|
||||
|
||||
f32 t_hit = 0;
|
||||
|
||||
Vec2I32 grid_pos = grid_p0;
|
||||
|
||||
b32 stepped_x = 0;
|
||||
b32 stepped_y = 0;
|
||||
|
||||
// TODO: Tune this
|
||||
u32 max_iterations = 32;
|
||||
|
||||
u32 iteration_idx = 0;
|
||||
b32 done = 0;
|
||||
while (!done && iteration_idx < max_iterations)
|
||||
{
|
||||
if (grid_pos.x == grid_p1.x && grid_pos.y == grid_p1.y)
|
||||
{
|
||||
done = 1;
|
||||
}
|
||||
else if (t_crossover_next.x < t_crossover_next.y)
|
||||
{
|
||||
grid_pos.x += grid_step_dir.x;
|
||||
t_hit = t_crossover_next.x - t_delta.x;
|
||||
t_crossover_next.x += t_delta.x;
|
||||
stepped_x = 1;
|
||||
stepped_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
grid_pos.y += grid_step_dir.y;
|
||||
t_hit = t_crossover_next.y - t_delta.y;
|
||||
t_crossover_next.y += t_delta.y;
|
||||
stepped_x = 0;
|
||||
stepped_y = 1;
|
||||
}
|
||||
|
||||
if (all(grid_pos >= 0) && all(grid_pos < countof(tiles)))
|
||||
{
|
||||
P_TileKind tile = tiles[grid_pos];
|
||||
if (tile == P_TileKind_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(particle_idx, 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;
|
||||
f32 x = particle.velocity.x;
|
||||
f32 y = particle.velocity.y;
|
||||
f32 c = cos(collision_angle);
|
||||
f32 s = sin(collision_angle);
|
||||
particle.velocity.x = x * c - y * s;
|
||||
particle.velocity.y = x * s + y * c;
|
||||
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 particle
|
||||
//////////////////////////////
|
||||
//- Commit
|
||||
|
||||
// FIXME: Atomic writes
|
||||
// FIXME: Atomic writes
|
||||
|
||||
{
|
||||
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_in_screen = all(screen_pos >= 0) && all(screen_pos < frame.screen_dims);
|
||||
|
||||
Vec4 color = particle.color;
|
||||
color.a *= prev_exists;
|
||||
b32 should_draw = is_in_world && is_in_screen;
|
||||
b32 should_stain = 0;
|
||||
|
||||
// Stain
|
||||
if (is_in_world)
|
||||
// TODO: Remove this
|
||||
Vec4 color = Color_Purple;
|
||||
switch (particle.kind)
|
||||
{
|
||||
b32 should_stain = (
|
||||
AnyBit(particle.flags, V_ParticleFlag_StainTrail) ||
|
||||
(AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0)
|
||||
);
|
||||
|
||||
if (should_stain)
|
||||
case V_ParticleKind_Test:
|
||||
{
|
||||
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;
|
||||
}
|
||||
color = Color_Yellow;
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
// // 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)
|
||||
{
|
||||
b32 should_draw = is_in_world;
|
||||
|
||||
if (should_draw)
|
||||
{
|
||||
cells[cell_pos] = color;
|
||||
}
|
||||
cells[cell_pos] = color;
|
||||
}
|
||||
|
||||
// {
|
||||
// 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_in_screen = 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Prune
|
||||
if (!is_in_world)
|
||||
{
|
||||
particle.kind = V_ParticleKind_None;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.kind = V_ParticleKind_None;
|
||||
}
|
||||
|
||||
particles[particle_idx] = particle;
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,56 +157,39 @@ Struct(V_SharedFrame)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Particle types
|
||||
|
||||
Enum(V_ParticleFlag)
|
||||
// NOTE: Higher particle kinds draw over lower ones
|
||||
Enum(V_ParticleKind)
|
||||
{
|
||||
V_ParticleFlag_None = 0,
|
||||
V_ParticleFlag_PruneWhenStill = (1 << 0),
|
||||
V_ParticleFlag_StainOnPrune = (1 << 1),
|
||||
V_ParticleFlag_StainTrail = (1 << 2),
|
||||
V_ParticleKind_None,
|
||||
|
||||
V_ParticleKind_Blood,
|
||||
V_ParticleKind_Debris,
|
||||
V_ParticleKind_Test,
|
||||
V_ParticleKind_BulletTrail,
|
||||
|
||||
V_ParticleKind_COUNT,
|
||||
};
|
||||
|
||||
Struct(V_Emitter)
|
||||
{
|
||||
V_ParticleFlag flags;
|
||||
V_ParticleKind kind;
|
||||
|
||||
u32 first_particle_seq;
|
||||
u32 count;
|
||||
|
||||
Vec2 start;
|
||||
Vec2 end;
|
||||
|
||||
f32 lifetime;
|
||||
f32 lifetime_spread;
|
||||
|
||||
f32 speed;
|
||||
f32 speed_spread;
|
||||
|
||||
f32 angle;
|
||||
f32 angle_spread;
|
||||
|
||||
f32 velocity_falloff;
|
||||
f32 velocity_falloff_spread;
|
||||
|
||||
Vec4 color_lin;
|
||||
Vec4 color_spread;
|
||||
Rng2 pos;
|
||||
Rng speed;
|
||||
Rng angle;
|
||||
};
|
||||
|
||||
// TODO: Pack this efficiently
|
||||
Struct(V_Particle)
|
||||
{
|
||||
u32 emitter_init_num; // if != 0, then initialize using emitter at index [emitter_init_num - 1]
|
||||
u32 seq;
|
||||
|
||||
V_ParticleFlag flags;
|
||||
|
||||
i32 kind; // If >= 0, then map to V_ParticleKind. Otherwize initialize particle using emitter at index [abs(kind) - 1]
|
||||
f32 life; // How many seconds has this particle been alive for
|
||||
u32 collisions_count;
|
||||
Vec2 pos;
|
||||
Vec2 velocity;
|
||||
|
||||
f32 exists;
|
||||
f32 lifetime;
|
||||
|
||||
f32 velocity_falloff;
|
||||
Vec4 color;
|
||||
};
|
||||
|
||||
#if IsCpu
|
||||
|
||||
Loading…
Reference in New Issue
Block a user