DragonMinded / libdragon

Open source library for N64 development.
https://libdragon.dev
The Unlicense
746 stars 109 forks source link

rdpq_sprite_blit draws 16x16 sprite as squished #603

Closed GetAGripGal closed 2 months ago

GetAGripGal commented 2 months ago

I am using the version of libdragon supplied by the docker image.

Drawing my sprite like so:

void hg_draw_player(struct hg_world *world, struct hg_asset_map *assets)
{
    struct hg_object *player = hg_fetch_object(world, world->player);

    sprite_t *sprite = (sprite_t *)assets->player_sprite_sheet.asset;
    rdpq_sprite_blit(sprite, player->transform.position.x, player->transform.position.y,
                     &(rdpq_blitparms_t){
                         .width = sprite->width,    
                         .height = sprite->height,
                     });
}

Causes the sprite to be drawn squished (screenshot in ares, but effects real hardware aswell): Screenshot_20240909_133356

I initialize my frame like so:

void hg_begin_frame(struct hg_renderer *renderer)
{
    assertf(renderer->display_surface == NULL, "hg_begin_frame called twice");
    renderer->display_surface = display_get();
    assertf(renderer->display_surface, "Failed to get display surface");

    graphics_fill_screen(renderer->display_surface, 0x0);

    rdpq_set_mode_standard();
    rdpq_attach(renderer->display_surface, NULL);
}

And the hardware is configured like so:

#define HG_CONFIG_RESOLUTION RESOLUTION_640x480
#define HG_CONFIG_BITDEPTH DEPTH_16_BPP
#define HG_CONFIG_BUFFER_AMOUNT 2
#define HG_CONFIG_GAMMA GAMMA_NONE
#define HG_CONFIG_FILTER FILTER_POINT
rasky commented 2 months ago

Can you please attach the original PNG that you convert into .sprite?

rasky commented 2 months ago

Not related but:

    graphics_fill_screen(renderer->display_surface, 0x0);

    rdpq_set_mode_standard();
    rdpq_attach(renderer->display_surface, NULL);

You can use rdpq_attach_clear to clear the screen with RDP at attach time (or rdpq_clear to clear it just after, or optionally), which is much faster than using the CPU (via graphics_fill_screen).

GetAGripGal commented 2 months ago

Here is the original png: gal

I use this line in my makefile to convert it:

$(N64_ROOTDIR)/bin/mksprite --verbose --output filesystem/sprites assets/sprites/*.png

And thanks for the tip! using the gpu seems much more sensible :P

thekovic commented 2 months ago

@GetAGripGal Did you by any chance call console_init() earlier in the program? I think the 640x240 provided by the libdragon console hasn't been closed so you find yourself currently in a 640x240 frame buffer without realizing it.

rasky commented 2 months ago

I'm not able to reproduce the issue. I've modified rdpqdemo but the sprite is correctly displayed:

diff --git a/examples/rdpqdemo/rdpqdemo.c b/examples/rdpqdemo/rdpqdemo.c
index 8032c65ae..8a08f102b 100644
--- a/examples/rdpqdemo/rdpqdemo.c
+++ b/examples/rdpqdemo/rdpqdemo.c
@@ -4,6 +4,7 @@

 static sprite_t *brew_sprite;
 static sprite_t *tiles_sprite;
+static sprite_t *test;

 static rspq_block_t *tiles_block;

@@ -93,6 +94,11 @@ void render(int cur_frame)
         });
     }

+    rdpq_sprite_blit(test, 100, 100, &(rdpq_blitparms_t){
+            .width = test->width, .height = test->height,
+
+    });
+
     rdpq_detach_show();
 }

@@ -101,7 +107,7 @@ int main()
     debug_init_isviewer();
     debug_init_usblog();

-    display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE);
+    display_init(RESOLUTION_640x480, DEPTH_16_BPP, 3, GAMMA_NONE, FILTER_POINT);

     joypad_init();
     timer_init();
@@ -115,6 +121,7 @@ int main()
     rdpq_debug_start();

     brew_sprite = sprite_load("rom:/n64brew.sprite");
+    test = sprite_load("rom:/test.sprite");

     obj_max_x = display_width - brew_sprite->width;
     obj_max_y = display_height - brew_sprite->height;
Screenshot 2024-09-13 alle 20 22 07

The sprite seems to have its correct square aspect. Even if I zoom it with scale_x/scale_y, it looks correct:

Screenshot 2024-09-13 alle 20 22 54

I guess we will need the full source code to reproduce and debug the issue. Btw, specifying width / height among the parms is not required if they match the sprite size (I guess it was just a test to debug the problem, but anyway).

GetAGripGal commented 2 months ago

@GetAGripGal Did you by any chance call console_init() earlier in the program? I think the 640x240 provided by the libdragon console hasn't been closed so you find yourself currently in a 640x240 frame buffer without realizing it.

Ah that was indeed the issue! Removing console_init fixed the issue! Thanks for the help everyone, i appriciate it!