This commit is contained in:
jacob 2026-02-17 08:22:25 -06:00
parent 2609dda88a
commit 88f37a4bbb
6 changed files with 87 additions and 51 deletions

View File

@ -29,6 +29,7 @@ Union(Vec2U64) { struct { u64 x, y; }; struct { u64 r, g; }; u64 v[2]; };
Struct(Vec2Array) { Vec2 *points; u64 count; };
#define CompVec2(x, y) { (x), (y) }
#define VEC2(x, y) (Vec2) { (x), (y) }
#define VEC2F64(x, y) (Vec2F64) { (x), (y) }
#define VEC2I32(x, y) (Vec2I32) { (x), (y) }
@ -54,6 +55,7 @@ Union(Vec3U64) { struct { u64 x, y, z; }; struct { u64 r, g, b; }; u64 v[3]; };
Struct(Vec3Array) { Vec3 *points; u64 count; };
#define CompVec3(x, y, z) { (x), (y), (z) }
#define VEC3(x, y, z) (Vec3) { (x), (y), (z) }
#define VEC3F64(x, y, z) (Vec3F64) { (x), (y), (z) }
#define VEC3I32(x, y, z) (Vec3I32) { (x), (y), (z) }
@ -79,6 +81,7 @@ Union(Vec4U64) { struct { u64 x, y, z, w; }; struct { u64 r, g, b, a; }; u64 v[4
Struct(Vec4Array) { Vec4 *points; u64 count; };
#define CompVec4(x, y, z, w) { (x), (y), (z), (w) }
#define VEC4(x, y, z, w) (Vec4) { (x), (y), (z), (w) }
#define VEC4F64(x, y, z, w) (Vec4F64) { (x), (y), (z), (w) }
#define VEC4I32(x, y, z, w) (Vec4I32) { (x), (y), (z), (w) }

View File

@ -47,6 +47,9 @@ u32 countof(T arr[N])
//~ C -> HLSL interoperability stubs
//- Constructors
#define CompVec2(x, y) { (x), (y) }
#define CompVec3(x, y, z) { (x), (y), (z) }
#define CompVec4(x, y, z, w) { (x), (y), (z), (w) }
#define VEC2(...) Vec2(__VA_ARGS__)
#define VEC3(...) Vec3(__VA_ARGS__)
#define VEC4(...) Vec4(__VA_ARGS__)

View File

@ -395,6 +395,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_ResourceHandle gpu_particle_cell_resources[V_ParticleLayer_COUNT];
G_ResourceHandle gpu_particle_density_resources[V_ParticleLayer_COUNT];
G_ResourceHandle gpu_stains_res = Zi;
G_ResourceHandle gpu_dry_stains_res = Zi;
G_ResourceHandle gpu_drynesses_res = Zi;
G_ResourceHandle gpu_occluders_res = Zi;
@ -403,6 +404,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_RWTexture2DRef gpu_particle_cells[V_ParticleLayer_COUNT];
G_RWTexture2DRef gpu_particle_densities[V_ParticleLayer_COUNT];
G_RWTexture2DRef gpu_stains = Zi;
G_RWTexture2DRef gpu_dry_stains = Zi;
G_RWTexture2DRef gpu_drynesses = Zi;
G_RWTexture2DRef gpu_occluders = Zi;
{
@ -473,6 +475,18 @@ void V_TickForever(WaveLaneCtx *lane)
);
gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
}
//- Init dry stains texture
{
gpu_dry_stains_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R16G16B16A16_Float,
cells_dims,
G_Layout_DirectQueue_ShaderReadWrite,
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Dry stains")
);
gpu_dry_stains = G_PushRWTexture2DRef(gpu_perm, gpu_dry_stains_res);
}
//- Init dryness texture
{
gpu_drynesses_res = G_PushTexture2D(
@ -622,6 +636,7 @@ void V_TickForever(WaveLaneCtx *lane)
frame->tiles = gpu_tiles;
frame->particles = gpu_particles;
frame->stains = gpu_stains;
frame->dry_stains = gpu_dry_stains;
frame->drynesses = gpu_drynesses;
frame->occluders = gpu_occluders;
}
@ -2699,14 +2714,14 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Push test explosion
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])
{
// Debris
// Fire
{
V_Emitter emitter = Zi;
emitter.kind = V_ParticleKind_Debris;
emitter.kind = V_ParticleKind_Fire;
f32 angle = AngleFromVec2(frame->look);
// f32 angle = 0;

View File

@ -16,7 +16,7 @@ Vec4 V_ColorFromParticle(V_ParticleDesc desc, u32 particle_idx, u32 density)
u64 seed = MixU64(V_ParticleColorBasis ^ particle_idx);
f32 rand_color = Norm16(seed >> 0);
result = desc.color;
result = desc.base_color;
// Apply density
{
@ -49,10 +49,6 @@ Vec4 V_ColorFromParticle(V_ParticleDesc desc, u32 particle_idx, u32 density)
}
result.rgb = result.rgb + (rand_color - 0.5) * 0.05;
// result.a += (rand_alpha - 0.5) * 0.025;
// result.a *= rand_alpha;
// Apply dryness
return result;
}
@ -85,6 +81,7 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_GpuConst_Frame)[0];
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<Vec4> dry_stains = G_Dereference<Vec4>(frame.dry_stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
@ -108,7 +105,8 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
//- Reset particle layers
Vec4 new_stain = 0;
Vec4 over_stain = 0;
Vec4 over_dry_stain = 0;
for (V_ParticleLayer layer = (V_ParticleLayer)0; layer < V_ParticleLayer_COUNT; layer += (V_ParticleLayer)1)
{
RWTexture2D<u32> cells = G_Dereference<u32>(frame.particle_cells[layer]);
@ -120,9 +118,15 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
V_ParticleDesc desc = V_DescFromParticleKind(particle_kind);
u32 density = densities[cell_pos];
u32 particle_idx = packed & ((1 << 24) - 1);
Vec4 particle_color = V_ColorFromParticle(desc, particle_idx, density);
particle_color.rgb *= particle_color.a;
new_stain = BlendPremul(particle_color, new_stain);
Vec4 base_color = V_ColorFromParticle(desc, particle_idx, density);
Vec4 dry_color = base_color * desc.dry_factor;
base_color.rgb *= base_color.a;
dry_color.rgb *= dry_color.a;
over_stain = BlendPremul(base_color, over_stain);
over_dry_stain = BlendPremul(dry_color, over_dry_stain);
}
cells[cell_pos] = 0;
densities[cell_pos] = 0;
@ -133,18 +137,28 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
if (frame.should_clear_particles)
{
stains[cell_pos] = 0;
dry_stains[cell_pos] = 0;
drynesses[cell_pos] = 0;
}
else if (new_stain.a > 0)
else if (over_stain.a > 0)
{
Vec4 stain = stains[cell_pos];
stain = BlendPremul(new_stain, stain);
Vec4 stain = dry_stains[cell_pos];
Vec4 dry_stain = max(dry_stains[cell_pos], 0);
stain = BlendPremul(over_stain, stain);
dry_stain = BlendPremul(over_dry_stain, dry_stain);
stains[cell_pos] = stain;
dry_stains[cell_pos] = dry_stain;
drynesses[cell_pos] = 0;
}
else
{
f32 dry_rate = frame.dt * 0.1;
f32 dry_rate = saturate(frame.dt * 0.1);
Vec4 before_stain = stains[cell_pos];
Vec4 before_dry_stain = dry_stains[cell_pos];
drynesses[cell_pos] = lerp(drynesses[cell_pos], 1, dry_rate);
}
}
@ -581,6 +595,7 @@ ComputeShader2D(V_CompositeCS, 8, 8)
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
RWTexture2D<Vec4> screen_tex = G_Dereference<Vec4>(frame.screen_rw);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<Vec4> dry_stains = G_Dereference<Vec4>(frame.dry_stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
@ -699,11 +714,10 @@ ComputeShader2D(V_CompositeCS, 8, 8)
// FIXME: Stain
Vec4 stain_color = 0;
{
Vec4 orig_stain = stains[cell_pos];
// FIXME: Dryness
// f32 dryness = drynesses[cell_pos];
stain_color = orig_stain;
Vec4 wet_stain = stains[cell_pos];
Vec4 dry_stain = dry_stains[cell_pos];
f32 dryness = drynesses[cell_pos];
stain_color = max(lerp(wet_stain, dry_stain, dryness), 0);
}
Vec4 ground_particle_color = 0;

View File

@ -11,47 +11,37 @@ 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, lifetime, r, g, b, a) flags,
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) flags,
V_ParticlesXList(X)
#undef X
};
PERSIST Readonly V_ParticleLayer layers[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) layer,
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) layer,
V_ParticlesXList(X)
#undef X
};
PERSIST Readonly f32 stain_rates[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) stain_rate,
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) stain_rate,
V_ParticlesXList(X)
#undef X
};
PERSIST Readonly f32 pen_rates[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) pen_rate,
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) 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,
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) lifetime,
V_ParticlesXList(X)
#undef X
};
PERSIST Readonly f32 r[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, r, g, b, a) r,
PERSIST Readonly Vec4 base_colors[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) base_color,
V_ParticlesXList(X)
#undef X
};
PERSIST Readonly f32 g[V_ParticleKind_COUNT] = {
#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, 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, lifetime, r, g, b, a) a,
PERSIST Readonly Vec4 dry_factor[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime, base_color, dry_factor) dry_factor,
V_ParticlesXList(X)
#undef X
};
@ -61,7 +51,8 @@ V_ParticleDesc V_DescFromParticleKind(V_ParticleKind 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]));
result.base_color = LinearFromSrgb(base_colors[kind]);
result.dry_factor = LinearFromSrgb(dry_factor[kind]);
}
return result;
}

View File

@ -53,7 +53,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Ground, \
/* Stain rate, pen chance */ 30, 0, \
/* Lifetime */ Inf, \
/* Base color */ 0, 0, 0, 0 \
/* Base color */ CompVec4(0, 0, 0, 0), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
\
/* Ground particles */ \
@ -63,7 +64,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Ground, \
/* Stain rate, pen chance */ 100, 0.25, \
/* Lifetime */ Inf, \
/* Base color */ 0.5, 0.1, 0.1, 0.05 \
/* Base color */ CompVec4(0.5, 0.1, 0.1, 0.05), \
/* Dry color factor */ CompVec4(0.5, 0.5, 0.5, 1) \
) \
X( \
/* Name */ BloodDebris, \
@ -71,7 +73,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 30, 0, \
/* Lifetime */ Inf, \
/* Base color */ 0.5, 0.1, 0.1, 0.8 \
/* Base color */ CompVec4(0.5, 0.1, 0.1, 0.8), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
X( \
/* Name */ Debris, \
@ -79,7 +82,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, \
/* Base color */ 0.4, 0.3, 0.2, 1 \
/* Base color */ CompVec4(0.4, 0.3, 0.2, 1), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
X( \
/* Name */ Fire, \
@ -87,7 +91,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, \
/* Base color */ 2, 0.5, 0, 1 \
/* Base color */ CompVec4(2, 0.5, 0, 1), \
/* Dry color factor */ CompVec4(0.2, 0.1, 0.0, 1) \
) \
\
/* Air particles */ \
@ -97,7 +102,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.075, \
/* Base color */ 0.8, 0.6, 0.2, 0.25 \
/* Base color */ CompVec4(0.8, 0.6, 0.2, 0.25), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
X( \
/* Name */ Smoke, \
@ -105,7 +111,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, \
/* Base color */ 0.25, 0.25, 0.25, 0.75 \
/* Base color */ CompVec4(0.25, 0.25, 0.25, 0.75), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
\
/* Test particles */ \
@ -115,7 +122,8 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, \
/* Base color */ 1, 1, 0, 1 \
/* Base color */ CompVec4(1, 1, 0, 1), \
/* Dry color factor */ CompVec4(1, 1, 1, 1) \
) \
/* ----------------------------------------------------------------------------------------------------------------------------------- */
@ -160,7 +168,8 @@ Struct(V_ParticleDesc)
f32 stain_rate;
f32 pen_rate;
f32 lifetime;
Vec4 color;
Vec4 base_color;
Vec4 dry_factor;
};
#if IsCpu
@ -341,6 +350,7 @@ Struct(V_SharedFrame)
G_RWStructuredBufferRef particles;
G_RWTexture2DRef stains;
G_RWTexture2DRef dry_stains;
G_RWTexture2DRef drynesses;
G_RWTexture2DRef occluders;