It is currently Thu Oct 19, 2017 8:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Thu May 25, 2017 8:40 am 
Offline
User avatar

Joined: Thu May 25, 2017 7:27 am
Posts: 21
Hi, since i don't know a place for N64 scene im trying here, i was wondering if anyone have done some tests with libdragon.

So far i did some.. well very basic tests, my target is always 60fps, so i use the RDP rasterizer, i have some question on the bottom of the message, sorry for my english and the long post.

These tests works on real hardware, maybe on CEN64 or MESS, some downloads are attached others on mega.

TEST 1: EXPLOSIONS
Random explosions on screen using textures of 16bits (32x32) with RDP.
Image

Performance without optimizations:
410 at 60fps (NTSC)
507 at 50fps (PAL)

Texture strategy, use the same texture for other sprites without reload TMEM:
480
579

Flush texture disabled:
593
728

Probably there must be other ways to optimize further.

DOWNLOAD
https://mega.nz/#!Rkp2jRgJ!GpFxMwJ3g294r1CjwrmYR6mi-nIq4nhMuINdrsJRPwo

TEST 2: BIGGER EXPLOSIONS
Instead of 2KB explosions these are around 122x96 (22KB), so they are split in several pieces to fit the 4KB cache (i dont use stride function on libdragon, is slower than manage single textures), i wonder if there is an easy way to use 4 or 8bit textures with libdragon (they are limited to 16bit-32bit).
Image

Performance is lower than expected, around 50 explosions at 60fps.

DOWNLOAD
https://mega.nz/#!loAQyQSb!NjiU9HUihztLdVz-ULFNcx8NhmLFnQBYuYk5FHTgFhw

TEST 3: SNOW
RDP rectangles (non textured) of 4x4 with a blue color.
Image

Performance:
5120 rectangles at 60fps
6430 rectangles at 50fps

Use int16 instead of int32:
5600
7120

DOWNLOAD
https://mega.nz/#!R9YEwBSD!_7jzjJd0UXLLDIgvKNxVt0pwtKhSdyJ46QhFRMG7EWA

CONTROLS
A - Increase
B - Decrease
Start - Min
Z - Max
C up - clean buffer with RDP (test 1,2)
C left - clean buffer with CPU (test 1,2)
C down - do not clean (test 1,2)
R - Color rectangles (test 3)

CASTLEVANIA: SOTN OST
The whole soundtrack converted into ogg 44KHz/Stereo/128kbps using libogg, 34 songs, fits on a 64MB cartridge, plays from start to end, can skip songs with c button.
Image

It slowdowns 25fps to sync with the audio (i don't know how to use threads), but since its static background there is no problem at all.

DOWNLOAD (wonder if can be shared?)
https://mega.nz/#!Y9pQjYgC!S3LojMylb3lQ-RWEpdtdVxzCJKy9Td1b9AHr7Sq370w

=> Added get_pixel function, this is already inside the libdragon but i didnt see the function for end users?

GET_PIXEL
Gets a pixel color from a buffer in x/y position.
- Returns a packed color (twice) in 16bits for RDP compatibility.

graphics.c:
Code:
uint32_t get_pixel( display_context_t disp, int x, int y )
{
    if( disp == 0 ) { return 0; }

    if( __bitdepth == 2 )
    {
        uint16_t *buffer16 = (uint16_t *)__get_buffer( disp );
        uint16_t packed_rdp = __get_pixel( buffer16, x, y );
        return packed_rdp | (packed_rdp << 16);
    }
    else
    {
        uint32_t *buffer32 = (uint32_t *)__get_buffer( disp );
        return __get_pixel( buffer32, x, y );
    }
   
}


graphics.h
Code:
uint32_t get_pixel( display_context_t disp, int x, int y);


USES
- Can be used on a paint program (or those racing games with a menu to select a color for a car)
- Can be used as hidden collision map (since it reads the current buffer)
- Allows users to create new functions
- Can transform color into data to copy block areas or do special effects (VERY SLOW)

TEST
A color table is written on the buffer, the mouse reads the color from the buffer and shows it on the rectangle.
Image

16bit value to RGB conversion (this conversion is not necessary, but just in case)
Code:
color=get_pixel(disp,mouse_x,mouse_y);

// Extract
uint8_t r1 = (color & 0xF800) >> 11; // 63488
uint8_t g1 = (color & 0x7C0) >> 6; // 1984
uint8_t b1 = (color & 0x3E) >> 1; // 62

// Expand to 8-bit
r = r1 << 3;
g = g1 << 3;
b = b1 << 3;


Uses RGB555, i was expecting 565.

CONTROLS
Joystick - Mouse
A - Set background color with the color selected
R - Alternate white or black letter fonts
Z - Reset background and letter colors

DOWNLOAD
https://mega.nz/#!g5IRgYwA!Mk-vrgPmAi0HhN5aPKPLNDNVnbtdgxFkGXTkmGBmZcg

Added math functions (fget_angle, fget_dist, get_distx, get_disty)

Allows some game logic and this kind of effects..
Image

Since i don't have yet raster effects (buffer) i had to use giant horizontally textures (320x4), so i can move the blocks separately.

- Libdragon won't allow textures beyond 256 wide, they are repeated at this point or mirrored depending on the settings.

The effect is generated in real time (instead of tables) and can be edited:
C left / C right = wave
C up / C down = radius
A / B = Speed
R = hide text

A better gif (graphics sample from Last Blade 2):
Image

DOWNLOAD
https://mega.nz/#!UpIBkJBb!TqZc9F3V8lZSpkxQoYp_T_QbyrhSNQcu29zsYVEpews

---
I could provide the source code of these examples, but probably the level skills on this board are better than me.

Right now im trying to figure how to add hardware flip to the sprites, it is possible by changing the order of the loading or using mirror S or T coords when drawing, but this code brings me headaches, i simply don't know where to start:

(the code is slightly modified from the source, i have removed texture slots)

rdp.c
Code:
static uint32_t __rdp_load_texture(int mirror_enabled, sprite_t *sprite, int sl, int tl, int sh, int th )
{
    /* Invalidate data associated with sprite in cache */
    if( flush_strategy == FLUSH_STRATEGY_AUTOMATIC )
    {
        data_cache_hit_writeback_invalidate( sprite->data, sprite->width * sprite->height * sprite->bitdepth );
    }

    /* Point the RDP at the actual sprite data */
    __rdp_ringbuffer_queue( 0xFD000000 | ((sprite->bitdepth == 2) ? 0x00100000 : 0x00180000) | (sprite->width - 1) );
    __rdp_ringbuffer_queue( (uint32_t)sprite->data );
    __rdp_ringbuffer_send();

    /* Figure out the s,t coordinates of the sprite we are copying out of */
    int twidth = sh - sl + 1;
    int theight = th - tl + 1;

    /* Figure out the power of two this sprite fits into */
    uint32_t real_width  = __rdp_round_to_power( twidth );
    uint32_t real_height = __rdp_round_to_power( theight );
    uint32_t wbits = __rdp_log2( real_width );
    uint32_t hbits = __rdp_log2( real_height );

    /* Because we are dividing by 8, we want to round up if we have a remainder */
    int16_t round_amount = (real_width % 8) ? 1 : 0;

    /* Instruct the RDP to copy the sprite data out */
    __rdp_ringbuffer_queue( 0xF5000000 | ((sprite->bitdepth == 2) ? 0x00100000 : 0x00180000) |
                                       (((((real_width / 8) + round_amount) * sprite->bitdepth) & 0x1FF) << 9));
    __rdp_ringbuffer_queue( (mirror_enabled == 1 ? 0x40100 : 0) | (hbits << 14 ) | (wbits << 4) );
    __rdp_ringbuffer_send();

    /* Copying out only a chunk this time */
    __rdp_ringbuffer_queue( 0xF4000000 | (((sl << 2) & 0xFFF) << 12) | ((tl << 2) & 0xFFF) );
    __rdp_ringbuffer_queue( (((sh << 2) & 0xFFF) << 12) | ((th << 2) & 0xFFF) );
    __rdp_ringbuffer_send();

    /* Save sprite width and height for managed sprite commands */
    cache.width = twidth - 1;
    cache.height = theight - 1;
    cache.s = sl;
    cache.t = tl;
   
    /* Return the amount of texture memory consumed by this texture */
    return ((real_width / 8) + round_amount) * 8 * real_height * sprite->bitdepth;
}


This second one is used for drawing the texture once is loaded into tmem, so either when loading could be mirrored or now, i have added if ( tx < -cache.width ) { return; }, prevents system to hang when a sprite is out of screen from the left (it seems to be the only exception).

Code:
void rdp_draw_textured_rectangle_scaled( int tx, int ty, int bx, int by, double x_scale, double y_scale )
{
    uint16_t s = cache.s << 5;
    uint16_t t = cache.t << 5;

    /* Cant display < 0, so must clip size and move S,T coord accordingly */
    if( tx < 0 )
    {
        if ( tx < -cache.width ) { return; }
        s += (int)(((double)((-tx) << 5)) * (1.0 / x_scale));
        tx = 0;
    }

    if( ty < 0 )
    {
        t += (int)(((double)((-ty) << 5)) * (1.0 / y_scale));
        ty = 0;
    }

    /* Calculate the scaling constants based on a 6.10 fixed point system */
    int xs = (int)((1.0 / x_scale) * 4096.0);
    int ys = (int)((1.0 / y_scale) * 1024.0);

    /* Set up rectangle position in screen space */
    __rdp_ringbuffer_queue( 0xE4000000 | (bx << 14) | (by << 2) );
    __rdp_ringbuffer_queue( (tx << 14) | (ty << 2) );

    /* Set up texture position and scaling to 1:1 copy */
    __rdp_ringbuffer_queue( (s << 16) | t );
    __rdp_ringbuffer_queue( (xs & 0xFFFF) << 16 | (ys & 0xFFFF) );

    /* Send command */
    __rdp_ringbuffer_send();
}


Attachments:
get_pixel.rar [62.14 KiB]
Downloaded 36 times
test3.rar [42.22 KiB]
Downloaded 38 times
test2.rar [87.83 KiB]
Downloaded 40 times
test1.rar [41.91 KiB]
Downloaded 38 times


Last edited by BMBx64 on Thu May 25, 2017 2:14 pm, edited 2 times in total.
Top
 Profile  
 
PostPosted: Thu May 25, 2017 10:39 am 
Offline
User avatar

Joined: Tue Dec 04, 2012 3:28 pm
Posts: 337
Location: Canada
Awesome stuff!

The SOTN demo worked really well, music played until it got to BGM 12, then it stalled the system. Had to reset.

Tried again, skipping tracks to get the BGM 12 which now worked, but when I skipped to BGM 13 it stalled again.

This is testing on an Everdrive64.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 10:57 am 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3071
Location: Nacogdoches, Texas
BMBx64 wrote:
i don't know a place for N64 scene

Because there isn't one. :?

May I ask, what is libdragon?

Also, I don't understand how the second explosion demo has such worse performance than the first. Are you drawing all the pieces of an explosion with the same graphic before swapping out the texture in the texture cache? This should improve GPU performance, put then you'd also have to use the hardware z-buffer when drawing the explosion pieces instead of just sorting the order they are drawn with the CPU, which may negate the performance increase from changing the texture cache less often.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 11:05 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19104
Location: NE Indiana, USA (NTSC)
A Google search for n64 libdragon brings up a library for N64 homebrew development by the developer of DSOrganize.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 11:10 am 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3071
Location: Nacogdoches, Texas
I actually did Google libdragon, but I didn't really know what I was looking at. Is it a full game engine, or routines that could be used to make one? Seems pretty limited if it apparently can't support 4bpp or 8bpp textures, which shouldn't have been any harder to implement than 16bpp or 24bpp or 32bpp textures other than a palette also needs to be uploaded. (Also to the texture cache?)


Top
 Profile  
 
PostPosted: Thu May 25, 2017 11:16 am 
Offline

Joined: Sun Mar 27, 2011 10:49 am
Posts: 192
Espozo wrote:
...but then you'd also have to use the hardware z-buffer when drawing the explosion pieces instead of just sorting the order they are drawn with the CPU, which may negate the performance increase from changing the texture cache less often.

I don't know the first thing about N64 development, but isn't the whole point of a hardware Z-buffer that it's faster than sorting polys on the CPU?


Top
 Profile  
 
PostPosted: Thu May 25, 2017 11:46 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19104
Location: NE Indiana, USA (NTSC)
I imagine that libdragon is analogous to Shiru's neslib.

Using a depth buffer incurs an extra memory read per pixel and write per drawn pixel, and it doesn't work for translucent objects. I don't know enough about the Nintendo 64's memory controller to know under what exact conditions the tradeoff is favorable. It was common on the PlayStation to use a bucket sort based on the Z coordinate of the centroid, which is fairly fast provided there are no pathological cases of large triangles close together.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 11:58 am 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3071
Location: Nacogdoches, Texas
adam_smasher wrote:
isn't the whole point of a hardware Z-buffer that it's faster than sorting polys on the CPU?

Yes. However, using the hardware Z-buffer is slower for the GPU. If you are not changing out the texture cache for identical pieces in this case, you have to use the hardware Z-buffer, because you won't be able to sort the pieces of the explosions on a per pixel level by the CPU like the hardware Z-buffer will. You can avoid using the hardware Z-buffer by writing entire explosions in order, but then you have to change out the texture cache for every piece being drawn.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 12:13 pm 
Offline

Joined: Sun Mar 27, 2011 10:49 am
Posts: 192
Yeah, I get it - I guess I'm just surprised using the Z-buffer is so much slower that it might be better to do CPU sorting & constantly trash the texture cache when you're not even pushing the GPU that hard (5000 unshaded unlit triangles per second). And that's not an "I'm surprised because that sounds unlikely and think you're wrong" kind of surprised, but a genuine, "woah, the N64's Z-buffer must be terrible" kind of surprised.


Top
 Profile  
 
PostPosted: Thu May 25, 2017 12:16 pm 
Offline
User avatar

Joined: Thu May 25, 2017 7:27 am
Posts: 21
getafixx wrote:
Awesome stuff!

The SOTN demo worked really well, music played until it got to BGM 12, then it stalled the system. Had to reset.

Tried again, skipping tracks to get the BGM 12 which now worked, but when I skipped to BGM 13 it stalled again.

This is testing on an Everdrive64.


Thanks :D , not sure why it crashes, do you use expansion pak? I have PAL N64 with expansion and works fine forcing PAL or NTSC modes on Everdrive 2.5.

However i know fopen/fclose have a memory leak, once the 100th file is open the next ones will fail (no handles), this can be "fixed" by using (dfs_open and dfs_close variant), i have to look at it, audio specially has been hard on N64 so far.

Here a bit more info about this memory leak:
https://krikzz.com/forum/index.php?topic=5969.15


Espozo wrote:
Also, I don't understand how the second explosion demo has such worse performance than the first. Are you drawing all the pieces of an explosion with the same graphic before swapping out the texture in the texture cache? This should improve GPU performance, put then you'd also have to use the hardware z-buffer when drawing the explosion pieces instead of just sorting the order they are drawn with the CPU, which may negate the performance increase from changing the texture cache less often.


I wanted to check how goes the performance when textures are loaded without strategy, just to imagine worst scenarios, the sorting is done by the order in the program, a loop from 0 to max number of explosions, i don't know if Z-buffer is available for 2D rectangles.

--

For 8bit palettes, the low 2KB of the TMEM are filled with data, but the higher 2KB needs the color table lookup, then there are different formats, the grayscale ones works different i think, you can take more TMEM and set the color on the vertex.

I may be interested specially on 4bit palette support (MD,SNES,etc), but i hope to fix all the basic things, like flip a sprite if anyone can help a bit with the rdp.c code i can do all kind of tests.

--

I forgot this one..

TEST: LAYERS
Small tiled scroll that manages unlimited layers (they impact performance at some point), some features:
- Layers can have a custom number of rows and columns
- Different tile sizes in each layer separately (ex: main scroll layer 32x32, background layer 64x32)
- Layers can be set to repeat horizontally or vertically.

This pic shows 8 full screen layers (320x240x16), each one with unique texture:
Image

CONTROLS
Push joystick to move camera at different speed

DOWNLOAD
https://mega.nz/#!IhgTwJwK!AK67vHgNl6LpGoasvQtTuD1wGbYBGynOKYNT0yek6PE


Attachments:
test4.rar [40.2 KiB]
Downloaded 38 times


Last edited by BMBx64 on Thu May 25, 2017 2:11 pm, edited 1 time in total.
Top
 Profile  
 
PostPosted: Thu May 25, 2017 1:07 pm 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6285
Location: Seattle
BMBx64, you should feel free to use the attachment interface here for anything that doesn't infringe copyright.

Especially when they're only 40 KiB


Top
 Profile  
 
PostPosted: Fri May 26, 2017 4:51 pm 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3071
Location: Nacogdoches, Texas
You know, I was going to post some thoughts I had on these demos and ideas on how to improve them, but I realized I really have no clue how exactly the N64 really works. I think the GPU is split into two parts, the RSP and the RDP, with the RSP being programmable and running the non-programmable RDP. Each one has 4KB of ram, with the RSP's ram holding instruction data and the RDP's ram holding texture data. What I really want to know, is how is the data changed? Is it by DMA initiated by the CPU, because if so, it seems the CPU would be doing nothing but waiting for the GPU to be done with its current task (like writing to the SPC700 on the SNES), unless the GPU can actually generate an interrupt.


Top
 Profile  
 
PostPosted: Fri May 26, 2017 7:29 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19104
Location: NE Indiana, USA (NTSC)
As I understand it: Ideally, while the RSP is rendering a frame, the CPU is running game logic and generating the display list for the RSP to render in the next frame.


Top
 Profile  
 
PostPosted: Sat May 27, 2017 5:07 am 
Offline
User avatar

Joined: Thu May 25, 2017 7:27 am
Posts: 21
I finally added hardware flip feature, i will bring an example later.

Instead of reverse texture on the load i though it was more wise when drawing, there could be plenty of uses without reload such as axial symmetry.

I had to debug first how it works, the textures seems to be power of two sizes, for example mario texture is 16x31 and its rounded to 16x32, s and t coords have to be set accordingly to avoid garbage.
Image

The performance seems to be about the same when setting MIRROR_ENABLED on the RDP (for hardware flip) so i removed some flags from rdp_load, this function previously used to be:
rdp_load_texture (uint32_t texslot, uint32_t texloc, mirror_t mirror_enabled, sprite_t *sprite)

Now its just the texture call (which is faster):
rdp_load_texture ( sprite_t *sprite )

Flags for the flip:
0 - Normal
1 - Horizontally
2 - Vertically
3 - Both

rdp.c

Changes on rdp_load:
Code:
static uint32_t __rdp_load_texture(sprite_t *sprite, int sl, int tl, int sh, int th )
{
    /* Invalidate data associated with sprite in cache */
    if( flush_strategy == FLUSH_STRATEGY_AUTOMATIC )
    {
        data_cache_hit_writeback_invalidate( sprite->data, sprite->width * sprite->height * sprite->bitdepth );
    }

    /* Point the RDP at the actual sprite data */
    __rdp_ringbuffer_queue( 0xFD000000 | ((sprite->bitdepth == 2) ? 0x00100000 : 0x00180000) | (sprite->width - 1) );
    __rdp_ringbuffer_queue( (uint32_t)sprite->data );
    __rdp_ringbuffer_send();

    /* Figure out the s,t coordinates of the sprite we are copying out of */
    int twidth = sh - sl + 1;
    int theight = th - tl + 1;
    uint8_t mirror_enabled = 0;

    /* Figure out the power of two this sprite fits into */
    uint32_t real_width  = __rdp_round_to_power( twidth );
    uint32_t real_height = __rdp_round_to_power( theight );
    uint32_t wbits = __rdp_log2( real_width );
    uint32_t hbits = __rdp_log2( real_height );

    /* Because we are dividing by 8, we want to round up if we have a remainder */
    int16_t round_amount = (real_width % 8) ? 1 : 0;

    /* Instruct the RDP to copy the sprite data out */
    __rdp_ringbuffer_queue( 0xF5000000 | ((sprite->bitdepth == 2) ? 0x00100000 : 0x00180000) |
                                       (((((real_width / 8) + round_amount) * sprite->bitdepth) & 0x1FF) << 9));
    __rdp_ringbuffer_queue( (mirror_enabled == 0 ? 0x40100 : 0) | (hbits << 14 ) | (wbits << 4) );
    __rdp_ringbuffer_send();

    /* Copying out only a chunk this time */
    __rdp_ringbuffer_queue( 0xF4000000 | (((sl << 2) & 0xFFF) << 12) | ((tl << 2) & 0xFFF) );
    __rdp_ringbuffer_queue( (((sh << 2) & 0xFFF) << 12) | ((th << 2) & 0xFFF) );
    __rdp_ringbuffer_send();

    /* Save sprite width and height for managed sprite commands */
    cache.width = twidth - 1;
    cache.height = theight - 1;
    cache.s = sl;
    cache.t = tl;
    cache.real_width = real_width;
    cache.real_height = real_height;
   
    /* Return the amount of texture memory consumed by this texture */
    return ((real_width / 8) + round_amount) * 8 * real_height * sprite->bitdepth;
}


Changes on rdp_draw_textured_rectangle_scaled, still i have to test different texture sizes just to make sure its correct.

Code:
   if (flags > 0)
   {   
      if (flags != 2)
         s += ( (cache.width+1) + ((cache.real_width-(cache.width+1))<<1) ) << 5;
   
      if (flags != 1)
         t += ( (cache.height+1) + ((cache.real_height-(cache.height+1))<<1) ) << 5;   
   }


Code:
void __rdp_draw_textured_rectangle_scaled( int tx, int ty, int bx, int by, double x_scale, double y_scale, int flags )
{
    uint16_t s = cache.s << 5;
    uint16_t t = cache.t << 5;

    /* Cant display < 0, so must clip size and move S,T coord accordingly */
    if( tx < 0 )
    {
      if ( tx < -cache.width ) { return; }
        s += (int)(((double)((-tx) << 5)) * (1.0 / x_scale));
        tx = 0;
    }

    if( ty < 0 )
    {
        t += (int)(((double)((-ty) << 5)) * (1.0 / y_scale));
        ty = 0;
    }

    /* Calculate the scaling constants based on a 6.10 fixed point system */
    int xs = (int)((1.0 / x_scale) * 4096.0);
    int ys = (int)((1.0 / y_scale) * 1024.0);

    if (flags > 0)
    {   
       if (flags != 2)
          s += ( (cache.width+1) + ((cache.real_width-(cache.width+1))<<1) ) << 5;
   
       if (flags != 1)
          t += ( (cache.height+1) + ((cache.real_height-(cache.height+1))<<1) ) << 5;   
    }
   
    /* Set up rectangle position in screen space */
    __rdp_ringbuffer_queue( 0xE4000000 | (bx << 14) | (by << 2) );
    __rdp_ringbuffer_queue( (tx << 14) | (ty << 2) );

    /* Set up texture position and scaling to 1:1 copy */
    __rdp_ringbuffer_queue( (s << 16) | t );
    __rdp_ringbuffer_queue( (xs & 0xFFFF) << 16 | (ys & 0xFFFF) );

    /* Send command */
    __rdp_ringbuffer_send();
}


I tried it combined with scale_x and scale_y, seems to be right with scale_y (also mid screen, with clipping):
Image

However i tested it with scale_x and pain arrived, i tried it without my code and still does the same, maybe a bug on the lib? I have to look at it.
Image


Top
 Profile  
 
PostPosted: Sat May 27, 2017 10:43 am 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6285
Location: Seattle
BMBx64 wrote:
However i tested it with scale_x and pain arrived, i tried it without my code and still does the same, maybe a bug on the lib? I have to look at it.
Image
Looks like it's reading the source pixels four pixels as a time...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group