LeonBlade's GPU Tutorial
Hello everyone,
You may have seen my post asking for help on getting my GPU to work, so why am I making a tutorial already?
1. There are no tutorials already.
2. I got my GPU to work 
Now I don't know everything about programming with the GPU, so if someone spots something that isn't optimized or is written wrong, PLEASE post a reply to correct me!
I do what works, but it's not necessarily the BEST way or even really the RIGHT way to do it.
With that in mind, let's get started...
Part 1: Setting up the screen
This is the part that confused me the most ^_^
Open up your menu and go to [Wire] and in [Wire - Advance] select the [Display - GPU].
When you place it down, you'll see an error on the screen.
All that is telling you is that there is no program running basically, so it ended unexpectedly.
Now you just need a program to run!
Open up the [Context Menu] with C (default key) and for the file name type in cube.txt and then hit [Quick Load] and then Left-Click on the GPU screen to apply the new program, if nothing comes up try using the Quick Load again and then clicking the screen.
I had some trouble with this myself, so if any of you experience the same thing, just keep trying and it should eventually work.
If the problem still keeps happening, then there could be something wrong with your GPU stuff.
If you see a fancy pants spinning cube then you win 
Now you're ready to write a simple GPU program!
Part 2a: Writing some basic code
This is the part where I hope that some of the people who know more about this than me correct anything that I write that isn't constructed properly!
Okay, let's go ahead and start making our own program!
We already know the screen works, but let's use the command (opcode) that runs a program for us.
By calling this, it will run a simple test of a bouncing square on the screen which changes colors (how fancy
)
You can just run it by itself I'm pretty sure... (correct me if I'm wrong)
You can get rid of this line now!
Part 2b: Writing some basic code
Let's clear the screen as a fancy color, like green or something.
If we use the opcode:
And pass in a color, x in this case, we can clear the screen to that color.
So how does this color work?
Well, you need to setup the color yourself.
So first let's make a color variable.
You need to define what variable you are making, and then it's name and optional parameters.
In this case, the colors optional parameters are Red, Green, and Blue values ranging from 0-255 (a total of 256).
So this is how our color should look:
Code:
color bgcolor,0,255,0;
Giving our color no Red and no Blue and full Green will produce a solid neon green color.
Now that we've defined that we can clear our screen to the color:
Note: Make sure that you have the same name in the screen clear as you do for your color.
Now you can just put an exit command to stop the program and leave everything on the screen into frame:
So here is what we got:
Code:
color bgcolor,0,255,0;
dclrscr bgcolor;
dexit;
So to recap, we define our dcolor called bgcolor and then clear the screen with it, and then we exit our code and leave the greeen screen left in frame.
So lets save this file as something like my_first_gpu and load it into our screen. Make sure to add the .txt after the name only when you are choosing what source code to load from.
Now you'll notice an error on the screen.
The fix for that is just moving your color to the bottom after dexit.
(If someone could explain why then that'd be great lol)
So your final code should look like this:
Code:
dclrscr bgcolor;
dexit;
color bgcolor,0,255,0;
There, now you can show everyone your fancy green screen!
But that's not that exciting now is it?
Let's try making some shapes!
Part 2c: Writing some basic code
Our current screen resolution is 512x512 and we can use this to our advantage when it comes to positioning your shape on the screen.
Let's use our existing code to make things easier for us.
Let's make another color right after our bgcolor we made before:
Code:
color c1,255,0,125;
This will give us a nice hot pink color, we will use this as our shape color.
Now let's go ahead and make a shape!
The shape wants 2 things, and those are two Vector2's that define the top left and bottom right positions of our shape.
Now that's a lot of 2's... let me explain.
A Vector2 is a variable that holds both an X and a Y value, which is why it's called a Vector2 because it holds 2 numbers.
You can think about it like battle ship if you want.
The rows and numbers on the game battle ship use a grid system.
If you want to sink someones ship on E2 then they need to go to the Eth row and the 2nd column (or the other way around lol).
That right there can be considered a Vector2!
It holds an X and Y position of E and 2.
You can also just think about graph paper with all the squares all over it.
You need an X and a Y and the Vector2 holds that for you in one easy location instead of storing them separately.
So we need 2 Vector2's because we are defining 2 separate points of our shape. We will be making a square for this example.
One trick you can try is using paint to help you get the coordinates for X and Y.
Open up paint or whatever you want to use and make the canvas 512x512 pixels. (Press Control+E to open up the menu for Paint)
This is the default resolution of our screen like I said before.
Now use the rectangle tool to make a square.
Zoom in an use the selection tool to position your mouse over the top left point of your square.
At the bottom towards the right you'll see a number, that is the position your mouse is on the canvas.
Write that number down for your first Vector2.
Now do the same for the bottom right corner of your rectangle and write those values down for your second Vector2.
For me, I'm going to use the numbers (100,125) for my first Vector2, and (260,350) for my second Vector2.
Now lets add these into our program.
Right under our colors let's add these new Vector2's.
A Vector2 is defined as vec2f or as vector2f which ever you prefer.
Code:
vector2f r1,100,125;
vector2f r2,260,350;
Now let's draw our rectangle, but first let's set the current color to our new color so that our rectangle will draw in that color.
We just pass in the color we want to set our current color too.
Now let's draw our rectangle:
In the end, our program should look like this:
Code:
dclrscr bgcolor;
dcolor c1;
drect r1,r2;
dexit;
color bgcolor,0,255,0;
color c1,255,0,125;
vector2f r1,100,125;
vector2f r2,260,350;
If all goes well, you should be able to compile and see your results 
Here's a picture of what mine looks like:

Now that you know how Vector2's work, try getting some other shapes in there. For a circle you use dcircle which takes the center point as a Vector2 and then the radius as a float. For a line it's the same thing as a rectangle but you're just drawing a line from one Vector2 to another.
Part 2d: Writing some basic code
Alright so this is the last of Part 2, we are going to display some text on the screen.
Let's make a new color for our text, let's try red.
I just called it red for a lack of a better name.
You should know where to put that by now.
Now let's go ahead and make a string that will hold our text.
If you don't know what a string is, it's a string of characters which are things like numbers, letters, and special characters. Basically a string is just words and stuff like a sentence.
In order to define a string, all you need is the name and what text it will hold:
Code:
string txt,"Pools Closed!";
NOTE: that the string has to be in quotes in order for it to work!
Now you just make a Vector2 defining it's position, I chose (100,400):
Code:
vector2 t1,100,400;
Now you just need to set the current color to red and display the text with dwrite which takes the Vector2 for it's position and what string to write.
Note that the position is defined at (0,0) in the top left corner of your text, that is where you want your Vector2 to be.
Code:
dcolor red;
dwrite t1,txt;
Good, now lets test it out!
You'll notice that our text is kinda small...
In order to make it larger, we can increase the font size using dsetsize and selecting a larger font size to use like 54;
Note: The font size is based on pixels.
You can also change your font with dsetfont.
After some "research" I found the fonts:
Code:
self.FontNames[0] = "Lucida Console"
self.FontNames[1] = "Courier New"
self.FontNames[2] = "Trebuchet"
self.FontNames[3] = "Arial"
self.FontNames[4] = "Times New Roman"
Don't worry about the self.FontNames thing just know that the number is what the font is. I'll use Courier New I guess, that would be 1;
Code:
dsetsize 54;
dsetfont 1;
So there we go, here is an updated screen shot:

Part 3: Move and Scale
Alright, we have a pretty good understanding on how the GPU screen works with displaying shapes. But these are just static objects that will never move! You might as well make a spray!
So let's get these things moving!
Now, we're going to use a rectangle that uses position and width and height rather than 2 positions, this will make it easier for us to move our object around, we could also use a circle.
First let's start off by clearing the screen:
Now lets set up a color like red at the bottom of everything.
Alright now back at the top lets set our current color to red:
Good, so we have this so far:
Code:
dclr;
dcolor red;
color red,255,0,0;
Let's make a few Vector2s that will define our position of our rectangle and the size of it. These will go after our color:
Code:
vector2f pos,50,224;
vector2f size,64,64;
Now we got a square 64x64 pixels that is on the left of the screen.
Let's go ahead and add in the code to draw it right after we set the color:
It's just like a regular rectangle, but it uses position and width and height Vector2s rather then a top-left and bottom-right Vector2.
Okay, so we are almost done!
Let's make another Vector2 that will hold our X and Y speed:
Code:
vector2f speed,0.05,0.10;
You can change these numbers around if they are too fast or too slow for you.
Now we can write our start label:
Now inside here lets start the movement process!
We can do this by adding our speed to our current X and Y position, moving them in a positive direction (in this case down and right):
Code:
add #pos.x,#speed.x;
add #pos.y,#speed.y;
Good, but if we leave it like this our rectangle will go off screen never to be seen again 
Let's add some checking to see if we have gone off the screen!
Remember how I told you before that our screen is 512x512?
Well we can use that to our advantage again.
We are going to use the opcode cmp which stands for compare.
It requires two things, what you are checking and what value you are checking it with.
For our first compare, we want to see if our square is too far off the screen to the right.
We can use 512 for this value, but by taking our square width (64 pixels) off of this then it will bounce from the right side of the square rather than the left side:
Now once you make a comparison, you must act imedietly to tell the program what to do!
There are several options, and they are all jumping to a certain label based on certain conditions.
Two of them happen to be jge and jle.
They stand for Jump if Greater than or Equal to.
You could also use jg for it to be just greater than, not greater than or equal to.
And the other is Jump if Less than or Equal to.
You can also use jl for it to be just less than, not less than or equal to.
Let's jump to a label called bouncex.
And right after that let's check to see if we are less than 0 (meaning we are too far left off the screen):
Code:
cmp #pos.x,448;
jge bouncex;
cmp #pos.x,0;
jle bouncex;
So this will jump if we are too far to the left or right.
Let's do the same for our Y axis as well:
Code:
cmp #pos.y,448;
jge bouncey;
cmp #pos.y,0;
jle bouncey;
And now we are done with the start label!
So here is the whole label:
Code:
start:
add #pos.x,#speed.x;
add #pos.y,#speed.y;
cmp #pos.x,448;
jge bouncex;
cmp #pos.x,0;
jge bouncex;
cmp #pos.y,448;
jge bouncey;
cmp #pos.y,0;
jle bouncey;
jmp start; Now we can write the bouncex and bouncey labels, they are extremely short!
We simply want to reflect our speed to move in the opposite direction.
So lets use the neg opcode to make our current number negative which will reverse the direction!
Code:
bouncex:
neg #dir.x;
neg #dir.y;
bouncey:
neg #dir.y; The reason we do both X and Y for bouncex and not bouncey is because when we bounce off the left and right sides at an angle it moves you backwards instead of bouncing like it's supposed to.
For whatever reason, the Y coordinate doesn't get that problem.
So the only thing left is to call the exit opcode:
So there you go, that's everything!
It should look like this:
Code:
dclr;
dcolor red;
drectwh pos,size;
start:
add #pos.x,#speed.x;
add #pos.y,#speed.y;
cmp #pos.x,448;
jge bouncex;
cmp #pos.x,0;
jle bouncex;
cmp #pos.y,448;
jge bouncey;
cmp #pos.y,0;
jle bouncey;
jmp start;
bouncex:
neg #speed.x;
neg #speed.y;
bouncey:
neg #speed.y;
dexit;
vector2f speed,0.05,0.10;
vector2f pos,50,224;
vector2f size,64,64;
color red,255,0,0;
Scaling works just the same!
In order to get a smoother scale you should also move the axis with the scale to make it look like the center is fixed and you're scaling from it.
Part 4: 2D Polygons
Here's a picture of what we will be creating:

This tutorial wont last long as it is fairly easy!
First off lets clear our screen to a color:
Now lets set our current color to another color:
Now let's draw our object, it needs the offset that the polygon is located and how many points.
The maximum points is 16, minimum is 3 (not sure if there is a true minimum, but any less wouldn't show anything :P)
Code:
dvxdata_2f shape1,3
Okay, now we can stop drawing:
Let's now define our colors:
Code:
color bg_color,255,255,125;
color fg_color,255,0,125;
Now let's make our offset for our points, this works like 3D does but without the Z value:
Code:
shape1:
db 100,100
db 100,200
db 200,200
Make sure that you are going in a motion either clockwise or counter-clockwise.
With triangles there is no wrong way to do it, but once you get into complex shapes, you need to go in a path so that it will draw the points correctly and not mess everything up.
NOTE: You can ONLY create convex shapes! Thanks BP for pointing this out! That's the reason my star didn't work right. If you have a complex shape that needs to be convex, try breaking it up into smaller sections!
Here is my full source:
Code:
//clear the screen
dclrscr bg;
//set color
dcolor fg;
//draw our shapes
dvxdata_2f shape1,3;
dvxdata_2f shape2,3;
dvxdata_2f star,10;
//quit drawing
dexit;
//define colors
color bg,255,255,125;
color fg,255,0,125;
//shape offsets
shape1:
db 100,100
db 200,200
db 100,200
shape2:
db 300,200
db 350,400
db 400,250
//star messed up :P
star:
db 81,327
db 68,372
db 11,372
db 57,410
db 42,457
db 79,428
db 116,459
db 103,409
db 150,372
db 93,372
Here is the power of polygons!!!!11

Part 5: Making 3D Objects
You ready for this?
This is going to get XTREME if you know what I mean, but I'll walk you through it, no need to fear!
Here is a screen shot of what we'll be making:

Pretty cool huh? It rotates and everything
Let's get started!
To make things easier, I will write the code then explain it:
Code:
dcvxpipe 3;
dvxpipe 5;
The first opcode sets our screen to use a -1..1 type coordinate system.
The second is our Matrix Projection which puts us in 3D.
Code:
mperspective mProjectionMatrix,vPerspective;
This sets our perspective with the projection and perspective of our screen. These calls for mProjectionMatrix and vPerspective will be defined later on. Don't worry if this confuses you too much.
This you should already know, we clear the screen to the color bg_color.
Code:
mlookat mViewMatrix,vLookAt;
This is our view matrix and defines stuff about our camera like where it is, what we are looking at, etc.
Code:
timer eax;
mov #vRotate.w,eax;
This sets up a timer that we tie to our vRotate to it to rotate our model over time.
Code:
mrotate mRotateMatrix,vRotate;
mtranslate mTranslateMatrix,vTranslate;
This is rotating the translate, it's handling how rotating will work and stuff.
Code:
mmov mModelMatrix,mTranslateMatrix;
mmul mModelMatrix,mRotateMatrix;
mmov mModelViewMatrix,mViewMatrix;
mmul mModelViewMatrix,mModelMatrix;
This is creating our model matrix, again you don't really need to know much about this right now.
Code:
mload mModelViewMatrix;
mloadproj mProjectionMatrix;
This is the last of these matrix calls until at the end when we define all the matrix stuff. We're basically loading in the view and projection matrix so now we are in 3D space... ooooo...
From here out things are MUCH more easier to understand 
Code:
dsetlight 0,lightdata;
This is setting up our lighting for the 3D environment, we will define our lightdata label later.
Code:
denable 0;
denable 1;
denable 2;
denable 3;
These are calls to enable certain things. From 0-3 in order we are enabling our vertex buffer, Z-Sorting, lighting, and face culling.
Our vertex buffer is for 3D stuff. Z-Sorting is so that things that are closer to you in Z space will show over stuff that is farther away i n Z space (like in real life). Something that is in front of something else is going to show up in front of what's behind it. Next is lighting which is obvious, and face culling is making it so we don't see the faces of our model that we can't see which makes the GPU run faster.
Code:
dcolor fg_color;
dvxdata_3f draw_pyramid,6;
dvxflush;
First we are setting our color to a fg_color. Then we use dvxdata_3f to draw 3D triangles. We are getting our information about these triangles from draw_pyramid and we are drawing 6 different triangles to make up our pyramid. Then we use dvxflush to flush our pyramid to the screen.
Code:
ddisable 0;
ddisable 1;
ddisable 2;
ddisable 3;
This is just disabling all that stuff from earlier that we have used and are done with.
Code:
dcvxpipe 0;
dvxpipe 0;
We are setting these back to default as well.
[code]dexit;[/b]
We are done drawing! 
We are half way there!
Now we just have to define all of our stuff.
Code:
draw_pyramid:
db 0,-1,0; // t (font)
db 1,1,-1;// br (front)
db -1,1,-1; // bl (front)
db 0,-1,0; // t (right)
db 1,1,1;// br (right)
db 1,1,-1; // bl (right)
db 0,-1,0; // t (left)
db -1,1,-1; // bl (left)
db -1,1,1; // br (left)
db 0,-1,0;// t (back)
db -1,1,1;// bl (back)
db 1,1,1;// br (back)
db -1,1,-1; // bottom (left)
db 1,1,1;
db -1,1,1;
db -1,1,-1; // bottom (right)
db 1,1,-1;
db 1,1,1;
WOAH WOAH WOAH!!!11
What is all this crap!?!?
Well, these are the points that we are loading in to draw the pyramid.
I used comments to let you know which block is for what.
Each triangle needs 3 points, which is why they are in sections of 3 lines each per section. Because we are using the -1..1 coordinate system we are using -1 as the minimum and 1 as the max.
Here is a picture for you to better understand how you go about picking these values.

Left-Right is the X coordinate.
Up-Down is the Y coordinate.
Front-Back is the Z coordinate.
The colors represent the Z coordinate.
So, here is what it looks like with the shape drawn within it:

It's not perfectly sized right, but you get the idea...
Basically we have to create each of those sides.
And because we are drawing with triangles, we need two to make the bottom square.
Hopefully you get this, if not, then make a reply and I'll be glad to further explain how it works!
Now, lets move on...
Code:
lightdata:
vector4f lightpos, 0,50,-50,0;
color lightcol,0,255,255,1;
So we are staring our lightdata, and the first thing we get is the position and brightness of our light. Then we get the light color, it's normally white (255,255,255) but if you make it something else, your object gets that color tint.
Code:
matrix mRotateMatrix;
matrix mTranslateMatrix;
matrix mProjectionMatrix;
matrix mViewMatrix;
matrix mModelMatrix;
matrix mModelViewMatrix;
Here is the last of the matrix calls!
The first two are for rotating and translation.
The next two are the projection to the screen and camera transformations.
Then the model transformations and the model relative to the camera.
Code:
vector4f vRotate, 0,1,0,0;
vector4f vTranslate, 0,0,0,0;
vector4f vPerspective, 30,1.6,1,20;
First we define where we are rotating on, then moving on, and then our perspective like field of view, aspect ratio, and how far you can see (Z-Near and Z-Far).
Code:
vLookAt:
vector3f vLookAt_Eye, 0,0,-5;
vector3f vLookAt_Center, 0,0,0;
vector3f vLookAt_Up, 0,1,0;
First we got our camera location. Then we got where we are looking. Then where our matt-hat is (not sure what this is).
Lastly we define our colors and we are done!
Code:
color fg_color,255,255,255;
color bg_color,255,0,125;
And that's everything!
It should work fine!
Your faces may not show up right.
If they don't you have to flip them, so try flipping two sides.
In this case the br and bl points can be switched to flip it.
The reason we don't flip t is because it is always the same because they meet in a point at the top.
So, this is a lot of stuff, but it's not that hard really!
Try making your own shapes if you want and post some pictures.
If you would like me to go over something from this 3D part more, please ask and I'll be glad to.
Here's the full code requested by haloguy922:
Code:
dcvxpipe 3; // -1,0,1 (opengl screen)
dvxpipe 5; // matrix projection
// initialize transform
mperspective mProjectionMatrix,vPerspective;
// render starts
dclrscr bg_color;
mlookat mViewMatrix,vLookAt; // view matrix
timer eax;
mov #vRotate.w,eax;
// rotate translate
mrotate mRotateMatrix,vRotate;
mtranslate mTranslateMatrix,vTranslate;
// create model matrix
mmov mModelMatrix,mTranslateMatrix;
mmul mModelMatrix,mRotateMatrix;
mmov mModelViewMatrix,mViewMatrix;
mmul mModelViewMatrix,mModelMatrix;
// load matrix
mload mModelViewMatrix
mloadproj mProjectionMatrix;
// setup light
dsetlight 0,lightdata;
// setup buffer
denable 0; // vertex buffer
denable 1; // z sorting
denable 2; // lighting
denable 3; // face culling
// render cube
dcolor fg_color;
dvxdata_3f drawpyramid,6;
dvxflush;
ddisable 0; // disable everything now
ddisable 1;
ddisable 2;
ddisable 3;
dcvxpipe 0;
dvxpipe 0;
dexit; // exit drawing
// pyramid points
drawpyramid:
db 0,-1,0; // t (font)
db 1,1,-1;// br (front)
db -1,1,-1; // bl (front)
db 0,-1,0; // t (right)
db 1,1,1;// br (right)
db 1,1,-1; // bl (right)
db 0,-1,0; // t (left)
db -1,1,-1; // bl (left)
db -1,1,1; // br (left)
db 0,-1,0;// t (back)
db -1,1,1;// bl (back)
db 1,1,1;// br (back)
db -1,1,-1; // bottom (left)
db 1,1,1;
db -1,1,1;
db -1,1,-1; // bottom (right)
db 1,1,-1;
db 1,1,1;
lightdata:
vector4f lightpos, 0,50,-50,0; // x y z <unused>
color lightcol,0,255,255,1; // R G B brightness
matrix mRotateMatrix;
matrix mTranslateMatrix;
matrix mProjectionMatrix; // this defines our projection to the screen
matrix mViewMatrix; // this defines our camera transformations
matrix mModelMatrix; // this is our model transformations
matrix mModelViewMatrix; // this is our model relatively to camera transform
vector4f vRotate, 0,1,0,0; // axis X Y Z angle
vector4f vTranslate, 0,0,0,0; // translation X Y Z 0
vector4f vPerspective, 30,1.6,1,20; // <FOV> <ASPECT RATIO> <ZNEAR> <ZFAR>
vLookAt:
vector3f vLookAt_Eye, 0,0,-5; // where our camera is
vector3f vLookAt_Center, 0,0,0; // what we look at
vector3f vLookAt_Up, 0,1,0; // where our matt-hat is
color fg_color,69,69,69;
color bg_color,255,0,125;
Bookmarks