Closed werkn closed 6 months ago
@werkn I'm going to open a PR on this "soonish". mksprite will implement all supported color formats, and I've updated rdp.c to support most formats.
Awesome @rasky, there is no rush on this but when you have a PR or its merged I'll check it out/test it for sure. Thanks for all the contributions on Libdragon, you've made some awesome contributions.
@rasky What is the status on this? I don't see a way to draw 8-bit sprites/textures on 16-bit surfaces in libdragon using the RDP.
I want to do a 8-bit surface to 16-bit surface blitter using the RDP as a (hopefully) fast way to emulate a VGA framebuffer in the N64.
Where is a snippet of what I am doing in software:
void RenderSurface(void)
{
surface_t *disp;
while( !(disp = display_lock()) );
int16_t w = Surface.width;
int16_t h = Surface.height;
uint32_t len = w*h;
const uint8_t *src_buffer = (const uint8_t*) Surface.buffer;
uint16_t *dest_buffer = (uint16_t*) disp->buffer;
for (int i = 0; i < len; i++)
*dest_buffer++ = VGA2N64Pal[*src_buffer++];
display_show(disp);
}
is there a way to do it in current libdragon?
It's implemented in the unstable branch in the new rdpq library.
Your function would be written like this:
void RenderSurface(void)
{
surface_t *disp;
while( !(disp = display_lock()) );
// Attach the RDP to the display buffer
rdpq_attach(disp);
// Load the palette
data_cache_hit_writeback(VGA2N64Pal, 256*2);
rdpq_tex_load_tlut(VGA2N64Pal, 0, 256);
// Set copy render mode, with palette lookup
rdpq_set_mode_copy(false);
rdpq_mode_tlut(TLUT_RGBA16);
// Blit the surface onto the display
surface_t src = surface_make(Surface.buffer, FMT_CI8, Surface.width, Surface.height, Surface.width);
rdpq_tex_blit(&src, 0, 0, NULL);
// Detach from the surface and display it once done
rdpq_detach_show();
}
Have a look at rdpq.h
as an entry point for the documentation of the new large rdpq library.
Thanks! That worked like a charm!
Also, how powerful is the RDP for drawing sprites on other 8-bit surfaces when compared to the CPU? The renderer performance improved substantially just by doing this final blit using the RDP.
Just a reminder that there is no extern "C"
on rdpq_attach.h header :)
It is much much more performant if it's a raw blit (+ transparency), but if you do something like blending the pixels (via playing index tricks with palettes) you can't use RDP anymore because unfortunately the various arithmetic operations you can program within the RDP (rdpq_mode_combiner
/ rdpq_mode_blender
) are not bit-exact (or rather, they get approximated in various ways) so you usually end up with off-by-ones in the destination pixels (aka palette indices) which are normally not acceptable in a palette scenario.
To do a CI8 -> CI8 blit, make sure to setup the source surface as FMT_I8
instead of FMT_CI8
so that you avoid the palette lookup. I8 surfaces are fetched as R=G=B=texel, and in general RDP will write to the CI8/I8 destination the red channel.
Make sure to enable the validator (rdpq_debug_start()
) as you play with this stuff in debug builds, it can be daunting at first otherwise.
Also have a look at rdpq_tex_blit()
documentation for all the nice features you might need. Remember to alway setup the render mode first (starting with one of rdpq_set_mode_*
and then rdpq_mode_*
APIs to tweak it -- rdpq_mode.h
should explain that). We don't have many examples yet, but examples/rdpqdemo
should give you some pointers.
Thanks for your explanation. I don't plan to mess with the combiner but the software uses a lot of CI8 -> CI8 blits with remap tables. In software that is basically:
for (i)
for (j)
// src and dst are 8-bit CI8 surfaces.
// remap[256] -> values in [0, 255]
dest[i][j] = remap[src[i][j]]
Is this the case where you said that using the RDP is not possible? In my understanding that is not exactly as using a combiner/blender as I am not applying a direct formula to the values.
The remap case can be covered with a TLUT (aka palette). You will have to load the remap table as if it was a palette, and then blit activating rdpq_mode_tlut
. You will not able to use RGBA16 palettes as those only have 5 bits for R (remember that RDP will draw the R channel in the output when the framebuffer is 8 bit, anything else is discarded), but you can use a IA16 palette, storing basically the remapped value as I, and an ignored value as A (zero will be fine).
BTW, if you want, we hang around on N64brew discord.
First, to the contributors/commiters you guys rock! I'm an IT guy that was happy enough to stumble across Libdragon about a year ago and have been loving it ever since. I know a tremendous amount of work goes into this project and just wanted to send a massive shout out to people with commits or that contribute and acknowledge all the hard work.
A feature that I would love to see added to Libdragon would be support for additional colour depths for doing palette based graphics.
Specifically 4BPP / 8BPP palette based graphics would be very desirable. According to https://n64squid.com/homebrew/n64-sdk/textures/image-formats/ and from what I've read in the official documentation this should be possible (although I'm not sure where to start).
A major benefit to the reduced bit depth would be more sprites essentially in TMEM.
Is this something that would be feasible in the long term? This is more of a feature request at this point more than an issue.