Feedback will be greatly appreciated!
OK.
You use a lot of very long paragraphs. This was particularly evident in Tutorial 2. Coupled with a larger than standard font, it’s somewhat difficult to read. You should also consider using a monospace font for actual code.
You also do something that will easily confuse readers: make references to features that you’re not immediately going to talk about. For example, in Tutorial 2:
This draw call is very simple and it it used for ordered draws (draw calls where there is only a vertex buffer without an index buffer) and no instances (a feature that enable you to internally redraw the same geometry with some parameters changed per instance).
Someone who isn’t familiar with OpenGL is asking questions like “what is an index buffer?” and “what ‘parameters’ is he talking about?” It’s better to raise these issues exactly and only when you’re prepared to discuss them.
Also, where is your shader? You say, “My focus is on the programmable pipeline so there is no usage of deprecated features or fixed function APIs,” yet you don’t use shaders until Tutorial 4, well after you have drawn things. That means you have been drawing things with the fixed-function pipeline. If this were core GL 3.3, you wouldn’t be able to draw anything at all.
In Tutorial 3, you introduce the concept of winding order. Specifically you state:
The reason I started with a dot is to overcome a nasty attribute of triangles - the danger of specifying the vertices in the incorrect order and having the triangle being rendered backfaced (i.e. not rendered at all).
This is not true. Backface culling is not enabled by default. You did not have to talk about winding order yet if you did not want to.
Also, it is strange to discuss winding order without bothering to detail the OpenGL functions that control winding order and backface culling.
In Tutorial 4, you have a large paragraph that skims complex topics (perspective projection, homogeneous coordinates, etc). But there’s one crucial bit of information that you ignore: what space the coordinates you are writing are in. Defining the extent of clip-space and normalized device coordinate space is very important to understanding what the rules for vertex shader output are.
Also, I would advise not bringing up geometry shaders unless you’re actually going to write one. It just confuses the pipeline.
In Tutorial 5, you have things pretty backwards. If you’re introducing uniforms, you should start with the shader, then show how the uniform from the shader gets filled in by the code.
In Tutorial 6, your math equations are low resolution and scaled. If you want them to be bigger, you should make them bigger in the source data. Consider using MathML as a source and convert it to SVG with something like SVGMath. That’s what I do anyway.
Also, one of the reasons why I introduce the perspective projection first, before other transformations, is that it introduces matrix-based transforms in a way that seems less frivolous. Using a matrix for mere translation seems like overkill until you’re dealing with multiple transformations and transformation composition.
You say:
The point is that C/C++ are row-major languages by default.
This is not true. C/C++ doesn’t know what a “row” is. If you want the first index in a multidimensional array to mean “column” instead of “row”, you can. It’s all a question of user conventions. C/C++ doesn’t impose anything on you. Your matrices are row-major because all of your code assumes them to be row-major by convention.
In Tutorial 7, you quickly introduce trigonometry. This assumes that your audience is familiar with trigonometry, sin, and cosine. If that’s your assumption, so be it, but you might want to make sure that you have an introduction somewhere that tells the reader that they need to know what these functions do before reading the tutorial. Or at least link to the Wikipedia article(s) on the subject.
To me, it seems wrong to go through the effort of introducing the three basic transforms, and then wait to discuss transform composition for 2 tutorials. It just seems more natural to have Tutorial 11 be Tutorial 9.
Tutorial 9 leads with what has to be the biggest paragraph ever. I know I mentioned this before, but it’s a wall of text that’s basically illegible.
In Tutorial 10, you introduce the concept of indexed rendering, which is good. One problem I have is that you don’t really stress the fact that you only get one index for all of the attributes. A lot of people, particularly people new to graphics, are going to assume that you can index each attribute individually. Having a paragraph explaining that you can’t, just to make it abundantly clear that this is not possible would be a good idea.
In Tutorial 11, you have this:
void Rotate(float RotateX, float RotateY, float RotateZ)
No discussion of this could ever possibly be considered complete without a thorough discussion of Gimbal Lock. Otherwise, you give the impression that this function is a good idea (it’s not) and that they can successively apply axial rotations like this to easily orient an object (they can’t).
Also, I think this “Pipeline” class of yours is very poor coding style. It forces 3 specific transforms, and forces them to act in a particular order. While this is the most common order of transforms, it is far from the only one they will ever use. Giving a reason why one might want the scale to be applied after rotation would at least point users who are looking to solve a transformation problem in the right direction.
Additionally, this discussion of transformations ensues without any discussion of coordinate systems or spaces. Nothing is said about model space, world space, clip space, or any other kind of space. Admittedly, some of that is hard considering that we haven’t introduced camera space and the perspective matrix yet.
Overall, it’s a good start, but somewhat slim on content and marred by poor information presentation.