smoke particle testing
This commit is contained in:
parent
d9228b78a3
commit
463e142727
@ -551,7 +551,7 @@ Vec2 CeilVec2(Vec2 a)
|
||||
return VEC2(CeilF32(a.x), CeilF32(a.y));
|
||||
}
|
||||
|
||||
//- Angle
|
||||
//- Rotation
|
||||
|
||||
// Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise
|
||||
i32 WindingFromVec2(Vec2 a, Vec2 b)
|
||||
|
||||
@ -384,7 +384,7 @@ Vec2 RoundVec2(Vec2 a);
|
||||
Vec2 FloorVec2(Vec2 a);
|
||||
Vec2 CeilVec2(Vec2 a);
|
||||
|
||||
//- Angle
|
||||
//- Rotation
|
||||
i32 WindingFromVec2(Vec2 a, Vec2 b);
|
||||
Vec2 RotateVec2Angle(Vec2 v, f32 a);
|
||||
Vec2 RotateVec2(Vec2 a, Vec2 b);
|
||||
|
||||
@ -138,12 +138,33 @@ Inline f64 Norm53(u64 v)
|
||||
#define MatchFloor(a, b) all(floor(a) == floor(b))
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Derivative helpers
|
||||
//~ Rotation
|
||||
|
||||
Inline Vec2 RotateVec2Angle(Vec2 v, f32 a)
|
||||
{
|
||||
f32 c = cos(a);
|
||||
f32 s = sin(a);
|
||||
return Vec2(v.x * c - v.y * s, v.x * s + v.y * c);
|
||||
}
|
||||
|
||||
Inline Vec2 RotateVec2(Vec2 a, Vec2 b)
|
||||
{
|
||||
return Vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
|
||||
}
|
||||
|
||||
Inline Vec2 InvertRot(Vec2 r)
|
||||
{
|
||||
r.y = -r.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Derivatives
|
||||
|
||||
#define fwidth_fine(v) (abs(ddx_fine((v))) + abs(ddy_fine((v))))
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Color helpers
|
||||
//~ Colors
|
||||
|
||||
Inline Vec4 Vec4FromU32(u32 v)
|
||||
{
|
||||
|
||||
@ -533,9 +533,11 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
|
||||
//- Dxc
|
||||
{
|
||||
PushStringToList(perm, &cp.flags_dxc, Lit("-O3"));
|
||||
PushStringToList(perm, &cp.flags_dxc, Lit("-Zi -Qembed_debug"));
|
||||
PushStringToList(perm, &cp.flags_dxc, Lit("-HV 202x")); // 202x makes numeric literals less weird
|
||||
|
||||
// TODO: Export debug info separately for release builds
|
||||
PushStringToList(perm, &cp.flags_dxc, Lit("-Zi -Qembed_debug"));
|
||||
|
||||
// Enable warnings
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wall"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Werror"));
|
||||
@ -544,6 +546,7 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
|
||||
// Disable warnings
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wno-unused-variable"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wno-conversion"));
|
||||
PushStringToList(perm, &cp.warnings_dxc, Lit("-Wno-switch"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
||||
}
|
||||
if (ent->is_weapon)
|
||||
{
|
||||
result.len += PushString(arena, Lit(" is_weapon\n")).len;
|
||||
result.len += PushString(arena, Lit(" weapon\n")).len;
|
||||
}
|
||||
if (ent->is_bullet)
|
||||
{
|
||||
|
||||
@ -392,17 +392,21 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// Init gpu state
|
||||
G_ResourceHandle gpu_tiles_res = Zi;
|
||||
G_ResourceHandle gpu_particles_res = Zi;
|
||||
G_ResourceHandle gpu_cells_res = Zi;
|
||||
G_ResourceHandle gpu_stains_res = Zi;
|
||||
G_ResourceHandle gpu_ground_cells_res = Zi;
|
||||
G_ResourceHandle gpu_air_cells_res = Zi;
|
||||
G_ResourceHandle gpu_ground_densities_res = Zi;
|
||||
G_ResourceHandle gpu_air_densities_res = Zi;
|
||||
G_ResourceHandle gpu_drynesses_res = Zi;
|
||||
G_ResourceHandle gpu_densities_res = Zi;
|
||||
|
||||
G_Texture2DRef gpu_tiles = Zi;
|
||||
G_RWStructuredBufferRef gpu_particles = Zi;
|
||||
G_RWTexture2DRef gpu_cells = Zi;
|
||||
G_RWTexture2DRef gpu_stains = Zi;
|
||||
G_RWTexture2DRef gpu_ground_cells = Zi;
|
||||
G_RWTexture2DRef gpu_air_cells = Zi;
|
||||
G_RWTexture2DRef gpu_ground_densities = Zi;
|
||||
G_RWTexture2DRef gpu_air_densities = Zi;
|
||||
G_RWTexture2DRef gpu_drynesses = Zi;
|
||||
G_RWTexture2DRef gpu_densities = Zi;
|
||||
{
|
||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||
{
|
||||
@ -429,29 +433,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_particles = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles_res, V_Particle);
|
||||
}
|
||||
// Init cells texture
|
||||
{
|
||||
gpu_cells_res = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
G_Format_R32_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
// G_Format_R10G10B10A2_Unorm,
|
||||
// G_Format_R16G16B16A16_Float,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||
.name = Lit("Cells")
|
||||
);
|
||||
gpu_cells = G_PushRWTexture2DRef(gpu_perm, gpu_cells_res);
|
||||
}
|
||||
// Init stain texture
|
||||
// Init stains texture
|
||||
{
|
||||
gpu_stains_res = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
// G_Format_R10G10B10A2_Unorm,
|
||||
G_Format_R16G16B16A16_Float,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
@ -460,14 +445,58 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
|
||||
}
|
||||
// Init ground cells texture
|
||||
{
|
||||
gpu_ground_cells_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("Ground cells")
|
||||
);
|
||||
gpu_ground_cells = G_PushRWTexture2DRef(gpu_perm, gpu_ground_cells_res);
|
||||
}
|
||||
// Init air cells texture
|
||||
{
|
||||
gpu_air_cells_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("Air cells")
|
||||
);
|
||||
gpu_air_cells = G_PushRWTexture2DRef(gpu_perm, gpu_air_cells_res);
|
||||
}
|
||||
// Init ground densities texture
|
||||
{
|
||||
gpu_ground_densities_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("Ground densities")
|
||||
);
|
||||
gpu_ground_densities = G_PushRWTexture2DRef(gpu_perm, gpu_ground_densities_res);
|
||||
}
|
||||
// Init air densities texture
|
||||
{
|
||||
gpu_air_densities_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("Air densities")
|
||||
);
|
||||
gpu_air_densities = G_PushRWTexture2DRef(gpu_perm, gpu_air_densities_res);
|
||||
}
|
||||
// Init drynesses texture
|
||||
{
|
||||
gpu_drynesses_res = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
// G_Format_R10G10B10A2_Unorm,
|
||||
// G_Format_R16_Float,
|
||||
G_Format_R32_Float,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
@ -476,22 +505,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
|
||||
}
|
||||
// Init densities texture
|
||||
{
|
||||
gpu_densities_res = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
// G_Format_R10G10B10A2_Unorm,
|
||||
// G_Format_R16_Float,
|
||||
G_Format_R32_Uint,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||
.name = Lit("Densities")
|
||||
);
|
||||
gpu_densities = G_PushRWTexture2DRef(gpu_perm, gpu_densities_res);
|
||||
}
|
||||
}
|
||||
G_CommitCommandList(cl);
|
||||
}
|
||||
@ -610,10 +623,12 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->pt_clamp_sampler = G_BasicPointClampSampler();
|
||||
frame->pt_wrap_sampler = G_BasicPointWrapSampler();
|
||||
frame->particles = gpu_particles;
|
||||
frame->cells = gpu_cells;
|
||||
frame->stains = gpu_stains;
|
||||
frame->ground_cells = gpu_ground_cells;
|
||||
frame->air_cells = gpu_air_cells;
|
||||
frame->ground_densities = gpu_ground_densities;
|
||||
frame->air_densities = gpu_air_densities;
|
||||
frame->drynesses = gpu_drynesses;
|
||||
frame->densities = gpu_densities;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -2523,43 +2538,84 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
//////////////////////////////
|
||||
//- Push test emitter
|
||||
|
||||
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])
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
// Debris
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
|
||||
emitter.kind = V_ParticleKind_Test;
|
||||
emitter.kind = V_ParticleKind_Debris;
|
||||
|
||||
f32 angle = AngleFromVec2(frame->look);
|
||||
// f32 angle = 0;
|
||||
// f32 angle_spread = Tau * 0.25;
|
||||
f32 angle_spread = Tau;
|
||||
// f32 angle_spread = 0;
|
||||
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;
|
||||
// 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.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.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 = 32;
|
||||
// emitter.count = 1;
|
||||
// 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);
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
|
||||
// Smoke
|
||||
{
|
||||
V_Emitter emitter = Zi;
|
||||
|
||||
emitter.kind = V_ParticleKind_Smoke;
|
||||
|
||||
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 = 50;
|
||||
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 = 32;
|
||||
// emitter.count = 1;
|
||||
|
||||
V_PushParticles(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4816,6 +4872,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
if (frame->should_clear_particles)
|
||||
{
|
||||
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
|
||||
V.particle_seq = 0;
|
||||
}
|
||||
|
||||
// Prepare screen RT
|
||||
|
||||
@ -36,18 +36,22 @@ ComputeShader2D(V_PrepareShadeCS, 8, 8)
|
||||
ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
||||
{
|
||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||
RWTexture2D<u32> cells = G_Dereference<u32>(frame.cells);
|
||||
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> densities = G_Dereference<u32>(frame.densities);
|
||||
|
||||
Vec2 cells_pos = SV_DispatchThreadID + 0.5;
|
||||
if (all(cells_pos < countof(cells)))
|
||||
if (all(cells_pos < countof(air_cells)))
|
||||
{
|
||||
// Clear cell
|
||||
cells[cells_pos] = 0;
|
||||
// Clear cells
|
||||
ground_cells[cells_pos] = 0;
|
||||
air_cells[cells_pos] = 0;
|
||||
|
||||
// Clear density
|
||||
densities[cells_pos] = 0;
|
||||
// Clear densities
|
||||
ground_densities[cells_pos] = 0;
|
||||
air_densities[cells_pos] = 0;
|
||||
|
||||
// Increase dryness
|
||||
// TODO: Use simulation dt
|
||||
@ -160,10 +164,12 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
{
|
||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
||||
RWTexture2D<u32> cells = G_Dereference<u32>(frame.cells);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||
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> densities = G_Dereference<u32>(frame.densities);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
@ -176,11 +182,11 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
|
||||
if (particle.kind != 0)
|
||||
{
|
||||
u64 seed = MixU64(P_ParticleSimBasis ^ particle_idx);
|
||||
f32 rand_offset = Norm16(seed >> 0);
|
||||
f32 rand_angle = Norm16(seed >> 16);
|
||||
f32 rand_speed = Norm16(seed >> 32);
|
||||
f32 rand_falloff = Norm16(seed >> 48);
|
||||
u64 seed0 = MixU64(P_ParticleSimBasis ^ 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);
|
||||
|
||||
//////////////////////////////
|
||||
//- Init
|
||||
@ -201,6 +207,26 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
|
||||
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
|
||||
|
||||
@ -288,18 +314,13 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
particle.velocity.y *= -1;
|
||||
}
|
||||
{
|
||||
u64 collision_seed = MixU64s(seed, particle.collisions_count);
|
||||
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;
|
||||
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 = RotateVec2Angle(particle.velocity, collision_angle);
|
||||
particle.velocity *= 1.0f - collision_velocity_falloff;
|
||||
}
|
||||
++particle.collisions_count;
|
||||
@ -317,12 +338,21 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
//- Commit
|
||||
|
||||
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);
|
||||
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 should_draw = is_in_world && is_in_screen;
|
||||
b32 should_stain = 0;
|
||||
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;
|
||||
b32 is_ground_particle = particle.kind == V_ParticleKind_Debris;
|
||||
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)
|
||||
@ -350,7 +380,7 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
// }
|
||||
|
||||
// Draw
|
||||
if (should_draw)
|
||||
if (should_draw_ground || should_draw_air)
|
||||
{
|
||||
u32 packed = 0;
|
||||
packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
||||
@ -358,15 +388,24 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
||||
StaticAssert(V_ParticleKind_COUNT <= 0xFF); // particle kind must fit in 8 bits
|
||||
|
||||
InterlockedMax(cells[cell_pos], packed);
|
||||
InterlockedAdd(densities[cell_pos], 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// 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);
|
||||
// b32 is_visible = all(screen_pos >= 0) && all(screen_pos < frame.screen_dims);
|
||||
|
||||
// Vec4 color = particle.color;
|
||||
// color.a *= prev_exists;
|
||||
@ -407,6 +446,9 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
// }
|
||||
// }
|
||||
|
||||
// Increment life
|
||||
particle.life += frame.dt;
|
||||
|
||||
// Prune
|
||||
if (!is_in_world)
|
||||
{
|
||||
@ -417,7 +459,6 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
{
|
||||
particle.kind = V_ParticleKind_None;
|
||||
}
|
||||
|
||||
particles[particle_idx] = particle;
|
||||
}
|
||||
}
|
||||
@ -485,11 +526,13 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_ro);
|
||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||
RWTexture2D<u32> cells = G_Dereference<u32>(frame.cells);
|
||||
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);
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
|
||||
RWTexture2D<u32> densities = G_Dereference<u32>(frame.densities);
|
||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
||||
|
||||
Vec2 screen_pos = input.sv_position.xy;
|
||||
@ -501,7 +544,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
||||
Vec2 world_bounds_screen_p0 = mul(frame.af.world_to_screen, Vec3(-half_world_dims.xy, 1));
|
||||
Vec2 world_bounds_screen_p1 = mul(frame.af.world_to_screen, Vec3(half_world_dims.xy, 1));
|
||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells));
|
||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(ground_cells));
|
||||
|
||||
P_TileKind tile = tiles[tile_pos];
|
||||
P_TileKind equipped_tile = frame.equipped_tile;
|
||||
@ -632,45 +675,83 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Particle
|
||||
//- Ground particle
|
||||
|
||||
// TODO: Remove this
|
||||
|
||||
// Vec4 particle_color = cells[cell_pos];
|
||||
// particle_color.rgb *= particle_color.a;
|
||||
|
||||
Vec4 particle_color = 0;
|
||||
Vec4 ground_particle_color = 0;
|
||||
{
|
||||
u32 packed = cells[cell_pos];
|
||||
|
||||
V_ParticleKind kind = (V_ParticleKind)((packed >> 24) & 0xFF);
|
||||
if (kind != V_ParticleKind_None)
|
||||
Vec4 color = 0;
|
||||
{
|
||||
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
u32 packed = ground_cells[cell_pos];
|
||||
V_ParticleKind kind = (V_ParticleKind)((packed >> 24) & 0xFF);
|
||||
if (kind != V_ParticleKind_None)
|
||||
{
|
||||
if (kind == V_ParticleKind_Test)
|
||||
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
{
|
||||
u64 seed = MixU64(P_ParticleCompositeBasis ^ particle_idx);
|
||||
f32 rand_color = Norm16(seed >> 0);
|
||||
|
||||
Vec4 color = Vec4(0.15, 0.15, 0.15, 1);
|
||||
color.rgb += (rand_color - 0.5) * 0.025;
|
||||
|
||||
if (kind == V_ParticleKind_Debris)
|
||||
{
|
||||
f32 density = densities[cell_pos];
|
||||
color.rgb = Color_Orange.rgb;
|
||||
}
|
||||
else if (kind == V_ParticleKind_Smoke)
|
||||
{
|
||||
color.rgb = Vec3(0.15, 0.15, 0.15);
|
||||
}
|
||||
color.rgb += (rand_color - 0.5) * 0.025;
|
||||
{
|
||||
f32 density = ground_densities[cell_pos];
|
||||
// f32 t = saturate(density / 10.0);
|
||||
f32 t = smoothstep(-10, 32, density);
|
||||
color.a = lerp(0, 0.85, t);
|
||||
}
|
||||
|
||||
particle_color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
ground_particle_color = color;
|
||||
ground_particle_color.rgb *= ground_particle_color.a;
|
||||
}
|
||||
|
||||
particle_color.rgb *= particle_color.a;
|
||||
//////////////////////////////
|
||||
//- Air particle
|
||||
|
||||
// TODO: Remove this
|
||||
|
||||
Vec4 air_particle_color = 0;
|
||||
{
|
||||
Vec4 color = 0;
|
||||
{
|
||||
u32 packed = air_cells[cell_pos];
|
||||
V_ParticleKind kind = (V_ParticleKind)((packed >> 24) & 0xFF);
|
||||
if (kind != V_ParticleKind_None)
|
||||
{
|
||||
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||
if (particle_idx < V_ParticlesCap)
|
||||
{
|
||||
u64 seed = MixU64(P_ParticleCompositeBasis ^ particle_idx);
|
||||
f32 rand_color = Norm16(seed >> 0);
|
||||
if (kind == V_ParticleKind_Debris)
|
||||
{
|
||||
color.rgb = Color_Orange.rgb;
|
||||
}
|
||||
else if (kind == V_ParticleKind_Smoke)
|
||||
{
|
||||
color.rgb = Vec3(0.15, 0.15, 0.15);
|
||||
}
|
||||
color.rgb += (rand_color - 0.5) * 0.025;
|
||||
{
|
||||
f32 density = air_densities[cell_pos];
|
||||
// f32 t = saturate(density / 10.0);
|
||||
f32 t = smoothstep(-10, 32, density);
|
||||
color.a = lerp(0, 0.85, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
air_particle_color = color;
|
||||
air_particle_color.rgb *= air_particle_color.a;
|
||||
}
|
||||
|
||||
|
||||
@ -679,7 +760,8 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
||||
|
||||
// world_color = BlendPremul(shade_color, world_color);
|
||||
world_color = BlendPremul(albedo_color, world_color);
|
||||
world_color = BlendPremul(particle_color, world_color);
|
||||
world_color = BlendPremul(ground_particle_color, world_color);
|
||||
world_color = BlendPremul(air_particle_color, world_color);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// #define V_ParticlesCap Kibi(128)
|
||||
// #define V_ParticlesCap Mebi(1)
|
||||
// #define V_ParticlesCap Mebi(2)
|
||||
#define V_ParticlesCap Mebi(16)
|
||||
#define V_ParticlesCap Mebi(2)
|
||||
// #define V_ParticlesCap Mebi(16)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ State types
|
||||
@ -146,10 +146,12 @@ Struct(V_SharedFrame)
|
||||
G_StructuredBufferRef emitters;
|
||||
G_RWStructuredBufferRef particles;
|
||||
|
||||
G_RWTexture2DRef cells;
|
||||
G_RWTexture2DRef stains;
|
||||
G_RWTexture2DRef ground_cells;
|
||||
G_RWTexture2DRef air_cells;
|
||||
G_RWTexture2DRef ground_densities;
|
||||
G_RWTexture2DRef air_densities;
|
||||
G_RWTexture2DRef drynesses;
|
||||
G_RWTexture2DRef densities;
|
||||
|
||||
G_StructuredBufferRef dverts;
|
||||
G_StructuredBufferRef quads;
|
||||
@ -166,11 +168,17 @@ Enum(V_ParticleKind)
|
||||
{
|
||||
V_ParticleKind_None,
|
||||
|
||||
//- Ground particles
|
||||
V_ParticleKind_Blood,
|
||||
V_ParticleKind_Debris,
|
||||
V_ParticleKind_Test,
|
||||
|
||||
//- Air particles
|
||||
V_ParticleKind_Smoke,
|
||||
V_ParticleKind_BulletTrail,
|
||||
|
||||
//- Test particles
|
||||
V_ParticleKind_Test,
|
||||
|
||||
V_ParticleKind_COUNT,
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user