separate decals into stains & cells
This commit is contained in:
parent
869b415ebb
commit
f30ed79e91
@ -15,7 +15,7 @@
|
||||
|
||||
@EmbedDir V_Resources pp_vis_res
|
||||
|
||||
@ComputeShader V_ClearDecalsCS
|
||||
@ComputeShader V_ClearCellsCS
|
||||
@ComputeShader V_ClearParticlesCS
|
||||
@ComputeShader V_BackdropCS
|
||||
@VertexShader V_DQuadVS
|
||||
|
||||
@ -309,7 +309,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
world->tiles = PushStructs(world_arena, u8, S_TilesCount);
|
||||
|
||||
Vec2I32 tiles_dims = VEC2I32(S_TilesPitch, S_TilesPitch);
|
||||
Vec2I32 decals_dims = VEC2I32(V_PixelsPerMeter * S_WorldPitch, V_PixelsPerMeter * S_WorldPitch);
|
||||
Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * S_WorldPitch, V_CellsPerMeter * S_WorldPitch);
|
||||
|
||||
// u32 max_particles = Kibi(128);
|
||||
u32 max_particles = Mebi(1);
|
||||
@ -320,11 +320,13 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
G_ResourceHandle gpu_state = Zi;
|
||||
G_ResourceHandle gpu_tiles = Zi;
|
||||
G_ResourceHandle gpu_particles = Zi;
|
||||
G_ResourceHandle gpu_decals = Zi;
|
||||
G_ResourceHandle gpu_cells = Zi;
|
||||
G_ResourceHandle gpu_stains = Zi;
|
||||
G_RWStructuredBufferRef gpu_state_ref = Zi;
|
||||
G_Texture2DRef gpu_tiles_ref = Zi;
|
||||
G_RWStructuredBufferRef gpu_particles_ref = Zi;
|
||||
G_RWTexture2DRef gpu_decals_ref = Zi;
|
||||
G_RWTexture2DRef gpu_cells_ref = Zi;
|
||||
G_RWTexture2DRef gpu_stains_ref = Zi;
|
||||
{
|
||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||
{
|
||||
@ -338,7 +340,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_state_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_state, V_GpuState);
|
||||
}
|
||||
|
||||
// Init tile map texture
|
||||
{
|
||||
gpu_tiles = G_PushTexture2D(
|
||||
@ -360,18 +361,31 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
);
|
||||
gpu_particles_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles, V_Particle);
|
||||
}
|
||||
// Init decal texture
|
||||
// Init cells texture
|
||||
{
|
||||
gpu_decals = G_PushTexture2D(
|
||||
gpu_cells = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
G_Format_R10G10B10A2_Unorm,
|
||||
decals_dims,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite
|
||||
);
|
||||
gpu_decals_ref = G_PushRWTexture2DRef(gpu_perm, gpu_decals);
|
||||
gpu_cells_ref = G_PushRWTexture2DRef(gpu_perm, gpu_cells);
|
||||
}
|
||||
// Init stain texture
|
||||
{
|
||||
gpu_stains = G_PushTexture2D(
|
||||
gpu_perm, cl,
|
||||
// G_Format_R8_Uint,
|
||||
// G_Format_R11G11B10_Float,
|
||||
G_Format_R10G10B10A2_Unorm,
|
||||
cells_dims,
|
||||
G_Layout_DirectQueue_ShaderReadWrite,
|
||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite
|
||||
);
|
||||
gpu_stains_ref = G_PushRWTexture2DRef(gpu_perm, gpu_stains);
|
||||
}
|
||||
}
|
||||
G_CommitCommandList(cl);
|
||||
@ -876,14 +890,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->xf.draw_to_world = InvertXform(frame->xf.world_to_draw);
|
||||
}
|
||||
|
||||
// World <-> decal
|
||||
// TODO: This can be constant (so shaders don't need to read it every frame)
|
||||
frame->xf.world_to_decal = XformIdentity;
|
||||
frame->xf.decal_to_world = XformIdentity;
|
||||
// World <-> cell
|
||||
// TODO: This never changes, should be #defined (so shaders don't need to read it every frame)
|
||||
frame->xf.world_to_cell = XformIdentity;
|
||||
frame->xf.cell_to_world = XformIdentity;
|
||||
{
|
||||
frame->xf.world_to_decal = ScaleXform(frame->xf.world_to_decal, VEC2(V_PixelsPerMeter, V_PixelsPerMeter));
|
||||
frame->xf.world_to_decal = TranslateXform(frame->xf.world_to_decal, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0)));
|
||||
frame->xf.decal_to_world = InvertXform(frame->xf.world_to_decal);
|
||||
frame->xf.world_to_cell = ScaleXform(frame->xf.world_to_cell, VEC2(V_CellsPerMeter, V_CellsPerMeter));
|
||||
frame->xf.world_to_cell = TranslateXform(frame->xf.world_to_cell, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0)));
|
||||
frame->xf.cell_to_world = InvertXform(frame->xf.world_to_cell);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -2168,14 +2182,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
{
|
||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor);
|
||||
Vec2 decal_pos = MulXformV2(frame->xf.world_to_decal, frame->world_cursor);
|
||||
Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor);
|
||||
i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
|
||||
{
|
||||
UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos));
|
||||
UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor));
|
||||
UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos));
|
||||
UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx));
|
||||
UI_BuildLabelF("Cursor decal pos: %F", FmtFloat2(decal_pos));
|
||||
UI_BuildLabelF("Cursor cell pos: %F", FmtFloat2(cell_pos));
|
||||
UI_BuildLabelF("Hovered ent: %F", S_FmtKey(hovered_ent->key));
|
||||
}
|
||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||
@ -2356,7 +2370,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
//////////////////////////////
|
||||
//- Process vis commands
|
||||
|
||||
b32 should_clear_decals = !TweakBool("Persist decals", 0);
|
||||
// b32 should_clear_stains = !TweakBool("Persist stains", 0);
|
||||
b32 should_clear_stains = 0;
|
||||
b32 should_clear_particles = 0;
|
||||
for (V_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||
{
|
||||
@ -2495,9 +2510,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
} break;
|
||||
|
||||
case V_CmdKind_clear_decals:
|
||||
case V_CmdKind_clear_stains:
|
||||
{
|
||||
should_clear_decals = 1;
|
||||
should_clear_stains = 1;
|
||||
} break;
|
||||
|
||||
case V_CmdKind_clear_particles:
|
||||
@ -2618,7 +2633,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->emitters_count += 1;
|
||||
emitter = &en->emitter;
|
||||
}
|
||||
V_ParticleFlag flags = 0;
|
||||
V_ParticleFlag flags = V_ParticleFlag_StainOnPrune;
|
||||
emitter->flags = flags;
|
||||
|
||||
Vec2 dir = victim_raycast.normal;
|
||||
@ -2628,16 +2643,16 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// emitter->count = 100;
|
||||
// emitter->count = 500;
|
||||
|
||||
emitter->speed = 20;
|
||||
emitter->speed_spread = 40;
|
||||
emitter->speed = 10;
|
||||
emitter->speed_spread = 20;
|
||||
|
||||
emitter->velocity_falloff = 30;
|
||||
emitter->velocity_falloff_spread = 60;
|
||||
|
||||
emitter->angle = AngleFromVec2(dir);
|
||||
// emitter->angle_spread = Tau / 4;
|
||||
// emitter->angle_spread = Tau / 20;
|
||||
emitter->angle_spread = Tau / 32;
|
||||
emitter->angle_spread = Tau / 20;
|
||||
// emitter->angle_spread = Tau / 32;
|
||||
|
||||
emitter->color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
emitter->color_spread = VEC3(0.1, 0, 0);
|
||||
@ -2874,7 +2889,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
params.max_particles = max_particles;
|
||||
params.particles = gpu_particles_ref;
|
||||
|
||||
params.decals = gpu_decals_ref;
|
||||
params.should_clear_stains = should_clear_stains;
|
||||
params.cells = gpu_cells_ref;
|
||||
params.stains = gpu_stains_ref;
|
||||
}
|
||||
G_ResourceHandle gpu_params = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromStruct(¶ms));
|
||||
G_StructuredBufferRef gpu_params_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_params, V_GpuParams);
|
||||
@ -2904,11 +2921,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
//////////////////////////////
|
||||
//- Setup pass
|
||||
|
||||
// Clear decals
|
||||
if (should_clear_decals)
|
||||
{
|
||||
G_Compute(frame->cl, V_ClearDecalsCS, V_ThreadGroupSizeFromTexSize(decals_dims));
|
||||
}
|
||||
// Clear cells
|
||||
G_Compute(frame->cl, V_ClearCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims));
|
||||
|
||||
// Clear particles
|
||||
if (should_clear_particles)
|
||||
@ -2935,7 +2949,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// Simulate particles
|
||||
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(max_particles));
|
||||
|
||||
// Barrier since decals were written
|
||||
// Barrier since stains were written
|
||||
G_DumbGlobalMemorySync(frame->cl);
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
X(spawn, Spawn/Teleport Player, V_CmdDescFlag_None, V_HOTKEY( Button_T ), ) \
|
||||
X(spawn_dummy, Spawn Dummy, V_CmdDescFlag_None, V_HOTKEY( Button_R ), ) \
|
||||
X(delete, Delete entity at cursor, V_CmdDescFlag_None, V_HOTKEY( Button_M2 ), ) \
|
||||
X(clear_decals, Clear decals, V_CmdDescFlag_None, V_HOTKEY( Button_C, .alt = 1 ), ) \
|
||||
X(clear_stains, Clear stains, V_CmdDescFlag_None, V_HOTKEY( Button_C, .alt = 1 ), ) \
|
||||
X(clear_particles, Clear particles, V_CmdDescFlag_None, V_HOTKEY( Button_C ), ) \
|
||||
/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Utility shaders
|
||||
|
||||
//- Clear decals
|
||||
ComputeShader2D(V_ClearDecalsCS, 8, 8)
|
||||
//- Clear cells
|
||||
ComputeShader2D(V_ClearCellsCS, 8, 8)
|
||||
{
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
RWTexture2D<Vec4> decals = G_Dereference<Vec4>(params.decals);
|
||||
Vec2 decal_idx = SV_DispatchThreadID;
|
||||
if (decal_idx.x < countof(decals).x && decal_idx.y < countof(decals).y)
|
||||
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
Vec2 cells_idx = SV_DispatchThreadID;
|
||||
if (cells_idx.x < countof(cells).x && cells_idx.y < countof(cells).y)
|
||||
{
|
||||
decals[decal_idx] = 0;
|
||||
cells[cells_idx] = 0;
|
||||
if (params.should_clear_stains)
|
||||
{
|
||||
stains[cells_idx] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,30 +153,38 @@ ComputeShader2D(V_BackdropCS, 8, 8)
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: Remove this
|
||||
// Decals test
|
||||
// Cells test
|
||||
{
|
||||
RWTexture2D<Vec4> decals = G_Dereference<Vec4>(params.decals);
|
||||
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
|
||||
// Vec2 decal_uv = decal_pos / countof(decals);
|
||||
Vec4 decal = decals.Load(decal_pos);
|
||||
if (decal.a != 0)
|
||||
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
|
||||
Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1)));
|
||||
Vec4 cell = cells.Load(cell_pos);
|
||||
if (cell.a != 0)
|
||||
{
|
||||
result = decal;
|
||||
result = cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
Vec4 stain = stains.Load(cell_pos);
|
||||
if (stain.a != 0)
|
||||
{
|
||||
result = stain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Remove this
|
||||
// Decals test
|
||||
// Stains test
|
||||
// {
|
||||
// RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
|
||||
// Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
|
||||
// // Vec2 decal_uv = decal_pos / countof(decals);
|
||||
// V_ParticleKind decal = decals.Load(decal_pos);
|
||||
// RWTexture2D<V_ParticleKind> stains = G_Dereference<V_ParticleKind>(params.stains);
|
||||
// Vec2 cell_pos = mul(params.xf.world_to_cell, Vec3(world_pos, 1));
|
||||
// V_ParticleKind stain = stains.Load(cell_pos);
|
||||
|
||||
// if (decal == V_ParticleKind_Test)
|
||||
// if (stain == V_ParticleKind_Test)
|
||||
// {
|
||||
// // result = Color_Yellow;
|
||||
// // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
@ -269,7 +282,8 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
{
|
||||
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
|
||||
RWTexture2D<Vec4> decals = G_Dereference<Vec4>(params.decals);
|
||||
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
|
||||
u32 particle_idx = SV_DispatchThreadID;
|
||||
if (particle_idx < params.max_particles)
|
||||
@ -319,22 +333,35 @@ ComputeShader(V_SimParticlesCS, 64)
|
||||
{
|
||||
particle.pos += particle.velocity * params.dt;
|
||||
particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt);
|
||||
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(particle.pos, 1));
|
||||
if (decal_pos.x >= 0 && decal_pos.y >= 0 && decal_pos.x < countof(decals).x && decal_pos.y < countof(decals).y)
|
||||
if (particle.exists < 0.0001)
|
||||
{
|
||||
// FIXME: Atomic write
|
||||
decals[floor(decal_pos)] = Vec4(particle.color, 1);
|
||||
particle.exists = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Commit
|
||||
{
|
||||
// FIXME: Atomic write
|
||||
Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(particle.pos, 1)));
|
||||
if (cell_pos.x >= 0 && cell_pos.y >= 0 && cell_pos.x < countof(stains).x && cell_pos.y < countof(stains).y)
|
||||
{
|
||||
b32 should_stain = 0;
|
||||
if (particle.flags & V_ParticleFlag_StainOnPrune && particle.exists == 0)
|
||||
{
|
||||
should_stain = 1;
|
||||
}
|
||||
|
||||
cells[cell_pos] = Vec4(particle.color, 1);
|
||||
if (should_stain)
|
||||
{
|
||||
stains[cell_pos] = Vec4(particle.color, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prune out of bounds particle
|
||||
particle.exists = 0;
|
||||
}
|
||||
|
||||
if (particle.exists < 0.0001)
|
||||
{
|
||||
particle.exists = 0;
|
||||
}
|
||||
}
|
||||
particles[particle_idx] = particle;
|
||||
}
|
||||
@ -447,22 +474,6 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
|
||||
}
|
||||
}
|
||||
|
||||
// // TODO: Remove this
|
||||
// // Decals test
|
||||
// {
|
||||
// RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
|
||||
// Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
|
||||
// // Vec2 decal_uv = decal_pos / countof(decals);
|
||||
// V_ParticleKind decal = decals.Load(decal_pos);
|
||||
|
||||
// if (decal == V_ParticleKind_Test)
|
||||
// {
|
||||
// result = Color_Yellow;
|
||||
// // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
V_OverlayPSOutput output;
|
||||
output.sv_target0 = result;
|
||||
return output;
|
||||
|
||||
@ -44,7 +44,7 @@ Struct(V_OverlayPSOutput)
|
||||
//~ Shaders
|
||||
|
||||
//- Utility shaders
|
||||
ComputeShader2D(V_ClearDecalsCS, 8, 8);
|
||||
ComputeShader2D(V_ClearCellsCS, 8, 8);
|
||||
ComputeShader(V_ClearParticlesCS, 64);
|
||||
|
||||
//- Backdrop shader
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#define V_PixelsPerMeter 48.0
|
||||
#define V_PixelsPerSqMeter (V_PixelsPerMeter * V_PixelsPerMeter)
|
||||
#define V_CellsPerMeter 48.0
|
||||
#define V_CellsPerSqMeter (V_CellsPerMeter * V_CellsPerMeter)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Constant types
|
||||
@ -28,9 +28,9 @@ Struct(V_Xforms)
|
||||
Xform world_to_draw;
|
||||
Xform draw_to_world;
|
||||
|
||||
// World <-> decal
|
||||
Xform world_to_decal;
|
||||
Xform decal_to_world;
|
||||
// World <-> cell
|
||||
Xform world_to_cell;
|
||||
Xform cell_to_world;
|
||||
};
|
||||
|
||||
Struct(V_GpuState)
|
||||
@ -74,7 +74,10 @@ Struct(V_GpuParams)
|
||||
|
||||
u32 max_particles;
|
||||
G_RWStructuredBufferRef particles;
|
||||
G_RWTexture2DRef decals;
|
||||
|
||||
b32 should_clear_stains;
|
||||
G_RWTexture2DRef cells;
|
||||
G_RWTexture2DRef stains;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -82,7 +85,8 @@ Struct(V_GpuParams)
|
||||
|
||||
Enum(V_ParticleFlag)
|
||||
{
|
||||
V_ParticleFlag_None = (0),
|
||||
V_ParticleFlag_None = 0,
|
||||
V_ParticleFlag_StainOnPrune = (1 << 0),
|
||||
};
|
||||
|
||||
Struct(V_Emitter)
|
||||
@ -112,6 +116,7 @@ Struct(V_Particle)
|
||||
V_ParticleFlag flags;
|
||||
|
||||
u32 emitter_init_num; // if != 0, then initialize using emitter at index (emitter_init_num - 1)
|
||||
u32 seq;
|
||||
u32 idx_in_emitter;
|
||||
|
||||
Vec2 pos;
|
||||
@ -137,7 +142,6 @@ Struct(V_Particle)
|
||||
Enum(V_DQuadFlag)
|
||||
{
|
||||
V_DQuadFlag_None = 0,
|
||||
V_DQuadFlag_DrawGrid = (1 << 0),
|
||||
};
|
||||
|
||||
Struct(V_DQuad)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user