diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 3193ebcf..1125ace6 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -2182,78 +2182,59 @@ 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.kind = V_ParticleKind_BulletTrail; + emitter.count = particles_count; - // // emitter.lifetime = 1; - // // emitter.lifetime_spread = 2; + f32 angle_spread = Tau / 4.0; - // emitter.count = particles_count; + emitter.angle.min = angle - angle_spread / 2; + emitter.angle.max = angle + angle_spread / 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.pos.p0 = start; + emitter.pos.p1 = end; - // emitter.angle = angle; - // // emitter.angle_spread = Tau / 4; - // emitter.angle_spread = Tau / 4; + // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1)); - // emitter.start = start; - // emitter.end = end; + // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 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.speed = 0; - // emitter.speed_spread = 1; - - // // emitter.speed = 1; - // // emitter.speed_spread = 1; - - // // emitter.velocity_falloff = 1; - // // emitter.velocity_falloff_spread = 0; - // } - // V_PushParticles(emitter); - // } - // } - // } + emitter.speed.min = 0; + emitter.speed.max = 1; + } + V_PushParticles(emitter); + } + } + } @@ -2385,7 +2366,7 @@ void V_TickForever(WaveLaneCtx *lane) 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.count = TweakFloat("Emitter count", 1, 0, 100) * (Kibi(32) * frame->dt); + emitter.count = TweakFloat("Emitter count", 1, 0, 100) * (Kibi(1) * frame->dt); V_PushParticles(emitter); } } diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index 2a0755b6..c9e014fa 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -20,7 +20,7 @@ Vec4 V_ColorFromParticle(V_ParticleDesc desc, u32 particle_idx, u32 density) // Apply density { - if (desc.kind == V_ParticleKind_Smoke) + if (desc.layer == V_ParticleLayer_Air) { // f32 t = saturate(density / 10.0); f32 t = smoothstep(-10, 32, density); @@ -297,17 +297,6 @@ ComputeShader(V_SimParticlesCS, 64) 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; - - Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1)); - if (IsInside(cell_pos, P_WorldCellsDims)) - { - particle.origin_occluder = occluders[cell_pos]; - particle.prev_occluder = particle.origin_occluder; - } - else - { - prune = 1; - } } if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT && !prune) @@ -322,17 +311,23 @@ ComputeShader(V_SimParticlesCS, 64) StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits StaticAssert(V_ParticleKind_COUNT <= 0x7F); // particle kind must fit in 7 bits - u32 start_occluder = 0; + if (particle.life == 0) { Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1)); if (IsInside(cell_pos, P_WorldCellsDims)) { - start_occluder = occluders[cell_pos]; - if (particle.life == 0) + u32 occluder = occluders[cell_pos]; + b32 occluder_is_wall = occluder == 0xFFFFFFFF; + if (!(AnyBit(desc.flags, V_ParticleFlag_OnlyCollideWithWalls) && !occluder_is_wall)) { - particle.origin_occluder = start_occluder; + particle.origin_occluder = occluders[cell_pos]; + particle.prev_occluder = particle.origin_occluder; } } + else + { + prune = 1; + } } ////////////////////////////// @@ -341,6 +336,7 @@ ComputeShader(V_SimParticlesCS, 64) b32 collision = 0; // TODO: Clip to avoid unnecessary iterations outside of world bounds + if (!prune) { Vec2 p0 = particle.pos; Vec2 p1 = particle.pos + particle.velocity * frame.dt; @@ -415,11 +411,16 @@ ComputeShader(V_SimParticlesCS, 64) //- Handle collision { u32 occluder = occluders[cell_pos]; + b32 occluder_is_wall = occluder == 0xFFFFFFFF; if (occluder != particle.origin_occluder) { particle.origin_occluder = 0; } - if (occluder != 0 && occluder != particle.origin_occluder) + if ( + occluder != 0 && + !(AnyBit(desc.flags, V_ParticleFlag_OnlyCollideWithWalls) && !occluder_is_wall) && + occluder != particle.origin_occluder + ) { u64 collision_seed = MixU64(V_ParticleCellBasis ^ seed0 ^ particle.cells_count); f32 rand_collision_angle = Norm16(collision_seed >> 0); @@ -481,7 +482,7 @@ ComputeShader(V_SimParticlesCS, 64) } } - if (!collision) + if (!collision && particle.origin_occluder != 0xFFFFFFFF) { u32 stain_count = floor(particle.stain_accum); u32 density = 1 + stain_count; @@ -702,7 +703,8 @@ ComputeShader2D(V_CompositeCS, 8, 8) stain_color = orig_stain; } - Vec4 particle_color = 0; + Vec4 ground_particle_color = 0; + Vec4 air_particle_color = 0; for (V_ParticleLayer layer = (V_ParticleLayer)0; layer < V_ParticleLayer_COUNT; layer += (V_ParticleLayer)1) @@ -718,70 +720,26 @@ ComputeShader2D(V_CompositeCS, 8, 8) u32 particle_idx = packed & ((1 << 24) - 1); Vec4 cell_color = V_ColorFromParticle(desc, particle_idx, density); cell_color.rgb *= cell_color.a; - particle_color = BlendPremul(cell_color, particle_color); + + if (layer == V_ParticleLayer_Ground) + { + ground_particle_color = BlendPremul(cell_color, ground_particle_color); + } + else + { + air_particle_color = BlendPremul(cell_color, air_particle_color); + } } } // Darken wall particles / stains if (tile == P_TileKind_Wall) { - particle_color *= 0.25; + ground_particle_color *= 0.25; + air_particle_color *= 0.25; stain_color *= 0.25; } - - - - // Vec4 stain_particle_color = 0; - // Vec4 ground_particle_color = 0; - // Vec4 air_particle_color = 0; - // { - // //- Stain - // { - // { - // u32 packed = stain_cells[cell_pos]; - // V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F); - // if (particle_kind != V_ParticleKind_None) - // { - // u32 particle_idx = packed & ((1 << 24) - 1); - // u32 density = stain_densities[cell_pos]; - // f32 dryness = drynesses[cell_pos]; - // stain_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, dryness); - // } - // } - // stain_particle_color.rgb *= 1.0 - (0.30 * tile_is_wall); // Darken wall stains - // stain_particle_color.rgb *= stain_particle_color.a; - // } - // //- Ground - // { - // { - // u32 packed = ground_cells[cell_pos]; - // V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F); - // if (particle_kind != V_ParticleKind_None) - // { - // u32 particle_idx = packed & ((1 << 24) - 1); - // u32 density = ground_densities[cell_pos]; - // ground_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, 0); - // } - // } - // ground_particle_color.rgb *= ground_particle_color.a; - // } - // //- Air - // { - // { - // u32 packed = air_cells[cell_pos]; - // V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F); - // if (particle_kind != V_ParticleKind_None) - // { - // u32 particle_idx = packed & ((1 << 24) - 1); - // u32 density = air_densities[cell_pos]; - // air_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, 0); - // } - // } - // air_particle_color.rgb *= air_particle_color.a; - // } - // } - ////////////////////////////// //- Compose world @@ -792,15 +750,16 @@ ComputeShader2D(V_CompositeCS, 8, 8) { world_color = BlendPremul(tile_color, world_color); // Blend ground tile world_color = BlendPremul(stain_color, world_color); // Blend ground stain - world_color = BlendPremul(particle_color, world_color); // Blend ground particle + world_color = BlendPremul(ground_particle_color, world_color); // Blend ground particle } world_color = BlendPremul(albedo_tex_color, world_color); if (tile_is_wall) { world_color = BlendPremul(tile_color, world_color); // Blend wall tile world_color = BlendPremul(stain_color, world_color); // Blend wall stain - world_color = BlendPremul(particle_color, world_color); // Blend wall particle + world_color = BlendPremul(ground_particle_color, world_color); // Blend wall particle } + world_color = BlendPremul(air_particle_color, world_color); // Blend air particle diff --git a/src/pp/pp_vis/pp_vis_shared.cg b/src/pp/pp_vis/pp_vis_shared.cg index 783558f6..875852d1 100644 --- a/src/pp/pp_vis/pp_vis_shared.cg +++ b/src/pp/pp_vis/pp_vis_shared.cg @@ -11,42 +11,47 @@ V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind) V_ParticleDesc result; { PERSIST Readonly V_ParticleFlag flags[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) flags, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) flags, V_ParticlesXList(X) #undef X }; PERSIST Readonly V_ParticleLayer layers[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) layer, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) layer, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 stain_rates[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) stain_rate, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) stain_rate, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 pen_rates[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) pen_rate, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) pen_rate, + V_ParticlesXList(X) + #undef X + }; + PERSIST Readonly f32 lifetimes[V_ParticleKind_COUNT] = { + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) lifetime, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 r[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) r, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) r, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 g[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) g, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) g, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 b[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) b, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) b, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 a[V_ParticleKind_COUNT] = { - #define X(name, flags, layer, stain_rate, pen_rate, r, g, b, a) a, + #define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) a, V_ParticlesXList(X) #undef X }; @@ -55,6 +60,7 @@ V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind) result.layer = layers[kind]; result.stain_rate = stain_rates[kind]; result.pen_rate = pen_rates[kind]; + result.lifetime = lifetimes[kind]; result.color = LinearFromSrgb(VEC4(r[kind], g[kind], b[kind], a[kind])); } return result; diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index 1e0a23e6..c355a522 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -32,6 +32,7 @@ Enum(V_ParticleFlag) V_ParticleFlag_NoPruneWhenStill = (1 << 0), V_ParticleFlag_StainWhenPruned = (1 << 1), V_ParticleFlag_NoReflect = (1 << 2), + V_ParticleFlag_OnlyCollideWithWalls = (1 << 3), }; Enum(V_ParticleLayer) @@ -50,6 +51,7 @@ Enum(V_ParticleLayer) /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Ground, \ /* Stain rate, pen chance */ 30, 0, \ + /* Lifetime */ Inf, \ /* Base color */ 0, 0, 0, 0 \ ) \ \ @@ -59,6 +61,7 @@ Enum(V_ParticleLayer) /* Flags */ V_ParticleFlag_NoReflect | V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Ground, \ /* Stain rate, pen chance */ 100, 0.25, \ + /* Lifetime */ Inf, \ /* Base color */ 0.5, 0.1, 0.1, 0.05 \ ) \ X( \ @@ -66,6 +69,7 @@ Enum(V_ParticleLayer) /* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 30, 0, \ + /* Lifetime */ Inf, \ /* Base color */ 0.5, 0.1, 0.1, 0.8 \ ) \ X( \ @@ -73,23 +77,26 @@ Enum(V_ParticleLayer) /* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ + /* Lifetime */ Inf, \ /* Base color */ 2, 0.5, 0, 1 \ ) \ \ /* Air particles */ \ X( \ /* Name */ Smoke, \ - /* Flags */ V_ParticleFlag_None, \ + /* Flags */ V_ParticleFlag_OnlyCollideWithWalls, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ + /* Lifetime */ Inf, \ /* Base color */ 0.15, 0.15, 0.15, 0.5 \ ) \ X( \ /* Name */ BulletTrail, \ - /* Flags */ V_ParticleFlag_None, \ + /* Flags */ V_ParticleFlag_OnlyCollideWithWalls, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ - /* Base color */ 1, 0, 1, 1 \ + /* Lifetime */ 0.075, \ + /* Base color */ 0.8, 0.6, 0.2, 0.25 \ ) \ \ /* Test particles */ \ @@ -98,6 +105,7 @@ Enum(V_ParticleLayer) /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ + /* Lifetime */ Inf, \ /* Base color */ 1, 1, 0, 1 \ ) \ /* ----------------------------------------------------------------------------------------------------------------------------------- */ @@ -142,6 +150,7 @@ Struct(V_ParticleDesc) V_ParticleLayer layer; f32 stain_rate; f32 pen_rate; + f32 lifetime; Vec4 color; };