Sep 11
10
Atli has commented on a post with the following CSS which (without testing it personally), should make the older tutorials readable up until I get the time to make them fit in with the current theme.
He used Firebug to test it for anyone interested.
table[width="100%"] > tbody > tr > td > p {
width: 507px;
}
Cheers,
Swiftless
Jun 11
2
I have switched the theme entirely, hopefully the site looks a little more professional and easy to read/navigate.
Major changes are removal of rating system. The site was on a steady 8.7 rating and this plugin was simply chewing up bandwidth I can put to use elsewhere. However I have added a Facebook “Like” button and a Google “+1″ button to every post, so please share or rate up the page for others to view.
As for content, which is what most of you are after. I still don’t have time. I’m busy working virtually full-time along with my full-time studies and all this to get my degree so I can make money later, while making money now to pay for my wedding which is coming up in Feb next year.
If anyone is interested in volunteering to help out with the website, re-write some of the older posts, provide images or movies of the tutorials which don’t have them, etc. Drop me an email at swiftless@gmail.com and I’ll be more than happy to link to your site if you have one, or mention you on the site.
Cheers,
Swiftless
Feb 11
10
In a sneak addition to the site, I have put up a demonstration of how to set up a WebGL canvas!
WebGL for those that do not know, is a form of OpenGL based on the OpenGL ES 2.0 specification which runs in the HTML 5 canvas element in a web browser.
This in my opinion is some impressive stuff!
The first live demonstration comes complete with the code supplied at the bottom of the page and shows simply how to set up a canvas.
You should see a blue square, and while it doesn’t look like much, this is a full OpenGL context in your browser!!
Expect to see more soon
Cheers,
Swiftless
Feb 11
10
Feb 11
10
After a long time of waiting, I have finally put up a new tutorial on OpenGL 4, this time showing how to use two VBO’s inside of our VAO to color and draw our shapes at the same time since glColor and glBegin have been removed from OpenGL.
I’m going to try to update some more of the the older tutorials now, along with integrating some WebGL examples into the site.
For those of you that don’t know, WebGL is an OpenGL ES based specification for rendering OpenGL in a HTML 5 canvas object and is already supported in Firefox 4, Chrome and Safari (Via the webdevkit).
Enjoy!
Swiftless
If you remember back to the last tutorial, I mentioned that because we no longer have the fixed function pipeline, we no longer have calls for creating primitives such as glBegin(GL_TRIANGLES). Well this also holds for the glColor calls as they were a part of the fixed function pipeline. So how do we change the colour of our shapes and vertices? Well just like we created a Vertex Buffer Object (VBO) to store our vertices, we can do exactly the same thing with our colours and then place this new VBO inside of the Vertex Array Object (VAO) with the vertices.
Is this difficult? Definitely not, all we have to do, is exactly the same thing as we did for the vertices. Also, because when we set up our shaders back in one of the first couple of tutorials, we specified permanent variables for passing vertices and colours to our shader, so our second VBO will automatically be interpreted as the colour portion of our VAO.
An important thing to note is that for every per-vertex attribute you have, you can store it all inside of the same Vertex Array Object, each in its own Vertex Buffer Object and link the VBO to the shader by binding the attribute locations, the same way we bound in_Position and in_Color.
To start off, I am going to open up opengl_3.h and you might remember we created an array to hold our VBO’s. Well this array had a length of 1, so we are going to give that a bump up to 2 like so:
unsigned int vboID[2]; // Our Vertex Buffer Object
Now switch over to opengl_3.cpp and we are going to start setting up our colour VBO. Go ahead, and just under where we created the variable for the vertices array, do a copy and paste, but call this variable colors. You will get something like this:
float *vertices = new float[18]; // Vertices for our square float *colors = new float[18]; // Colors for our vertices
As a vertex takes up 3 values for x, y and z. We are going to use 3 values for our colour, being r, g and b. You can also jump this up to r, g, b and a, you just need to add an extra float value for each vertex you have and also change the VBO to use 4 variables per vertex instead of 3.
But for simplicity we are going to stick with no alpha value, and hence no alpha blending. So just as we created our vertices, do the exact same thing, but using the colour variable. I am using the colours white for bottom left, red for top left, green for top right and blue for bottom right.
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner colors[0] = 1.0; colors[1] = 1.0; colors[2] = 1.0; // Bottom left corner vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner colors[3] = 1.0; colors[4] = 0.0; colors[5] = 0.0; // Top left corner vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner colors[6] = 0.0; colors[7] = 1.0; colors[8] = 0.0; // Top Right corner vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner colors[9] = 0.0; colors[10] = 0.0; colors[11] = 1.0; // Bottom right corner vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; // Bottom left corner colors[12] = 1.0; colors[13] = 1.0; colors[14] = 1.0; // Bottom left corner vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner colors[15] = 0.0; colors[16] = 1.0; colors[17] = 0.0; // Top Right corner
That should all be looking pretty straight forward. Now we need to go jump down a couple of lines to where we call glGenBuffers(1, &vboID[0]); Bump this also up to 2, so that we are generating 2 vertex buffer objects.
glGenBuffers(2, &vboID[0]); // Generate our two Vertex Buffer Object
And then virtually do a copy and paste of the lines from glBindBuffer to glEnableVertexAttrribArray. Then inside of this big paste block, we want to change our glBindBuffer go the second vboID, so vboID[1] and change the variable vertices from the line glBufferData to the variable colors. Finally we need to change the value from glEnableVertexAttribArray from 0 to 1. So we get this:
glBindBuffer(GL_ARRAY_BUFFER, vboID[1]); // Bind our second Vertex Buffer Object glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), colors, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer glEnableVertexAttribArray(1); // Enable the second vertex attribute array
And last but not least, make a call to delete the colors array before we finish our method:
delete [] colors; // Delete our vertices from memory
All you have to do now is give this modified code a compile and run it. You should now see a square which instead of red, black (or any other color as it is undefined in the previous tutorial), is now a blend of colours.
If you have any questions you can comment below or email me at swiftless@gmail.com
Dec 10
16
As promised, I have put up a new tutorial, this time for OpenGL 3.x and 4.x showing how to use VAO’s and VBOS (Vertex Array Objects and Vertex Buffer Objects) to render geometry to the screen.
Cheers,
Swiftless
With the removal of OpenGL states and the fixed function mode, we no longer have any glEnable calls, which means no glEnable(GL_TRIANGLES), or similar calls. It also means no more calls to glVertex or glColor. What this means is we need a new way of transferring data to the graphics card to render our geometry. We could use VBO’s which I introduced in one of the terrain tutorials, or we could use a new feature in OpenGL 3+, known as VAO’s. VAO’s are Vertex Array Objects and allow you to store multiple VBO’s in one VAO. With this ability, we can now store vertex data and colour data in separate VBO’s, but in the same VAO. The same goes for all types of data you usually send through as a VBO, including data for normals or anything that you need on a per-vertex rate.
What a VAO is, is a way to store object information straight on the graphics card, instead of sending vertices through to the graphics card as we need them. This is how Direct3D works as it doesn’t have the immediate mode which OpenGL had up until OpenGL 3.x. This then means our application doesn’t have to transfer data to and from the graphics card and we get extreme increases in performance.
The best part, is that this isn’t too difficult to set up. It just means that instead of a bunch of glVertex calls, we store all our vertices in an array and then place that into a VBO and then into a VAO. OpenGL takes care of everything behind the scenes, and we get all the advantages that come with VBO’s and VAO’s.
While I understand you may not have done the terrain tutorial which introduces VBO’s, I’m going to be starting from the basics and I will still be explaining everything as I go. The best part is we don’t have to do too much to get the output for this tutorial, which is a square on the screen.
Open up opengl_3.h and inside of it we are going to create two variables and one method. The method will be take no parameters and will return nothing, but inside of it we will be creating our VAO and VBO to draw a square. In that mindset, I am going to call the method createSquare.
void createSquare(void); // Method for creating our squares Vertex Array Object
Our two variables are going to both be arrays of unsigned int’s and they are both going to be of length 1, so we have one VAO and one VBO. I am calling these vaoID and vboID and am using these as private variables in our class.
unsigned int vaoID[1]; // Our Vertex Array Object unsigned int vboID[1]; // Our Vertex Buffer Object
Now that’s not so scary, let’s go and jump into opengl_3.cpp and start making use of this. Inside of the setupScene method I am adding the call to createSquare and next we will start creating this method. Keep in mind that I am creating the square and the VAO and VBO before I actually use them, otherwise we might run into issues with empty memory.
void OpenGLContext::setupScene(void) {
...
createSquare(); // Create our square
}
And now to create our createSquare method. I have jumped down to the bottom of the opengl_3.cpp file, however you can place this anywhere in the file if you prefer to order your methods by name or something of the like. Here is what the empty method will initially look like:
/**
createSquare is used to create the Vertex Array Object which will hold our square. We will
be hard coding in the vertices for the square, which will be done in this method.
*/
void OpenGLContext::createSquare(void) {
}
Before we create our VAO and VBO, we need some data which describes the vertices for our shape. I am drawing a square made up of two triangles, so we need 6 vertices, 3 for each triangle. Then, because we have 6 vertices, each vertex is made up of 3 values, the x, y and z coordinates, giving us a total of 18 values we need to describe our square. These are going to be float values and stored in an array called vertices. As I am using a dynamic array, don’t forget to call the delete method afterwards to make sure we free up our memory again.
/**
createSquare is used to create the Vertex Array Object which will hold our square. We will
be hard coding in the vertices for the square, which will be done in this method.
*/
void OpenGLContext::createSquare(void) {
float* vertices = new float[18]; // Vertices for our square
delete [] vertices; // Delete our vertices from memory
}
Now it’s time to fill in some values for the vertices. I am going to place all the vertices at 0 on the z axis and I am going to give the square a size of 1 unit. That means I need to go up and to the left half a unit, and down and to the right half a unit as 0.5 + 0.5 = 1, giving us a length of 1 for the sides of the square. So the top left vertex is (-0.5, 0.5, 0.0) and the bottom right vertex is (0.5, -0.5, 0.0). Filling in all 18 values based on this, we get:
/**
createSquare is used to create the Vertex Array Object which will hold our square. We will
be hard coding in the vertices for the square, which will be done in this method.
*/
void OpenGLContext::createSquare(void) {
float* vertices = new float[18]; // Vertices for our square
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner
vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; // Bottom left corner
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner
delete [] vertices; // Delete our vertices from memory
}
So we’ve now filled in our vertices coordinates, we need to go and create a Vertex Array Object which is done with a call to glGenVertexArrays. We then need a call to glBindVertexArray to make the VAO active. Once the VAO is active, we need to call glGenBuffers to create our Vertex Buffer Object, and then we also need to bind it with glBindBuffer.
So it goes in this order:
1. Generate Vertex Array Object
2. Bind Vertex Array Object
3. Generate Vertex Buffer Object
4. Bind Vertex Buffer Object
Once we have done step 4, we need to fill our VBO with the vertex data. When creating VBO’s, you can set why type of VBO it is, and in this case we are going for GL_STATIC_DRAW, this tells OpenGL that we do not intend on changing the data in any way, and we just want to be able to render it. There are types for data which changes as well, for all types, I suggest checking out the OpenGL API or the OpenGL wiki: http://www.opengl.org/wiki/Vertex_Buffer_Object
Now, we need to call glBufferData to set the data for our VBO to the float array we created above, before telling OpenGL that this VBO is for storing vertex data. Finally we clean up by disabling our Vertex Attribute Array and also disabling our Vertex Array Object.
/**
createSquare is used to create the Vertex Array Object which will hold our square. We will
be hard coding in the vertices for the square, which will be done in this method.
*/
void OpenGLContext::createSquare(void) {
...
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(1, vboID); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Disable our Vertex Array Object
glBindVertexArray(0); // Disable our Vertex Buffer Object
delete [] vertices; // Delete our vertices from memory
}
What we have now, is a VAO with a VBO storing vertex data for a square. So far it’s been straight forward, so now we need to render this data to the screen. Go ahead and jump to our renderScene method and after we set our glUniformMatrix4vf variables for our shader from the previous tutorial, we need to add three lines of code to render. First off we need to enable our Vertex Array Object, then we need to draw the VAO and finally disable the VAO. Like so:
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square glBindVertexArray(0); // Unbind our Vertex Array Object
And well done, you can now create a square using no immediate mode and storing everything on the graphics card, which will run at maximum framerates. One more optimization to this, would be to use a GL_TRIANGLE_STRIP instead of GL_TRIANGLES and you could get away with 4 vertices. In the next tutorial we will look at adding colour to our square.
Visual Studio 2010 Project
PDF version
If you have any questions you can comment below or email me at swiftless@gmail.com
Dec 10
6
There has been quite a delay since my last update to the site, about 2 and a bit months I believe.
Well I have finished Uni for the year now and plan to get back into the swing of things with code ready for several tutorials on OpenGL 4, one ready for shadow mapping and even a new graphics card so I can take full advantage of OpenGL 4.
I hope to have another tutorial up in the next 2 weeks and will be replying to comments along the way.
If you would like to help out with the site or have any suggestions for now, drop me an email at swiftless@gmail.com. Just don’t go asking me to do your assignment, I get enough of that…
Cheers,
Swifless
Sep 10
30
This article is going to give a brief comparison of OSX and Windows 7 in relation to OpenGL programming, and programming in general. I am in no way wanting to start a flame war, but feel free to fight amongst yourselves in the comments section. I will admit it sounds like I’m bashing Windows and praising OSX, but in relation to OpenGL, this is the truth.
If any of you have taken a real good look at the tutorials on the site, you may notice that some of them have screenshots from Windows and others have screenshots from OSX, the newer tutorials being from OSX. This is because I first started programming on Windows many years ago, and whilst I still program on Windows when I have to, a majority of my work is now done on OSX. Don’t get yourselves thinking that I automatically have some money behind me, just because I own a Mac, doesn’t automatically translate to “He’s got a Mac, how the heck did he afford that?! …Must be some rich guy.” I’m a uni student, who spent half a year saving for it, and these days it’s my most valuable asset.
Anyway, I started my OpenGL programming back on Windows XP and as Windows Vista and Windows 7 were released, I migrated from one to the other. The downside to being an OpenGL programmer in a Windows environment, is that while you can get everything setup easily, you still have to go through that setting up stage every time you format, reinstall or upgrade your operating system, as Windows is primarily meant for DirectX, and while you still need the DirectX SDK to develop on your operating system, you can generally run your previous programs no worries.
Well after quite a few years, I finally grew up and was able to come to University, where I was given a good rundown of Ubuntu and I started doing some research in one of the labs which also used Ubuntu. From then on, I spent about a year and a half developing with OpenGL on Ubuntu and it was all fairly straight forward after you had the correct packages installed, although it was a little confusing as to which OpenGL packages I had to install, and I still am unsure about what they all are.
Finally, I met a guy at the University who suggested I borrow one of the Macbooks and start porting my stuff onto it in an attempt to get me to the WWDC on a scholarship, as one person had recently left the lab I was in, and his old Macbook was floating around with no one to use it. This was a 2004 model Macbook, but it was running OSX 10.5 at the time.
I ported some of my better demos to OSX and to my excitement, I was accepted to go over to the WWDC in 2009. While at the WWDC, it was a little funny to see such hardcore Apple fans, I think I was the only person with a PC laptop and a Nokia phone, while everyone else had an iPhone and a Macbook. But as the conference went on, I was intrigued as to some of the upcoming features in OSX 10.6. More importantly OpenCL, which still isn’t really supported on PC’s unless you get the drivers from GPU manufacturers, and the fact that OSX is powered by OpenGL and they have so much support for it.
One thing to learn when developing with OpenGL on OSX, is that OSX will forever love you and be nice to you. Once you have XCode installed, which is the preferred IDE for developing on OSX and the iPhone, you will find that all you have to do is create a new command line project, and import the OpenGL and GLUT frameworks into your project. You don’t have to worry about dll files in the correct directory, or having to download the library and header files and put them in the right location. You just add the frameworks and go. This is because OSX uses OpenGL for it’s entire GUI, everything you see on the screen. This is awesome to wrap your head around as an OpenGL developer, because it shows you a new side to Computer Graphics. It isn’t just 3D games and visualizations which was what I was familiar with, it has now extended to entire User Interfaces.
Apple have also done some amazing things in terms of OpenGL debugging. Yes, you can in fact debug an OpenGL application on OSX, there is a tool for that! Or if you have an iPhone and are doing iPhone development, I’ll use the pun “There’s an app for that!”. The OpenGL debugger shows you how much time you are spending on different calls, just like a regular debugger, but my favourite part, is that you can pause your application and view all your current buffers, your depth buffers and your colour buffers, at any time. So you can make sure your application is running as expected, which saves a lot of time compared to not knowing what is going on in the GPU.
If you are on Windows and you have tried my GLSL tutorials, and you haven’t read the comments section, you may run into an error when you try executing any of the tutorials. This is because I have not included a line to glewInit() that is essential on Windows. It’s just one of those things you have to do, to make sure you have access to your extensions when using the GLEW library. Well on OSX there is no GLEW library, OSX has full support for all OpenGL extensions right off the bat and you don’t have to worry about declaring what extensions are available. It’s little things like this all over the place that make developing for OpenGL on OSX so nice.
Starting off with OpenGL, I have come to love it extensively, but there is no denying it is not the be all and end all of computer graphics. Microsoft DirectX has it’s Direct3D API which can do everything that OpenGL can do, just in it’s own way (well eventually, often OpenGL is just that tiny step ahead). While OSX has a GUI powered completely by OpenGL, the GUI for Windows now uses DirectX to offload everything on the GPU and speed it up. I remember watching videos of codename Longhorn, now known as Windows Vista, and it was thought of as quite an achievement to have a GUI that runs on the GPU. I even remember stories at the time, that suggested Microsoft didn’t want to support OpenGL at all in Windows, and that if they did, it was going to be a bunch of Direct3D calls underneath the OpenGL calls which would slow down your program dramatically. Luckily they never went along with this and OpenGL is natively supported still on Windows. Could you imagine the backlash they would have suffered, when for example, games by iD software, including the Quake and Doom series, rely on OpenGL!
But while you can get the DirectX SDK and various SDK’s from GPU manufacturers, there is no “it just works” approach to computer graphics programming in Windows like there is on OSX. The only advantage to Windows is that it runs both DirectX and OpenGL whilst OSX only runs OpenGL (which is not their fault). You have to install your editor, just as you do on OSX, but then you also have to install the SDK’s, correct drivers and there are no Direct3D debuggers that I am aware of. This isn’t too much hassle if you know what you are doing but for beginners, can cause some initial headaches.
When it comes to debugging Direct3D, you can enable debugging information, but I am yet to see anything that offers the functionality that the OpenGL debuggers provide.