particle descs
This commit is contained in:
parent
a4bb13d59d
commit
e4426ab0d2
@ -15,8 +15,6 @@ typedef uint2 Vec2U32;
|
|||||||
typedef uint3 Vec3U32;
|
typedef uint3 Vec3U32;
|
||||||
typedef uint4 Vec4U32;
|
typedef uint4 Vec4U32;
|
||||||
typedef float2x3 Affine;
|
typedef float2x3 Affine;
|
||||||
typedef float4 Rect;
|
|
||||||
typedef float4 ClipRect;
|
|
||||||
typedef float4 Aabb;
|
typedef float4 Aabb;
|
||||||
typedef float4 Quad;
|
typedef float4 Quad;
|
||||||
typedef float4x4 Mat4x4;
|
typedef float4x4 Mat4x4;
|
||||||
@ -48,6 +46,17 @@ u32 countof(T arr[N])
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ C -> HLSL interoperability stubs
|
//~ C -> HLSL interoperability stubs
|
||||||
|
|
||||||
|
//- Constructors
|
||||||
|
#define VEC2(...) Vec2(__VA_ARGS__)
|
||||||
|
#define VEC3(...) Vec3(__VA_ARGS__)
|
||||||
|
#define VEC4(...) Vec4(__VA_ARGS__)
|
||||||
|
#define VEC2I32(...) Vec2I32(__VA_ARGS__)
|
||||||
|
#define VEC3I32(...) Vec3I32(__VA_ARGS__)
|
||||||
|
#define VEC4I32(...) Vec4I32(__VA_ARGS__)
|
||||||
|
#define VEC2U32(...) Vec2U32(__VA_ARGS__)
|
||||||
|
#define VEC3U32(...) Vec3U32(__VA_ARGS__)
|
||||||
|
#define VEC4U32(...) Vec4U32(__VA_ARGS__)
|
||||||
|
|
||||||
//- Min
|
//- Min
|
||||||
#define MinU8 (u8)min
|
#define MinU8 (u8)min
|
||||||
#define MinI8 (i8)min
|
#define MinI8 (i8)min
|
||||||
|
|||||||
2
src/pp/pp_vis/pp_vis.lay
generated
2
src/pp/pp_vis/pp_vis.lay
generated
@ -41,5 +41,7 @@
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Impl
|
//- Impl
|
||||||
|
|
||||||
|
@IncludeC pp_vis_shared.cg
|
||||||
@IncludeC pp_vis_core.c
|
@IncludeC pp_vis_core.c
|
||||||
|
@IncludeG pp_vis_shared.cg
|
||||||
@IncludeG pp_vis_gpu.g
|
@IncludeG pp_vis_gpu.g
|
||||||
|
|||||||
@ -392,9 +392,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// 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_stains_res = Zi;
|
G_ResourceHandle gpu_stain_cells_res = Zi;
|
||||||
G_ResourceHandle gpu_ground_cells_res = Zi;
|
G_ResourceHandle gpu_ground_cells_res = Zi;
|
||||||
G_ResourceHandle gpu_air_cells_res = Zi;
|
G_ResourceHandle gpu_air_cells_res = Zi;
|
||||||
|
G_ResourceHandle gpu_stain_densities_res = Zi;
|
||||||
G_ResourceHandle gpu_ground_densities_res = Zi;
|
G_ResourceHandle gpu_ground_densities_res = Zi;
|
||||||
G_ResourceHandle gpu_air_densities_res = Zi;
|
G_ResourceHandle gpu_air_densities_res = Zi;
|
||||||
G_ResourceHandle gpu_drynesses_res = Zi;
|
G_ResourceHandle gpu_drynesses_res = Zi;
|
||||||
@ -402,9 +403,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
G_Texture2DRef gpu_tiles = Zi;
|
G_Texture2DRef gpu_tiles = Zi;
|
||||||
G_RWStructuredBufferRef gpu_particles = Zi;
|
G_RWStructuredBufferRef gpu_particles = Zi;
|
||||||
G_RWTexture2DRef gpu_stains = Zi;
|
G_RWTexture2DRef gpu_stain_cells = Zi;
|
||||||
G_RWTexture2DRef gpu_ground_cells = Zi;
|
G_RWTexture2DRef gpu_ground_cells = Zi;
|
||||||
G_RWTexture2DRef gpu_air_cells = Zi;
|
G_RWTexture2DRef gpu_air_cells = Zi;
|
||||||
|
G_RWTexture2DRef gpu_stain_densities = Zi;
|
||||||
G_RWTexture2DRef gpu_ground_densities = Zi;
|
G_RWTexture2DRef gpu_ground_densities = Zi;
|
||||||
G_RWTexture2DRef gpu_air_densities = Zi;
|
G_RWTexture2DRef gpu_air_densities = Zi;
|
||||||
G_RWTexture2DRef gpu_drynesses = Zi;
|
G_RWTexture2DRef gpu_drynesses = Zi;
|
||||||
@ -435,17 +437,17 @@ 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 stains texture
|
// Init stain cells texture
|
||||||
{
|
{
|
||||||
gpu_stains_res = G_PushTexture2D(
|
gpu_stain_cells_res = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
G_Format_R16G16B16A16_Float,
|
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("Stains")
|
.name = Lit("Stain cells")
|
||||||
);
|
);
|
||||||
gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
|
gpu_stain_cells = G_PushRWTexture2DRef(gpu_perm, gpu_stain_cells_res);
|
||||||
}
|
}
|
||||||
// Init ground cells texture
|
// Init ground cells texture
|
||||||
{
|
{
|
||||||
@ -471,6 +473,18 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
);
|
);
|
||||||
gpu_air_cells = G_PushRWTexture2DRef(gpu_perm, gpu_air_cells_res);
|
gpu_air_cells = G_PushRWTexture2DRef(gpu_perm, gpu_air_cells_res);
|
||||||
}
|
}
|
||||||
|
// Init stain densities 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
|
// Init ground densities texture
|
||||||
{
|
{
|
||||||
gpu_ground_densities_res = G_PushTexture2D(
|
gpu_ground_densities_res = G_PushTexture2D(
|
||||||
@ -631,15 +645,15 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//- Initialize persistent gpu resources
|
//- Initialize persistent gpu resources
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// Persistent resources
|
// Persistent resources
|
||||||
frame->tiles = gpu_tiles;
|
frame->tiles = gpu_tiles;
|
||||||
frame->pt_clamp_sampler = G_BasicPointClampSampler();
|
frame->pt_clamp_sampler = G_BasicPointClampSampler();
|
||||||
frame->pt_wrap_sampler = G_BasicPointWrapSampler();
|
frame->pt_wrap_sampler = G_BasicPointWrapSampler();
|
||||||
frame->particles = gpu_particles;
|
frame->particles = gpu_particles;
|
||||||
frame->stains = gpu_stains;
|
frame->stain_cells = gpu_stain_cells;
|
||||||
frame->ground_cells = gpu_ground_cells;
|
frame->ground_cells = gpu_ground_cells;
|
||||||
frame->air_cells = gpu_air_cells;
|
frame->air_cells = gpu_air_cells;
|
||||||
|
frame->stain_densities = gpu_stain_densities;
|
||||||
frame->ground_densities = gpu_ground_densities;
|
frame->ground_densities = gpu_ground_densities;
|
||||||
frame->air_densities = gpu_air_densities;
|
frame->air_densities = gpu_air_densities;
|
||||||
frame->drynesses = gpu_drynesses;
|
frame->drynesses = gpu_drynesses;
|
||||||
@ -2176,6 +2190,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
quad->quad_uv_to_world_af = wep_uv_to_world_af;
|
quad->quad_uv_to_world_af = wep_uv_to_world_af;
|
||||||
quad->tex = wep.tex;
|
quad->tex = wep.tex;
|
||||||
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
|
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
|
||||||
|
quad->occluder = P_OccluderKind_Guy;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Push body quad
|
//- Push body quad
|
||||||
@ -2187,6 +2202,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
quad->quad_uv_to_world_af = body_uv_to_world_af;
|
quad->quad_uv_to_world_af = body_uv_to_world_af;
|
||||||
quad->tex = body.tex;
|
quad->tex = body.tex;
|
||||||
quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims);
|
quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims);
|
||||||
|
quad->occluder = P_OccluderKind_Guy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2550,17 +2566,18 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
V_Emitter emitter = Zi;
|
V_Emitter emitter = Zi;
|
||||||
|
|
||||||
emitter.kind = V_ParticleKind_Test;
|
emitter.kind = V_ParticleKind_Blood;
|
||||||
|
|
||||||
f32 angle = AngleFromVec2(frame->look);
|
f32 angle = AngleFromVec2(frame->look);
|
||||||
// f32 angle = 0;
|
// f32 angle = 0;
|
||||||
// f32 angle_spread = Tau * 0.25;
|
f32 angle_spread = Tau * 0.25;
|
||||||
f32 angle_spread = Tau;
|
// f32 angle_spread = Tau;
|
||||||
// f32 angle_spread = 0;
|
// f32 angle_spread = 0;
|
||||||
|
|
||||||
// f32 speed = 25;
|
// f32 speed = 5;
|
||||||
|
f32 speed = 25;
|
||||||
// f32 speed = 50;
|
// f32 speed = 50;
|
||||||
f32 speed = 100;
|
// f32 speed = 100;
|
||||||
f32 speed_spread = speed * 2;
|
f32 speed_spread = speed * 2;
|
||||||
|
|
||||||
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
||||||
@ -2632,42 +2649,42 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Smoke
|
// Smoke
|
||||||
{
|
// {
|
||||||
V_Emitter emitter = Zi;
|
// V_Emitter emitter = Zi;
|
||||||
|
|
||||||
emitter.kind = V_ParticleKind_Smoke;
|
// emitter.kind = V_ParticleKind_Smoke;
|
||||||
|
|
||||||
f32 angle = AngleFromVec2(frame->look);
|
// f32 angle = AngleFromVec2(frame->look);
|
||||||
// f32 angle = 0;
|
// // f32 angle = 0;
|
||||||
// f32 angle_spread = Tau * 0.25;
|
// // f32 angle_spread = Tau * 0.25;
|
||||||
f32 angle_spread = Tau;
|
// f32 angle_spread = Tau;
|
||||||
// f32 angle_spread = 0;
|
// // f32 angle_spread = 0;
|
||||||
|
|
||||||
f32 speed = 25;
|
// f32 speed = 25;
|
||||||
// f32 speed = 50;
|
// // f32 speed = 50;
|
||||||
// f32 speed = 50;
|
// // f32 speed = 50;
|
||||||
f32 speed_spread = speed * 2;
|
// f32 speed_spread = speed * 2;
|
||||||
|
|
||||||
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
// emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor;
|
||||||
emitter.speed.min = speed - speed_spread * 0.5;
|
// emitter.speed.min = speed - speed_spread * 0.5;
|
||||||
emitter.speed.max = speed + speed_spread * 0.5;
|
// emitter.speed.max = speed + speed_spread * 0.5;
|
||||||
emitter.angle.min = angle - angle_spread * 0.5;
|
// emitter.angle.min = angle - angle_spread * 0.5;
|
||||||
emitter.angle.max = 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 = CeilF32(Kibi(64) * frame->dt);
|
||||||
// emitter.count = Mebi(16);
|
// // emitter.count = Mebi(16);
|
||||||
// emitter.count = Mebi(2);
|
// // emitter.count = Mebi(2);
|
||||||
// emitter.count = Kibi(32);
|
// // emitter.count = Kibi(32);
|
||||||
emitter.count = Kibi(8);
|
// emitter.count = Kibi(8);
|
||||||
// emitter.count = Kibi(1);
|
// // emitter.count = Kibi(1);
|
||||||
// emitter.count = 128;
|
// // emitter.count = 128;
|
||||||
// emitter.count = 32;
|
// // emitter.count = 32;
|
||||||
// emitter.count = 1;
|
// // emitter.count = 1;
|
||||||
|
|
||||||
V_PushParticles(emitter);
|
// V_PushParticles(emitter);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4945,9 +4962,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
G_DumbGlobalMemorySync(frame->cl);
|
G_DumbGlobalMemorySync(frame->cl);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Quads pass
|
//- Quads & emitters pass
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// Draw quads
|
||||||
G_Rasterize(
|
G_Rasterize(
|
||||||
frame->cl,
|
frame->cl,
|
||||||
V_QuadVS, V_QuadPS,
|
V_QuadVS, V_QuadPS,
|
||||||
@ -4956,29 +4974,29 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
screen_viewport, screen_scissor,
|
screen_viewport, screen_scissor,
|
||||||
G_RasterMode_TriangleList
|
G_RasterMode_TriangleList
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Emit particles
|
||||||
|
G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(frame->emitters_count));
|
||||||
|
|
||||||
|
// Sync particles & occluders
|
||||||
|
G_DumbGlobalMemorySync(frame->cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Particle simulation pass
|
//- Particle simulation pass
|
||||||
|
|
||||||
{
|
{
|
||||||
// Emit particles
|
|
||||||
G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(frame->emitters_count));
|
|
||||||
|
|
||||||
// Barrier particles buffer
|
|
||||||
G_DumbMemorySync(frame->cl, gpu_particles_res);
|
|
||||||
|
|
||||||
// Simulate particles
|
// Simulate particles
|
||||||
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
|
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
|
||||||
|
|
||||||
// Barrier since stains were written
|
// Sync cells
|
||||||
G_DumbGlobalMemorySync(frame->cl);
|
G_DumbGlobalMemorySync(frame->cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Shading pass
|
//- Shading pass
|
||||||
|
|
||||||
G_DumbGlobalMemorySync(frame->cl);
|
// TODO: Remove this
|
||||||
|
|
||||||
{
|
{
|
||||||
G_Compute(frame->cl, V_ShadeCS, V_ThreadGroupSizeFromTexSize(frame->shade_dims));
|
G_Compute(frame->cl, V_ShadeCS, V_ThreadGroupSizeFromTexSize(frame->shade_dims));
|
||||||
|
|||||||
@ -10,10 +10,54 @@ f32 V_RandFromPos(Vec3 pos)
|
|||||||
return rand;
|
return rand;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 V_DryColor(Vec4 color, f32 dryness)
|
Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 density, f32 dryness)
|
||||||
{
|
{
|
||||||
Vec4 result = color;
|
V_ParticleDesc desc = V_DescFromParticleKind(particle_kind);
|
||||||
|
|
||||||
|
Vec4 result = 0;
|
||||||
|
u64 seed = MixU64(P_ParticleColorBasis ^ particle_idx);
|
||||||
|
f32 rand_color = Norm16(seed >> 0);
|
||||||
|
|
||||||
|
result = desc.color;
|
||||||
|
|
||||||
|
// // FIXME: Base color on particle desc
|
||||||
|
// if (particle_kind == V_ParticleKind_Test)
|
||||||
|
// {
|
||||||
|
// // result.rgb = Vec3(0, 0, 0);
|
||||||
|
// result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 0.5));
|
||||||
|
// }
|
||||||
|
// else if (particle_kind == V_ParticleKind_Debris)
|
||||||
|
// {
|
||||||
|
// result = Color_Orange;
|
||||||
|
// }
|
||||||
|
// else if (particle_kind == V_ParticleKind_Smoke)
|
||||||
|
// {
|
||||||
|
// result = Vec4(0.15, 0.15, 0.15, 1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Apply density
|
||||||
|
{
|
||||||
|
if (particle_kind == V_ParticleKind_Smoke)
|
||||||
|
{
|
||||||
|
// f32 t = saturate(density / 10.0);
|
||||||
|
// f32 t = smoothstep(-10, 32, density);
|
||||||
|
f32 t = smoothstep(0, 2, (f32)density);
|
||||||
|
result.a = lerp(0, 0.85, t);
|
||||||
|
}
|
||||||
|
else if (particle_kind == V_ParticleKind_Blood)
|
||||||
|
{
|
||||||
|
f32 t = (f32)density / 10000;
|
||||||
|
t = pow(t, 2);
|
||||||
|
t = saturate(t);
|
||||||
|
result.rgb *= 1.0 - (t * 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.rgb += (rand_color - 0.5) * 0.025;
|
||||||
|
|
||||||
|
// Apply dryness
|
||||||
result.rgb *= 1.0 - (dryness * 0.75);
|
result.rgb *= 1.0 - (dryness * 0.75);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +81,10 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
{
|
{
|
||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_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<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
||||||
RWTexture2D<u32> air_cells = G_Dereference<u32>(frame.air_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> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
||||||
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_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);
|
||||||
@ -51,6 +97,28 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
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
|
||||||
|
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
|
// Clear cells
|
||||||
ground_cells[cell_pos] = 0;
|
ground_cells[cell_pos] = 0;
|
||||||
air_cells[cell_pos] = 0;
|
air_cells[cell_pos] = 0;
|
||||||
@ -59,15 +127,6 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
ground_densities[cell_pos] = 0;
|
ground_densities[cell_pos] = 0;
|
||||||
air_densities[cell_pos] = 0;
|
air_densities[cell_pos] = 0;
|
||||||
|
|
||||||
// Increase dryness
|
|
||||||
// TODO: Use simulation dt
|
|
||||||
f32 dry_rate = frame.dt * 0.1;
|
|
||||||
{
|
|
||||||
f32 old_dryness = drynesses[cell_pos];
|
|
||||||
f32 new_dryness = lerp(old_dryness, 1, dry_rate);
|
|
||||||
drynesses[cell_pos] = new_dryness;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset occluders
|
// Reset occluders
|
||||||
P_OccluderKind occluder = P_OccluderKind_None;
|
P_OccluderKind occluder = P_OccluderKind_None;
|
||||||
if (tile == P_TileKind_Wall)
|
if (tile == P_TileKind_Wall)
|
||||||
@ -75,14 +134,6 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
|
|||||||
occluder = P_OccluderKind_Wall;
|
occluder = P_OccluderKind_Wall;
|
||||||
}
|
}
|
||||||
occluders[cell_pos] = occluder;
|
occluders[cell_pos] = occluder;
|
||||||
|
|
||||||
// Clear stain
|
|
||||||
if (frame.should_clear_particles)
|
|
||||||
{
|
|
||||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
|
||||||
stains[cell_pos] = 0;
|
|
||||||
drynesses[cell_pos] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +171,7 @@ VertexShader(V_QuadVS, V_QuadPSInput)
|
|||||||
V_QuadPSInput result;
|
V_QuadPSInput result;
|
||||||
result.sv_position = Vec4(NdcFromPos(screen_pos, frame.screen_dims).xy, 0, 1);
|
result.sv_position = Vec4(NdcFromPos(screen_pos, frame.screen_dims).xy, 0, 1);
|
||||||
result.quad_idx = SV_InstanceID;
|
result.quad_idx = SV_InstanceID;
|
||||||
|
result.world_pos = world_pos;
|
||||||
result.samp_uv = samp_uv;
|
result.samp_uv = samp_uv;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -130,14 +182,29 @@ VertexShader(V_QuadVS, V_QuadPSInput)
|
|||||||
PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
|
PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
|
||||||
{
|
{
|
||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||||
|
RWTexture2D<u32> occluders = G_Dereference<u32>(frame.occluders);
|
||||||
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
|
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
|
||||||
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
|
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
|
||||||
|
|
||||||
V_Quad quad = quads[input.quad_idx];
|
V_Quad quad = quads[input.quad_idx];
|
||||||
|
|
||||||
Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
|
Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
|
||||||
|
|
||||||
|
Vec2 world_pos = input.world_pos;
|
||||||
|
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));
|
||||||
|
|
||||||
Vec4 albedo = tex.Sample(clamp_sampler, input.samp_uv);
|
Vec4 albedo = tex.Sample(clamp_sampler, input.samp_uv);
|
||||||
|
|
||||||
|
if (is_in_world)
|
||||||
|
{
|
||||||
|
// TODO: Remove this
|
||||||
|
if (albedo.a > 0 && quad.occluder != P_OccluderKind_None && is_in_world)
|
||||||
|
{
|
||||||
|
InterlockedMax(occluders[cell_pos], quad.occluder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
V_QuadPSOutput output;
|
V_QuadPSOutput output;
|
||||||
output.sv_target0 = albedo;
|
output.sv_target0 = albedo;
|
||||||
return output;
|
return output;
|
||||||
@ -180,9 +247,10 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_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<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_cells);
|
||||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
||||||
RWTexture2D<u32> air_cells = G_Dereference<u32>(frame.air_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> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
||||||
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_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);
|
||||||
@ -230,6 +298,16 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
|
|
||||||
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_ParticleFlag flags = desc.flags;
|
||||||
|
|
||||||
|
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 7 bits
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Move
|
//- Move
|
||||||
|
|
||||||
@ -257,7 +335,7 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
t_max *= inv_delta;
|
t_max *= inv_delta;
|
||||||
t_max = abs(t_max);
|
t_max = abs(t_max);
|
||||||
|
|
||||||
f32 t_hit = 1;
|
f32 t_hit = 0;
|
||||||
|
|
||||||
Vec2I32 cell_pos = cell_p0;
|
Vec2I32 cell_pos = cell_p0;
|
||||||
|
|
||||||
@ -269,6 +347,13 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
b32 done = 0;
|
b32 done = 0;
|
||||||
for (u32 iteration_idx = 0; iteration_idx < max_iterations && !done; ++iteration_idx)
|
for (u32 iteration_idx = 0; iteration_idx < max_iterations && !done; ++iteration_idx)
|
||||||
{
|
{
|
||||||
|
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 < countof(air_cells));
|
||||||
|
b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||||
|
|
||||||
if (cell_pos.x == cell_p1.x && cell_pos.y == cell_p1.y)
|
if (cell_pos.x == cell_p1.x && cell_pos.y == cell_p1.y)
|
||||||
{
|
{
|
||||||
done = 1;
|
done = 1;
|
||||||
@ -290,20 +375,58 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
stepped_y = 1;
|
stepped_y = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all(cell_pos >= 0) && all(cell_pos < countof(occluders)))
|
if (is_in_world)
|
||||||
{
|
{
|
||||||
|
// Check collision
|
||||||
P_OccluderKind occluder = (P_OccluderKind)occluders[cell_pos];
|
P_OccluderKind occluder = (P_OccluderKind)occluders[cell_pos];
|
||||||
if (occluder != P_OccluderKind_None)
|
if (occluder != P_OccluderKind_None)
|
||||||
{
|
{
|
||||||
done = 1;
|
done = 1;
|
||||||
collision = 1;
|
collision = 1;
|
||||||
particle.velocity *= 0.5;
|
// particle.velocity *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
{
|
||||||
|
b32 should_stain = 0;
|
||||||
|
b32 should_draw_ground = !collision && is_visible && AnyBit(flags, V_ParticleFlag_Ground);
|
||||||
|
b32 should_draw_air = !collision && is_visible && AnyBit(flags, V_ParticleFlag_Air);
|
||||||
|
if (AnyBit(flags, V_ParticleFlag_Stain))
|
||||||
|
{
|
||||||
|
should_stain = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_stain)
|
||||||
|
{
|
||||||
|
// InterlockedMax(stain_cells[cell_pos], packed);
|
||||||
|
// InterlockedAdd(stain_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stains[cell_pos] = Color_Black;
|
// stain_cells[cell_pos] = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||||
|
// stain_cells[cell_pos] = Color_Black;
|
||||||
// ground_cells[cell_pos] = Color_White;
|
// ground_cells[cell_pos] = Color_White;
|
||||||
|
|
||||||
|
// if (should_stain)
|
||||||
|
// {
|
||||||
|
// InterlockedMax(ground_cells[cell_pos], packed);
|
||||||
|
// InterlockedAdd(ground_densities[cell_pos], 1);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -347,45 +470,48 @@ ComputeShader(V_SimParticlesCS, 64)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Commit
|
//- Commit
|
||||||
|
|
||||||
|
// {
|
||||||
|
// Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 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 < countof(air_cells));
|
||||||
|
// b32 is_visible = all(cell_screen_pos_p1 >= 0) && all(cell_screen_pos_p0 < frame.screen_dims);
|
||||||
|
|
||||||
|
// b32 should_draw_ground = is_in_world && is_visible && AnyBit(flags, V_ParticleFlag_Ground);
|
||||||
|
// b32 should_draw_air = is_in_world && is_visible && AnyBit(flags, V_ParticleFlag_Air);
|
||||||
|
|
||||||
|
// // Draw
|
||||||
|
// if (should_draw_ground || should_draw_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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Prune
|
||||||
|
// if (!is_in_world)
|
||||||
|
// {
|
||||||
|
// particle.kind = V_ParticleKind_None;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Increment life
|
||||||
|
// particle.life += frame.dt;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
|
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 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 < countof(air_cells));
|
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 || particle.kind == V_ParticleKind_Test;
|
|
||||||
b32 is_ground_particle = particle.kind == V_ParticleKind_Debris || particle.kind == V_ParticleKind_Test;
|
|
||||||
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;
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
if (should_draw_ground || should_draw_air)
|
|
||||||
{
|
|
||||||
u32 packed = 0;
|
|
||||||
packed |= (particle_idx & ((1 >> 24) - 1)) << 0;
|
|
||||||
packed |= (particle.kind & 0xFF) << 24;
|
|
||||||
StaticAssert(V_ParticlesCap <= (1 << 24)); // particle idx must fit in 24 bits
|
|
||||||
StaticAssert(V_ParticleKind_COUNT <= 0xFF); // particle kind must fit in 8 bits
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prune
|
// Prune
|
||||||
if (!is_in_world)
|
if (!is_in_world)
|
||||||
@ -614,7 +740,7 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
|||||||
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
|
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
|
||||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
||||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
|
||||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
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);
|
||||||
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
|
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
|
||||||
|
|
||||||
@ -626,7 +752,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(stains));
|
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(stain_cells));
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Compute result
|
//- Compute result
|
||||||
@ -664,8 +790,9 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
|||||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||||
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_ro);
|
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_ro);
|
||||||
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
|
||||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
|
RWTexture2D<u32> stain_cells = G_Dereference<u32>(frame.stain_cells);
|
||||||
RWTexture2D<u32> ground_cells = G_Dereference<u32>(frame.ground_cells);
|
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> air_cells = G_Dereference<u32>(frame.air_cells);
|
||||||
RWTexture2D<u32> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
RWTexture2D<u32> ground_densities = G_Dereference<u32>(frame.ground_densities);
|
||||||
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_densities);
|
RWTexture2D<u32> air_densities = G_Dereference<u32>(frame.air_densities);
|
||||||
@ -704,11 +831,6 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
|||||||
// shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0);
|
// shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Albedo
|
|
||||||
|
|
||||||
Vec4 albedo_color = 0;
|
|
||||||
{
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Tile
|
//- Tile
|
||||||
|
|
||||||
@ -781,125 +903,83 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Stain
|
|
||||||
|
|
||||||
Vec4 stain_color = 0;
|
|
||||||
{
|
|
||||||
f32 dryness = drynesses[cell_pos];
|
|
||||||
Vec4 stain = stains[cell_pos];
|
|
||||||
stain_color = V_DryColor(stain, dryness);
|
|
||||||
stain_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Albedo tex
|
//- Albedo tex
|
||||||
|
|
||||||
Vec4 albedo_tex_color = albedo_tex[screen_pos];
|
Vec4 albedo_tex_color = albedo_tex[screen_pos];
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Compose albedo
|
//- Particles
|
||||||
|
|
||||||
if (!tile_is_wall)
|
|
||||||
{
|
|
||||||
albedo_color = BlendPremul(tile_color, albedo_color); // Blend floor tile
|
|
||||||
albedo_color = BlendPremul(stain_color, albedo_color); // Blend floor stain
|
|
||||||
}
|
|
||||||
albedo_color = BlendPremul(albedo_tex_color, albedo_color);
|
|
||||||
if (tile_is_wall)
|
|
||||||
{
|
|
||||||
albedo_color = BlendPremul(tile_color, albedo_color); // Blend wall tile
|
|
||||||
albedo_color = BlendPremul(stain_color, albedo_color); // Blend wall stain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Ground particle
|
|
||||||
|
|
||||||
// TODO: Remove this
|
|
||||||
|
|
||||||
|
Vec4 stain_particle_color = 0;
|
||||||
Vec4 ground_particle_color = 0;
|
Vec4 ground_particle_color = 0;
|
||||||
{
|
|
||||||
Vec4 color = 0;
|
|
||||||
{
|
|
||||||
u32 packed = ground_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 || kind == V_ParticleKind_Test)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ground_particle_color = color;
|
|
||||||
ground_particle_color.rgb *= ground_particle_color.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Air particle
|
|
||||||
|
|
||||||
// TODO: Remove this
|
|
||||||
|
|
||||||
Vec4 air_particle_color = 0;
|
Vec4 air_particle_color = 0;
|
||||||
{
|
{
|
||||||
Vec4 color = 0;
|
//- Stain
|
||||||
{
|
{
|
||||||
u32 packed = air_cells[cell_pos];
|
{
|
||||||
V_ParticleKind kind = (V_ParticleKind)((packed >> 24) & 0xFF);
|
u32 packed = stain_cells[cell_pos];
|
||||||
if (kind != V_ParticleKind_None)
|
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
||||||
|
if (particle_kind != V_ParticleKind_None)
|
||||||
{
|
{
|
||||||
u32 particle_idx = packed & ((1 << 24) - 1);
|
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||||
if (particle_idx < V_ParticlesCap)
|
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.75 * tile_is_wall); // Darken wall stains
|
||||||
|
stain_particle_color.rgb *= stain_particle_color.a;
|
||||||
|
}
|
||||||
|
//- Ground
|
||||||
{
|
{
|
||||||
u64 seed = MixU64(P_ParticleCompositeBasis ^ particle_idx);
|
|
||||||
f32 rand_color = Norm16(seed >> 0);
|
|
||||||
if (kind == V_ParticleKind_Debris || kind == V_ParticleKind_Test)
|
|
||||||
{
|
{
|
||||||
color.rgb = Color_Orange.rgb;
|
u32 packed = ground_cells[cell_pos];
|
||||||
}
|
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
||||||
else if (kind == V_ParticleKind_Smoke)
|
if (particle_kind != V_ParticleKind_None)
|
||||||
{
|
{
|
||||||
color.rgb = Vec3(0.15, 0.15, 0.15);
|
u32 particle_idx = packed & ((1 << 24) - 1);
|
||||||
|
u32 density = ground_densities[cell_pos];
|
||||||
|
ground_particle_color = V_ColorFromParticle(particle_kind, particle_idx, density, 0);
|
||||||
}
|
}
|
||||||
color.rgb += (rand_color - 0.5) * 0.025;
|
}
|
||||||
|
ground_particle_color.rgb *= ground_particle_color.a;
|
||||||
|
}
|
||||||
|
//- Air
|
||||||
{
|
{
|
||||||
f32 density = air_densities[cell_pos];
|
{
|
||||||
// f32 t = saturate(density / 10.0);
|
u32 packed = air_cells[cell_pos];
|
||||||
f32 t = smoothstep(-10, 32, density);
|
V_ParticleKind particle_kind = (V_ParticleKind)((packed >> 24) & 0x7F);
|
||||||
color.a = lerp(0, 0.85, t);
|
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 = color;
|
|
||||||
air_particle_color.rgb *= air_particle_color.a;
|
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(albedo_color, world_color);
|
world_color = BlendPremul(stain_particle_color, world_color);
|
||||||
world_color = BlendPremul(ground_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);
|
world_color = BlendPremul(air_particle_color, world_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ Struct(V_QuadPSInput)
|
|||||||
{
|
{
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
Semantic(nointerpolation u32, quad_idx);
|
Semantic(nointerpolation u32, quad_idx);
|
||||||
|
Semantic(Vec2, world_pos);
|
||||||
Semantic(Vec2, samp_uv);
|
Semantic(Vec2, samp_uv);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ Struct(V_DVertPSOutput)
|
|||||||
//~ Helpers
|
//~ Helpers
|
||||||
|
|
||||||
f32 V_RandFromPos(Vec3 pos);
|
f32 V_RandFromPos(Vec3 pos);
|
||||||
Vec4 V_DryColor(Vec4 color, f32 dryness);
|
Vec4 V_ColorFromParticle(V_ParticleKind particle_kind, u32 particle_idx, u32 density, f32 dryness);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Shaders
|
//~ Shaders
|
||||||
|
|||||||
42
src/pp/pp_vis/pp_vis_shared.cg
Normal file
42
src/pp/pp_vis/pp_vis_shared.cg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Helpers
|
||||||
|
|
||||||
|
V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind)
|
||||||
|
{
|
||||||
|
if (kind < 0 || kind >= V_ParticleKind_COUNT)
|
||||||
|
{
|
||||||
|
kind = V_ParticleKind_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
V_ParticleDesc result;
|
||||||
|
{
|
||||||
|
PERSIST Readonly V_ParticleFlag flags[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, r, g, b, a) flags,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
PERSIST Readonly f32 r[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, r, g, b, a) r,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
PERSIST Readonly f32 g[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, r, g, b, a) g,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
PERSIST Readonly f32 b[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, r, g, b, a) b,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
PERSIST Readonly f32 a[V_ParticleKind_COUNT] = {
|
||||||
|
#define X(name, flags, r, g, b, a) a,
|
||||||
|
V_ParticlesXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
result.flags = flags[kind];
|
||||||
|
result.color = LinearFromSrgb(VEC4(r[kind], g[kind], b[kind], a[kind]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -146,9 +146,10 @@ Struct(V_SharedFrame)
|
|||||||
G_StructuredBufferRef emitters;
|
G_StructuredBufferRef emitters;
|
||||||
G_RWStructuredBufferRef particles;
|
G_RWStructuredBufferRef particles;
|
||||||
|
|
||||||
G_RWTexture2DRef stains;
|
G_RWTexture2DRef stain_cells;
|
||||||
G_RWTexture2DRef ground_cells;
|
G_RWTexture2DRef ground_cells;
|
||||||
G_RWTexture2DRef air_cells;
|
G_RWTexture2DRef air_cells;
|
||||||
|
G_RWTexture2DRef stain_densities;
|
||||||
G_RWTexture2DRef ground_densities;
|
G_RWTexture2DRef ground_densities;
|
||||||
G_RWTexture2DRef air_densities;
|
G_RWTexture2DRef air_densities;
|
||||||
G_RWTexture2DRef drynesses;
|
G_RWTexture2DRef drynesses;
|
||||||
@ -164,6 +165,7 @@ Struct(V_SharedFrame)
|
|||||||
Enum(P_OccluderKind)
|
Enum(P_OccluderKind)
|
||||||
{
|
{
|
||||||
P_OccluderKind_None,
|
P_OccluderKind_None,
|
||||||
|
P_OccluderKind_Guy,
|
||||||
P_OccluderKind_Wall,
|
P_OccluderKind_Wall,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,24 +173,58 @@ Enum(P_OccluderKind)
|
|||||||
//~ Particle types
|
//~ Particle types
|
||||||
|
|
||||||
#define P_ParticleSimBasis 0xb49f2d9e406873b9ull
|
#define P_ParticleSimBasis 0xb49f2d9e406873b9ull
|
||||||
#define P_ParticleCompositeBasis 0x569aa8341ecc0ea3ull
|
#define P_ParticleColorBasis 0x569aa8341ecc0ea3ull
|
||||||
|
|
||||||
|
Enum(V_ParticleFlag)
|
||||||
|
{
|
||||||
|
V_ParticleFlag_None = 0,
|
||||||
|
V_ParticleFlag_Stain = (1 << 0),
|
||||||
|
V_ParticleFlag_Ground = (1 << 1),
|
||||||
|
V_ParticleFlag_Air = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: Higher particle enum values take priority over lower ones
|
||||||
|
#define V_ParticlesXList(X) \
|
||||||
|
X( \
|
||||||
|
None, \
|
||||||
|
V_ParticleFlag_None, \
|
||||||
|
0, 0, 0, 0 \
|
||||||
|
) \
|
||||||
|
/* Ground particles */ \
|
||||||
|
X( \
|
||||||
|
Blood, \
|
||||||
|
V_ParticleFlag_Stain, \
|
||||||
|
0.5, 0.1, 0.1, 0.5 \
|
||||||
|
) \
|
||||||
|
X( \
|
||||||
|
Debris, \
|
||||||
|
V_ParticleFlag_Ground | V_ParticleFlag_Stain, \
|
||||||
|
1, 0.5, 0, 1 \
|
||||||
|
) \
|
||||||
|
/* Air particles */ \
|
||||||
|
X( \
|
||||||
|
Smoke, \
|
||||||
|
V_ParticleFlag_Air, \
|
||||||
|
0.15, 0.15, 0.15, 0.5 \
|
||||||
|
) \
|
||||||
|
X( \
|
||||||
|
BulletTrail, \
|
||||||
|
V_ParticleFlag_Air, \
|
||||||
|
1, 0, 1, 1 \
|
||||||
|
) \
|
||||||
|
/* Test particles */ \
|
||||||
|
X( \
|
||||||
|
Test, \
|
||||||
|
V_ParticleFlag_Stain, \
|
||||||
|
1, 1, 0, 1 \
|
||||||
|
) \
|
||||||
|
/* -------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
// NOTE: Higher particle kinds draw over lower ones
|
|
||||||
Enum(V_ParticleKind)
|
Enum(V_ParticleKind)
|
||||||
{
|
{
|
||||||
V_ParticleKind_None,
|
#define X(name, ...) V_ParticleKind_##name,
|
||||||
|
V_ParticlesXList(X)
|
||||||
//- Ground particles
|
#undef X
|
||||||
V_ParticleKind_Blood,
|
|
||||||
V_ParticleKind_Debris,
|
|
||||||
|
|
||||||
//- Air particles
|
|
||||||
V_ParticleKind_Smoke,
|
|
||||||
V_ParticleKind_BulletTrail,
|
|
||||||
|
|
||||||
//- Test particles
|
|
||||||
V_ParticleKind_Test,
|
|
||||||
|
|
||||||
V_ParticleKind_COUNT,
|
V_ParticleKind_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -214,6 +250,12 @@ Struct(V_Particle)
|
|||||||
Vec2 velocity;
|
Vec2 velocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(V_ParticleDesc)
|
||||||
|
{
|
||||||
|
V_ParticleFlag flags;
|
||||||
|
Vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
#if IsCpu
|
#if IsCpu
|
||||||
Struct(V_EmitterNode)
|
Struct(V_EmitterNode)
|
||||||
{
|
{
|
||||||
@ -233,6 +275,7 @@ Enum(V_QuadFlag)
|
|||||||
Struct(V_Quad)
|
Struct(V_Quad)
|
||||||
{
|
{
|
||||||
V_QuadFlag flags;
|
V_QuadFlag flags;
|
||||||
|
P_OccluderKind occluder;
|
||||||
Affine quad_uv_to_world_af;
|
Affine quad_uv_to_world_af;
|
||||||
G_Texture2DRef tex;
|
G_Texture2DRef tex;
|
||||||
Rng2 tex_slice_uv;
|
Rng2 tex_slice_uv;
|
||||||
@ -252,3 +295,5 @@ Struct(V_DVert)
|
|||||||
|
|
||||||
#define V_ThreadGroupSizeFromBufferSize(buffer_size) VEC3I32((((buffer_size) + 63) / 64), 1, 1)
|
#define V_ThreadGroupSizeFromBufferSize(buffer_size) VEC3I32((((buffer_size) + 63) / 64), 1, 1)
|
||||||
#define V_ThreadGroupSizeFromTexSize(tex_size) VEC3I32(((tex_size).x + 7) / 8, ((tex_size).y + 7) / 8, 1)
|
#define V_ThreadGroupSizeFromTexSize(tex_size) VEC3I32(((tex_size).x + 7) / 8, ((tex_size).y + 7) / 8, 1)
|
||||||
|
|
||||||
|
V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user