automatically split particle emitter uploads
This commit is contained in:
parent
52ecdf378b
commit
d6d3c8915f
@ -3329,7 +3329,7 @@ void G_D12_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame
|
||||
}
|
||||
else
|
||||
{
|
||||
G_D12.free_releases.first = async->free_releases.first;;
|
||||
G_D12.free_releases.first = async->free_releases.first;
|
||||
}
|
||||
G_D12.free_releases.last = async->free_releases.last;
|
||||
async->free_releases.first = 0;
|
||||
|
||||
@ -319,7 +319,7 @@ Vec2 S_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal)
|
||||
return result;
|
||||
}
|
||||
|
||||
S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1, Vec2 sweep)
|
||||
S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1)
|
||||
{
|
||||
S_CollisionResult result = Zi;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
@ -496,9 +496,8 @@ S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1, Ve
|
||||
//////////////////////////////
|
||||
//- EPA
|
||||
|
||||
// Find dir from origin to closest edge
|
||||
Vec2 normal = Zi;
|
||||
Vec2 sweep_dir = NormVec2(sweep);
|
||||
b32 is_sweeping = !IsVec2Zero(sweep_dir);
|
||||
S_MenkowskiSimplex closest_feature = Zi;
|
||||
{
|
||||
S_MenkowskiPoint *proto = 0;
|
||||
@ -522,61 +521,30 @@ S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1, Ve
|
||||
{
|
||||
++epa_iterations;
|
||||
|
||||
// Find dir from origin to closest edge
|
||||
// FIXME: Winding order of ps & pe index
|
||||
S_MenkowskiPoint closest_a = Zi;
|
||||
S_MenkowskiPoint closest_b = Zi;
|
||||
u32 closest_b_index = 0;
|
||||
{
|
||||
if (is_sweeping)
|
||||
// Find edge segment on prototype closest to the origin
|
||||
f32 closest_len_sq = Inf;
|
||||
for (u32 i = 0; i < proto_count; ++i)
|
||||
{
|
||||
// Find edge segment on prototype furthest along the sweep direction
|
||||
// FIXME: This is not very stable at the moment, needs refining
|
||||
for (u32 i = 0; i < proto_count; ++i)
|
||||
u32 a_index = i;
|
||||
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
||||
S_MenkowskiPoint a = proto[a_index];
|
||||
S_MenkowskiPoint b = proto[b_index];
|
||||
Vec2 vab = SubVec2(b.p, a.p);
|
||||
Vec2 vao = NegVec2(a.p);
|
||||
f32 proj_ratio = ClampF32(DotVec2(vao, vab) / Vec2LenSq(vab), 0, 1);
|
||||
Vec2 proj = AddVec2(a.p, MulVec2(vab, proj_ratio));
|
||||
f32 proj_len_sq = Vec2LenSq(proj);
|
||||
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq)
|
||||
{
|
||||
u32 a_index = i;
|
||||
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
||||
S_MenkowskiPoint a = proto[a_index];
|
||||
S_MenkowskiPoint b = proto[b_index];
|
||||
Vec2 vab = SubVec2(b.p, a.p);
|
||||
if (WedgeVec2(vab, sweep_dir) * winding > 0)
|
||||
{
|
||||
f32 wedge_a = WedgeVec2(sweep_dir, a.p);
|
||||
f32 wedge_b = WedgeVec2(sweep_dir, b.p);
|
||||
i32 wedge_sign_a = (wedge_a >= 0) - (wedge_a < 0);
|
||||
i32 wedge_sign_b = (wedge_b >= 0) - (wedge_b < 0);
|
||||
if (wedge_sign_a != wedge_sign_b)
|
||||
{
|
||||
closest_a = a;
|
||||
closest_b = b;
|
||||
closest_b_index = b_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find edge segment on prototype closest to the origin
|
||||
f32 closest_len_sq = Inf;
|
||||
for (u32 i = 0; i < proto_count; ++i)
|
||||
{
|
||||
u32 a_index = i;
|
||||
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
||||
S_MenkowskiPoint a = proto[a_index];
|
||||
S_MenkowskiPoint b = proto[b_index];
|
||||
Vec2 vab = SubVec2(b.p, a.p);
|
||||
Vec2 vao = NegVec2(a.p);
|
||||
f32 proj_ratio = ClampF32(DotVec2(vao, vab) / Vec2LenSq(vab), 0, 1);
|
||||
Vec2 proj = AddVec2(a.p, MulVec2(vab, proj_ratio));
|
||||
f32 proj_len_sq = Vec2LenSq(proj);
|
||||
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq)
|
||||
{
|
||||
closest_a = a;
|
||||
closest_b = b;
|
||||
closest_b_index = b_index;
|
||||
closest_len_sq = proj_len_sq;
|
||||
}
|
||||
closest_a = a;
|
||||
closest_b = b;
|
||||
closest_b_index = b_index;
|
||||
closest_len_sq = proj_len_sq;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1090,9 +1058,16 @@ S_RaycastResult S_RaycastShape(S_Shape shape, Vec2 ray_start, Vec2 ray_dir)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Vec2 S_EdgePointFromShape(S_Shape shape, Vec2 dir)
|
||||
{
|
||||
Vec2 result = shape.centroid;
|
||||
S_RaycastResult raycast = S_RaycastShape(shape, shape.centroid, NegVec2(dir));
|
||||
if (raycast.is_intersecting)
|
||||
{
|
||||
result = raycast.p;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Lookup helpers
|
||||
@ -1627,18 +1602,56 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
{
|
||||
if (firer->fire_held)
|
||||
{
|
||||
Xform firer_xf = firer->xf;
|
||||
S_Shape firer_world_shape = S_MulXformShape(firer_xf, firer->local_shape);
|
||||
// i64 fire_delta_ns = world->time_ns - firer->last_fire_ns;
|
||||
|
||||
S_Ent *bullet = S_PushTempEnt(frame_arena, &bullets_to_spawn);
|
||||
bullet->is_bullet = 1;
|
||||
bullet->key = S_RandKey();
|
||||
// i64 single_bullet_delta_ns = NsFromSeconds(1) / firer->fire_rate;
|
||||
|
||||
f32 speed = 40 * sim_dt;
|
||||
// i64 tick_bullets_count = sim_dt * firer->fire_rate;
|
||||
|
||||
bullet->bullet_start = firer_world_shape.centroid;
|
||||
bullet->bullet_end = AddVec2(bullet->bullet_start, MulVec2(NormVec2(firer->look), speed));
|
||||
bullet->bullet_firer = firer->key;
|
||||
f32 fire_rate = 50;
|
||||
f32 bullets_per_fire = 3;
|
||||
f32 spread = Tau * 0.05;
|
||||
// f32 spread = Tau * 0.01;
|
||||
f32 tweak_speed = TweakFloat("Bullet speed", 100, 1, 100);
|
||||
|
||||
b32 can_fire = (firer->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= world->time_ns;
|
||||
if (can_fire)
|
||||
{
|
||||
i64 tick_bullets_count = bullets_per_fire;
|
||||
if (tick_bullets_count > 0)
|
||||
{
|
||||
Xform firer_xf = firer->xf;
|
||||
S_Shape firer_world_shape = S_MulXformShape(firer_xf, firer->local_shape);
|
||||
|
||||
Vec2 pos = S_EdgePointFromShape(firer_world_shape, firer->look);
|
||||
|
||||
for (i64 bullet_idx = 0; bullet_idx < tick_bullets_count; ++bullet_idx)
|
||||
{
|
||||
S_Ent *bullet = S_PushTempEnt(frame_arena, &bullets_to_spawn);
|
||||
bullet->is_bullet = 1;
|
||||
bullet->key = S_RandKey();
|
||||
|
||||
|
||||
// FIXME: Remove this
|
||||
PERSIST RandState rand = Zi;
|
||||
f32 rand_speed = RandF64FromState(&rand, -0.5, 0.5);
|
||||
f32 rand_angle = RandF64FromState(&rand, -0.5, 0.5);
|
||||
|
||||
f32 speed = tweak_speed * sim_dt;
|
||||
f32 angle = AngleFromVec2(firer->look);
|
||||
|
||||
speed += (speed * 0.5) * rand_speed;
|
||||
angle += rand_angle * spread;
|
||||
|
||||
Vec2 dir = Vec2FromAngle(angle);
|
||||
|
||||
bullet->bullet_start = pos;
|
||||
bullet->bullet_end = AddVec2(bullet->bullet_start, MulVec2(dir, speed));
|
||||
bullet->bullet_firer = firer->key;
|
||||
}
|
||||
}
|
||||
firer->last_fire_ns = world->time_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
S_SpawnEntsFromList(world_arena, world, bullets_to_spawn);
|
||||
@ -1673,19 +1686,22 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
Xform victim_xf = victim->xf;
|
||||
S_Shape victim_world_shape = S_MulXformShape(victim_xf, victim->local_shape);
|
||||
|
||||
S_RaycastResult raycast = S_RaycastShape(victim_world_shape, ray_start, ray_dir);
|
||||
if (raycast.is_intersecting)
|
||||
S_RaycastResult entrance_raycast = S_RaycastShape(victim_world_shape, ray_start, ray_dir);
|
||||
Vec2 entrance = entrance_raycast.p;
|
||||
if (entrance_raycast.is_intersecting)
|
||||
{
|
||||
Vec2 hit = raycast.p;
|
||||
Vec2 dir_to_hit = SubVec2(hit, ray_start);
|
||||
if (DotVec2(ray_dir, dir_to_hit) <= 0 || Vec2LenSq(dir_to_hit) <= Vec2LenSq(ray_dir))
|
||||
S_RaycastResult exit_raycast = S_RaycastShape(victim_world_shape, ray_start, NegVec2(ray_dir));
|
||||
Vec2 exit = exit_raycast.p;
|
||||
f32 da = DotVec2(ray_dir, SubVec2(entrance, ray_start));
|
||||
f32 db = DotVec2(ray_dir, SubVec2(exit, ray_start));
|
||||
if (db > 0 && (da <= Vec2LenSq(ray_dir) || da <= 0))
|
||||
{
|
||||
f32 len_sq = Vec2LenSq(SubVec2(raycast.p, ray_start));
|
||||
f32 len_sq = Vec2LenSq(SubVec2(entrance_raycast.p, ray_start));
|
||||
if (len_sq < closest_len_sq)
|
||||
{
|
||||
closest_len_sq = len_sq;
|
||||
closest_victim = victim;
|
||||
victim_raycast = raycast;
|
||||
victim_raycast = entrance_raycast;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1839,46 +1855,6 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Raycast testing
|
||||
|
||||
// FIXME: Remove this
|
||||
|
||||
|
||||
{
|
||||
S_Ent *player = &S_NilEnt;
|
||||
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent))
|
||||
{
|
||||
if (ent->is_player)
|
||||
{
|
||||
player = ent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PERSIST Vec2 start = { 5, 1 };
|
||||
PERSIST Vec2 end = { 4, -1 };
|
||||
|
||||
Vec2 dir = SubVec2(end, start);
|
||||
|
||||
Xform xf = player->xf;
|
||||
S_Shape world_shape = S_MulXformShape(xf, player->local_shape);
|
||||
|
||||
S_RaycastResult raycast = S_RaycastShape(world_shape, start, dir);
|
||||
|
||||
S_DebugDrawPoint(raycast.p, Color_Blue);
|
||||
S_DebugDrawLine(raycast.p, AddVec2(raycast.p, raycast.normal), Color_White);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Debug draw entities
|
||||
|
||||
|
||||
@ -72,6 +72,8 @@ Struct(S_Ent)
|
||||
Vec2 look;
|
||||
f32 fire_held;
|
||||
|
||||
// TODO: Remove this (weapon testing)
|
||||
i64 last_fire_ns;
|
||||
b32 has_weapon;
|
||||
|
||||
S_Key bullet_firer;
|
||||
@ -399,9 +401,11 @@ S_MenkowskiPoint S_MenkowskiPointFromShapes(S_Shape shape0, S_Shape shape1, Vec2
|
||||
S_ClippedLine S_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal);
|
||||
Vec2 S_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal);
|
||||
|
||||
S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1, Vec2 sweep);
|
||||
S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1);
|
||||
S_RaycastResult S_RaycastShape(S_Shape shape, Vec2 ray_start, Vec2 ray_dir);
|
||||
|
||||
Vec2 S_EdgePointFromShape(S_Shape shape, Vec2 dir);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Lookup helpers
|
||||
|
||||
|
||||
@ -72,18 +72,31 @@ String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey)
|
||||
return StringFromList(arena, parts, Lit(" + "));
|
||||
}
|
||||
|
||||
V_Emitter *V_PushEmitter(u32 particle_count)
|
||||
void V_PushParticles(V_Emitter src)
|
||||
{
|
||||
particle_count = MinU32(particle_count, Mebi(1));
|
||||
V_Frame *frame = V_CurrentFrame();
|
||||
V_EmitterNode *en = PushStruct(frame->arena, V_EmitterNode);
|
||||
SllQueuePush(frame->first_emitter_node, frame->last_emitter_node, en);
|
||||
frame->emitters_count += 1;
|
||||
V_Emitter *emitter = &en->emitter;
|
||||
emitter->count = particle_count;
|
||||
emitter->first_particle_seq = V.particle_seq;
|
||||
V.particle_seq += emitter->count;
|
||||
return emitter;
|
||||
i64 split_threshold = 256; // Arbitrary threshold. Lower counts cause less shader work but more cpu -> gpu upload bandwidth.
|
||||
src.count = MinU64(src.count, V_MaxParticles);
|
||||
if (src.seed == 0)
|
||||
{
|
||||
src.seed = RandU64FromState(&frame->rand);
|
||||
}
|
||||
i64 remaining_particles = src.count;
|
||||
while (remaining_particles > 0)
|
||||
{
|
||||
V_Emitter *emitter = 0;
|
||||
{
|
||||
V_EmitterNode *en = PushStruct(frame->arena, V_EmitterNode);
|
||||
SllQueuePush(frame->first_emitter_node, frame->last_emitter_node, en);
|
||||
frame->emitters_count += 1;
|
||||
emitter = &en->emitter;
|
||||
}
|
||||
*emitter = src;
|
||||
emitter->count = MinI64(remaining_particles, split_threshold);
|
||||
emitter->first_particle_seq = V.particle_seq;
|
||||
V.particle_seq += emitter->count;
|
||||
remaining_particles -= split_threshold;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -335,11 +348,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Vec2I32 tiles_dims = VEC2I32(S_TilesPitch, S_TilesPitch);
|
||||
Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * S_WorldPitch, V_CellsPerMeter * S_WorldPitch);
|
||||
|
||||
// u32 max_particles = Kibi(128);
|
||||
// u32 max_particles = Mebi(1);
|
||||
u32 max_particles = Mebi(2);
|
||||
// u32 max_particles = Mebi(16);
|
||||
|
||||
// Init gpu state
|
||||
G_ResourceHandle gpu_state = Zi;
|
||||
G_ResourceHandle gpu_tiles = Zi;
|
||||
@ -380,7 +388,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
gpu_particles = G_PushBuffer(
|
||||
gpu_perm, cl,
|
||||
V_Particle,
|
||||
max_particles,
|
||||
V_MaxParticles,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite
|
||||
);
|
||||
gpu_particles_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles, V_Particle);
|
||||
@ -986,7 +994,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent))
|
||||
{
|
||||
S_Shape ent_shape = S_MulXformShape(ent->xf, ent->local_shape);
|
||||
b32 is_hovered = S_CollisionResultFromShapes(ent_shape, cursor_shape, VEC2(0, 0)).collision_points_count > 0;
|
||||
b32 is_hovered = S_CollisionResultFromShapes(ent_shape, cursor_shape).collision_points_count > 0;
|
||||
if (is_hovered)
|
||||
{
|
||||
hovered_ent = ent;
|
||||
@ -2648,39 +2656,46 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
|
||||
// f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
|
||||
|
||||
V_Emitter *emitter = V_PushEmitter(particles_count);
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
// emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
// emitter.flags |= V_ParticleFlag_StainTrail;
|
||||
|
||||
// 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->lifetime = 0.15;
|
||||
// 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;
|
||||
// emitter.velocity_falloff = 1;
|
||||
// emitter.velocity_falloff_spread = 0;
|
||||
}
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
|
||||
|
||||
@ -2814,35 +2829,40 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100);
|
||||
f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||
|
||||
V_Emitter *emitter = V_PushEmitter(count);
|
||||
emitter->flags = flags;
|
||||
V_Emitter emitter = Zi;
|
||||
{
|
||||
emitter.count = count;
|
||||
emitter.flags = flags;
|
||||
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
|
||||
emitter->start = hit_entry;
|
||||
emitter->end = emitter->start;
|
||||
emitter.start = hit_entry;
|
||||
emitter.end = emitter.start;
|
||||
|
||||
emitter->speed = speed;
|
||||
emitter->speed_spread = speed * 2;
|
||||
emitter.speed = speed;
|
||||
emitter.speed_spread = speed * 2;
|
||||
|
||||
emitter->velocity_falloff = falloff;
|
||||
emitter->velocity_falloff_spread = falloff * 1.5;
|
||||
emitter.velocity_falloff = falloff;
|
||||
emitter.velocity_falloff_spread = falloff * 1.5;
|
||||
|
||||
emitter->angle = AngleFromVec2(dir);
|
||||
// emitter->angle_spread = Tau / 4;
|
||||
emitter->angle_spread = angle_spread;
|
||||
// emitter->angle_spread = Tau / 32;
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau / 4;
|
||||
emitter.angle_spread = angle_spread;
|
||||
// emitter.angle_spread = Tau / 32;
|
||||
|
||||
emitter->color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
emitter->color_spread = VEC4(0.1, 0, 0, 0);
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
|
||||
// emitter->color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
emitter.color_spread = VEC4(0.1, 0, 0, 0);
|
||||
|
||||
emitter->seed = RandU64FromState(&frame->rand);
|
||||
// emitter->angle_spread = 1;
|
||||
// emitter->angle_spread = 0.5;
|
||||
// emitter->angle_spread = Tau;
|
||||
// emitter.color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
|
||||
// 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);
|
||||
@ -2957,24 +2977,26 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
if (frame->held_buttons[Button_F])
|
||||
{
|
||||
V_Emitter *emitter = V_PushEmitter(25);;
|
||||
V_Emitter emitter = Zi;
|
||||
|
||||
Vec2 dir = frame->look;
|
||||
emitter->start = frame->world_cursor;
|
||||
emitter->end = emitter->start;
|
||||
emitter->angle = AngleFromVec2(dir);
|
||||
emitter.start = frame->world_cursor;
|
||||
emitter.end = emitter.start;
|
||||
emitter.angle = AngleFromVec2(dir);
|
||||
|
||||
// emitter->count = 100;
|
||||
emitter->speed = 10;
|
||||
emitter.count = 128;
|
||||
// emitter.count = 100;
|
||||
emitter.speed = 10;
|
||||
|
||||
emitter->color_lin = LinearFromSrgb(Color_Yellow);
|
||||
emitter.color_lin = LinearFromSrgb(Color_Yellow);
|
||||
|
||||
emitter->seed = RandU64FromState(&frame->rand);
|
||||
emitter->speed_spread = 1;
|
||||
// emitter->angle_spread = 1;
|
||||
// emitter->angle_spread = 0.5;
|
||||
emitter->angle_spread = Tau / 4;
|
||||
// emitter->angle_spread = Tau;
|
||||
emitter.speed_spread = 1;
|
||||
// emitter.angle_spread = 1;
|
||||
// emitter.angle_spread = 0.5;
|
||||
emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle_spread = Tau;
|
||||
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -3064,8 +3086,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
case S_DebugDrawKind_Shape:
|
||||
{
|
||||
S_Shape ui_shape = S_MulXformShape(frame->xf.world_to_ui, desc->shape);
|
||||
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
||||
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_None);
|
||||
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
||||
V_DrawShape(ui_shape, color, detail, V_DrawFlag_None);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@ -3144,7 +3166,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
params.emitters_count = frame->emitters_count;
|
||||
params.emitters = gpu_emitters_ref;
|
||||
|
||||
params.max_particles = max_particles;
|
||||
params.particles = gpu_particles_ref;
|
||||
|
||||
params.should_clear_stains = should_clear_particles;
|
||||
@ -3185,7 +3206,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// Clear particles
|
||||
if (should_clear_particles)
|
||||
{
|
||||
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(max_particles));
|
||||
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_MaxParticles));
|
||||
}
|
||||
|
||||
// Discard render target
|
||||
@ -3205,7 +3226,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
G_DumbMemorySync(frame->cl, gpu_particles);
|
||||
|
||||
// Simulate particles
|
||||
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(max_particles));
|
||||
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(V_MaxParticles));
|
||||
|
||||
// Barrier since stains were written
|
||||
G_DumbGlobalMemorySync(frame->cl);
|
||||
|
||||
@ -315,7 +315,7 @@ V_Frame *V_LastFrame(void);
|
||||
V_Cmd *V_PushVisCmd(String name);
|
||||
S_Cmd *V_PushSimCmd(S_CmdKind kind);
|
||||
String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey);
|
||||
V_Emitter *V_PushEmitter(u32 particle_count);
|
||||
void V_PushParticles(V_Emitter src);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Draw helpers
|
||||
|
||||
@ -24,7 +24,7 @@ ComputeShader(V_ClearParticlesCS, 64)
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < params.max_particles)
|
||||
if (particle_idx < V_MaxParticles)
|
||||
{
|
||||
particles[particle_idx].exists = 0;
|
||||
}
|
||||
@ -299,7 +299,7 @@ ComputeShader(V_EmitParticlesCS, 64)
|
||||
for (u32 i = 0; i < emitter.count; ++i)
|
||||
{
|
||||
u32 particle_seq = emitter.first_particle_seq + i;
|
||||
u32 particle_idx = particle_seq % params.max_particles;
|
||||
u32 particle_idx = particle_seq % (u32)V_MaxParticles;
|
||||
particles[particle_idx].exists = 1;
|
||||
particles[particle_idx].emitter_init_num = emitter_idx + 1;
|
||||
particles[particle_idx].seq = particle_seq;
|
||||
@ -318,7 +318,7 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < params.max_particles)
|
||||
if (particle_idx < V_MaxParticles)
|
||||
{
|
||||
V_Particle particle = particles[particle_idx];
|
||||
if (particle.exists > 0)
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
#define V_CellsPerMeter 40.0
|
||||
#define V_CellsPerSqMeter (V_CellsPerMeter * V_CellsPerMeter)
|
||||
|
||||
// #define V_MaxParticles Kibi(128)
|
||||
// #define V_MaxParticles Mebi(1)
|
||||
#define V_MaxParticles Mebi(2)
|
||||
// #define V_MaxParticles Mebi(16)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Constant types
|
||||
|
||||
@ -73,7 +78,6 @@ Struct(V_GpuParams)
|
||||
u32 emitters_count;
|
||||
G_StructuredBufferRef emitters;
|
||||
|
||||
u32 max_particles;
|
||||
G_RWStructuredBufferRef particles;
|
||||
|
||||
b32 should_clear_stains;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user