A few summers ago I dove into the world of OpenGL, and quickly found myself way over my head! However, looking back, I ended up learning a lot more than I thought I did! Some of the concepts from learning OpenGL end up crossing over with the PVR, given how the functions are setup.
I'll attach the OpenGL tutorial I followed in the references below, in case anyone is interested!
What Is the PVR?
The PVR is the Dreamcast's built-in graphics chip. It handles all the heavy lifting when it comes to rendering. This is in contrast to software rendering (which people seem to love making tutorials about), which uses the CPU to render pixels on the screen and is much slower.There's a ton of documentation all over on the hardware, and how it functions, but very little on how to actually use it (aside from this tutorial, but quite frankly I was left a little confused afterwards).
The end goal of this tutorial will be to get something like the following on your screen using only the PVR! No OpenGL, no SDL, no software rendering!
Relevant Example Projects
- kos/examples/dreamcast/png/example.c
More or less what I'll be basing this tutorial off. - kos/examples/dreamcast/pvr
Literally anything in here will be relevant, but probably more advanced.
The Code
A lot more here than the input tutorial! I don't want to break down every single line here, so I made sure to put a sufficient amount of comments to help people along! Also, if you're struggling to figure out where this is coming from, I'd highly encourage checking out the KOS documentation!
Initialization
First, we have to initialize our PVR. We do this by first setting up the video mode, more details on that can be found here, and then we initialize the default values for the PVR. If we don't do this, nothing will show up on the screen!
The Render Loop
Like most things in game development, we're going to want to draw our scene in a loop. Here we have our Draw() function sandwiched between a bunch of other nonsensical PVR-related functions. The comments should help, but the big idea here is that we're setting up a list of polygons to draw with pvr_list_begin, and then calling a function that handles the drawing of them.
I included the transparency list from the aforementioned PVR tutorial just to show where it'd go if you had anything that needed transparency.
The Draw Function
Here we handle setting up our PVR polygon context, header, and vertices we're going to be rendering.
Again, most of this is already commented, so I won't explain a ton. The idea is that we need a PVR header in order to actually render anything. We take our context, with our list of polygons to render, and compile it into a header that the PVR uses to render our vertices.
The Vertices
Here we have a single vertex. The pvr_vertex_t struct consists of X, Y, and Z values for positioning (Z being depth), and U and V values for texturing. Vertices are a big part of 3D, so if you're not familiar with them, I'd recommend brushing up on things. Download Blender, mess around with it, and things will start to make sense.
Note: The aforementioned PVR tutorial makes a point to state that triangle vertices must be rendered in a clockwise fashion. Rendering them in any other order may result in issues.
We also have my favorite part: The color! Our vertices' colors (vert.argb) consist of an alpha value (transparency), followed by our red value, green value and finally blue value! We use PVR_PACK_COLOR to get our color values.
You can change these colors to whatever you want! I just went with the traditional red corner, green corner, and blue corner.
And that's pretty much it! We pack our vertices into primitives to render, the PVR runs through our list of vertices, and boom! Triangle!
A Few Notes
If you're like me, you probably tried to mess with the Z-values of the vertices to see if you could do something fancy. If you did, you'll probably notice you'll get something weird like this (where the bottom-right Z value is < 1)
Why is that? Isn't Z our depth? Well, it is, but this is showing us that our camera is rendering in orthographically, and not with perspective.
An example of perspective vs orthographic projections. Author: Unknown |
If you trick your mind into believing that the red corner in the triangle above being really far away, it makes a little more sense.
I'm not quite sure how to get perspective working just yet, but I'm quite eager to find out! I'd really love to provide some solid tutorials on how to work with a camera in a scene, once I figure it out, myself!
References
- OpenGL Tutorial by SonarSystems
A good OpenGL tutorial, teaching you the basics of OpenGL and 3D graphics.
Hello! Thanks for the tutorials, they were very helpful, especially this one. I just wanted to share here that I found that pvr.h doesn't cover perspective transformations. In other words, programming PVR for now only in 2D, if you want 3D you have to use KGL or GLdc. This is reported in a comment at the beginning of the file. See for yourself, follow file link: http://gamedev.allusion.net/docs/kos-current/pvr_8h_source.html
ReplyDeleteAhh, interesting! Thanks for the info! I'll definitely keep that in mind.
DeleteI think the documentation might be indicating that the PVR itself doesn't have built-in functionality for doing transformations, but I believe you can still rely on third-party libraries to help! For instance, it also seems to mention that the PVR API doesn't support matrix transformations at all, but I seem to recall using the matrix3d.h library when I was messing around with the PVR... I'm not sure though! It'd be worth looking into!
In any case, I'd strongly recommend people to use GLdc now-a-days anyway! It's so much nicer to work with! :)
Yes friend, it sure is possible. I think I expressed myself badly, what I meant was that the PVR API doesn't support transformations. But no doubt you can get around this limitation by implementing the matrices or using third-party libraries as you said. By the way, this is a very interesting project. Let's see what we got! See you
ReplyDelete