DCEmulation

dreamcast development • homebrew software • hardware hacking • indie games • emulators • and more!
Back to main site
It is currently Wed Oct 22, 2014 4:04 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 89 posts ]  Go to page 1, 2, 3, 4, 5  Next
Author Message
PostPosted: Tue Aug 05, 2003 9:53 pm 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
This is the start of a fairly simple graphics tutorial, aimed at the Dreamcast. I'll probably do a better version later, with a couple of examples, diagrams, decent formatting, and stuff like that, but this is just a quick draft of the first part.

It's aimed mostly at people who have a little bit of graphics knowledge, and have already got all the DC development kit set up, and know how to compile stuff. Anyway, here it goes. Any feedback would be appreciated.

Setting up a video mode
The first thing you should do when doing any kind of graphics programming is set up a video mode. On the Dreamcast, this isn't really that important - KallistiOS will automatically set the video hardware up into 640x480, 16 bit 60Hz mode. However, it's still a good idea to set the video mode manually, in case they change something.

This couldn't really be much simpler - we just need to call the function vid_set_mode, giving it our desired resolution and colour mode, and it'll do the rest:
Code:
vid_set_mode(display_mode, pixel_mode);


display_mode can be one of:
Code:
   DM_320x240         320 x 240, 60Hz (or VGA)
   DM_640x480         640 x 480, 60Hz (or VGA)
   DM_800x608         800 x 608, 60Hz (or VGA)
   DM_256x256         256 x 256, 60Hz (or VGA)
   DM_768x480         768 x 480, 60Hz (or VGA)
   DM_768x576         768 x 576, 60Hz (or VGA)
   DM_640x480_PAL_IL   640 x 480, 50Hz
   DM_256x256_PAL_IL   256 x 256, 50Hz
   DM_768x480_PAL_IL   768 x 480, 50Hz
   DM_768x576_PAL_IL   768 x 576, 50Hz


The 60Hz modes will always be 60Hz, even on a PAL Dreamcast. The 50Hz modes will always be 50Hz, even on an NTSC Dreamcast. While most PAL TVs can display a 60Hz signal, some can not, and virtually no NTSC TVs can display a 50Hz signal. So it's usually safe to use the 60Hz modes, but you might want to put in an option to use 50Hz on PAL Dreamcasts. I'll go into more detail on that later.

One rather strange omission that is worth taking note of - there is no 320x240 50Hz mode. I don't know why this is, because it's certainly not too difficult to do - it was just never included in KOS. If anyone really needs it, there is a patch to add that mode (DM_320x240_PAL) to KOS 1.2.0

pixel_mode can be one of:
Code:
   PM_RGB555         15-bit (xRRRRRGGGGGBBBBB)
   PM_RGB565         16-bit (RRRRRGGGGGGBBBBB)
   PM_RGB888         24-bit (RRRRRRRR GGGGGGGG BBBBBBBB)


The best mode to use on the Dreamcast is RGB565 - it provides fairly good colour quality, it's significantly faster than 24-bit mode, and it uses less memory. Just trust me on this - it's the best mode to use for pretty much everything that we're going to be doing.

So, to initialise the screen to 640x480 60Hz, in RGB565 colour mode, we'd use the following line:
Code:
vid_set_mode(DM_640x480, PM_RGB565);


RGB565 colour mode
In RGB565 mode, the three colour components are packed into two bytes. The upper 5 bits contain the red data, the next 6 contain the green data, and the last 5 contain the blue data. Red and blue range from 0 to 31, and green ranges from 0 to 63. The reason that green is given more space is because the human eye is more sensitive to green.

Colours on a computer are typically represented using three bytes - one each for red, green and blue, ranging from 0 to 255. There's an easy way to convert from this format to the 16-bit RGB565 format that we need - we just use a macro:
Code:
#define PACK_PIXEL(r, g, b) ( ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3) )


That macro uses two AND operations to mask out the unnecessary bits of the red and green components, bit shifts the values to get them into the correct place, and ORs them together. For some strange reason, that macro isn't included anywhere in KOS.

Drawing a single pixel
No matter how complex the graphics we're trying to make, no matter how many complex formulae and techniques we're using, no matter how long it's taken to draw our artwork, ALL 2D graphics come down to this - drawing a single pixel. For many things, where we need to plot multiple pixels at once, we can modify this routime to make it faster, but it'll still just be a variation on this. So how exactly do we draw a single pixel?

On the Dreamcast, the image currently being displayed on the screen is stored in an area of video memory called the framebuffer. The pixels are stored in order, from left to right, then from top to bottom, each as a single 16-bit value. So in order to find the location in the framebuffer of a single pixel, we can use this formula:
Code:
location = x_coordinate + (y_coordinate * width)


So, assuming a resolution of 640x480, we can do this:
Code:
location = x + (y * 640)


Now all we need to know is where the framebuffer is. KOS provides us with a pointer to this location, named vram_s. So all we need to do the get the location in memory of a single pixel on the screen is:
Code:
vram_s[x + (y * 640)]


From there, it should be easy to see how to draw a single pixel - we just need to set the value of that location in memory to the colour we want the pixel to be:
Code:
vram_s[x + (y * 640)] = PACK_PIXEL(r, g, b);


Clipping
Now that all works fine, until we come across one additional problem - clipping. What happens if we were to try to write to negative X or Y coordinates, or write off the bottom or the right of the screen? We'd be writing either to the wrong part of the screen, or an area of memory that we aren't allowed to write to. We could cause all kinds of problems. So we just don't do it - we have to add some checking to make sure we aren't trying to draw outside the screen:
Code:
if((x >= 0) && (x < 640) && (y >= 0) && (y < 480))
   vram_s[x + (y * 640)] = PACK_PIXEL(r, g, b);


Now we have a safe, effective way to draw a single pixel on the screen. Of course, it'd be more convenient as a macro:
Code:
#define DRAW_PIXEL(x, y, c) \
   if((x >= 0) && (x < 640) && (y >= 0) && (y < 480)) \
      vram_s[x + (y * 640)] = c;


Now, to draw a single pixel, we can just work out the colour we want to set it to using PACK_PIXEL, and the use DRAW_PIXEL to draw it.


Last edited by BlackAura on Tue Aug 19, 2003 10:22 pm, edited 3 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2003 10:55 pm 
Offline
Insane DCEmu
Insane DCEmu
User avatar

Joined: Sat Jun 14, 2003 10:00 pm
Posts: 223
Location: melb.vic.au
Thanks a bunch, I'll be sure to save it for future reference. Just a question though, when running the PAL resolutions: would they have black borders like some of the DC PAL games? They all have the same no. pixels as the 60Hz equivalents, and as PAL has more vertical scan lines than NTSC, I'm assuming this will give those ugly black borders.

_________________
- Interesting.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2003 11:08 pm 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
You do get the black borders at the top and bottom of the screen, I'm afraid. It seems to be part of the DC's hardware. The screen resolutions are otherwise identical - same number of scanlines, same number of pixels per scanline. It might be possible to create a slightly hacked graphics mode that didn't have the borders, and thus had a higher resolution, but I don't know how well the rest of KOS would handle it, especially the stuff to handle the PVR.

So I think the best way is to detect a PAL console, and pop up a "60Hz or 50Hz" screen, like most commercial games do. It's not really that hard to code, and it's the only way that you can let everybody use the program, while still letting PAL users see it in full screen.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 12:11 am 
Offline
Insane DCEmu
Insane DCEmu
User avatar

Joined: Sat Jun 14, 2003 10:00 pm
Posts: 223
Location: melb.vic.au
Strange, could have sworn some of my DC games ran fullscreen at 50Hz. Maybe it's only certain resolutions? *shrug* I'll have a look later. I'll be opting for a 60/50 selection screen in any case.

_________________
- Interesting.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 12:14 am 
Offline
DCEmu Banned
DCEmu Banned

Joined: Fri Jul 11, 2003 7:56 pm
Posts: 4850
Rather neat if any one wants i could do the same thing in SDL.

_________________
Image

Join the Muppet posse!
http://www.dcemulation.com/phpBB/viewtopic.php?t=54866


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 12:26 am 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
As I said, there might be a tweaked resolution that doesn't have borders - as with most things that connect to a TV instead of a monitor, you have a lot of control over the way the signal's generated. But if there is such a resolution, KOS doesn't have it.

IM(r)eaper - Go for it. The more, the merrier.

I'm currently writing code for lines (horizontal, vertical, and arbitrary angled lines) and circles (filled and hollow), along with boxes (filled and hollow). The next tutorial will probably cover that lot. The hollow circles and the arbitrary angle lines are the hardest to do - they others are basically just simple loops combined with pixel plotting.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 12:55 am 
Offline
Insane DCEmu
Insane DCEmu
User avatar

Joined: Sat Jun 14, 2003 10:00 pm
Posts: 223
Location: melb.vic.au
I'm guessing you can't create hardware anti-aliased vectors on the DC? I suppose it shouldn't be too hard to write a basic software AA algorithm. Eh, nevermind me, just thinking out loud again.

_________________
- Interesting.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 1:14 am 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
I think you can actually, but you need to be rendering everything using the PVR hardware. And I don't know how to enable hardware AA on the DC. It can do it, I just don't know how. Oh wait... the PVR hardware can't actually do lines - you have to fake them using triangles. Should still be possible though.

I think that you could do anti-aliased lines in software. It shouldn't really be that hard - it's basically an extension of standard line drawing. But you'd have to be using double-buffering of some kind.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 1:51 am 
Offline
DCEmu Banned
DCEmu Banned

Joined: Fri Jul 11, 2003 7:56 pm
Posts: 4850
Ok With SDL ill try do the same thing as you in kos but with it. just working on my port having problems patching sdl when i get it fixed ill start writting the tuts. after that.

_________________
Image

Join the Muppet posse!
http://www.dcemulation.com/phpBB/viewtopic.php?t=54866


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 2:08 am 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
Line drawing's nearly finished - horizontal and vertical lines are done, and I'm working on the general line drawing, using Bresenham's algorithm. It's not the fastest, but it's at least comprehensible. And, as an added bonus, I found an anti-aliased variant of it which I can use to do anti-aliased vectors. But that'll have to wait until I get to blending, which should be a real pain in the backside in 16-bit mode.

So, without further ado...

Horizontal Lines
Drawing pixels is probably getting kinda boring by now, so let's draw something more interesting. As a start, we'll draw a simple horizontal line, which is about the simplest shape you can do. A line is basically a load of pixels, arranged in a line. So they shouldn't be that hard to draw - we just need to draw a load of pixels in a line:
Code:
void draw_hline(int x1, int x2, int y, uint16 c)
{
   int cx;
      // Draw the line
   for(cx = x1; cx <= x2; cx++)
      DRAW_PIXEL(cx, y, c);
}


One problem there - what if x2 is smaller than x1? The line won't be drawn. So, if x2 is smaller than x1, we should swap them around:
Code:
void draw_hline(int x1, int x2, int y, uint16 c)
{
   int cx;

   // Swap x1 and x2 if necessary
   if(x1 > x2)
   {
      cx = x1;
      x1 = x2;
      x2 = cx;
   }

   // Draw the line
   for(cx = x1; cx <= x2; cx++)
      DRAW_PIXEL(cx, y, c);
}


And that's it... Or is it? The more observant of you may notice that this code is actually very bloated. Remember that DRAW_PIXEL is checking if the pixel is on the screen for every pixel we draw. But, since this is just a horizontal line, we know that if both points are on the screen, the whole line is on the screen. If the line's off the screen entirely, we can just ignore it. If the line is on the screen, we can tell how much of the line is on the screen, and adjust the left and right coordinates appropriately. So we can do this:
Code:
void draw_hline(int x1, int x2, int y, uint16 c)
{
   int cx;

   // Swap x1 and x2 if necessary
   if(x1 > x2)
   {
      cx = x1;
      x1 = x2;
      x2 = cx;
   }

   // Don't bother if the line's off the screen
   if( (y < 0) || (y > 479) || (x1 > 639) || (x2 < 0) )
      return;

   // Clip the line to the edge of the screen
   if(x1 < 0)
      x1 = 0;
   if(x2 > 639)
      x2 = 639;

   // Draw the line
   for(cx = x1; cx <= x2; cx++)
      vram_s[cx + (y*640)] = c;
}


That's a bit better, but there's still one problem - for each pixel, we're doing y*640, which will be the same for each and every pixel. In face, since we're drawing from left to right, each pixel will be next to the previous pixel. So we can do something like this:
Code:
void draw_hline(int x1, int x2, int y, uint16 c)
{
   int cx;
   uint16 *line_buffer;

   // Swap x1 and x2 if necessary
   if(x1 > x2)
   {
      cx = x1;
      x1 = x2;
      x2 = cx;
   }

   // Don't bother if the line's off the screen
   if( (y < 0) || (y > 479) || (x1 > 639) || (x2 < 0) )
      return;

   // Clip the line to the edge of the screen
   if(x1 < 0)
      x1 = 0;
   if(x2 > 639)
      x2 = 639;

   // Set line_buffer to the beginning of the line
   line_buffer = vram_s + x1 + (y * 640);

   // Draw the line
   for(cx = x1; cx <= x2; cx++)
      *line_buffer++ = c;
}


That probably won't make a lot of sense unless you know something about pointers in C - line_buffer is set to the location of the first pixel of the line we're drawing. We then draw the pixel, and increment line_buffer by one pixel, so it now points to the location of the next pixel.

A horizontal line is actually far more useful than it would first appear. A horizontal line is very useful for drawing filled shapes - you just draw a horizontal line from the left-most point of the shape on a given line, to the right-most point of the shape. Then you repeat that for each line. That's how most software rendered 3D games fill polygons.

Vertical Lines
These are pretty much exactly the same as horizontal lines. However, we're now drawing down instead of right. Basically, we swap the X and Y coordinates around, and we skip 640 pixels instead of 1 - we jump down one pixel instead of right one pixel:
Code:
void draw_vline(int x, int y1, int y2, uint16 c)
{
   int cy;
   uint16 *line_buffer;

   // Swap y1 and y2 if necessary
   if(y1 > y2)
   {
      cy = y1;
      y1 = y2;
      y2 = cy;
   }

   // Don't bother if the line's off the screen
   if( (x < 0) || (x > 639) || (y1 > 479) || (y2 < 0) )
      return;

   // Clip the line to the edge of the screen
   if(y1 < 0)
      y1 = 0;
   if(y2 > 479)
      y2 = 479;

   // Set line_buffer to the beginning of the line
   line_buffer = vram_s + x + (y1 * 640);

   // Draw the line
   for(cy = y1; cy <= y2; cy++)
   {
      *line_buffer = c;
      line_buffer += 640;
   }
}


Hollow Boxes
Now that we have the code to draw horizontal and vertical lines, drawing a hollow box should be very easy - we just draw tow horizontal lines, and two vertical lines:
Code:
void draw_hbox(int x1, int y1, int x2, int y2, uint16 c)
{
   draw_hline(x1, x2, y1, c);
   draw_hline(x1, x2, y2, c);
   draw_vline(x1, y1, y2, c);
   draw_vline(x2, y1, y2, c);
}


Filled Boxes
All we do here is draw a series of horizontal lines, which will fill an area of the screen. We know what the left and right coordinates of the box are on each scanline, and we know how far up and down the box goes. So we can just do:
Code:
void draw_fbox(int x1, int y1, int x2, int y2, uint16 c)
{
   int cy;
   for(cy = y1; cy <= y2; cy++)
      draw_hline(x1, x2, cy, c);
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 12:45 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4242
I figured I'd throw some knowledge in the ring, especially since I just started working with PVR code in my game again. So, without further ado, a PVRized version of the lines tutorial.

Initialization:

Just a few little differences between regular, and PVR init. First of all, set your video mode, like BlackAura stated above. Immediately after this, you need to initialize the PVR, if you'd like to use it. This can be done most simply like this:
Code:
pvr_init_defaults();

This will set up the PVR with reasonable defaults for all settings. I've never had to muck around with the settings, and I find the defaults to be pretty good.

Scene Drawing:

When using the PVR, one needs to tell it when beginning a new scene, and what polygon lists will be used. This is done as follows. (You also must close everything when you're done with it!)
Code:
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
// Do opaque drawing here!
pvr_list_finish();
pvr_list_begin(PVR_LIST_TR_POLY);
// Do Translucent drawing here
pvr_list_finish();
pvr_scene_finish();


Horizontal Lines:

Horizontal lines are fun, aren't they! Anyway, here's a method I use to draw horizontal lines of any color on the screen.

Code:
void hline_tr(float x1, float x2, float y, uint8 a, uint8 r, uint8 g, uint8 b)   {
   pvr_poly_hdr_t hdr;
   pvr_poly_cxt_t cxt;
   pvr_vertex_t vert;
   float cx;
   if(x1 > x2)   {
      cx = x1;
      x1 = x2;
      x2 = cx;
   }

   pvr_poly_cxt_col(&cxt, PVR_LIST_TR_POLY);
   pvr_poly_compile(&hdr, &cxt);

   pvr_prim(&hdr, sizeof(hdr));
   vert.flags = PVR_CMD_VERTEX;
   vert.x = x1;
   vert.y = y + 1;
   vert.z = 5.0f;
   vert.u = 0;
   vert.v = 0;
   vert.argb = PVR_PACK_COLOR(a / 255, r / 255, g / 255, b / 255);
   vert.oargb = 0;
   pvr_prim(&vert, sizeof(vert));

   vert.y = y;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x2;
   vert.y = y + 1;
   pvr_prim(&vert, sizeof(vert));

   vert.flags = PVR_CMD_VERTEX_EOL;
   vert.y = y;
   pvr_prim(&vert, sizeof(vert));
}

Simple enough, eh? For this function, you can pass in values between 0 and 255 for each color (r, g, and b) and how opaque it is (a).

Vertical Lines:

Once again, the wonderful vertical line. Here's my method of drawing vertical lines:
Code:
void vline_tr(float x, float y1, float y2, uint8 a, uint8 r, uint8 g, uint8 b)   {
   pvr_poly_hdr_t hdr;
   pvr_poly_cxt_t cxt;
   pvr_vertex_t vert;
   float cy;
   if(y1 > y2)   {
      cy = y1;
      y1 = y2;
      y2 = cy;
   }

   pvr_poly_cxt_col(&cxt, PVR_LIST_TR_POLY);
   pvr_poly_compile(&hdr, &cxt);

   pvr_prim(&hdr, sizeof(hdr));
   vert.flags = PVR_CMD_VERTEX;
   vert.x = x /* - 1 */;
   vert.y = y2;
   vert.z = 5.0f;
   vert.u = 0;
   vert.v = 0;
   vert.argb = PVR_PACK_COLOR(a / 255, r / 255, g / 255, b / 255);
   vert.oargb = 0;
   pvr_prim(&vert, sizeof(vert));

   vert.y = y1;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x + 1;
   vert.y = y2;
   pvr_prim(&vert, sizeof(vert));

   vert.flags = PVR_CMD_VERTEX_EOL;
   vert.y = y1;
   pvr_prim(&vert, sizeof(vert));
}


Arrows (AKA Triangles):

Just a short note about triangles. All verteces need to be submitted clockwise. The same goes for the diagonal line function later. These functions have no protection for if someone submits them in the wrong order, and most likely, there will be no triangle on the screen if you do.
Code:
void arrow(float x1, float y1, float x2, float y2, float x3, float y3, uint8 a, uint8 r, uint8 g, uint8 b)   {
   pvr_poly_hdr_t hdr;
   pvr_poly_cxt_t cxt;
   pvr_vertex_t vert;

   pvr_poly_cxt_col(&cxt, PVR_LIST_TR_POLY);
   pvr_poly_compile(&hdr, &cxt);
   pvr_prim(&hdr, sizeof(hdr));

   vert.flags = PVR_CMD_VERTEX;
   vert.x = x1;
   vert.y = y1;
   vert.z = 5.0f;
   vert.u = 0;
   vert.v = 0;
   vert.argb = PVR_PACK_COLOR(a / 255, r / 255, g / 255, b / 255);
   vert.oargb = 0;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x2;
   vert.y = y2;
   pvr_prim(&vert, sizeof(vert));

   vert.flags = PVR_CMD_VERTEX_EOL;
   vert.x = x3;
   vert.y = y3;
   pvr_prim(&vert, sizeof(vert));
}


Diagonal Lines:

The last thing I'll be covering, at least today, is diagonal lines. Remember Coordinates must be put in in a certain order. (see note below code)
Code:
void line_tr(float x1, float y1, float x2, float y2, uint8 a, uint8 r, uint8 g, uint8 b)   {
   pvr_poly_hdr_t hdr;
   pvr_poly_cxt_t cxt;
   pvr_vertex_t vert;

   pvr_poly_cxt_col(&cxt, PVR_LIST_TR_POLY);
   pvr_poly_compile(&hdr, &cxt);
   pvr_prim(&hdr, sizeof(hdr));

   vert.flags = PVR_CMD_VERTEX;
   vert.x = x1;
   vert.y = y1;
   vert.z = 5.0f;
   vert.u = 0;
   vert.v = 0;
   vert.argb = PVR_PACK_COLOR(a / 255, r / 255, g / 255, b / 255);
   vert.oargb = 0;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x2;
   vert.y = y2;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x1 + 1;
   vert.y = y1;
   pvr_prim(&vert, sizeof(vert));

   vert.flags = PVR_CMD_VERTEX_EOL;
   vert.x = x2 + 1;
   vert.y = y2;
   pvr_prim(&vert, sizeof(vert));
}


This diagonal line code should be able to handle any kind of line, I just use the horizontal and vertical line routines above. Anyway, here's the note I mentioned above:

Code:
line_tr(32, 48, 48, 32, 255, 255, 255, 255);
Will draw a line like this slash: / that is white, and completely opaque.

Code:
line_tr(48, 288, 32, 272, 255, 255, 255, 255);
Will draw a completely opaque, white line that looks similar to this slash: \

That's all for today, let me know if you see any improvements, or problems with this tutorial lesson.


Last edited by BlueCrab on Thu Aug 07, 2003 7:48 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: 2D graphics tutorial
PostPosted: Wed Aug 06, 2003 1:04 pm 
Offline
DC Developer
DC Developer

Joined: Thu Jan 16, 2003 3:01 am
Posts: 1753
Location: The Netherlands
BlackAura wrote:
One rather strange omission that is worth taking note of - there is no 320x240 50Hz mode. I don't know why this is, because it's certainly not too difficult to do - it was just never included in KOS. If anyone really needs it, there is a patch to add that mode (DM_320x240_PAL) to KOS 1.2.0
It's indeed weird that that mode was missing. Anyway, I talked about that with Mekanaizer on #dreamcastdev a few months ago. He had a text file which explained the video registers and he submitted a patch to add that mode. It's now included in CVS, so it will be included in KOS 1.2.1 as well when it comes out.

But I always use CVS anyway. ;)


Top
 Profile  
 
 Post subject: Re: 2D graphics tutorial
PostPosted: Wed Aug 06, 2003 3:30 pm 
Offline
Administrator
Administrator
User avatar

Joined: Sat Mar 09, 2002 7:35 am
Posts: 13567
Location: Swansea, Wales
BlackAura wrote:
While most PAL TVs can display a 50Hz signal, some can not, and virtually no NTSC TVs can display a 50Hz signal.


Shouldn't that bit say 60Hz? 50Hz is the PAL standard, and so all PAL TVs will display 50Hz, with most displaying 60Hz.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 5:24 pm 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
Yeah, it should... I'll just go back and edit it. Thanks for pointing that out.

BlueCrab - Nice job.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2003 7:31 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4242
Thanks, thought it'd make a good addition when I saw this topic.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 07, 2003 1:36 am 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
Those lines are being draws as a quad, yes? It might have been a better idea to cover drawing triangles first, since they're slightly simpler than quads. And, while you're at it, you could have done a filled rectangle quite simply too.

I've been converting the stuff I've got into HTML, writing some examples for each tutorial (up to part 4 now) and preparing to put it up as a webpage. D'ya mind if I put that up too?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 07, 2003 7:44 am 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4242
Well, I have drawing triangles in there too! I'll add some stuff with more general filled quads in a bit. And sure, you can include the tutorial, just make sure I get the proper credit, ok? And feel free to rearrange the stuff in the HTML page...


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 07, 2003 7:58 am 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4242
Drawing Filled Rectangles with the PVR:

Drawing filled rectangles with the PVR is just as easy as drawing those lines earlier.

Code:
void frect_tr(float x1, float y1, float x2, float y2, uint8 a, uint8 r, uint8 g, uint8 b)   {
   pvr_poly_hdr_t hdr;
   pvr_poly_cxt_t cxt;
   pvr_vertex_t vert;
   float cx, cy;
   if(x1 > x2)   {
      cx = x1;
      x1 = x2;
      x2 = cx;
   }
   if(y1 > y2)   {
      cy = y1;
      y1 = y2;
      y2 = cy;
   }

   pvr_poly_cxt_col(&cxt, PVR_LIST_OP_POLY);
   pvr_poly_compile(&hdr, &cxt);

   pvr_prim(&hdr, sizeof(hdr));
   vert.flags = PVR_CMD_VERTEX;
   vert.x = x1;
   vert.y = y2;
   vert.z = 5.0f;
   vert.u = 0.0f;
   vert.v = 0.0f;
   vert.argb = PVR_PACK_COLOR(a / 255, r / 255, g / 255, b / 255);
   vert.oargb = 0;
   pvr_prim(&vert, sizeof(vert));

   vert.y = y1;
   pvr_prim(&vert, sizeof(vert));

   vert.x = x2;
   vert.y = y2;
   pvr_prim(&vert, sizeof(vert));

   vert.flags = PVR_CMD_VERTEX_EOL;
   vert.y = y1;
   pvr_prim(&vert, sizeof(vert));
}


And that's how you draw filled rectangles with the PVR.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 07, 2003 6:20 pm 
Offline
DC Developer
DC Developer

Joined: Sun Dec 30, 2001 8:02 am
Posts: 9951
Cool, thanks! I'll put it up there when I get around to it - I'm still working on converting my own ones and writing some examples to go with them. Line clipping is proving to be more of a pain in the neck than I thought...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 08, 2003 6:22 pm 
Offline
DCEmu Nutter
DCEmu Nutter

Joined: Sun Aug 11, 2002 3:07 pm
Posts: 964
I am using visual c++ and kos 1.9, and the following "vram_s[x + (y * 640)] = PACK_PIXEL(r, g, b); " would not work for me. Is this method not supported in 1.9?


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

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 0 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