gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Graphics > Vector Graphics on Gba?

#8371 - Sckuz - Wed Jul 09, 2003 9:31 am

Ive started a project that uses vector graphics similar to early arcade games. So far, i have to basic graphics engine built, but its super slow. Im even compiling it using thumb. Ive tried everything i can think of. I think the reason its so slow is because im using Bresenham's Line Algorithm and plotting each pixel individually? Im not sure though. If anyone could give me some advice or point me to demo that uses vector graphics, i would really appreciate it. I know the GBA is capable of doing this.
_________________
"There is no right and wrong. There's only fun and boring." - The Plague

#8383 - Sweex - Wed Jul 09, 2003 2:04 pm

You should be able to draw lines quite fast. Floats usually slowdown a lot. Are you using floats or doubles?

#8389 - Cyberman - Wed Jul 09, 2003 4:01 pm

Sckuz wrote:
Ive started a project that uses vector graphics similar to early arcade games. So far, i have to basic graphics engine built, but its super slow. Im even compiling it using thumb. Ive tried everything i can think of. I think the reason its so slow is because im using Bresenham's Line Algorithm and plotting each pixel individually? Im not sure though. If anyone could give me some advice or point me to demo that uses vector graphics, i would really appreciate it. I know the GBA is capable of doing this.


Bresenham's algo is very fast, obviously it's not the problem.

A few things to realize.


    1:) Thumb mode is slower than ARM mode, depending on WHERE the code is located, if it's in ROM it's actually faster, if it's in IRAM it's slower than ARM.
    2:) floating point should be used sparingly at best. This is because the GBA must emulate it. Fixed point is better.
    3:) DON'T I repeat DON'T use a divide unless you HAVE to. Divide is not supported in GBA hardware AGAIN this must be emulated for both floating point and integers and both are fairly slow. If you are dividing by a constant take it's recipricol and multiply by it JUST to be sure.
    4:) Try using fixed point for calculations and move your drawing routines from ROM to IRAM and use ARM instructions instead. Heck just moving it to IRAM will boost the performance but using ARM mode for the code will boost it even more.


My recomendation is to be sure you are only handing your line drawing function integers.
If you are drawing in mode 3 treat the display as a linear array. In mode 4 don't do this. It's not an array of char. Writting to it a char will give you a headache namely it won't work right. You should have a local variable to read the 16 bit aligned word you are operating on in the VRAM and perform masking and bit twiddling in your function. When you cross a 16 bit boundry write out your little scratch buffer.

If you go with using fixed point, be sure your objects won't cause an overun of your variables when scaled etc. :)

Cyb

#8392 - DekuTree64 - Wed Jul 09, 2003 4:29 pm

Hmm, I'm nto really sure what style you mean (I never played arcade games), but I'll guess you mean 3D drawn in wireframe mode? Well it should be perfectly possible, seeing as how GBA can (kinda) do polygonal 3D, which requires tracing all the edge lines anyway, and a lot more pixel drawing time. But Sweex is right, if you're using floats, that's your whole problem. Use fixed-point instead, or a fractional method, where like for a line with a slope of 2/3 (just take yEnd - yStart as the numerator (the 2 in this case) and xEnd - xStart as the denomenator (the 3 (we have a very short line)), and swap them if the numer is greater then the denom), then you plot a pixel, add 1 to x, add the numerator of your slope fraction to yError (that would be 2 for this example), and as soon as yError gets to be greater than or equal to the denominator of your slope fraction, you add 1 to the screen Y coord, and subtract the denominator from yError. That way, in this example, after the first 2 increments, you've added 2 to yError twice, so it's 4. Then you subtract 3 from it, so you have 1. On the next step, you add 2 to it again, so you have 3, and that means another pixel, so you add 1 to y, and subtract 3 again. So as you can see, you get 2 pixels, then 1 pixel, then 2, then 1. Which turns out to move precisely 2 pixels vertically for every 3 horizontal ones. And since the slope was 2/3, that's exactly how it should be.

I've heard of a more advanced line drawing technique though (I think it was called run-length slice), but I've never tried it myself. The basic theory was to use that pattern of alternating run lengths, which in the example was 2, 1, 2, 1, 2, 1... to speed up the line drawing process.
So you figure out what those 2 lengths will be, and then make a fast loop to draw that many pixels in a straight line, then increment y (or x the runs are vertical), then draw the second length, inc y again, then do the first again, until your line is drawn. You can make a huge unrolled loop to draw the full length of the screen, and jump to the (end - runLength)th pixel in the loop so you don't have to do any checking if x is greater than the length at all. Would be fast if you got it working, especially if you have a pointer to the urrent pixel on the sreen, and in your pixel drawnig loop, you just increment it as you draw, and then add/subtract the screen width to/from it so you move down/up a pixel and you're ready for the next row without any multiplying the y coord by the width.
You have to special case the endpoints though, cause depending on the length of your line, you might end up starting with a run of say 10 pixels, and then ending with a run of 2. Then the end would look kinda funny, so you need to average those 2, so it would be 6 on each end. Actually now that I think about it that would happen with the fraction method I was talking about before too. I've never tried it either though, I just use fixed point. Much simpler.

EDIT: Cyberman posted while I was writing all that and pointed out something important: You can't have a direct pointer to a pixel in mode4, so the run-length slice would loose a lot of its advantage. But it would gain some in being able to write 2 pixels at a time in long runs, whereas the fixed point style draws one pixel at a time, so it's not worth the trouble of checking if you can draw the next pixel while you're doing the current one.

#8414 - Sckuz - Wed Jul 09, 2003 10:07 pm

Hey, thanks for the help. I'll start rewriting some code using your suggestions and see if it helps. I have one question though.

Quote:

1:) Thumb mode is slower than ARM mode, depending on WHERE the code is located, if it's in ROM it's actually faster, if it's in IRAM it's slower than ARM.


How exactly do I store the code in the IRAM? Sorry if that's a stupid question. As I'm sure you can tell, I'm pretty new to Gba Development.
_________________
"There is no right and wrong. There's only fun and boring." - The Plague

#8426 - Sckuz - Thu Jul 10, 2003 4:46 am

Also... Ive never had to work with fixed point before. I wont make you explain it to me, but if you could point me to any helpful references, I would appreciate it. Thanks!
_________________
"There is no right and wrong. There's only fun and boring." - The Plague

#8466 - Sckuz - Fri Jul 11, 2003 11:04 am

Ok.. Scratch that last request. I found some useful resources on Fixed Points. Yeah.. taking those floats out at the least tripled my game's performance. I still would like to know how you load the code into IRAM.
_________________
"There is no right and wrong. There's only fun and boring." - The Plague

#8468 - Quirky - Fri Jul 11, 2003 12:54 pm

Here's my interupt routine. It's compiled in arm and placed in iwram:

Code:

// inter.h
#define CODE_IN_IWRAM __attribute__ ((section (".iwram"), long_call))
CODE_IN_IWRAM void InterruptProcess(void);

// inter.arm.c
#include "inter.h"
CODE_IN_IWRAM void InterruptProcess(void) {
  //blah
}



The .c file has the extension ".arm.c" so that make knows to compiled it in arm mode. All my other ".c" files are -mthumbed (for rom).