diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 4f1ab701..e63e96f9 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -2190,7 +2190,7 @@ void V_TickForever(WaveLaneCtx *lane) 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); - quad->occluder = V_OccluderKind_Guy; + // quad->occluder = V_OccluderKind_Guy; } //- Push body quad @@ -2560,8 +2560,8 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Push test emitter - if (frame->held_buttons[Button_F]) - // if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F]) + // if (frame->held_buttons[Button_F]) + if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F]) { { V_Emitter emitter = Zi; diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index 34bca99a..103045fa 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -346,8 +346,9 @@ ComputeShader(V_SimParticlesCS, 64) b32 stepped_x = 0; b32 stepped_y = 0; - // u32 max_iterations = 32; + // TODO: Tune this u32 max_iterations = 128; + b32 done = 0; f32 t_diff = 0; for (u32 iteration_idx = 0; iteration_idx < max_iterations && !done; ++iteration_idx) @@ -393,32 +394,45 @@ ComputeShader(V_SimParticlesCS, 64) V_OccluderKind occluder = (V_OccluderKind)occluders[cell_pos]; if (occluder != V_OccluderKind_None) { - collision = 1; - done = 1; + u64 collision_seed = MixU64(V_ParticleCellBasis ^ seed0 ^ particle.cells_count); + f32 rand_collision_angle = Norm16(collision_seed >> 0); + f32 rand_collision_velocity = Norm16(collision_seed >> 16); + f32 rand_collision_penetration = Norm16(collision_seed >> 32); + if (rand_collision_penetration >= desc.pen_rate) { + collision = 1; + done = 1; + { + if (stepped_x) + { + if (!AnyBit(desc.flags, V_ParticleFlag_NoReflect)) + { + particle.velocity.x *= -1; + } + t = saturate(t_hit.x); + } + else if (stepped_y) + { + if (!AnyBit(desc.flags, V_ParticleFlag_NoReflect)) + { + particle.velocity.y *= -1; + } + t = saturate(t_hit.y); + } + { + f32 collision_angle = lerp(-0.05 * Tau, 0.05 * Tau, rand_collision_angle); - if (stepped_x) - { - particle.velocity.x *= -1; - t = saturate(t_hit.x); + f32 collision_velocity_falloff = lerp(50, 100, rand_collision_velocity); + // f32 collision_velocity_falloff = lerp(5000, 10000, rand_collision_velocity); + // f32 collision_velocity_falloff = lerp(500, 10000, rand_collision_velocity); + // f32 collision_velocity_falloff = 0; + + particle.velocity = RotateVec2Angle(particle.velocity, collision_angle); + particle.velocity *= 1.0f - saturate(collision_velocity_falloff * frame.dt); + } } - else if (stepped_y) - { - particle.velocity.y *= -1; - t = saturate(t_hit.y); - } - { - u64 collision_seed = MixU64(V_ParticleCollisionBasis ^ 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; } + } if (AnyBit(desc.flags, V_ParticleFlag_PruneWhenStill)) @@ -434,31 +448,34 @@ ComputeShader(V_SimParticlesCS, 64) particle.stain_accum += 1; } - //- Stain - u32 stains_count = floor(particle.stain_accum); - if (stains_count > 0) + if (!collision) { - InterlockedMax(stain_cells[cell_pos], packed); - InterlockedAdd(stain_densities[cell_pos], stains_count); - drynesses[cell_pos] = 0; - particle.stain_accum -= stains_count; - } - - //- Draw - { - b32 should_draw_ground = !collision && is_visible && AnyBit(desc.flags, V_ParticleFlag_Ground); - b32 should_draw_air = !collision && is_visible && AnyBit(desc.flags, V_ParticleFlag_Air); - - if (should_draw_ground) + //- Stain + u32 stains_count = floor(particle.stain_accum); + if (stains_count > 0) { - InterlockedMax(ground_cells[cell_pos], packed); - InterlockedAdd(ground_densities[cell_pos], 1); + InterlockedMax(stain_cells[cell_pos], packed); + InterlockedAdd(stain_densities[cell_pos], stains_count); + drynesses[cell_pos] = 0; + particle.stain_accum -= stains_count; } - if (should_draw_air) + //- Draw { - InterlockedMax(air_cells[cell_pos], packed); - InterlockedAdd(air_densities[cell_pos], 1); + b32 should_draw_ground = is_visible && AnyBit(desc.flags, V_ParticleFlag_Ground); + b32 should_draw_air = is_visible && AnyBit(desc.flags, V_ParticleFlag_Air); + + 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); + } } } } @@ -467,6 +484,8 @@ ComputeShader(V_SimParticlesCS, 64) done = 1; prune = 1; } + + particle.cells_count += 1; iteration_idx += 1; } } @@ -691,7 +710,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) stain_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, dryness); } } - stain_particle_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains + stain_particle_color.rgb *= 1.0 - (0.30 * tile_is_wall); // Darken wall stains stain_particle_color.rgb *= stain_particle_color.a; } //- Ground diff --git a/src/pp/pp_vis/pp_vis_shared.cg b/src/pp/pp_vis/pp_vis_shared.cg index 029e5371..fd96b32c 100644 --- a/src/pp/pp_vis/pp_vis_shared.cg +++ b/src/pp/pp_vis/pp_vis_shared.cg @@ -11,37 +11,43 @@ V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind) V_ParticleDesc result; { PERSIST Readonly V_ParticleFlag flags[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) flags, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) flags, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 stain_rates[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) stain_rate, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) stain_rate, + V_ParticlesXList(X) + #undef X + }; + PERSIST Readonly f32 pen_rates[V_ParticleKind_COUNT] = { + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) pen_rate, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 r[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) r, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) r, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 g[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) g, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) g, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 b[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) b, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) b, V_ParticlesXList(X) #undef X }; PERSIST Readonly f32 a[V_ParticleKind_COUNT] = { - #define X(name, flags, stain_rate, r, g, b, a) a, + #define X(name, flags, stain_rate, pen_rate, r, g, b, a) a, V_ParticlesXList(X) #undef X }; result.flags = flags[kind]; result.stain_rate = stain_rates[kind]; + result.pen_rate = pen_rates[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 3157b6e4..64bc0452 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -174,60 +174,64 @@ Enum(V_OccluderKind) #define V_ParticleSimBasis 0xb49f2d9e406873b9ull #define V_ParticleColorBasis 0x569aa8341ecc0ea3ull -#define V_ParticleCollisionBasis 0xf60c0cff344b0c5dull +#define V_ParticleCellBasis 0xf60c0cff344b0c5dull #define V_ParticleStainBasis 0x3c64e8226d98d376ull Enum(V_ParticleFlag) { - V_ParticleFlag_None = 0, - V_ParticleFlag_Ground = (1 << 0), - V_ParticleFlag_Air = (1 << 1), - V_ParticleFlag_PruneWhenStill = (1 << 2), - V_ParticleFlag_StainWhenPruned = (1 << 3), + V_ParticleFlag_None = 0, + V_ParticleFlag_Ground = (1 << 0), + V_ParticleFlag_Air = (1 << 1), + V_ParticleFlag_PruneWhenStill = (1 << 2), + V_ParticleFlag_StainWhenPruned = (1 << 3), + V_ParticleFlag_NoReflect = (1 << 4), }; // NOTE: Higher particle enum values take priority over lower ones -#define V_ParticlesXList(X) \ - X( \ - None, \ - V_ParticleFlag_None, \ - 0, \ - 0, 0, 0, 0 \ - ) \ - /* Ground particles */ \ - X( \ - Blood, \ - V_ParticleFlag_Ground | V_ParticleFlag_PruneWhenStill, \ - 500, \ - 0.5, 0.1, 0.1, 1 \ - ) \ - X( \ - Debris, \ - V_ParticleFlag_Ground | V_ParticleFlag_PruneWhenStill | V_ParticleFlag_StainWhenPruned , \ - 0, \ - 1, 0.5, 0, 1 \ - ) \ - /* Air particles */ \ - X( \ - Smoke, \ - V_ParticleFlag_Air, \ - 0, \ - 0.15, 0.15, 0.15, 0.5 \ - ) \ - X( \ - BulletTrail, \ - V_ParticleFlag_Air, \ - 0, \ - 1, 0, 1, 1 \ - ) \ - /* Test particles */ \ - X( \ - Test, \ - V_ParticleFlag_PruneWhenStill, \ - 0, \ - 1, 1, 0, 1 \ - ) \ -/* -------------------------------------------------------------------------------- */ +#define V_ParticlesXList(X) \ + X( \ + /* Name */ None, \ + /* Flags */ V_ParticleFlag_None, \ + /* Stain rate, pen chance */ 0, 0, \ + /* Base color */ 0, 0, 0, 0 \ + ) \ + \ + /* Ground particles */ \ + X( \ + /* Name */ Blood, \ + /* Flags */ V_ParticleFlag_None | V_ParticleFlag_NoReflect, \ + /* Stain rate, pen chance */ 500, 0.25, \ + /* Base color */ 0.5, 0.1, 0.1, 1 \ + ) \ + X( \ + /* Name */ Debris, \ + /* Flags */ V_ParticleFlag_Ground | V_ParticleFlag_PruneWhenStill | V_ParticleFlag_StainWhenPruned, \ + /* Stain rate, pen chance */ 0, 0, \ + /* Base color */ 1, 0.5, 0, 1 \ + ) \ + \ + /* Air particles */ \ + X( \ + /* Name */ Smoke, \ + /* Flags */ V_ParticleFlag_Air, \ + /* Stain rate, pen chance */ 0, 0, \ + /* Base color */ 0.15, 0.15, 0.15, 0.5 \ + ) \ + X( \ + /* Name */ BulletTrail, \ + /* Flags */ V_ParticleFlag_Air, \ + /* Stain rate, pen chance */ 0, 0, \ + /* Base color */ 1, 0, 1, 1 \ + ) \ + \ + /* Test particles */ \ + X( \ + /* Name */ Test, \ + /* Flags */ V_ParticleFlag_PruneWhenStill, \ + /* Stain rate, pen chance */ 0, 0, \ + /* Base color */ 1, 1, 0, 1 \ + ) \ +/* -------------------------------------------------------------------------- */ Enum(V_ParticleKind) { @@ -255,7 +259,7 @@ Struct(V_Particle) i32 kind; // If >= 0, then map to V_ParticleKind. Otherwize initialize particle using emitter at index [abs(kind) - 1] f32 life; f32 stain_accum; - u32 collisions_count; + u32 cells_count; Vec2 pos; Vec2 velocity; }; @@ -264,6 +268,7 @@ Struct(V_ParticleDesc) { V_ParticleFlag flags; f32 stain_rate; + f32 pen_rate; Vec4 color; };