particle layer testing
This commit is contained in:
parent
7e05e4292a
commit
a9ca711892
@ -11,6 +11,9 @@
|
|||||||
#define P_TilesCount (P_TilesPitch * P_TilesPitch)
|
#define P_TilesCount (P_TilesPitch * P_TilesPitch)
|
||||||
#define P_CellsCount (P_CellsPitch * P_TilesPitch)
|
#define P_CellsCount (P_CellsPitch * P_TilesPitch)
|
||||||
|
|
||||||
|
#define P_WorldTilesDims VEC2(P_TilesPitch, P_TilesPitch)
|
||||||
|
#define P_WorldCellsDims VEC2(P_CellsPitch, P_CellsPitch)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Material types
|
//~ Material types
|
||||||
|
|
||||||
|
|||||||
@ -389,32 +389,26 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
Vec2I32 tiles_dims = VEC2I32(P_TilesPitch, P_TilesPitch);
|
Vec2I32 tiles_dims = VEC2I32(P_TilesPitch, P_TilesPitch);
|
||||||
Vec2I32 cells_dims = VEC2I32(P_CellsPitch, P_CellsPitch);
|
Vec2I32 cells_dims = VEC2I32(P_CellsPitch, P_CellsPitch);
|
||||||
|
|
||||||
// Init gpu state
|
//- Init gpu state
|
||||||
G_ResourceHandle gpu_tiles_res = Zi;
|
G_ResourceHandle gpu_tiles_res = Zi;
|
||||||
G_ResourceHandle gpu_particles_res = Zi;
|
G_ResourceHandle gpu_particles_res = Zi;
|
||||||
G_ResourceHandle gpu_stain_cells_res = Zi;
|
G_ResourceHandle gpu_particle_cell_resources[V_ParticleLayer_COUNT];
|
||||||
G_ResourceHandle gpu_ground_cells_res = Zi;
|
G_ResourceHandle gpu_particle_density_resources[V_ParticleLayer_COUNT];
|
||||||
G_ResourceHandle gpu_air_cells_res = Zi;
|
G_ResourceHandle gpu_stains_res = Zi;
|
||||||
G_ResourceHandle gpu_stain_densities_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_drynesses_res = Zi;
|
||||||
G_ResourceHandle gpu_occluders_res = Zi;
|
G_ResourceHandle gpu_occluders_res = Zi;
|
||||||
|
|
||||||
G_Texture2DRef gpu_tiles = Zi;
|
G_Texture2DRef gpu_tiles = Zi;
|
||||||
G_RWStructuredBufferRef gpu_particles = Zi;
|
G_RWStructuredBufferRef gpu_particles = Zi;
|
||||||
G_RWTexture2DRef gpu_stain_cells = Zi;
|
G_RWTexture2DRef gpu_particle_cells[V_ParticleLayer_COUNT];
|
||||||
G_RWTexture2DRef gpu_ground_cells = Zi;
|
G_RWTexture2DRef gpu_particle_densities[V_ParticleLayer_COUNT];
|
||||||
G_RWTexture2DRef gpu_air_cells = Zi;
|
G_RWTexture2DRef gpu_stains = Zi;
|
||||||
G_RWTexture2DRef gpu_stain_densities = Zi;
|
|
||||||
G_RWTexture2DRef gpu_ground_densities = Zi;
|
|
||||||
G_RWTexture2DRef gpu_air_densities = Zi;
|
|
||||||
G_RWTexture2DRef gpu_drynesses = Zi;
|
G_RWTexture2DRef gpu_drynesses = Zi;
|
||||||
G_RWTexture2DRef gpu_occluders = Zi;
|
G_RWTexture2DRef gpu_occluders = Zi;
|
||||||
{
|
{
|
||||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||||
{
|
{
|
||||||
// Init tile map texture
|
//- Init tile map texture
|
||||||
{
|
{
|
||||||
gpu_tiles_res = G_PushTexture2D(
|
gpu_tiles_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
@ -426,7 +420,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
);
|
);
|
||||||
gpu_tiles = G_PushTexture2DRef(gpu_perm, gpu_tiles_res);
|
gpu_tiles = G_PushTexture2DRef(gpu_perm, gpu_tiles_res);
|
||||||
}
|
}
|
||||||
// Init particle buffer
|
//- Init particle buffer
|
||||||
{
|
{
|
||||||
gpu_particles_res = G_PushBuffer(
|
gpu_particles_res = G_PushBuffer(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
@ -437,79 +431,49 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
);
|
);
|
||||||
gpu_particles = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles_res, V_Particle);
|
gpu_particles = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles_res, V_Particle);
|
||||||
}
|
}
|
||||||
// Init stain cells texture
|
//- Init particle textures
|
||||||
|
for (V_ParticleLayer layer = 0; layer < V_ParticleLayer_COUNT; ++layer)
|
||||||
{
|
{
|
||||||
gpu_stain_cells_res = G_PushTexture2D(
|
{
|
||||||
|
G_ResourceHandle cells_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
G_Format_R32_Uint,
|
G_Format_R32_Uint,
|
||||||
cells_dims,
|
cells_dims,
|
||||||
G_Layout_DirectQueue_ShaderReadWrite,
|
G_Layout_DirectQueue_ShaderReadWrite,
|
||||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||||
.name = Lit("Stain cells")
|
.name = StringF(perm, "Particle cells - layer %F", FmtSint(layer))
|
||||||
);
|
);
|
||||||
gpu_stain_cells = G_PushRWTexture2DRef(gpu_perm, gpu_stain_cells_res);
|
G_RWTexture2DRef cells = G_PushRWTexture2DRef(gpu_perm, cells_res);
|
||||||
|
gpu_particle_cell_resources[layer] = cells_res;
|
||||||
|
gpu_particle_cells[layer] = cells;
|
||||||
}
|
}
|
||||||
// Init ground cells texture
|
|
||||||
{
|
{
|
||||||
gpu_ground_cells_res = G_PushTexture2D(
|
G_ResourceHandle densities_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
G_Format_R32_Uint,
|
G_Format_R32_Uint,
|
||||||
cells_dims,
|
cells_dims,
|
||||||
G_Layout_DirectQueue_ShaderReadWrite,
|
G_Layout_DirectQueue_ShaderReadWrite,
|
||||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||||
.name = Lit("Ground cells")
|
.name = StringF(perm, "Particle densities - layer %F", FmtSint(layer))
|
||||||
);
|
);
|
||||||
gpu_ground_cells = G_PushRWTexture2DRef(gpu_perm, gpu_ground_cells_res);
|
G_RWTexture2DRef densities = G_PushRWTexture2DRef(gpu_perm, densities_res);
|
||||||
|
gpu_particle_density_resources[layer] = densities_res;
|
||||||
|
gpu_particle_densities[layer] = densities;
|
||||||
}
|
}
|
||||||
// Init air cells texture
|
}
|
||||||
|
//- Init stains texture
|
||||||
{
|
{
|
||||||
gpu_air_cells_res = G_PushTexture2D(
|
gpu_stains_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
G_Format_R32_Uint,
|
G_Format_R16G16B16A16_Float,
|
||||||
cells_dims,
|
cells_dims,
|
||||||
G_Layout_DirectQueue_ShaderReadWrite,
|
G_Layout_DirectQueue_ShaderReadWrite,
|
||||||
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
|
||||||
.name = Lit("Air cells")
|
.name = Lit("Stains")
|
||||||
);
|
);
|
||||||
gpu_air_cells = G_PushRWTexture2DRef(gpu_perm, gpu_air_cells_res);
|
gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
|
||||||
}
|
}
|
||||||
// Init stain densities texture
|
//- Init dryness texture
|
||||||
{
|
|
||||||
gpu_stain_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("Stain densities")
|
|
||||||
);
|
|
||||||
gpu_stain_densities = G_PushRWTexture2DRef(gpu_perm, gpu_stain_densities_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_drynesses_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
@ -521,7 +485,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
);
|
);
|
||||||
gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
|
gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
|
||||||
}
|
}
|
||||||
// Init occluders texture
|
//- Init occluders texture
|
||||||
{
|
{
|
||||||
gpu_occluders_res = G_PushTexture2D(
|
gpu_occluders_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
@ -650,14 +614,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
frame->basic_samplers[sampler_kind] = G_BasicSamplerFromKind(sampler_kind);
|
frame->basic_samplers[sampler_kind] = G_BasicSamplerFromKind(sampler_kind);
|
||||||
}
|
}
|
||||||
|
for (V_ParticleLayer layer = 0; layer < V_ParticleLayer_COUNT; ++layer)
|
||||||
|
{
|
||||||
|
frame->particle_cells[layer] = gpu_particle_cells[layer];
|
||||||
|
frame->particle_densities[layer] = gpu_particle_densities[layer];
|
||||||
|
}
|
||||||
frame->tiles = gpu_tiles;
|
frame->tiles = gpu_tiles;
|
||||||
frame->particles = gpu_particles;
|
frame->particles = gpu_particles;
|
||||||
frame->stain_cells = gpu_stain_cells;
|
frame->stains = gpu_stains;
|
||||||
frame->ground_cells = gpu_ground_cells;
|
|
||||||
frame->air_cells = gpu_air_cells;
|
|
||||||
frame->stain_densities = gpu_stain_densities;
|
|
||||||
frame->ground_densities = gpu_ground_densities;
|
|
||||||
frame->air_densities = gpu_air_densities;
|
|
||||||
frame->drynesses = gpu_drynesses;
|
frame->drynesses = gpu_drynesses;
|
||||||
frame->occluders = gpu_occluders;
|
frame->occluders = gpu_occluders;
|
||||||
}
|
}
|
||||||
@ -2562,8 +2526,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Push test emitter
|
//- Push test emitter
|
||||||
|
|
||||||
// if (frame->held_buttons[Button_F])
|
if (frame->held_buttons[Button_F])
|
||||||
if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F])
|
// if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F])
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
V_Emitter emitter = Zi;
|
V_Emitter emitter = Zi;
|
||||||
@ -5045,8 +5009,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
i32 mips_count = G_CountMips(bloom_target);
|
i32 mips_count = G_CountMips(bloom_target);
|
||||||
|
|
||||||
G_DumbMemoryLayoutSync(frame->cl, screen_target, G_Layout_DirectQueue_ShaderRead);
|
|
||||||
|
|
||||||
//- Downsample + blur passes
|
//- Downsample + blur passes
|
||||||
for (i32 mip_idx = 0; mip_idx < mips_count; ++mip_idx)
|
for (i32 mip_idx = 0; mip_idx < mips_count; ++mip_idx)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,10 +10,8 @@ f32 V_RandFromPos(Vec3 pos)
|
|||||||
return rand;
|
return rand;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 density, f32 dryness)
|
Vec4 V_ColorFromParticle(V_ParticleDesc desc, u32 particle_idx, u32 density)
|
||||||
{
|
{
|
||||||
V_ParticleDesc desc = V_DescFromParticleKind(particle_kind);
|
|
||||||
|
|
||||||
Vec4 result = 0;
|
Vec4 result = 0;
|
||||||
u64 seed = MixU64(V_ParticleColorBasis ^ particle_idx);
|
u64 seed = MixU64(V_ParticleColorBasis ^ particle_idx);
|
||||||
f32 rand_color = Norm16(seed >> 0);
|
f32 rand_color = Norm16(seed >> 0);
|
||||||
@ -21,30 +19,30 @@ Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 den
|
|||||||
result = desc.color;
|
result = desc.color;
|
||||||
|
|
||||||
// // FIXME: Base color on particle desc
|
// // FIXME: Base color on particle desc
|
||||||
// if (particle_kind == V_ParticleKind_Test)
|
// if (desc.kind == V_ParticleKind_Test)
|
||||||
// {
|
// {
|
||||||
// // result.rgb = Vec3(0, 0, 0);
|
// // result.rgb = Vec3(0, 0, 0);
|
||||||
// result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 0.5));
|
// result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 0.5));
|
||||||
// }
|
// }
|
||||||
// else if (particle_kind == V_ParticleKind_Debris)
|
// else if (desc.kind == V_ParticleKind_Debris)
|
||||||
// {
|
// {
|
||||||
// result = Color_Orange;
|
// result = Color_Orange;
|
||||||
// }
|
// }
|
||||||
// else if (particle_kind == V_ParticleKind_Smoke)
|
// else if (desc.kind == V_ParticleKind_Smoke)
|
||||||
// {
|
// {
|
||||||
// result = Vec4(0.15, 0.15, 0.15, 1);
|
// result = Vec4(0.15, 0.15, 0.15, 1);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Apply density
|
// Apply density
|
||||||
{
|
{
|
||||||
if (particle_kind == V_ParticleKind_Smoke)
|
if (desc.kind == V_ParticleKind_Smoke)
|
||||||
{
|
{
|
||||||
// f32 t = saturate(density / 10.0);
|
// f32 t = saturate(density / 10.0);
|
||||||
f32 t = smoothstep(-10, 32, density);
|
f32 t = smoothstep(-10, 32, density);
|
||||||
// f32 t = smoothstep(0, 2, (f32)density);
|
// f32 t = smoothstep(0, 2, (f32)density);
|
||||||
result.a = lerp(0, 0.85, t);
|
result.a = lerp(0, 0.85, t);
|
||||||
}
|
}
|
||||||
else if (particle_kind == V_ParticleKind_BloodTrail || particle_kind == V_ParticleKind_BloodDebris)
|
else if (desc.kind == V_ParticleKind_BloodTrail || desc.kind == V_ParticleKind_BloodDebris)
|
||||||
{
|
{
|
||||||
// f32 t = (f32)density / 5;
|
// f32 t = (f32)density / 5;
|
||||||
// t = pow(t, 2);
|
// t = pow(t, 2);
|
||||||
@ -67,7 +65,6 @@ Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 den
|
|||||||
// result.a *= rand_alpha;
|
// result.a *= rand_alpha;
|
||||||
|
|
||||||
// Apply dryness
|
// Apply dryness
|
||||||
result.rgb *= 1.0 - (dryness * 0.75);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -99,53 +96,20 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
{
|
{
|
||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_GpuConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_GpuConst_Frame)[0];
|
||||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||||
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_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> stain_densities = G_Dereference<u32>(frame.stain_densities);
|
|
||||||
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<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||||
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
||||||
|
|
||||||
Vec2 cell_pos = SV_DispatchThreadID + 0.5;
|
Vec2 cell_pos = SV_DispatchThreadID + 0.5;
|
||||||
if (all(cell_pos < countof(air_cells)))
|
if (all(cell_pos < P_WorldCellsDims))
|
||||||
{
|
{
|
||||||
Vec2 world_pos = mul(frame.af.cell_to_world, Vec3(cell_pos, 1));
|
Vec2 world_pos = mul(frame.af.cell_to_world, Vec3(cell_pos, 1));
|
||||||
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
|
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
|
||||||
P_TileKind tile = tiles[tile_pos];
|
P_TileKind tile = tiles[tile_pos];
|
||||||
|
|
||||||
// Update stains
|
//- Reset occluders
|
||||||
if (frame.should_clear_particles)
|
|
||||||
{
|
|
||||||
stain_densities[cell_pos] = 0;
|
|
||||||
stain_cells[cell_pos] = 0;
|
|
||||||
drynesses[cell_pos] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 stain = stain_cells[cell_pos];
|
|
||||||
{
|
|
||||||
stain &= ~(1 << 31);
|
|
||||||
}
|
|
||||||
f32 dryness = drynesses[cell_pos];
|
|
||||||
{
|
|
||||||
f32 dry_rate = frame.dt * 0.1;
|
|
||||||
dryness = lerp(dryness, 1, dry_rate);
|
|
||||||
}
|
|
||||||
stain_cells[cell_pos] = stain;
|
|
||||||
drynesses[cell_pos] = dryness;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear cells
|
{
|
||||||
ground_cells[cell_pos] = 0;
|
|
||||||
air_cells[cell_pos] = 0;
|
|
||||||
|
|
||||||
// Clear densities
|
|
||||||
ground_densities[cell_pos] = 0;
|
|
||||||
air_densities[cell_pos] = 0;
|
|
||||||
|
|
||||||
// Reset occluders
|
|
||||||
V_OccluderKind occluder = V_OccluderKind_None;
|
V_OccluderKind occluder = V_OccluderKind_None;
|
||||||
if (tile == P_TileKind_Wall)
|
if (tile == P_TileKind_Wall)
|
||||||
{
|
{
|
||||||
@ -153,6 +117,49 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
}
|
}
|
||||||
occluders[cell_pos] = occluder;
|
occluders[cell_pos] = occluder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Reset particle layers
|
||||||
|
|
||||||
|
Vec4 new_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]);
|
||||||
|
RWTexture2D<u32> densities = G_Dereference<u32>(frame.particle_densities[layer]);
|
||||||
|
u32 packed = cells[cell_pos];
|
||||||
|
if (packed & (1 << 31))
|
||||||
|
{
|
||||||
|
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
cells[cell_pos] = 0;
|
||||||
|
densities[cell_pos] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Update stains
|
||||||
|
|
||||||
|
if (frame.should_clear_particles)
|
||||||
|
{
|
||||||
|
stains[cell_pos] = 0;
|
||||||
|
drynesses[cell_pos] = 0;
|
||||||
|
}
|
||||||
|
else if (new_stain.a > 0)
|
||||||
|
{
|
||||||
|
Vec4 stain = stains[cell_pos];
|
||||||
|
stain = BlendPremul(new_stain, stain);
|
||||||
|
stains[cell_pos] = stain;
|
||||||
|
drynesses[cell_pos] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f32 dry_rate = frame.dt * 0.1;
|
||||||
|
drynesses[cell_pos] = lerp(drynesses[cell_pos], 1, dry_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Clear particles
|
//- Clear particles
|
||||||
@ -210,7 +217,7 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
|
|||||||
Vec2 world_pos = input.world_pos;
|
Vec2 world_pos = input.world_pos;
|
||||||
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1));
|
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1));
|
||||||
|
|
||||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(occluders));
|
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < P_WorldCellsDims);
|
||||||
|
|
||||||
Vec4 albedo = tex.Sample(sampler, input.samp_uv);
|
Vec4 albedo = tex.Sample(sampler, input.samp_uv);
|
||||||
|
|
||||||
@ -270,13 +277,6 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_GpuConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_GpuConst_Frame)[0];
|
||||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
||||||
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_cells);
|
|
||||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
|
||||||
RWTexture2D<u32> air_cells = G_Dereference<u32>(frame.air_cells);
|
|
||||||
RWTexture2D<u32> stain_densities = G_Dereference<u32>(frame.stain_densities);
|
|
||||||
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> occluders = G_Dereference<u32>(frame.occluders);
|
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
||||||
|
|
||||||
u32 particle_idx = SV_DispatchThreadID;
|
u32 particle_idx = SV_DispatchThreadID;
|
||||||
@ -317,17 +317,29 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
particle.velocity = Vec2(cos(initial_angle), sin(initial_angle)) * initial_speed;
|
particle.velocity = Vec2(cos(initial_angle), sin(initial_angle)) * initial_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
||||||
{
|
{
|
||||||
V_ParticleDesc desc = V_DescFromParticleKind((V_ParticleKind)particle.kind);
|
V_ParticleDesc desc = V_DescFromParticleKind((V_ParticleKind)particle.kind);
|
||||||
|
RWTexture2D<u32> cells = G_Dereference<u32>(frame.particle_cells[desc.layer]);
|
||||||
|
RWTexture2D<u32> densities = G_Dereference<u32>(frame.particle_densities[desc.layer]);
|
||||||
|
|
||||||
u32 packed = 0;
|
u32 packed = 0;
|
||||||
packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
||||||
packed |= (particle.kind & 0xFF) << 24;
|
packed |= (particle.kind & 0xFF) << 24;
|
||||||
packed |= 1 << 31;
|
|
||||||
StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
||||||
StaticAssert(V_ParticleKind_COUNT <= 0x7F); // particle kind must fit in 7 bits
|
StaticAssert(V_ParticleKind_COUNT <= 0x7F); // particle kind must fit in 7 bits
|
||||||
|
|
||||||
|
if (AnyBit(desc.flags, V_ParticleFlag_StainTrail))
|
||||||
|
{
|
||||||
|
packed |= 1 << 31;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Move
|
//- Move
|
||||||
|
|
||||||
@ -397,13 +409,13 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
Vec2 cell_screen_pos_p1 = mul(frame.af.world_to_screen, Vec3(mul(frame.af.cell_to_world, Vec3(ceil(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);
|
cell_screen_pos_p1 = max(cell_screen_pos_p1, cell_screen_pos_p0 + 1);
|
||||||
|
|
||||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(air_cells));
|
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < P_WorldCellsDims);
|
||||||
b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||||
|
|
||||||
if (is_in_world)
|
if (is_in_world)
|
||||||
{
|
{
|
||||||
f32 stain_delta = abs(t_diff) * desc.stain_rate * frame.dt;
|
f32 commit_delta = abs(t_diff) * desc.commit_rate * frame.dt;
|
||||||
particle.stain_accum += stain_delta;
|
particle.commit_accum += commit_delta;
|
||||||
|
|
||||||
//- Handle collision
|
//- Handle collision
|
||||||
V_OccluderKind occluder = (V_OccluderKind)occluders[cell_pos];
|
V_OccluderKind occluder = (V_OccluderKind)occluders[cell_pos];
|
||||||
@ -450,49 +462,31 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AnyBit(desc.flags, V_ParticleFlag_PruneWhenStill))
|
if (!AnyBit(desc.flags, V_ParticleFlag_NoPruneWhenStill) && dot(particle.velocity, particle.velocity) < 0.0001)
|
||||||
{
|
|
||||||
if (dot(particle.velocity, particle.velocity) < 0.0001)
|
|
||||||
{
|
{
|
||||||
prune = 1;
|
prune = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (prune && AnyBit(desc.flags, V_ParticleFlag_StainWhenPruned))
|
if (prune)
|
||||||
{
|
{
|
||||||
particle.stain_accum += 1;
|
done = 1;
|
||||||
|
if (AnyBit(desc.flags, V_ParticleFlag_StainWhenPruned))
|
||||||
|
{
|
||||||
|
// particle.commit_accum = max(particle.commit_accum, 1);
|
||||||
|
particle.commit_accum += 1;
|
||||||
|
packed |= 1 << 31;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!collision)
|
if (!collision)
|
||||||
{
|
{
|
||||||
//- Stain
|
u32 commit_count = floor(particle.commit_accum);
|
||||||
u32 stains_count = floor(particle.stain_accum);
|
u32 density = commit_count;
|
||||||
if (stains_count > 0)
|
|
||||||
{
|
|
||||||
// TODO: Fixed point
|
|
||||||
u32 density = round(stains_count * rand_density);
|
|
||||||
InterlockedMax(stain_cells[cell_pos], packed);
|
|
||||||
InterlockedAdd(stain_densities[cell_pos], density);
|
|
||||||
drynesses[cell_pos] = 0;
|
|
||||||
particle.stain_accum -= stains_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Draw
|
|
||||||
{
|
{
|
||||||
b32 should_draw_ground = is_visible && AnyBit(desc.flags, V_ParticleFlag_Ground);
|
InterlockedMax(cells[cell_pos], packed);
|
||||||
b32 should_draw_air = is_visible && AnyBit(desc.flags, V_ParticleFlag_Air);
|
InterlockedAdd(densities[cell_pos], density);
|
||||||
|
particle.commit_accum -= commit_count;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,6 +512,230 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
particle.life += frame.dt;
|
particle.life += frame.dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (particle.kind > V_ParticleKind_None && particle.kind < V_ParticleKind_COUNT)
|
||||||
|
// {
|
||||||
|
// V_ParticleDesc desc = V_DescFromParticleKind((V_ParticleKind)particle.kind);
|
||||||
|
|
||||||
|
// u32 packed = 0;
|
||||||
|
// packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
||||||
|
// packed |= (particle.kind & 0xFF) << 24;
|
||||||
|
// packed |= 1 << 31;
|
||||||
|
// StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
||||||
|
// StaticAssert(V_ParticleKind_COUNT <= 0x7F); // particle kind must fit in 6 bits
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Move
|
||||||
|
|
||||||
|
// b32 collision = 0;
|
||||||
|
|
||||||
|
// // TODO: Clip to avoid unnecessary iterations outside of world bounds
|
||||||
|
// {
|
||||||
|
// Vec2 p0 = particle.pos;
|
||||||
|
// Vec2 p1 = particle.pos + particle.velocity * frame.dt;
|
||||||
|
// f32 t = 1;
|
||||||
|
// {
|
||||||
|
// Vec2 occluder_p0 = mul(frame.af.world_to_cell, Vec3(p0, 1));
|
||||||
|
// Vec2 occluder_p1 = mul(frame.af.world_to_cell, Vec3(p1, 1));
|
||||||
|
// Vec2I32 cell_p0 = floor(occluder_p0);
|
||||||
|
// Vec2I32 cell_p1 = floor(occluder_p1);
|
||||||
|
|
||||||
|
// Vec2 delta = occluder_p1 - occluder_p0;
|
||||||
|
// Vec2 inv_delta = 1.0 / delta;
|
||||||
|
// Vec2 dda_step_dir = Vec2((delta.x > 0) - (delta.x < 0), (delta.y > 0) - (delta.y < 0));
|
||||||
|
// Vec2 t_delta = abs(inv_delta);
|
||||||
|
// Vec2 t_max = cell_p0 - occluder_p0;
|
||||||
|
// t_max.x += dda_step_dir.x > 0;
|
||||||
|
// t_max.y += dda_step_dir.y > 0;
|
||||||
|
// t_max *= inv_delta;
|
||||||
|
// t_max = abs(t_max);
|
||||||
|
|
||||||
|
// Vec2 t_hit = 0;
|
||||||
|
|
||||||
|
// Vec2I32 cell_pos = cell_p0;
|
||||||
|
|
||||||
|
// b32 stepped_x = 0;
|
||||||
|
// b32 stepped_y = 0;
|
||||||
|
|
||||||
|
// // 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)
|
||||||
|
// {
|
||||||
|
// if (cell_pos.x == cell_p1.x && cell_pos.y == cell_p1.y)
|
||||||
|
// {
|
||||||
|
// done = 1;
|
||||||
|
// }
|
||||||
|
// else if (t_max.x < t_max.y)
|
||||||
|
// {
|
||||||
|
// cell_pos.x += dda_step_dir.x;
|
||||||
|
// f32 old = t_hit.x;
|
||||||
|
// t_hit.x = t_max.x - t_delta.x;
|
||||||
|
// t_diff = t_hit.x - old;
|
||||||
|
// t_max.x += t_delta.x;
|
||||||
|
// stepped_x = 1;
|
||||||
|
// stepped_y = 0;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// cell_pos.y += dda_step_dir.y;
|
||||||
|
// f32 old = t_hit.y;
|
||||||
|
// t_hit.y = t_max.y - t_delta.y;
|
||||||
|
// t_diff = t_hit.y - old;
|
||||||
|
// t_max.y += t_delta.y;
|
||||||
|
// stepped_x = 0;
|
||||||
|
// stepped_y = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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 is_in_world = all(cell_pos >= 0) && all(cell_pos < P_WorldCellsDims);
|
||||||
|
// b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||||
|
|
||||||
|
// if (is_in_world)
|
||||||
|
// {
|
||||||
|
// f32 commit_delta = abs(t_diff) * desc.commit_rate * frame.dt;
|
||||||
|
// particle.commit_accum += commit_delta;
|
||||||
|
|
||||||
|
// //- Handle collision
|
||||||
|
// V_OccluderKind occluder = (V_OccluderKind)occluders[cell_pos];
|
||||||
|
// if (occluder != V_OccluderKind_None)
|
||||||
|
// {
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (AnyBit(desc.flags, V_ParticleFlag_PruneWhenStill))
|
||||||
|
// {
|
||||||
|
// if (dot(particle.velocity, particle.velocity) < 0.0001)
|
||||||
|
// {
|
||||||
|
// prune = 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (prune && AnyBit(desc.flags, V_ParticleFlag_StainWhenPruned))
|
||||||
|
// {
|
||||||
|
// particle.commit_accum += 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!collision)
|
||||||
|
// {
|
||||||
|
// //- Stain
|
||||||
|
// u32 stains_count = floor(particle.commit_accum);
|
||||||
|
// if (stains_count > 0)
|
||||||
|
// {
|
||||||
|
// // TODO: Fixed point
|
||||||
|
// u32 density = round(stains_count * rand_density);
|
||||||
|
// InterlockedMax(stain_cells[cell_pos], packed);
|
||||||
|
// InterlockedAdd(stain_densities[cell_pos], density);
|
||||||
|
// drynesses[cell_pos] = 0;
|
||||||
|
// particle.commit_accum -= stains_count;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //- Draw
|
||||||
|
// {
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// done = 1;
|
||||||
|
// prune = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// particle.cells_count += 1;
|
||||||
|
// iteration_idx += 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// f32 falloff = saturate(lerp(10, 20, rand_falloff) * frame.dt);
|
||||||
|
// // f32 falloff = saturate(lerp(1, 2, rand_falloff) * frame.dt);
|
||||||
|
// particle.velocity *= 1.0f - falloff;
|
||||||
|
|
||||||
|
// particle.pos = p0 + (p1 - p0) * t;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Increment life
|
||||||
|
// particle.life += frame.dt;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (prune)
|
if (prune)
|
||||||
{
|
{
|
||||||
particle.kind = V_ParticleKind_None;
|
particle.kind = V_ParticleKind_None;
|
||||||
@ -540,7 +758,6 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
|||||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
||||||
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
|
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
|
||||||
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_cells);
|
|
||||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||||
|
|
||||||
Vec2 shade_pos = SV_DispatchThreadID + 0.5;
|
Vec2 shade_pos = SV_DispatchThreadID + 0.5;
|
||||||
@ -551,7 +768,7 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
|||||||
P_TileKind tile = tiles[tile_pos];
|
P_TileKind tile = tiles[tile_pos];
|
||||||
|
|
||||||
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
||||||
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(stain_cells));
|
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < P_WorldCellsDims);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Compute result
|
//- Compute result
|
||||||
@ -577,12 +794,7 @@ ComputeShader2D(V_CompositeCS, 8, 8)
|
|||||||
SamplerState sampler = G_Dereference(frame.basic_samplers[G_BasicSamplerKind_PointClamp]);
|
SamplerState sampler = G_Dereference(frame.basic_samplers[G_BasicSamplerKind_PointClamp]);
|
||||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
||||||
RWTexture2D<Vec4> screen_tex = G_Dereference<Vec4>(frame.screen_rw);
|
RWTexture2D<Vec4> screen_tex = G_Dereference<Vec4>(frame.screen_rw);
|
||||||
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_cells);
|
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
||||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
|
||||||
RWTexture2D<u32> stain_densities = G_Dereference<u32>(frame.stain_densities);
|
|
||||||
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<f32> drynesses = G_Dereference<f32>(frame.drynesses);
|
||||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||||
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
|
||||||
@ -596,7 +808,7 @@ ComputeShader2D(V_CompositeCS, 8, 8)
|
|||||||
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
|
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_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));
|
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(ground_cells));
|
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < P_WorldCellsDims);
|
||||||
b32 is_in_screen = all(screen_pos >= 0) && all(screen_pos < countof(screen_tex));
|
b32 is_in_screen = all(screen_pos >= 0) && all(screen_pos < countof(screen_tex));
|
||||||
|
|
||||||
P_TileKind tile = tiles[tile_pos];
|
P_TileKind tile = tiles[tile_pos];
|
||||||
@ -698,76 +910,129 @@ ComputeShader2D(V_CompositeCS, 8, 8)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Particles
|
//- Particles
|
||||||
|
|
||||||
Vec4 stain_particle_color = 0;
|
// FIXME: Stain
|
||||||
Vec4 ground_particle_color = 0;
|
Vec4 stain_color = 0;
|
||||||
Vec4 air_particle_color = 0;
|
|
||||||
{
|
{
|
||||||
//- Stain
|
Vec4 orig_stain = stains[cell_pos];
|
||||||
|
|
||||||
|
// FIXME: Dryness
|
||||||
|
// f32 dryness = drynesses[cell_pos];
|
||||||
|
stain_color = orig_stain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vec4 particle_color = 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]);
|
||||||
u32 packed = stain_cells[cell_pos];
|
RWTexture2D<u32> densities = G_Dereference<u32>(frame.particle_densities[layer]);
|
||||||
|
u32 packed = cells[cell_pos];
|
||||||
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
||||||
if (particle_kind != V_ParticleKind_None)
|
if (particle_kind != V_ParticleKind_None)
|
||||||
{
|
{
|
||||||
|
u32 density = densities[cell_pos];
|
||||||
|
V_ParticleDesc desc = V_DescFromParticleKind(particle_kind);
|
||||||
u32 particle_idx = packed & ((1 << 24) - 1);
|
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||||
u32 density = stain_densities[cell_pos];
|
Vec4 cell_color = V_ColorFromParticle(desc, particle_idx, density);
|
||||||
f32 dryness = drynesses[cell_pos];
|
cell_color.rgb *= cell_color.a;
|
||||||
stain_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, dryness);
|
particle_color = BlendPremul(cell_color, particle_color);
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
//- Compose world
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// world_color = BlendPremul(shade_color, world_color);
|
// world_color = BlendPremul(shade_color, world_color);
|
||||||
world_color = BlendPremul(stain_particle_color, world_color);
|
|
||||||
world_color = BlendPremul(ground_particle_color, world_color);
|
|
||||||
if (!tile_is_wall)
|
if (!tile_is_wall)
|
||||||
{
|
{
|
||||||
world_color = BlendPremul(tile_color, world_color); // Blend ground tile
|
world_color = BlendPremul(tile_color, world_color); // Blend ground tile
|
||||||
world_color = BlendPremul(stain_particle_color, world_color); // Blend ground stain
|
world_color = BlendPremul(stain_color, world_color); // Blend ground stain
|
||||||
world_color = BlendPremul(ground_particle_color, world_color); // Blend ground particle
|
world_color = BlendPremul(particle_color, world_color); // Blend ground particle
|
||||||
}
|
}
|
||||||
world_color = BlendPremul(albedo_tex_color, world_color);
|
world_color = BlendPremul(albedo_tex_color, world_color);
|
||||||
if (tile_is_wall)
|
if (tile_is_wall)
|
||||||
{
|
{
|
||||||
world_color = BlendPremul(tile_color, world_color); // Blend wall tile
|
world_color = BlendPremul(tile_color, world_color); // Blend wall tile
|
||||||
world_color = BlendPremul(stain_particle_color, world_color); // Blend wall stain
|
world_color = BlendPremul(stain_color, world_color); // Blend wall stain
|
||||||
world_color = BlendPremul(ground_particle_color, world_color); // Blend wall particle
|
world_color = BlendPremul(particle_color, world_color); // Blend wall particle
|
||||||
}
|
}
|
||||||
world_color = BlendPremul(air_particle_color, world_color);
|
|
||||||
|
|
||||||
|
|
||||||
|
// // world_color = BlendPremul(shade_color, world_color);
|
||||||
|
// world_color = BlendPremul(stain_particle_color, world_color);
|
||||||
|
// world_color = BlendPremul(ground_particle_color, world_color);
|
||||||
|
// if (!tile_is_wall)
|
||||||
|
// {
|
||||||
|
// world_color = BlendPremul(tile_color, world_color); // Blend ground tile
|
||||||
|
// world_color = BlendPremul(stain_particle_color, world_color); // Blend ground stain
|
||||||
|
// 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_particle_color, world_color); // Blend wall stain
|
||||||
|
// world_color = BlendPremul(ground_particle_color, world_color); // Blend wall particle
|
||||||
|
// }
|
||||||
|
// world_color = BlendPremul(air_particle_color, world_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|||||||
@ -45,7 +45,7 @@ Struct(V_DVertPSOutput)
|
|||||||
//~ Helpers
|
//~ Helpers
|
||||||
|
|
||||||
f32 V_RandFromPos(Vec3 pos);
|
f32 V_RandFromPos(Vec3 pos);
|
||||||
Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 density, f32 dryness);
|
Vec4 V_ColorFromParticle(V_ParticleDesc desc, u32 particle_idx, u32 density);
|
||||||
Vec3 V_ToneMap(Vec3 v);
|
Vec3 V_ToneMap(Vec3 v);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -11,42 +11,49 @@ V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind)
|
|||||||
V_ParticleDesc result;
|
V_ParticleDesc result;
|
||||||
{
|
{
|
||||||
PERSIST Readonly V_ParticleFlag flags[V_ParticleKind_COUNT] = {
|
PERSIST Readonly V_ParticleFlag flags[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) flags,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) flags,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 stain_rates[V_ParticleKind_COUNT] = {
|
PERSIST Readonly V_ParticleLayer layers[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) stain_rate,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) layer,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
PERSIST Readonly f32 commit_rates[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) commit_rate,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 pen_rates[V_ParticleKind_COUNT] = {
|
PERSIST Readonly f32 pen_rates[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) pen_rate,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) pen_rate,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 r[V_ParticleKind_COUNT] = {
|
PERSIST Readonly f32 r[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) r,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) r,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 g[V_ParticleKind_COUNT] = {
|
PERSIST Readonly f32 g[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) g,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) g,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 b[V_ParticleKind_COUNT] = {
|
PERSIST Readonly f32 b[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) b,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) b,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
PERSIST Readonly f32 a[V_ParticleKind_COUNT] = {
|
PERSIST Readonly f32 a[V_ParticleKind_COUNT] = {
|
||||||
#define X(name, flags, stain_rate, pen_rate, r, g, b, a) a,
|
#define X(name, flags, layer, commit_rate, pen_rate, r, g, b, a) a,
|
||||||
V_ParticlesXList(X)
|
V_ParticlesXList(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
result.kind = kind;
|
||||||
result.flags = flags[kind];
|
result.flags = flags[kind];
|
||||||
result.stain_rate = stain_rates[kind];
|
result.layer = layers[kind];
|
||||||
|
result.commit_rate = commit_rates[kind];
|
||||||
result.pen_rate = pen_rates[kind];
|
result.pen_rate = pen_rates[kind];
|
||||||
result.color = LinearFromSrgb(VEC4(r[kind], g[kind], b[kind], a[kind]));
|
result.color = LinearFromSrgb(VEC4(r[kind], g[kind], b[kind], a[kind]));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,176 @@ G_DeclConstant(G_Texture3DRef, V_GpuConst_NoiseTex, 2);
|
|||||||
G_DeclConstant(G_Texture2DRef, V_GpuConst_BloomRead, 3);
|
G_DeclConstant(G_Texture2DRef, V_GpuConst_BloomRead, 3);
|
||||||
G_DeclConstant(G_RWTexture2DRef, V_GpuConst_BloomWrite, 4);
|
G_DeclConstant(G_RWTexture2DRef, V_GpuConst_BloomWrite, 4);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Occluder types
|
||||||
|
|
||||||
|
Enum(V_OccluderKind)
|
||||||
|
{
|
||||||
|
V_OccluderKind_None,
|
||||||
|
V_OccluderKind_Guy,
|
||||||
|
V_OccluderKind_Wall,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Particle types
|
||||||
|
|
||||||
|
#define V_ParticleSimBasis 0xb49f2d9e406873b9ull
|
||||||
|
#define V_ParticleColorBasis 0x569aa8341ecc0ea3ull
|
||||||
|
#define V_ParticleCellBasis 0xf60c0cff344b0c5dull
|
||||||
|
#define V_ParticleStainBasis 0x3c64e8226d98d376ull
|
||||||
|
|
||||||
|
Enum(V_ParticleFlag)
|
||||||
|
{
|
||||||
|
V_ParticleFlag_None = 0,
|
||||||
|
V_ParticleFlag_NoPruneWhenStill = (1 << 0),
|
||||||
|
V_ParticleFlag_StainWhenPruned = (1 << 1),
|
||||||
|
V_ParticleFlag_NoReflect = (1 << 2),
|
||||||
|
V_ParticleFlag_StainTrail = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
Enum(V_ParticleLayer)
|
||||||
|
{
|
||||||
|
V_ParticleLayer_Ground,
|
||||||
|
V_ParticleLayer_Mid,
|
||||||
|
V_ParticleLayer_Air,
|
||||||
|
|
||||||
|
V_ParticleLayer_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: Higher particle enum values take priority over lower ones
|
||||||
|
#define V_ParticlesXList(X) \
|
||||||
|
X( \
|
||||||
|
/* Name */ None, \
|
||||||
|
/* Flags */ V_ParticleFlag_None, \
|
||||||
|
/* Layer */ V_ParticleLayer_Ground, \
|
||||||
|
/* Commit rate, pen chance */ 30, 0, \
|
||||||
|
/* Base color */ 0, 0, 0, 0 \
|
||||||
|
) \
|
||||||
|
\
|
||||||
|
/* Ground particles */ \
|
||||||
|
X( \
|
||||||
|
/* Name */ BloodTrail, \
|
||||||
|
/* Flags */ V_ParticleFlag_NoReflect | V_ParticleFlag_StainTrail, \
|
||||||
|
/* Layer */ V_ParticleLayer_Ground, \
|
||||||
|
/* Commit rate, pen chance */ 500, 0.25, \
|
||||||
|
/* Base color */ 0.5, 0.1, 0.1, 0.1 \
|
||||||
|
) \
|
||||||
|
X( \
|
||||||
|
/* Name */ BloodDebris, \
|
||||||
|
/* Flags */ V_ParticleFlag_StainWhenPruned, \
|
||||||
|
/* Layer */ V_ParticleLayer_Mid, \
|
||||||
|
/* Commit rate, pen chance */ 30, 0, \
|
||||||
|
/* Base color */ 0.5, 0.1, 0.1, 0.8 \
|
||||||
|
) \
|
||||||
|
X( \
|
||||||
|
/* Name */ Debris, \
|
||||||
|
/* Flags */ V_ParticleFlag_StainWhenPruned, \
|
||||||
|
/* Layer */ V_ParticleLayer_Mid, \
|
||||||
|
/* Commit rate, pen chance */ 10000, 0, \
|
||||||
|
/* Base color */ 2, 0.5, 0, 1 \
|
||||||
|
) \
|
||||||
|
\
|
||||||
|
/* Air particles */ \
|
||||||
|
X( \
|
||||||
|
/* Name */ Smoke, \
|
||||||
|
/* Flags */ V_ParticleFlag_None, \
|
||||||
|
/* Layer */ V_ParticleLayer_Air, \
|
||||||
|
/* Commit rate, pen chance */ 30, 0, \
|
||||||
|
/* Base color */ 0.15, 0.15, 0.15, 0.5 \
|
||||||
|
) \
|
||||||
|
X( \
|
||||||
|
/* Name */ BulletTrail, \
|
||||||
|
/* Flags */ V_ParticleFlag_None, \
|
||||||
|
/* Layer */ V_ParticleLayer_Air, \
|
||||||
|
/* Commit rate, pen chance */ 30, 0, \
|
||||||
|
/* Base color */ 1, 0, 1, 1 \
|
||||||
|
) \
|
||||||
|
\
|
||||||
|
/* Test particles */ \
|
||||||
|
X( \
|
||||||
|
/* Name */ Test, \
|
||||||
|
/* Flags */ V_ParticleFlag_None, \
|
||||||
|
/* Layer */ V_ParticleLayer_Mid, \
|
||||||
|
/* Commit rate, pen chance */ 30, 0, \
|
||||||
|
/* Base color */ 1, 1, 0, 1 \
|
||||||
|
) \
|
||||||
|
/* ----------------------------------------------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
Enum(V_ParticleKind)
|
||||||
|
{
|
||||||
|
#define X(name, ...) V_ParticleKind_##name,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
V_ParticleKind_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_Emitter)
|
||||||
|
{
|
||||||
|
V_ParticleKind kind;
|
||||||
|
|
||||||
|
u32 first_particle_seq;
|
||||||
|
u32 count;
|
||||||
|
|
||||||
|
Rng2 pos;
|
||||||
|
Rng speed;
|
||||||
|
Rng angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Pack this efficiently
|
||||||
|
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 commit_accum;
|
||||||
|
u32 cells_count;
|
||||||
|
Vec2 pos;
|
||||||
|
Vec2 velocity;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_ParticleDesc)
|
||||||
|
{
|
||||||
|
V_ParticleKind kind;
|
||||||
|
V_ParticleFlag flags;
|
||||||
|
V_ParticleLayer layer;
|
||||||
|
f32 commit_rate;
|
||||||
|
f32 pen_rate;
|
||||||
|
Vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if IsCpu
|
||||||
|
Struct(V_EmitterNode)
|
||||||
|
{
|
||||||
|
V_EmitterNode *next;
|
||||||
|
V_Emitter emitter;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Quad types
|
||||||
|
|
||||||
|
Enum(V_QuadFlag)
|
||||||
|
{
|
||||||
|
V_QuadFlag_None = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_Quad)
|
||||||
|
{
|
||||||
|
V_QuadFlag flags;
|
||||||
|
V_OccluderKind occluder;
|
||||||
|
Affine quad_uv_to_world_af;
|
||||||
|
G_Texture2DRef tex;
|
||||||
|
Rng2 tex_slice_uv;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Debug vert types
|
||||||
|
|
||||||
|
Struct(V_DVert)
|
||||||
|
{
|
||||||
|
Vec2 pos;
|
||||||
|
Vec4 color_lin;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
|
|
||||||
@ -161,172 +331,17 @@ Struct(V_SharedFrame)
|
|||||||
G_StructuredBufferRef emitters;
|
G_StructuredBufferRef emitters;
|
||||||
G_RWStructuredBufferRef particles;
|
G_RWStructuredBufferRef particles;
|
||||||
|
|
||||||
G_RWTexture2DRef stain_cells;
|
G_RWTexture2DRef stains;
|
||||||
G_RWTexture2DRef ground_cells;
|
|
||||||
G_RWTexture2DRef air_cells;
|
|
||||||
G_RWTexture2DRef stain_densities;
|
|
||||||
G_RWTexture2DRef ground_densities;
|
|
||||||
G_RWTexture2DRef air_densities;
|
|
||||||
G_RWTexture2DRef drynesses;
|
G_RWTexture2DRef drynesses;
|
||||||
G_RWTexture2DRef occluders;
|
G_RWTexture2DRef occluders;
|
||||||
|
|
||||||
|
G_RWTexture2DRef particle_cells[V_ParticleLayer_COUNT];
|
||||||
|
G_RWTexture2DRef particle_densities[V_ParticleLayer_COUNT];
|
||||||
|
|
||||||
G_StructuredBufferRef dverts;
|
G_StructuredBufferRef dverts;
|
||||||
G_StructuredBufferRef quads;
|
G_StructuredBufferRef quads;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Occluder types
|
|
||||||
|
|
||||||
Enum(V_OccluderKind)
|
|
||||||
{
|
|
||||||
V_OccluderKind_None,
|
|
||||||
V_OccluderKind_Guy,
|
|
||||||
V_OccluderKind_Wall,
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Particle types
|
|
||||||
|
|
||||||
#define V_ParticleSimBasis 0xb49f2d9e406873b9ull
|
|
||||||
#define V_ParticleColorBasis 0x569aa8341ecc0ea3ull
|
|
||||||
#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_NoReflect = (1 << 4),
|
|
||||||
};
|
|
||||||
|
|
||||||
// NOTE: Higher particle enum values take priority over lower ones
|
|
||||||
#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 */ BloodTrail, \
|
|
||||||
/* Flags */ V_ParticleFlag_NoReflect, \
|
|
||||||
/* Stain rate, pen chance */ 500, 0.25, \
|
|
||||||
/* Base color */ 0.5, 0.1, 0.1, 0.1 \
|
|
||||||
) \
|
|
||||||
X( \
|
|
||||||
/* Name */ BloodDebris, \
|
|
||||||
/* Flags */ V_ParticleFlag_Ground | V_ParticleFlag_PruneWhenStill | V_ParticleFlag_StainWhenPruned, \
|
|
||||||
/* Stain rate, pen chance */ 1, 0, \
|
|
||||||
/* Base color */ 0.5, 0.1, 0.1, 0.8 \
|
|
||||||
) \
|
|
||||||
X( \
|
|
||||||
/* Name */ Debris, \
|
|
||||||
/* Flags */ V_ParticleFlag_Ground | V_ParticleFlag_PruneWhenStill | V_ParticleFlag_StainWhenPruned, \
|
|
||||||
/* Stain rate, pen chance */ 0, 0, \
|
|
||||||
/* Base color */ 2, 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)
|
|
||||||
{
|
|
||||||
#define X(name, ...) V_ParticleKind_##name,
|
|
||||||
V_ParticlesXList(X)
|
|
||||||
#undef X
|
|
||||||
V_ParticleKind_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(V_Emitter)
|
|
||||||
{
|
|
||||||
V_ParticleKind kind;
|
|
||||||
|
|
||||||
u32 first_particle_seq;
|
|
||||||
u32 count;
|
|
||||||
|
|
||||||
Rng2 pos;
|
|
||||||
Rng speed;
|
|
||||||
Rng angle;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Pack this efficiently
|
|
||||||
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 cells_count;
|
|
||||||
Vec2 pos;
|
|
||||||
Vec2 velocity;
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(V_ParticleDesc)
|
|
||||||
{
|
|
||||||
V_ParticleFlag flags;
|
|
||||||
f32 stain_rate;
|
|
||||||
f32 pen_rate;
|
|
||||||
Vec4 color;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if IsCpu
|
|
||||||
Struct(V_EmitterNode)
|
|
||||||
{
|
|
||||||
V_EmitterNode *next;
|
|
||||||
V_Emitter emitter;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Quad types
|
|
||||||
|
|
||||||
Enum(V_QuadFlag)
|
|
||||||
{
|
|
||||||
V_QuadFlag_None = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(V_Quad)
|
|
||||||
{
|
|
||||||
V_QuadFlag flags;
|
|
||||||
V_OccluderKind occluder;
|
|
||||||
Affine quad_uv_to_world_af;
|
|
||||||
G_Texture2DRef tex;
|
|
||||||
Rng2 tex_slice_uv;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Debug vert types
|
|
||||||
|
|
||||||
Struct(V_DVert)
|
|
||||||
{
|
|
||||||
Vec2 pos;
|
|
||||||
Vec4 color_lin;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Helpers
|
//~ Helpers
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user