Homebrew [Release] {beta} sf2dlib - Simple and Fast 2D library (using the GPU)

xerpi

Well-Known Member
OP
Member
Joined
Dec 25, 2011
Messages
212
Trophies
1
Age
28
Location
Barcelona
XP
1,329
Country
Hi there, lately I've been coding a GPU accelerated 2D library for the Nintendo 3DS, on top of ctrulib. I've got to the point where it starts to be usable, so I think it's time to release it.
This will benefit you if you want to code a 2D game/app/emulator, as you obviously will need to draw textures/images. Maybe software rendering is enough, but if you have a GPU out there, why don't you use it ? ;)

DOCUMENTATION: http://xerpi.github.io/sf2dlib/html/sf2d_8h.html#func-members

DOWNLOAD: https://github.com/xerpi/sf2dlib

Precompiled portlibs: https://github.com/xerpi/3ds_portlibs/releases/tag/1

If you need to load images, take a look at this lib: https://github.com/xerpi/sfillib

Here there are the functions SF2D provides:
Code:
int sf2d_init();
int sf2d_init_advanced(int gpucmd_size, int temppool_size);
int sf2d_fini();

void sf2d_set_3D(int enable);

void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side);
void sf2d_end_frame();

void sf2d_swapbuffers();
void sf2d_set_vblank_wait(int enable);

float sf2d_get_fps();

void *sf2d_pool_malloc(u32 size);
void *sf2d_pool_memalign(u32 size, u32 alignment);
unsigned int sf2d_pool_space_free();
void sf2d_pool_reset();

void sf2d_set_clear_color(u32 color);

void sf2d_draw_line(int x0, int y0, int x1, int y1, u32 color);
void sf2d_draw_rectangle(int x, int y, int w, int h, u32 color);
void sf2d_draw_rectangle_rotate(int x, int y, int w, int h, u32 color, float rad);

sf2d_texture *sf2d_create_texture(int width, int height, GPU_TEXCOLOR pixel_format, sf2d_place place);
void sf2d_free_texture(sf2d_texture *texture);

void sf2d_fill_texture_from_RGBA8(sf2d_texture *dst, const void *rgba8, int source_w, int source_h);
sf2d_texture *sf2d_create_texture_mem_RGBA8(const void *src_buffer, int src_w, int src_h, GPU_TEXCOLOR pixel_format, sf2d_place place);

void sf2d_bind_texture(const sf2d_texture *texture, GPU_TEXUNIT unit);
void sf2d_bind_texture_color(const sf2d_texture *texture, GPU_TEXUNIT unit, u32 color);

void sf2d_draw_texture(const sf2d_texture *texture, int x, int y);
void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad);
void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h);
void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale);
void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale);
void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color);
void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color);
void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z);
void sf2d_texture_tile32(sf2d_texture *texture);

void sf2d_set_scissor_test(GPU_SCISSORMODE mode, u32 x, u32 y, u32 w, u32 h);

gfxScreen_t sf2d_get_current_screen();
gfx3dSide_t sf2d_get_current_side();

The 2D coordinate system goes like this:
Code:
Top screen:
      X
  ---------->
  | (0,0)
  |  ______________________
Y | |                      |
  | |                      |
  v |                      |
    |                      |
    |                      |
    |______________________|
                      (400, 240)
Bottom screen:
        X
    ---------->
    | (0,0)
    |  ________________
  Y | |                |
    | |                |
    v |                |
      |                |
      |                |
      |________________|
                  (320, 240)
And the skeleton of a program using this lib:
Code:
int main()
{
    sf2d_init();
    sf2d_set_clear_color(RGBA8(0x00, 0x00, 0x00, 0x00));

    while (aptMainLoop()) {

        hidScanInput();
        if (hidKeysDown() & KEY_START) break;

        sf2d_start_frame(GFX_TOP, GFX_LEFT);
            //Draws a 100x100 yellow rectangle (255, 255, 00, 255) at (150, 70)
            sf2d_draw_rectangle(150, 70, 100, 100, RGBA8(0xFF, 0xFF, 0x00, 0xFF));
        sf2d_end_frame();

        sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
            //Draws a 70x100 blue rectangle (0, 0, 00, 255) at (120, 30)
            sf2d_draw_rectangle(120, 30, 70, 100, RGBA8(0x00, 0x00, 0xFF, 0xFF));
        sf2d_end_frame();

        sf2d_swapbuffers();
    }

    sf2d_fini();
    return 0;
}

A more complex sample: https://github.com/xerpi/sf2dlib/blob/master/sample/source/main.c

Screenshot of Citra emulator running a sample using my lib:
v93z1eU.png
 
Last edited by xerpi,

xerpi

Well-Known Member
OP
Member
Joined
Dec 25, 2011
Messages
212
Trophies
1
Age
28
Location
Barcelona
XP
1,329
Country
I was just starting converting lpp-3ds luaGraphics to ctrGL for GPU usage but this sounds much more better, very thanks for sharing this :D

No problem :D Btw this will be a 2D-only lib, so if you want to do some 3D on lpp-3ds maybe it's not the best option.
I'll add texture rotation/zoom support very soon!
 

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
No problem :D Btw this will be a 2D-only lib, so if you want to do some 3D on lpp-3ds maybe it's not the best option.
I'll add texture rotation/zoom support very soon!

luaGraphics module is only for 2D Graphics (probably for 3D i'll use another module name like lua3D).
 
  • Like
Reactions: Margen67

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
Got an error during compilation, i'm using GPU folder from latest libctru revision:
Code:
c:/Users/Alessio/Desktop/lpp-3ds/source/include/sf2d/sf2d.c:48:58: error: request for member 'vertexShader' in something not a structure or union
  modelview_desc = shaderInstanceGetUniformLocation(shader.vertexShader, "modelview");
 

xerpi

Well-Known Member
OP
Member
Joined
Dec 25, 2011
Messages
212
Trophies
1
Age
28
Location
Barcelona
XP
1,329
Country
Got an error during compilation, i'm using GPU folder from latest libctru revision:
Code:
c:/Users/Alessio/Desktop/lpp-3ds/source/include/sf2d/sf2d.c:48:58: error: request for member 'vertexShader' in something not a structure or union
  modelview_desc = shaderInstanceGetUniformLocation(shader.vertexShader, "modelview");

Weird, are you sure you are using the latest ctrulib version?
I've shader defined as:
Code:
static shaderProgram_s shader;
And if you look at the source of ctrulib: https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/gpu/shaderProgram.h#L28
It has the vertexShader member.
 

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
  • Like
Reactions: xerpi

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
Yes, this also happens with the ctrulib's GPU sample.
Are you using my sf2d sample?

I just tried to blend two simple rectangles:

Code:
Graphics.init()
while true do
    Graphics.initBlend(TOP_SCREEN)
    Graphics.fillRect(50,100,50,100,Color.new(255,255,0,255))
    Graphics.termBlend()
    Graphics.initBlend(BOTTOM_SCREEN)
    Graphics.fillRect(70,120,100,120,Color.new(255,255,0,255))
    Graphics.termBlend()
end

where:
Code:
static int lua_init(lua_State *L) {
    int argc = lua_gettop(L);
    if (argc != 0) return luaL_error(L, "wrong number of arguments"); 
    sf2d_init();
    sf2d_set_clear_color(RGBA8(0x00, 0x00, 0x00, 0xFF));
    return 0;
}
 
static int lua_initblend(lua_State *L) {
    int argc = lua_gettop(L);
    if ((argc != 1) && (argc != 2))  return luaL_error(L, "wrong number of arguments");
    int screen = luaL_checkinteger(L,1);
    int side=0;
    if (argc == 2) side = luaL_checkinteger(L,2);
    gfxScreen_t my_screen;
    gfx3dSide_t eye;
    if (screen == 0) my_screen = GFX_TOP;
    else my_screen = GFX_BOTTOM;
    if (side == 0) eye = GFX_LEFT;
    else eye = GFX_RIGHT;
    sf2d_start_frame(my_screen,eye);
    return 0;
}
 
static int lua_rect(lua_State *L) {
    int argc = lua_gettop(L);
    if (argc != 5) return luaL_error(L, "wrong number of arguments");
    int x1 = luaL_checkinteger(L,1);
    int x2 = luaL_checkinteger(L,2);
    int y1 = luaL_checkinteger(L,3);
    int y2 = luaL_checkinteger(L,4);
    if (x2 < x1){
        int tmp = x2;
        x2 = x1;
        x1 = tmp;
    }
    if (y2 < y1){
        int tmp = y2;
        y2 = y1;
        y1 = tmp;
    }
    u32 color = luaL_checkinteger(L,5);
    sf2d_draw_rectangle(x1, y1, x2-x1, y2-y1, RGBA8((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color) & 0xFF, (color >> 24) & 0xFF));
    return 0;
}
 
static int lua_termblend(lua_State *L) {
    int argc = lua_gettop(L);
    if (argc != 0) return luaL_error(L, "wrong number of arguments");
    sf2d_end_frame();
    return 0;
}
 

xerpi

Well-Known Member
OP
Member
Joined
Dec 25, 2011
Messages
212
Trophies
1
Age
28
Location
Barcelona
XP
1,329
Country
I just tried to blend two simple rectangles:


I see what's wrong, you have to call sf2d_swapbuffers(); once after rendering, something like this:
Code:
sf2d_start_frame(GFX_TOP, GFX_LEFT);
    //Draw top
sf2d_end_frame();
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
    //Draw bottom
sf2d_end_frame();
sf2d_swapbuffers();
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • BakerMan
    I rather enjoy a life of taking it easy. I haven't reached that life yet though.
  • Xdqwerty
    what are you looking at?
  • AncientBoi @ AncientBoi:
    Both of mine are i5's lol
  • AncientBoi @ AncientBoi:
    All right! Who stole my right sock? :angry:
  • RedColoredStars @ RedColoredStars:
    At least someone other than myself thought it was funny :rofl:
    +2
  • BakerMan @ BakerMan:
    DNDBD (DND×DBD) IS A REAL THING
  • Xdqwerty @ Xdqwerty:
    I didnt have school today
  • Xdqwerty @ Xdqwerty:
    Cuz it's some kind of holiday related to the town I live in
  • Xdqwerty @ Xdqwerty:
    Am I [R WORD]?
  • SylverReZ @ SylverReZ:
    @Xdqwerty, People who create revival services for the Wii end up in disaster, same goes for Pretendo lol.
    +1
  • Xdqwerty @ Xdqwerty:
    @SylverReZ, atleast wiimmfii went fine although people only use it for Mario kart Wii
  • SylverReZ @ SylverReZ:
    At least if they ban you for cheating, get another Wii. They're cheap as chips.
    +1
  • SylverReZ @ SylverReZ:
    Remember when RiiShop was a thing?
  • BakerMan @ BakerMan:
    not really
  • SylverReZ @ SylverReZ:
    It got shutdown because somebody "accidentally" leaked the database for the amount of people using the beta.
  • SylverReZ @ SylverReZ:
    RiiShop is the laziest way of downloading Wii games. Did somebody not think of this through?
  • BakerMan @ BakerMan:
    although i ended up accidentally changing my nand with no way of going back bc i didn't know you needed a gamecube controller to restore it (i have a wii minus/1.1, which doesn't have gamecube controller support)
  • SylverReZ @ SylverReZ:
    @BakerMan, I think you're talking about the recovery mode that the SaveMii used, and also was to restore softbricked systems.
  • SylverReZ @ SylverReZ:
    If your NAND was hardbricked, then just buy another Wii. Or go with the dirty NAND flasher method.
  • BakerMan @ BakerMan:
    and if i find the sd card i have my NAND backed up on, i can not only restore the NAND if i solder the right part in, but i can also put my NAND on dolphin, then i can play dolphin online, like PMEX Remix or MKWii Riibalanced
  • Xdqwerty @ Xdqwerty:
    Brb
  • SylverReZ @ SylverReZ:
    @BakerMan, Oh yeah, that was a thing too. Dolphin does support Wiimmfi.
  • BakerMan @ BakerMan:
    yeah you just need to put your NAND backup with wiimmfi on it
  • BakerMan @ BakerMan:
    ngl i feel like if a bunch of my friends have wiis and know how to get wiimmfi and back up their NAND, then we could do a PMEX Remix tournament
  • BakerMan @ BakerMan:
    maybe even add UMVC3/DBFZ and make it a biathlon/triathlon
    BakerMan @ BakerMan: maybe even add UMVC3/DBFZ and make it a biathlon/triathlon