Tutorial Proofreading and Correcting.

I have started work on a series of OpenGL tutorials, available here online and here for download.

I only have 5 complete thus far, but more will be added in the future. I’m primarily interested in getting feedback as to how useful these are currently. Is anything unclear, does it all make sense, and most importantly do the tutorial projects work on your machine (currently restricted to Visual Studio builds)?

Wow. This looks great; I like your shader-based, close to the metal, approach. I also like the use of small code samples. Looks like you put an incredible amount of work into this!

There is a small typo in On Vertex Shader Performance:

The second vertex shader we use, the one that computes the offset itself, does a lot of complex map.

I believe map should be math.

Also, you may want to consider simplifying the build process - having to build a single .sln would be ideal for many readers. I’m sure a lot of people will be ok with downloading Premake 4 and following the necessary steps but anything you can do to simplify this will lower the barrier to entry.

I’m looking forward to the later chapters!


There is a small typo in On Vertex Shader Performance:


Also, you may want to consider simplifying the build process - having to build a single .sln would be ideal for many readers.

There are two problems with this.

1: What kind of .sln should it be? VS 2002, 2003, 2005, 2008, 2010? VC6? All of these? Using Premake makes it easy to avoid the question altogether; just build the one for your version of Visual Studio.

2: I do fully intend to get the tutorials working on non-Visual Studio/non-Windows platforms. Eventually. When that happens, Premake will be able to handle these platforms.

That being said, I could have a single Premake file in the root that creates a project that builds all of the tutorials.

Well, depending on how much additional work you want to put into it, you could of course use premake to create ALL visual studio projects and supply different downloads for each version.

I agree that it is much easier to use a build-tool (personally i use cmake), but for a beginner this is indeed something that may sound to complicated and thus scares them away.

Other than that, i skipped over the tutorials and was also very impressed by what i saw.

Keep at it!

Maybe even include Premake in the download if its license/install process allows you to do so. Similarly, I have a package that includes unit tests written with NUnit, so I include NUnit in the package so users can build and run the tests without downloading anything else.


I like it, nice to see you want to teach. I wonder what motivated you to do this?

Looks very nice so far, but one suggestion if i may - drop the ridiculous feet/inches and use SI units (for obvious reasons).

good stuff, but the Clip Space Transformation section is a bit vague. The W coordinate ends up being the Z coordinate, you miss that bit. Maybe you’re leaving the perspective stuff till later - didn’t read it all.

wclip = -zeye for perspective, but = 1 for orthographic (both assuming weye = 1, of course).

Haven’t browsed the tutorials yet so apologies if this isn’t applicable.

Well, that might be the most common projection matrices in use, but not the only ones possible. The dot product of the last row of the projection matrix (which might in fact have arbitrary values) and the incoming 4D eyespace vector determines W.
If you further think about it, the last row is the plane-equation of the image plane.

good stuff, but the Clip Space Transformation section is a bit vague. The W coordinate ends up being the Z coordinate, you miss that bit. Maybe you’re leaving the perspective stuff till later - didn’t read it all.

If you’re talking about the introduction section on clip-space, I wanted to keep that one general at that point. For similar reasons, I don’t introduce camera space until the tutorial on perspective projection, because camera space is an arbitrarily-defined construct of the vertex shader. In the intro, I only want to talk about what OpenGL requires from the user.

Here’s a few more minor things…

Figure 5.5 is missing in the Depth Precision section.

A bit later, the text cuts off after:

There are certainly ways around it (and we will discuss some later), but if you need a camera-space range that

Finally, I’m curious about this:

By reducing detail in distant objects, you are also less likely to have z-fighting

How exactly does this work? A lower resolution model doesn’t mean it is going to take up less total camera space? Do you mean that it will have less triangles so the flicker is less noisy? Or are you talking about using imposters?


How exactly does this work?

It depends on the source of the z-fighting. If you have z-fighting within the same model (because some part of the model overlaps with itself), then having a lower-detail version where the details are abstracted can help. Think of a window-sill or something of that nature. Something that, in a low-LOD would just be flat.

I’ll clarify this in the text.

Thanks everyone for the feedback so far.

Right, I see. This is also true when models are replaced with imposters regardless of the shape of the original model.


Yes, thanks, I realised that as I read more. Should have kept my trap shut.
I think it’s a fantastic bit of work. Wish something like that had been around when I was learning this stuff.

Nice work Alfonse!

I quite agree with a couple of people here, CMake could accomplish what you need in a much easier way for yours readers!

For the developer CMake isn’t perfect I think but so far I don’t know a better cross-platform build system…

EDIT: Oh actually the build system is pretty good I think. I am going to have a closer look at it actually, it seems interesting!

Well, I say try bjam from the boost project for the build system. I build everything with bjam. If not, just write a custom make file build system that will work on linux and windows and forget the other OSes.

I just found and downloaded your tutorials yesterday. Though I have only just finished reading and working through chapter one, I wanted to provide a little feedback now rather than wait until I have finished everything.

First, THANK YOU VERY MUCH for undertaking this task. You have a made a tremendous start. I think MANY people will appreciate what you’re doing. I certainly do. I have been searching in vain for weeks trying to find anything that teaches “modern” (non-deprecated) OpenGL.

I believe I noticed one small error in your text. In Chapter One, Following the Data page, Vertex Transfer section, in your discussion of the code fragment for glBindBuffer(), glEnableVertexAttribArray(), and glVertexAttribPointer(), you wrote:

“This means that our data of 24 floats represents enough information for the 3 vertices of a single triangle; this is exactly what we want.”

I believe you should say that “… our data of 12 floats…” rather than 24 floats.

Here’s the feedback I have for you that I think is very significant, though. In your program code tut1.cpp, in function init(), you call glGenVertexArrays() and glBindVertexArrays(). However, I don’t believe you have discussed the significance of those two functions, what they do, or why they are where they are. Nor have they been included among the Chapter One, In Review page, OpenGL Functions of Note section.

Here’s why I think those two functions are so noteworthy. I am just starting to learn OpenGL, and want to learn proper techniques for core profile OpenGL 4.0. Before finding your tutorial, I have read parts of the OpenGL 4.0 core spec including section 2.10 (Vertex Array Objects), the entire book Beginning OpenGL Game Programming, second edition (2009), by Benstead, Astle, and Hawkins (which purports to teach “modern” (non-deprecated) OpenGL as in more-or-less core OpenGL 3.0), and the only other tutorial I have found that attempts to teach “modern” OpenGL.

The OpenGL 4.0 core spec doesn’t provide any useful information (at least that I can understand) as to Vertex Array Objects: are they required, and how, where, & why are they used?

Vertex Array Objects were not mentioned even once in the 290+ pages of the Benstead book. The only other “modern” OpenGL tutorial on the internet I have found also does not use Vertex Array Objects. I have spent two weeks trying to make the simplest OpenGL 4.0 core profile program display a single triangle without success. I have tried to write my own based on what I learned from the previously mentioned educational sources, I have tried to recreate the demo program from the other “modern” OpenGL tutorial I mentioned. None have worked.

Then, only after suffering extreme frustration and desperation, I found your tutorials. Your demo code uses a Vertex Array Object and it’s the first OpenGL 4.0 core profile program I have ever witnessed that actually works. I added a Vertex Array Object to my other programs, and now they also work. But I don’t really understand why. It isn’t clear to me how Vertex Array Objects connect or interact with other OpenGL objects. I don’t know whether or when I should use more than one VAO. All I know is, they are essential but not obvious.

I’m grateful your tutorial has finally set me on the correct path. Given that it seems other OpenGL experts don’t really seem to understand Vertex Array Objects, but that they are essential, it seems that VAOs really do deserve some discussion in chapter one of your tutorial.

Given that it seems other OpenGL experts don’t really seem to understand Vertex Array Objects, but that they are essential, it seems that VAOs really do deserve some discussion in chapter one of your tutorial.

VAOs are discussed, at some length, in Tutorial 5. I don’t bring them up in Tutorial 1 for a couple of reasons.

1: Tutorial 1 is already packed with information as it is. For someone who is new to OpenGL and rendering in general, it’s simply adding complexity to something that’s already borderline overwhelming.

2: Until you are actually rendering more than one set of geometry, VAOs don’t really function any differently from the non-VAO case. So explaining what they do doesn’t really make sense at that point.

david_f_knight, there’s some more info about VAOs at:

They are basically a collection of all the vertex array state, and binding another VAO changes to another collection of vertex array state.

The currently bound VAO will store information set when:

a) Enabling different attributes


b) Setting up attribute info

// note: buffer bound to GL_ARRAY_BUFFER is not part of VAO state, it only
// becomes part of VAO state when you perform the call to glVertexAttribPointer.
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
glVertexAttribPointer(index, size, type, normalized, stride, &offset);

c) Binding index buffer

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);

Binding a different VAO gives you a different set of state. A brand new VAO generated with glGenVertexArrays will have all attributes disabled, no buffers bound etc.

VAOs are required to get a functioning program with OpenGL 3+ using only core profile features, since the default VAO is deprecated in OpenGL 3.0, removed in 3.1, so you should get errors when calling glEnableVertexAttrib/glVertexAttribPointer/glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID) or any drawing commands without a VAO bound.

Unfortunately NVidia still allows you to use the default VAO in a core profile, whereas ATI do not, which is a potential cause of failure when developing on NVidia hardware, then running on other hardware that follows the spec. If you want a quick workaround to get a program running using core profile, then at the start of your app you can just do:

glGenVertexArrays(1, &dummyVAO);

I personally don’t understand why the default VAO was deprecated, but there was probably a reason, and if you want your program to work on both NVidia + ATI, then you need to make sure a VAO is bound. The main spec body should really include error messages that occur with each function call if no VAO is bound, rather than only being mentioned once in the appendices.

This is all mentioned in the chapter 5 of the tutorial, except that NVidia currently allows use of default VAO in core profile, which shouldn’t be allowed according to spec.