begin animation work

This commit is contained in:
jacob 2026-01-23 12:39:23 -06:00
parent 6e167ce499
commit 7ee7a7f531
12 changed files with 145 additions and 47 deletions

View File

@ -193,7 +193,7 @@ Inline Vec4 BlendPremul(Vec4 src, Vec4 dst)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Vertex ID helpers //~ Vertex ID helpers
Inline Vec2 RectUvFromVertexId(u32 id) Inline Vec2 RectUvFromIdx(u32 idx)
{ {
static const Vec2 uvs[4] = { static const Vec2 uvs[4] = {
Vec2(0, 0), Vec2(0, 0),
@ -201,7 +201,7 @@ Inline Vec2 RectUvFromVertexId(u32 id)
Vec2(1, 1), Vec2(1, 1),
Vec2(0, 1) Vec2(0, 1)
}; };
return uvs[id]; return uvs[idx];
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -197,6 +197,36 @@ P_Shape P_WorldShapeFromEnt(P_Ent *ent)
return world; return world;
} }
////////////////////////////////////////////////////////////
//~ Animation helpers
P_Anim P_AnimFromEnt(P_Ent *ent, i64 time_ns)
{
P_Anim result = Zi;
// result.slice_to_world_xf = XformIdentity;
// result.slice_to_world_xf = ent->xf;
{
Vec2 world_dims = VEC2(0.5, 0.5);
result.slice_to_world_xf = XformIdentity;
result.slice_to_world_xf.og = ent->xf.og;
// result.slice_to_world_xf.og = SubVec2(result.slice_to_world_xf.og, MulVec2(world_dims, 0.25));
result.slice_to_world_xf = XformWithWorldRotation(result.slice_to_world_xf, AngleFromVec2(ent->control.look));
result.slice_to_world_xf = TranslateXform(result.slice_to_world_xf, MulVec2(world_dims, -0.5));
result.slice_to_world_xf = ScaleXform(result.slice_to_world_xf, world_dims);
ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, Lit("sprite/bla3.ase"));
SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource);
result.slice = SPR_SliceFromSheet(sheet, Lit(""));
}
return result;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Collision //~ Collision

View File

@ -166,6 +166,15 @@ Struct(P_EntBin)
P_Ent *last; P_Ent *last;
}; };
////////////////////////////////////////////////////////////
//~ Animation types
Struct(P_Anim)
{
Xform slice_to_world_xf;
SPR_Slice slice;
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Constraint types //~ Constraint types
@ -476,6 +485,11 @@ Rng2 P_BoundingBoxFromShape(P_Shape shape);
P_Shape P_LocalShapeFromEnt(P_Ent *ent); P_Shape P_LocalShapeFromEnt(P_Ent *ent);
P_Shape P_WorldShapeFromEnt(P_Ent *ent); P_Shape P_WorldShapeFromEnt(P_Ent *ent);
////////////////////////////////////////////////////////////
//~ Animation helpers
P_Anim P_AnimFromEnt(P_Ent *ent, i64 time_ns);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Collision //~ Collision

View File

@ -4,6 +4,7 @@
//- Dependencies //- Dependencies
@Dep net @Dep net
@Dep sprite
////////////////////////////// //////////////////////////////
//- Resources //- Resources

BIN
src/pp/pp_res/sprite/bla3.ase (Stored with Git LFS)

Binary file not shown.

View File

@ -5,6 +5,7 @@
@Dep pp @Dep pp
@Dep net @Dep net
@Dep sprite
@Dep platform @Dep platform
////////////////////////////// //////////////////////////////

View File

@ -67,10 +67,6 @@ void V_PushParticles(V_Emitter src)
V_Frame *frame = V_CurrentFrame(); V_Frame *frame = V_CurrentFrame();
i64 split_threshold = 256; // Arbitrary threshold. Lower counts cause less shader work but more cpu -> gpu upload bandwidth. i64 split_threshold = 256; // Arbitrary threshold. Lower counts cause less shader work but more cpu -> gpu upload bandwidth.
src.count = MinU64(src.count, V_ParticlesCap); src.count = MinU64(src.count, V_ParticlesCap);
if (src.seed == 0)
{
src.seed = RandU64FromState(&frame->rand);
}
i64 remaining_particles = src.count; i64 remaining_particles = src.count;
while (remaining_particles > 0) while (remaining_particles > 0)
{ {
@ -488,6 +484,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
V_Frame *frame = &V.frames[i]; V_Frame *frame = &V.frames[i];
frame->arena = AcquireArena(Gibi(64)); frame->arena = AcquireArena(Gibi(64));
frame->quads_arena = AcquireArena(Gibi(64));
frame->dverts_arena = AcquireArena(Gibi(64)); frame->dverts_arena = AcquireArena(Gibi(64));
frame->dvert_idxs_arena = AcquireArena(Gibi(64)); frame->dvert_idxs_arena = AcquireArena(Gibi(64));
frame->gpu_arena = G_AcquireArena(); frame->gpu_arena = G_AcquireArena();
@ -545,17 +542,20 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
Arena *old_arena = frame->arena; Arena *old_arena = frame->arena;
Arena *old_quads_arena = frame->quads_arena;
Arena *old_dverts_arena = frame->dverts_arena; Arena *old_dverts_arena = frame->dverts_arena;
Arena *old_dvert_idxs_arena = frame->dvert_idxs_arena; Arena *old_dvert_idxs_arena = frame->dvert_idxs_arena;
G_ArenaHandle old_gpu_arena = frame->gpu_arena; G_ArenaHandle old_gpu_arena = frame->gpu_arena;
ZeroStruct(frame); ZeroStruct(frame);
frame->arena = old_arena; frame->arena = old_arena;
frame->quads_arena = old_quads_arena;
frame->dverts_arena = old_dverts_arena; frame->dverts_arena = old_dverts_arena;
frame->dvert_idxs_arena = old_dvert_idxs_arena; frame->dvert_idxs_arena = old_dvert_idxs_arena;
frame->gpu_arena = old_gpu_arena; frame->gpu_arena = old_gpu_arena;
} }
frame->cl = G_PrepareCommandList(G_QueueKind_Direct); frame->cl = G_PrepareCommandList(G_QueueKind_Direct);
ResetArena(frame->arena); ResetArena(frame->arena);
ResetArena(frame->quads_arena);
ResetArena(frame->dverts_arena); ResetArena(frame->dverts_arena);
ResetArena(frame->dvert_idxs_arena); ResetArena(frame->dvert_idxs_arena);
G_ResetArena(frame->cl, frame->gpu_arena); G_ResetArena(frame->cl, frame->gpu_arena);
@ -1828,8 +1828,27 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Push guy quads
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
if (ent->is_guy)
{
P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns);
// Push weapon quad
{
}
// Push body quad
{
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->to_shade_xf = MulXform(frame->xf.world_to_shade, anim.slice_to_world_xf);
quad->slice = anim.slice;
}
}
}
@ -4104,8 +4123,8 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_AllowRenderTarget .flags = G_ResourceFlag_AllowRenderTarget
); );
G_Texture2DRef screen_target_ro = G_PushTexture2DRef(frame->gpu_arena, screen_target); G_Texture2DRef screen_target_ro = G_PushTexture2DRef(frame->gpu_arena, screen_target);
Rng3 viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1)); Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1));
Rng2 scissor = RNG2(VEC2(viewport.p0.x, viewport.p0.y), VEC2(viewport.p1.x, viewport.p1.y)); Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y));
// Shade texture // Shade texture
G_ResourceHandle shade_target = G_PushTexture2D( G_ResourceHandle shade_target = G_PushTexture2D(
@ -4117,6 +4136,8 @@ void V_TickForever(WaveLaneCtx *lane)
); );
G_Texture2DRef shade_target_ro = G_PushTexture2DRef(frame->gpu_arena, shade_target); G_Texture2DRef shade_target_ro = G_PushTexture2DRef(frame->gpu_arena, shade_target);
G_RWTexture2DRef shade_target_rw = G_PushRWTexture2DRef(frame->gpu_arena, shade_target); G_RWTexture2DRef shade_target_rw = G_PushRWTexture2DRef(frame->gpu_arena, shade_target);
Rng3 shade_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->shade_dims.x, frame->shade_dims.y, 1));
Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y));
// Albedo texture // Albedo texture
G_ResourceHandle albedo_target = G_PushTexture2D( G_ResourceHandle albedo_target = G_PushTexture2D(
@ -4128,10 +4149,14 @@ void V_TickForever(WaveLaneCtx *lane)
); );
G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target); G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target);
// Quad buffers
G_ResourceHandle quads_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->quads_arena));
G_StructuredBufferRef quads_ref = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad);
// Debug shape buffers // Debug shape buffers
G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dverts_arena)); G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dverts_arena));
G_ResourceHandle dvert_idxs_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dvert_idxs_arena)); G_ResourceHandle dvert_idxs_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dvert_idxs_arena));
G_StructuredBufferRef dverts_ro = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert); G_StructuredBufferRef dverts_ref = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert);
G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff); G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff);
// Emitters // Emitters
@ -4185,7 +4210,8 @@ void V_TickForever(WaveLaneCtx *lane)
params.screen_dims = frame->screen_dims; params.screen_dims = frame->screen_dims;
params.tiles = gpu_tiles_ref; params.tiles = gpu_tiles_ref;
params.shape_verts = dverts_ro; params.quads = quads_ref;
params.shape_verts = dverts_ref;
params.emitters_count = frame->emitters_count; params.emitters_count = frame->emitters_count;
params.emitters = gpu_emitters_ref; params.emitters = gpu_emitters_ref;
@ -4246,27 +4272,46 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Setup pass //- Setup pass
// Prepare shade
G_Compute(frame->cl, V_PrepareShadeCS, V_ThreadGroupSizeFromTexSize(frame->shade_dims));
// Prepare cells
G_Compute(frame->cl, V_PrepareCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims));
// Clear particles
if (should_clear_particles)
{ {
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap)); // Prepare shade
G_Compute(frame->cl, V_PrepareShadeCS, V_ThreadGroupSizeFromTexSize(frame->shade_dims));
// Prepare cells
G_Compute(frame->cl, V_PrepareCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims));
// Clear particles
if (should_clear_particles)
{
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
}
// Clear albedo RT
G_ClearRenderTarget(frame->cl, albedo_target, VEC4(0, 0, 0, 0));
// Discard screen RT
G_DiscardRenderTarget(frame->cl, screen_target);
} }
// Clear albedo RT
G_ClearRenderTarget(frame->cl, albedo_target, VEC4(0, 0, 0, 0));
// Discard screen RT
G_DiscardRenderTarget(frame->cl, screen_target);
// Sync // Sync
G_DumbGlobalMemorySync(frame->cl); G_DumbGlobalMemorySync(frame->cl);
//////////////////////////////
//- Quads pass
{
G_Rasterize(
frame->cl,
V_QuadVS, V_QuadPS,
G_CountBuffer(quads_buff, V_Quad), G_QuadIndices(),
1, &G_Rt(albedo_target, G_BlendMode_CompositeStraightAlpha),
shade_viewport, shade_scissor,
G_RasterMode_TriangleList
);
// Transition albedo to readonly
G_DumbMemoryLayoutSync(frame->cl, albedo_target, G_Layout_DirectQueue_ShaderRead);
}
////////////////////////////// //////////////////////////////
//- Particle simulation pass //- Particle simulation pass
@ -4305,7 +4350,7 @@ void V_TickForever(WaveLaneCtx *lane)
V_CompositeVS, V_CompositePS, V_CompositeVS, V_CompositePS,
1, G_QuadIndices(), 1, G_QuadIndices(),
1, &G_Rt(screen_target, G_BlendMode_CompositeStraightAlpha), 1, &G_Rt(screen_target, G_BlendMode_CompositeStraightAlpha),
viewport, scissor, screen_viewport, screen_scissor,
G_RasterMode_TriangleList G_RasterMode_TriangleList
); );
} }
@ -4319,7 +4364,7 @@ void V_TickForever(WaveLaneCtx *lane)
V_DVertVS, V_DVertPS, V_DVertVS, V_DVertPS,
1, dvert_idxs_ib, 1, dvert_idxs_ib,
1, &G_Rt(screen_target, G_BlendMode_CompositeStraightAlpha), 1, &G_Rt(screen_target, G_BlendMode_CompositeStraightAlpha),
viewport, scissor, screen_viewport, screen_scissor,
G_RasterMode_TriangleList G_RasterMode_TriangleList
); );
} }
@ -4330,8 +4375,8 @@ void V_TickForever(WaveLaneCtx *lane)
G_DumbMemoryLayoutSync(frame->cl, screen_target, G_Layout_DirectQueue_ShaderRead); G_DumbMemoryLayoutSync(frame->cl, screen_target, G_Layout_DirectQueue_ShaderRead);
{ {
Rng2 uv = Zi; Rng2 uv = Zi;
uv.p0 = Vec2FromVec(viewport.p0); uv.p0 = Vec2FromVec(screen_viewport.p0);
uv.p1 = Vec2FromVec(viewport.p1); uv.p1 = Vec2FromVec(screen_viewport.p1);
uv = DivRng2Vec2(uv, Vec2FromVec(frame->screen_dims)); uv = DivRng2Vec2(uv, Vec2FromVec(frame->screen_dims));
UI_SetRawTexture(vis_box, screen_target_ro, uv); UI_SetRawTexture(vis_box, screen_target_ro, uv);
} }

View File

@ -224,6 +224,7 @@ Enum(V_EditMode)
Struct(V_Frame) Struct(V_Frame)
{ {
Arena *arena; Arena *arena;
Arena *quads_arena;
Arena *dverts_arena; Arena *dverts_arena;
Arena *dvert_idxs_arena; Arena *dvert_idxs_arena;
G_ArenaHandle gpu_arena; G_ArenaHandle gpu_arena;

View File

@ -88,14 +88,16 @@ VertexShader(V_QuadVS, V_QuadPSInput)
V_Quad quad = quads[SV_InstanceID]; V_Quad quad = quads[SV_InstanceID];
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID); Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
// Vec2 tex_uv = lerp(quad.tex_uv0, quad.tex_uv1, rect_uv); Vec2 shade_pos = mul(quad.to_shade_xf, Vec3(rect_uv, 1));
// Vec2 screen_pos = lerp(quad.p0, quad.p1, rect_uv);
Vec2 screen_pos = 0; Vec2 tex_uv = lerp(quad.slice.uv_rect.p0, quad.slice.uv_rect.p1, rect_uv);
// Vec2 shade_pos = lerp(quad.p0, quad.p1, rect_uv);
V_QuadPSInput result; V_QuadPSInput result;
result.sv_position = Vec4(NdcFromPos(screen_pos, params.screen_dims).xy, 0, 1); result.sv_position = Vec4(NdcFromPos(shade_pos, params.shade_dims).xy, 0, 1);
result.quad_idx = SV_InstanceID; result.quad_idx = SV_InstanceID;
result.tex_uv = tex_uv;
return result; return result;
} }
@ -106,12 +108,17 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads); StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
V_Quad quad = quads[input.quad_idx]; V_Quad quad = quads[input.quad_idx];
Vec4 final_color = 0; // Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.slice.tex);
// Vec4 albedo = tex.Sample(clamp_sampler, input.tex_uv);
Vec4 albedo = Color_Cyan;
V_QuadPSOutput output; V_QuadPSOutput output;
output.sv_target0 = final_color; output.sv_target0 = albedo;
return output; return output;
} }
@ -377,7 +384,7 @@ ComputeShader(V_SimParticlesCS, 64)
{ {
V_Emitter emitter = G_Dereference<V_Emitter>(params.emitters)[particle.emitter_init_num - 1]; V_Emitter emitter = G_Dereference<V_Emitter>(params.emitters)[particle.emitter_init_num - 1];
u64 seed0 = MixU64(emitter.seed + particle.seq); u64 seed0 = MixU64(particle.seq);
u64 seed1 = MixU64(seed0); u64 seed1 = MixU64(seed0);
f32 rand_speed = (f32)((seed0 >> 0) & 0xFFFF) / (f32)0xFFFF; f32 rand_speed = (f32)((seed0 >> 0) & 0xFFFF) / (f32)0xFFFF;
@ -586,9 +593,10 @@ ComputeShader2D(V_ShadeCS, 8, 8)
//- Composite albedo //- Composite albedo
albedo = BlendPremul(!tile_is_wall * tile_color, albedo); // Blend floor tile albedo = BlendPremul(!tile_is_wall * tile_color, albedo); // Blend floor tile
albedo = BlendPremul(!tile_is_wall * stain_color, albedo); // Blend floor stain
albedo = BlendPremul(albedo_tex_color, albedo); albedo = BlendPremul(albedo_tex_color, albedo);
albedo = BlendPremul(tile_is_wall * tile_color, albedo); // Blend wall tile albedo = BlendPremul(tile_is_wall * tile_color, albedo); // Blend wall tile
albedo = BlendPremul(stain_color, albedo); albedo = BlendPremul(tile_is_wall * stain_color, albedo); // Blend wall stain
} }
////////////////////////////// //////////////////////////////
@ -613,7 +621,7 @@ ComputeShader2D(V_ShadeCS, 8, 8)
VertexShader(V_CompositeVS, V_CompositePSInput) VertexShader(V_CompositeVS, V_CompositePSInput)
{ {
Vec2 uv = RectUvFromVertexId(SV_VertexID); Vec2 uv = RectUvFromIdx(SV_VertexID);
V_CompositePSInput result; V_CompositePSInput result;
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1); result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
return result; return result;

View File

@ -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, tex_uv);
}; };
Struct(V_QuadPSOutput) Struct(V_QuadPSOutput)
@ -31,7 +32,6 @@ Struct(V_DVertPSOutput)
Struct(V_CompositePSInput) Struct(V_CompositePSInput)
{ {
Semantic(Vec4, sv_position); Semantic(Vec4, sv_position);
}; };

View File

@ -123,7 +123,6 @@ Struct(V_Emitter)
u32 first_particle_seq; u32 first_particle_seq;
u32 count; u32 count;
u64 seed;
Vec2 start; Vec2 start;
Vec2 end; Vec2 end;
@ -182,8 +181,7 @@ Struct(V_Quad)
{ {
V_QuadFlag flags; V_QuadFlag flags;
Xform to_shade_xf;
SPR_Slice slice; SPR_Slice slice;
}; };

View File

@ -10,7 +10,7 @@ VertexShader(UI_DRectVS, UI_DRectPSInput)
StructuredBuffer<UI_GpuRect> rects = G_Dereference<UI_GpuRect>(params.rects); StructuredBuffer<UI_GpuRect> rects = G_Dereference<UI_GpuRect>(params.rects);
UI_GpuRect rect = rects[SV_InstanceID]; UI_GpuRect rect = rects[SV_InstanceID];
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID); Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
Vec2 tex_uv = lerp(rect.tex_slice_uv.p0, rect.tex_slice_uv.p1, rect_uv); Vec2 tex_uv = lerp(rect.tex_slice_uv.p0, rect.tex_slice_uv.p1, rect_uv);
Vec2 target_pos = lerp(rect.bounds.p0, rect.bounds.p1, rect_uv); Vec2 target_pos = lerp(rect.bounds.p0, rect.bounds.p1, rect_uv);
@ -122,7 +122,7 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
VertexShader(UI_BlitVS, UI_BlitPSInput) VertexShader(UI_BlitVS, UI_BlitPSInput)
{ {
Vec2 uv = RectUvFromVertexId(SV_VertexID); Vec2 uv = RectUvFromIdx(SV_VertexID);
UI_BlitPSInput result; UI_BlitPSInput result;
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1); result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
result.src_uv = uv; result.src_uv = uv;