Copy Link
Add to Bookmark
Report

PowerVR Introduction

Dreamcast's profile picture
Published in 
Dreamcast technical
 · 21 Dec 2018

Introduction
This tutorial was written by BlueCrab, and was converted to HTML by me (BlackAura). It's covers using the PowerVR hardware of the Dreamcast to do pretty much the same thing as my first four 2D graphics tutorials, so it might be a good idea to have a look at those first - much of it, especially in the first part about Dreamcast video modes, still applies when using the PowerVR hardware. I also added a couple of comments to clarify the usage of some of the code. Those notes are written in italics. Anyway, over to BlueCrab...

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:

 
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!)

The Dreamcast uses display lists when it's drawing the screen, and it expects all the opaque drawing instructions to be in one part of the list, followed by all the transparent parts. So if something's going to be transparent, make sure you draw it into the transparent display list!

 
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.

 
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));
}


Since these lines can be transparent, you have to draw lines into the transparent display list. If you try to draw it into the opaque list, nothing will happen.

Vertical lines
Once again, the wonderful vertical line. Here's my method of drawing vertical lines:

 
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));
}

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.

 
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)

 
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:

 
line_tr(32, 48, 48, 32, 255, 255, 255, 255);


Will draw a line like this slash: / that is white, and completely opaque.

 
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.

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT