weapon animation wip

This commit is contained in:
jacob 2026-01-31 08:33:24 -06:00
parent ecb115a540
commit da643646a8
10 changed files with 221 additions and 194 deletions

View File

@ -389,6 +389,11 @@ Vec2 DivVec2Vec2(Vec2 a, Vec2 b)
return VEC2(a.x * (1 / b.x), a.y * (1 / b.y));
}
Vec2 RecipVec2(Vec2 a)
{
return VEC2(1.0 / a.x, 1.0 / a.y);
};
//- Add
Vec2 AddVec2(Vec2 a, Vec2 b)
@ -879,7 +884,7 @@ Affine TranslateAffine(Affine af, Vec2 v)
return af;
}
Affine WorldTranslateAffine(Affine af, Vec2 v)
Affine PreTranslateAffine(Affine af, Vec2 v)
{
af.og = AddVec2(af.og, v);
return af;
@ -897,26 +902,16 @@ Affine RotateAffineAngle(Affine af, f32 r)
return MulAffine(af, AffineFromAngle(r));
}
Affine WorldRotateAffineAngle(Affine af, f32 r)
Affine PreRotateAffine(Affine af, Vec2 r)
{
return MulAffine(AffineFromRot(r), af);
}
Affine PreRotateAffineAngle(Affine af, f32 r)
{
return MulAffine(AffineFromAngle(r), af);
}
Affine WorldRotateAffineBasisAngle(Affine af, f32 r)
{
f32 diff = r;
f32 c = CosF32(diff);
f32 s = SinF32(diff);
af.bx = VEC2(af.bx.x * c - af.bx.y * s, af.bx.x * s + af.bx.y * c);
af.by = VEC2(af.by.x * c - af.by.y * s, af.by.x * s + af.by.y * c);
return af;
}
Affine AffineWithWorldRotationAngle(Affine af, f32 r)
{
return WorldRotateAffineBasisAngle(af, r - AngleFromAffine(af));
}
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale)
@ -926,7 +921,7 @@ Affine ScaleAffine(Affine af, Vec2 scale)
return af;
}
Affine WorldScaleAffine(Affine af, Vec2 scale)
Affine PreScaleAffine(Affine af, Vec2 scale)
{
Affine result;
result.bx = MulVec2Vec2(af.bx, scale);
@ -993,21 +988,6 @@ Vec2 MulAffineVec2(Affine af, Vec2 v)
return result;
}
Vec2 InvertAffineBasisMulVec2(Affine af, Vec2 v)
{
Affine inv = InvertAffine(af);
Vec2 result = MulAffineBasisVec2(inv, v);
return result;
}
// TODO: Get rid of this? Just force caller to use invert manually since it's expensive.
Vec2 InvertAffineMulVec2(Affine af, Vec2 v)
{
Affine inv = InvertAffine(af);
return MulAffineVec2(inv, v);
}
//- Helpers
Affine AffineFromXform(Xform xf)

View File

@ -356,6 +356,7 @@ Vec2 NegVec2(Vec2 a);
//- Div
Vec2 DivVec2(Vec2 a, f32 s);
Vec2 DivVec2Vec2(Vec2 a, Vec2 b);
Vec2 RecipVec2(Vec2 a);
//- Add
Vec2 AddVec2(Vec2 a, Vec2 b);
@ -469,18 +470,17 @@ Affine AffineFromScale(Vec2 scale);
//- Translation
Affine TranslateAffine(Affine af, Vec2 v);
Affine WorldTranslateAffine(Affine af, Vec2 v);
Affine PreTranslateAffine(Affine af, Vec2 v);
//- Rotation
Affine RotateAffine(Affine af, Vec2 r);
Affine RotateAffineAngle(Affine af, f32 r);
Affine WorldRotateAffineAngle(Affine af, f32 r);
Affine WorldRotateAffineBasisAngle(Affine af, f32 r);
Affine AffineWithWorldRotationAngle(Affine af, f32 r);
Affine PreRotateAffine(Affine af, Vec2 r);
Affine PreRotateAffineAngle(Affine af, f32 r);
//- Scale
Affine ScaleAffine(Affine af, Vec2 scale);
Affine WorldScaleAffine(Affine af, Vec2 scale);
Affine PreScaleAffine(Affine af, Vec2 scale);
//- Lerp
Affine LerpAffine(Affine a, Affine b, f32 t);
@ -492,8 +492,6 @@ Affine InvertAffine(Affine af);
Vec2 MulAffineVec2(Affine af, Vec2 v);
Affine MulAffine(Affine a, Affine b);
Vec2 MulAffineBasisVec2(Affine af, Vec2 v);
Vec2 InvertAffineMulVec2(Affine af, Vec2 v);
Vec2 InvertAffineBasisMulVec2(Affine af, Vec2 v);
//- Helpers
Affine AffineFromXform(Xform xf);

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

Binary file not shown.

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

Binary file not shown.

View File

@ -827,17 +827,17 @@ void V_TickForever(WaveLaneCtx *lane)
b32 should_zoom = prev_frame->zooms != 0 && (frame->edit_camera_zoom != prev_frame->edit_camera_zoom);
if (prev_frame->is_editing && (should_zoom || (frame->is_panning && prev_frame->is_panning)))
{
Affine prev_frame_edit_to_screen_af = Zi;
Affine edit_to_screen_af = Zi;
Affine prev_frame_edit_to_screen_af = AffineIdentity;
Affine edit_to_screen_af = AffineIdentity;
{
f32 prev_edit_camera_scale = (f32)prev_frame->screen_dims.x / (meters_per_camera_width * prev_frame->edit_camera_zoom);
f32 edit_camera_scale = (f32)frame->screen_dims.x / (meters_per_camera_width * frame->edit_camera_zoom);
prev_frame_edit_to_screen_af = AffineFromScale(VEC2(prev_edit_camera_scale, prev_edit_camera_scale));
prev_frame_edit_to_screen_af = TranslateAffine(prev_frame_edit_to_screen_af, MulVec2(Vec2FromVec(frame->screen_dims), 0.5));
prev_frame_edit_to_screen_af = ScaleAffine(prev_frame_edit_to_screen_af, VEC2(prev_edit_camera_scale, prev_edit_camera_scale));
prev_frame_edit_to_screen_af = TranslateAffine(prev_frame_edit_to_screen_af, NegVec2(prev_frame->edit_camera_pos));
prev_frame_edit_to_screen_af = WorldTranslateAffine(prev_frame_edit_to_screen_af, MulVec2(Vec2FromVec(frame->screen_dims), 0.5));
edit_to_screen_af = AffineFromScale(VEC2(edit_camera_scale, edit_camera_scale));
edit_to_screen_af = TranslateAffine(edit_to_screen_af, MulVec2(Vec2FromVec(frame->screen_dims), 0.5));
edit_to_screen_af = ScaleAffine(edit_to_screen_af, VEC2(edit_camera_scale, edit_camera_scale));
edit_to_screen_af = TranslateAffine(edit_to_screen_af, NegVec2(frame->edit_camera_pos));
edit_to_screen_af = WorldTranslateAffine(edit_to_screen_af, MulVec2(Vec2FromVec(frame->screen_dims), 0.5));
}
Vec2 prev_target_cursor = MulAffineVec2(InvertAffine(prev_frame_edit_to_screen_af), prev_frame->screen_cursor);
Vec2 target_cursor = MulAffineVec2(InvertAffine(edit_to_screen_af), ui_frame->cursor_pos);
@ -905,9 +905,9 @@ void V_TickForever(WaveLaneCtx *lane)
frame->af.screen_to_world = AffineIdentity;
{
f32 camera_scale = frame->screen_dims.x / (meters_per_camera_width * frame->camera_zoom);
frame->af.world_to_screen = AffineFromScale(VEC2(camera_scale, camera_scale));
frame->af.world_to_screen = TranslateAffine(frame->af.world_to_screen, MulVec2(frame->screen_dims, 0.5));
frame->af.world_to_screen = ScaleAffine(frame->af.world_to_screen, VEC2(camera_scale, camera_scale));
frame->af.world_to_screen = TranslateAffine(frame->af.world_to_screen, NegVec2(frame->camera_pos));
frame->af.world_to_screen = WorldTranslateAffine(frame->af.world_to_screen, MulVec2(frame->screen_dims, 0.5));
frame->af.world_to_screen.og = RoundVec2(frame->af.world_to_screen.og);
frame->af.screen_to_world = InvertAffine(frame->af.world_to_screen);
}
@ -917,9 +917,9 @@ void V_TickForever(WaveLaneCtx *lane)
frame->af.shade_to_world = AffineIdentity;
{
f32 camera_scale = (frame->shade_dims.x - shade_extra_dims.x) / (meters_per_camera_width * frame->camera_zoom);
frame->af.world_to_shade = AffineFromScale(VEC2(camera_scale, camera_scale));
frame->af.world_to_shade = TranslateAffine(frame->af.world_to_shade, MulVec2(frame->shade_dims, 0.5));
frame->af.world_to_shade = ScaleAffine(frame->af.world_to_shade, VEC2(camera_scale, camera_scale));
frame->af.world_to_shade = TranslateAffine(frame->af.world_to_shade, NegVec2(frame->camera_pos));
frame->af.world_to_shade = WorldTranslateAffine(frame->af.world_to_shade, MulVec2(frame->shade_dims, 0.5));
frame->af.world_to_shade.og = RoundVec2(frame->af.world_to_shade.og);
frame->af.shade_to_world = InvertAffine(frame->af.world_to_shade);
}
@ -1836,6 +1836,7 @@ void V_TickForever(WaveLaneCtx *lane)
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
if (ent->is_guy)
@ -1845,122 +1846,36 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter);
//- Compute body
SPR_Slice body_slice = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
Affine body_slice_to_origin_af = AffineIdentity;
Xform body_ap_to_origin_xf = XformIdentity;
SPR_Slice body = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
Vec2 body_dims = DimsFromRng2(body.tex_rect);
Affine body_to_origin_af = AffineIdentity;
{
Vec2 body_slice_dims = DimsFromRng2(body_slice.bounds);
Xform origin_to_slice_corner_xf = body_slice.rays[SPR_RayKind_Origin];
origin_to_slice_corner_xf.t = SubVec2(origin_to_slice_corner_xf.t, body_slice.bounds.p0);
origin_to_slice_corner_xf = InvertXform(origin_to_slice_corner_xf);
Xform anchor_to_body_xf = InvertXform(body.rays[SPR_RayKind_Anchor]);
Xform ap_to_slice_corner_xf = body_slice.rays[SPR_RayKind_Ap];
ap_to_slice_corner_xf.t = SubVec2(ap_to_slice_corner_xf.t, body_slice.bounds.p0);
ap_to_slice_corner_xf = InvertXform(ap_to_slice_corner_xf);
body_to_origin_af = ScaleAffine(body_to_origin_af, pix_scale);
body_to_origin_af = RotateAffine(body_to_origin_af, anchor_to_body_xf.r);
body_to_origin_af = TranslateAffine(body_to_origin_af, anchor_to_body_xf.t);
}
// body_ap_to_origin_xf = MulXform(InvertXform(origin_to_slice_corner_xf), ap_to_slice_corner_xf);
Affine body_origin_to_ent_af = AffineIdentity;
{
// FIXME: Remove this
Xform ent_xf = ent->xf;
ent_xf.r = ent->control.look;
//- Push body quad
if (body.ready)
{
Xform a = InvertXform(origin_to_slice_corner_xf);
Xform b = ap_to_slice_corner_xf;
Affine body_to_world_af = MulAffine(AffineFromXform(ent_xf), MulAffine(body_origin_to_ent_af, body_to_origin_af));
Affine body_uv_to_world_af = ScaleAffine(body_to_world_af, DimsFromRng2(body.tex_rect));
body_ap_to_origin_xf.r = RotateVec2(a.r, b.r);
body_ap_to_origin_xf.t = AddVec2(b.t, a.t);
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, body_uv_to_world_af);
quad->tex = body.tex;
quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims);
}
body_slice_to_origin_af = ScaleAffine(body_slice_to_origin_af, pix_scale);
body_slice_to_origin_af = RotateAffine(body_slice_to_origin_af, origin_to_slice_corner_xf.r);
body_slice_to_origin_af = TranslateAffine(body_slice_to_origin_af, origin_to_slice_corner_xf.t);
body_slice_to_origin_af = ScaleAffine(body_slice_to_origin_af, body_slice_dims);
}
//- Compute weapon
SPR_Slice wep_slice = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
Affine wep_slice_to_origin_af = AffineIdentity;
{
Vec2 wep_slice_dims = DimsFromRng2(wep_slice.bounds);
Xform origin_ray = wep_slice.rays[SPR_RayKind_Origin];
origin_ray.t = SubVec2(origin_ray.t, wep_slice.bounds.p0);
origin_ray = InvertXform(origin_ray);
wep_slice_to_origin_af = ScaleAffine(wep_slice_to_origin_af, pix_scale);
wep_slice_to_origin_af = RotateAffine(wep_slice_to_origin_af, origin_ray.r);
wep_slice_to_origin_af = TranslateAffine(wep_slice_to_origin_af, origin_ray.t);
wep_slice_to_origin_af = ScaleAffine(wep_slice_to_origin_af, wep_slice_dims);
}
//- Compute weapon
// SPR_Slice wep_slice = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
// Affine wep_to_world_af = AffineIdentity;
// {
// Vec2 pix_dims = DimsFromRng2(wep_slice.bounds);
// Vec2 world_dims = DivVec2(pix_dims, P_CellsPerMeter);
// Xform origin_ray = wep_slice.rays[SPR_RayKind_Origin];
// origin_ray.t = SubVec2(origin_ray.t, wep_slice.bounds.p0);
// origin_ray = InvertXform(origin_ray);
// Affine origin_to_wep_af = AffineIdentity;
// origin_to_wep_af = ScaleAffine(origin_to_wep_af, DivVec2Vec2(VEC2(1.0, 1.0), pix_dims));
// origin_to_wep_af = RotateAffine(origin_to_wep_af, origin_ray.r);
// origin_to_wep_af = TranslateAffine(origin_to_wep_af, origin_ray.t);
// origin_to_wep_af = ScaleAffine(origin_to_wep_af, pix_dims);
// Affine wep_to_ap_af = AffineIdentity;
// wep_to_ap_af = ScaleAffine(wep_to_ap_af, world_dims);
// wep_to_ap_af = MulAffine(wep_to_ap_af, origin_to_wep_af);
// Affine ap_to_ent_af = AffineIdentity;
// Xform ent_xf = ent->xf;
// // FIXME: Remove this
// ent_xf.r = ent->control.look;
// wep_to_world_af = MulAffine(AffineFromXform(ent_xf), wep_to_ent_af);
// }
Affine body_slice_to_ent_af = AffineIdentity;
body_slice_to_ent_af = MulAffine(body_slice_to_ent_af, body_slice_to_origin_af);
Affine body_ap_to_ent_af = AffineIdentity;
body_ap_to_ent_af = MulAffine(body_ap_to_ent_af, AffineFromXform(body_ap_to_origin_xf));
Affine wep_slice_to_ent_af = AffineIdentity;
wep_slice_to_ent_af = MulAffine(body_ap_to_ent_af, wep_slice_to_origin_af);
// FIXME: Remove this
Xform ent_xf = ent->xf;
ent_xf.r = ent->control.look;
//- Push body quad
if (body_slice.ready)
{
Affine body_slice_to_world_af = MulAffine(AffineFromXform(ent_xf), body_slice_to_ent_af);
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->to_shade_af = MulAffine(frame->af.world_to_shade, body_slice_to_world_af);
quad->tex = body_slice.tex;
quad->tex_rect_uv = body_slice.tex_rect_uv;
}
//- Push weapon quad
if (body_slice.ready && wep_slice.ready)
{
Affine wep_slice_to_world_af = MulAffine(AffineFromXform(ent_xf), wep_slice_to_ent_af);
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
quad->to_shade_af = MulAffine(frame->af.world_to_shade, wep_slice_to_world_af);
quad->tex = wep_slice.tex;
quad->tex_rect_uv = wep_slice.tex_rect_uv;
}
}
}
@ -1969,6 +1884,142 @@ void V_TickForever(WaveLaneCtx *lane)
// 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);
// Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter);
// //- Compute body
// SPR_Slice body_slice = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq);
// Affine body_slice_to_origin_af = AffineIdentity;
// Xform body_ap_to_origin_xf = XformIdentity;
// {
// Vec2 body_slice_dims = DimsFromRng2(body_slice.bounds);
// Xform origin_to_slice_corner_xf = body_slice.rays[SPR_RayKind_Origin];
// origin_to_slice_corner_xf.t = SubVec2(origin_to_slice_corner_xf.t, body_slice.bounds.p0);
// origin_to_slice_corner_xf = InvertXform(origin_to_slice_corner_xf);
// Xform ap_to_slice_corner_xf = body_slice.rays[SPR_RayKind_Ap];
// ap_to_slice_corner_xf.t = SubVec2(ap_to_slice_corner_xf.t, body_slice.bounds.p0);
// ap_to_slice_corner_xf = InvertXform(ap_to_slice_corner_xf);
// // body_ap_to_origin_xf = MulXform(InvertXform(origin_to_slice_corner_xf), ap_to_slice_corner_xf);
// // FIXME: Remove this
// {
// Xform a = InvertXform(origin_to_slice_corner_xf);
// Xform b = ap_to_slice_corner_xf;
// body_ap_to_origin_xf.r = RotateVec2(a.r, b.r);
// body_ap_to_origin_xf.t = AddVec2(b.t, a.t);
// }
// body_slice_to_origin_af = ScaleAffine(body_slice_to_origin_af, pix_scale);
// body_slice_to_origin_af = RotateAffine(body_slice_to_origin_af, origin_to_slice_corner_xf.r);
// body_slice_to_origin_af = TranslateAffine(body_slice_to_origin_af, origin_to_slice_corner_xf.t);
// body_slice_to_origin_af = ScaleAffine(body_slice_to_origin_af, body_slice_dims);
// }
// //- Compute weapon
// // SPR_Slice wep_slice = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
// // Affine wep_slice_to_origin_af = AffineIdentity;
// // {
// // Vec2 wep_slice_dims = DimsFromRng2(wep_slice.bounds);
// // Xform origin_ray = wep_slice.rays[SPR_RayKind_Origin];
// // origin_ray.t = SubVec2(origin_ray.t, wep_slice.bounds.p0);
// // origin_ray = InvertXform(origin_ray);
// // wep_slice_to_origin_af = ScaleAffine(wep_slice_to_origin_af, pix_scale);
// // wep_slice_to_origin_af = RotateAffine(wep_slice_to_origin_af, origin_ray.r);
// // wep_slice_to_origin_af = TranslateAffine(wep_slice_to_origin_af, origin_ray.t);
// // wep_slice_to_origin_af = ScaleAffine(wep_slice_to_origin_af, wep_slice_dims);
// // }
// //- Compute weapon
// // SPR_Slice wep_slice = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
// // Affine wep_to_world_af = AffineIdentity;
// // {
// // Vec2 pix_dims = DimsFromRng2(wep_slice.bounds);
// // Vec2 world_dims = DivVec2(pix_dims, P_CellsPerMeter);
// // Xform origin_ray = wep_slice.rays[SPR_RayKind_Origin];
// // origin_ray.t = SubVec2(origin_ray.t, wep_slice.bounds.p0);
// // origin_ray = InvertXform(origin_ray);
// // Affine origin_to_wep_af = AffineIdentity;
// // origin_to_wep_af = ScaleAffine(origin_to_wep_af, DivVec2Vec2(VEC2(1.0, 1.0), pix_dims));
// // origin_to_wep_af = RotateAffine(origin_to_wep_af, origin_ray.r);
// // origin_to_wep_af = TranslateAffine(origin_to_wep_af, origin_ray.t);
// // origin_to_wep_af = ScaleAffine(origin_to_wep_af, pix_dims);
// // Affine wep_to_ap_af = AffineIdentity;
// // wep_to_ap_af = ScaleAffine(wep_to_ap_af, world_dims);
// // wep_to_ap_af = MulAffine(wep_to_ap_af, origin_to_wep_af);
// // Affine ap_to_ent_af = AffineIdentity;
// // Xform ent_xf = ent->xf;
// // // FIXME: Remove this
// // ent_xf.r = ent->control.look;
// // wep_to_world_af = MulAffine(AffineFromXform(ent_xf), wep_to_ent_af);
// // }
// Affine body_slice_to_ent_af = AffineIdentity;
// body_slice_to_ent_af = MulAffine(body_slice_to_ent_af, body_slice_to_origin_af);
// // Affine body_ap_to_ent_af = AffineIdentity;
// // body_ap_to_ent_af = MulAffine(body_ap_to_ent_af, AffineFromXform(body_ap_to_origin_xf));
// // Affine wep_slice_to_ent_af = AffineIdentity;
// // wep_slice_to_ent_af = MulAffine(body_ap_to_ent_af, wep_slice_to_origin_af);
// // FIXME: Remove this
// Xform ent_xf = ent->xf;
// ent_xf.r = ent->control.look;
// //- Push body quad
// if (body_slice.ready)
// {
// Affine body_slice_to_world_af = MulAffine(AffineFromXform(ent_xf), body_slice_to_ent_af);
// V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
// quad->to_shade_af = MulAffine(frame->af.world_to_shade, body_slice_to_world_af);
// quad->tex = body_slice.tex;
// quad->tex_rect_uv = body_slice.tex_rect_uv;
// }
// //- Push weapon quad
// // if (body_slice.ready && wep_slice.ready)
// // {
// // Affine wep_slice_to_world_af = MulAffine(AffineFromXform(ent_xf), wep_slice_to_ent_af);
// // V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
// // quad->to_shade_af = MulAffine(frame->af.world_to_shade, wep_slice_to_world_af);
// // quad->tex = wep_slice.tex;
// // quad->tex_rect_uv = wep_slice.tex_rect_uv;
// // }
// }
// }
// for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
// {
// if (ent->is_guy)
@ -4439,8 +4490,8 @@ void V_TickForever(WaveLaneCtx *lane)
}
V_TileDesc tile_desc = Zi;
{
tile_desc.tex_slice_uv = tile_slice.tex_rect_uv;
tile_desc.tex = tile_slice.tex;
tile_desc.tex_slice_uv = DivRng2Vec2(tile_slice.tex_rect, tile_slice.tex_dims);
}
params.tile_descs[tile_kind] = tile_desc;
}

View File

@ -89,15 +89,15 @@ VertexShader(V_QuadVS, V_QuadPSInput)
V_Quad quad = quads[SV_InstanceID];
Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
Vec2 shade_pos = mul(quad.to_shade_af, Vec3(rect_uv, 1));
Vec2 shade_pos = mul(quad.quad_uv_to_shade_af, Vec3(rect_uv, 1));
Vec2 tex_uv = lerp(quad.tex_rect_uv.p0, quad.tex_rect_uv.p1, rect_uv);
Vec2 tex_pos_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv);
// Vec2 shade_pos = lerp(quad.p0, quad.p1, rect_uv);
V_QuadPSInput result;
result.sv_position = Vec4(NdcFromPos(shade_pos, params.shade_dims).xy, 0, 1);
result.quad_idx = SV_InstanceID;
result.tex_uv = tex_uv;
result.tex_pos_uv = tex_pos_uv;
return result;
}
@ -113,7 +113,7 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
V_Quad quad = quads[input.quad_idx];
Texture2D<Vec4> tex = G_Dereference<Vec4>(quad.tex);
Vec4 albedo = tex.Sample(clamp_sampler, input.tex_uv);
Vec4 albedo = tex.Sample(clamp_sampler, input.tex_pos_uv);
// Vec4 albedo = Color_Cyan;

View File

@ -5,7 +5,7 @@ Struct(V_QuadPSInput)
{
Semantic(Vec4, sv_position);
Semantic(nointerpolation u32, quad_idx);
Semantic(Vec2, tex_uv);
Semantic(Vec2, tex_pos_uv);
};
Struct(V_QuadPSOutput)

View File

@ -48,8 +48,8 @@ Struct(V_Affines)
Struct(V_TileDesc)
{
Rng2 tex_slice_uv;
G_Texture2DRef tex;
Rng2 tex_slice_uv;
};
Struct(V_GpuState)
@ -183,9 +183,9 @@ Enum(V_QuadFlag)
Struct(V_Quad)
{
V_QuadFlag flags;
Affine to_shade_af;
Affine quad_uv_to_shade_af;
G_Texture2DRef tex;
Rng2 tex_rect_uv;
Rng2 tex_slice_uv;
};
////////////////////////////////////////////////////////////

View File

@ -5,6 +5,8 @@ SPR_Ctx SPR = Zi;
void SPR_Bootstrap(void)
{
// FIXME: Initialize nil/unready sprite texture here
OnAsyncTick(SPR_TickAsync);
}
@ -107,7 +109,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
for (i64 slice_idx = 0; slice_idx < sheet->slices_count; ++slice_idx)
{
SPR_SliceEntry *slice = &sheet->slices[slice_idx];
slice->bounds = Rng2Empty;
slice->canvas_rect = Rng2Empty;
Atomic64Set(&slice->atlas_copy_completion_target, I64Max);
for (SPR_RayKind ray_kind = 0; ray_kind < SPR_RayKind_COUNT; ++ray_kind)
{
@ -115,7 +117,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
}
}
//- Compute slice bounds
//- Compute slice rect
for (ASE_Layer *ase_layer = sheet->meta.first_layer; ase_layer; ase_layer = ase_layer->next)
{
SPR_LayerKind kind = SPR_LayerKindFromName(ase_layer->name);
@ -125,7 +127,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
{
ASE_Cel *cel = &ase_layer->cels[slice_idx];
SPR_SliceEntry *slice = &sheet->slices[slice_idx];
slice->bounds = UnionRng2(slice->bounds, cel->bounds);
slice->canvas_rect = UnionRng2(slice->canvas_rect, cel->bounds);
}
}
}
@ -139,7 +141,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
for (i64 slice_idx = 0; slice_idx < sheet->meta.frames_count; ++slice_idx)
{
SPR_SliceEntry *slice = &sheet->slices[slice_idx];
if (!IsRng2Empty(slice->bounds))
if (!IsRng2Empty(slice->canvas_rect))
{
SPR_CmdNode *cmd_node = SPR.submit.first_free;
if (cmd_node)
@ -194,7 +196,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
f32 rot_y = (((f32)((ray_pix >> 8) & 0xFF) / 255.0) * 2.0) - 1;
Vec2 rot = NormVec2(VEC2(rot_x, rot_y));
slice->rays[ray_kind].r = rot;
slice->rays[ray_kind].t = ase_cel->bounds.p0;
slice->rays[ray_kind].t = SubVec2(ase_cel->bounds.p0, slice->canvas_rect.p0);
}
}
}
@ -310,15 +312,15 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
// Fill tex info
if (slice_ready)
{
result.tex_dims = Vec2FromVec(slice->atlas->dims);
result.tex = slice->atlas->tex_ref;
result.tex_rect_uv = slice->atlas_rect_uv;
result.bounds = slice->bounds;
result.tex_rect = RNG2(slice->atlas_pos, AddVec2(slice->atlas_pos, DimsFromRng2(slice->canvas_rect)));
}
else
{
result.tex_dims = SPR.unready_tex_dims;
result.tex = SPR.unready_tex;
result.tex_rect_uv = RNG2(VEC2(0, 0), VEC2(1, 1));
result.bounds = RNG2(VEC2(0, 0), SPR.unready_tex_dims);
result.tex_rect = RNG2(VEC2(0, 0), SPR.unready_tex_dims);
}
// Fill rays
@ -382,12 +384,12 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// LogInfoF("Rasterizing sprite sheet %F \"%F\" (%F bytes)", FmtHandle(sheet->key.r), FmtString(name), FmtUint(encoded.len));
SPR_SliceEntry *slice = &sheet->slices[cmd->slice_idx];
Vec2 slice_dims = DimsFromRng2(slice->bounds);
Vec2 slice_dims = DimsFromRng2(slice->canvas_rect);
//////////////////////////////
//- Composite
ASE_Image composite = ASE_PushBlankImage(frame_arena, slice->bounds);
ASE_Image composite = ASE_PushBlankImage(frame_arena, slice->canvas_rect);
for (ASE_Layer *ase_layer = sheet->meta.first_layer; ase_layer; ase_layer = ase_layer->next)
{
SPR_LayerKind kind = SPR_LayerKindFromName(ase_layer->name);
@ -412,7 +414,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// TODO: Use a more efficient atlas packing algorithm for less wasted space
SPR_Atlas *atlas = SPR.first_atlas;
b32 can_use_atlas = 0;
Vec2I32 pos_in_atlas = Zi;
Vec2I32 atlas_pos = Zi;
while (can_use_atlas == 0)
{
// Create atlas
@ -435,9 +437,9 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
++SPR.atlases_count;
}
// Determine pos in atlas
pos_in_atlas = atlas->cur_pos;
atlas_pos = atlas->cur_pos;
atlas->cur_row_height = MaxI32(atlas->cur_row_height, slice_dims.y);
if (pos_in_atlas.x + slice_dims.x > atlas->dims.x);
if (atlas_pos.x + slice_dims.x > atlas->dims.x);
{
atlas->cur_pos.x = 0;
atlas->cur_pos.y += atlas->cur_row_height;
@ -456,18 +458,14 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// Fill slice_entry atlas info
{
Rng2I32 atlas_rect = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, Vec2I32FromVec(slice_dims)));
slice->atlas = atlas;
slice->atlas_rect_uv.p0.x = (f32)atlas_rect.p0.x / (f32)atlas->dims.x;
slice->atlas_rect_uv.p0.y = (f32)atlas_rect.p0.y / (f32)atlas->dims.x;
slice->atlas_rect_uv.p1.x = (f32)atlas_rect.p1.x / (f32)atlas->dims.x;
slice->atlas_rect_uv.p1.y = (f32)atlas_rect.p1.y / (f32)atlas->dims.x;
slice->atlas_pos = Vec2FromVec(atlas_pos);
}
// Copy to atlas
G_CopyCpuToTexture(
cl,
atlas->tex, VEC3I32(pos_in_atlas.x, pos_in_atlas.y, 0),
atlas->tex, VEC3I32(atlas_pos.x, atlas_pos.y, 0),
composite.pixels, VEC3I32(slice_dims.x, slice_dims.y, 1),
RNG3I32(
VEC3I32(0, 0, 0),

View File

@ -25,7 +25,7 @@ Struct(SPR_Atlas)
//~ Ray types
#define SPR_RayKindXMacro(X) \
X(Origin, .origin) \
X(Anchor, .anchor) \
X(Ap, .ap) \
/* ----------------------------- */
@ -53,9 +53,9 @@ Struct(SPR_Slice)
{
Xform rays[SPR_RayKind_COUNT];
Vec2 tex_dims;
G_Texture2DRef tex;
Rng2 tex_rect_uv;
Rng2 bounds;
Rng2 tex_rect;
b32 matched;
b32 ready;
@ -70,12 +70,12 @@ Struct(SPR_SliceEntry)
{
SPR_SliceEntry *next_in_bin;
Rng2 canvas_rect;
Xform rays[SPR_RayKind_COUNT];
SPR_Atlas *atlas;
Rng2 atlas_rect_uv;
Rng2 bounds;
Atomic64 atlas_copy_completion_target;
SPR_Atlas *atlas;
Vec2 atlas_pos;
};
//- Span