Convert from legacy immediate mode to modern opengl

I came across the following legacy immediate code for drawing truchet tiles. I ran it and it works fine:

void setWindow(float left, float right, float bottom, float top)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(left, right, bottom, top);
}
void drawTile()
{
	glBegin(GL_LINE_LOOP);
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		glVertex2f(250 * cos(angle), 250 * sin(angle));
	}
	glEnd();
	glFlush();

	glBegin(GL_LINE_LOOP);
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		glVertex2f(500+ 250 * cos(angle) , 500 + 250 * sin(angle));
	}
	glEnd();

	glFlush();
}
float random()
{
	float lc = 0.0f;
	srand(time(NULL));
	lc = ((double)rand() / (RAND_MAX));
	return lc;
}
void screen()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			srand(time(NULL));
			if (rand() % 2 == 0)
			{
				setWindow(500.0, 0.0, 0.0, 500.0);
		    }
			else
			{
				setWindow(0.0, 500.0, 0.0, 500.0);
			}
			
			glViewport(i * 50, j * 50, 50, 50);
			 
			drawTile();
			for (int i = 0; i < 99999999; i++);
		}
	}
}
void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);     // clear the screen 
	
	screen();
}

void setWindow(float left, float right, float bottom, float top)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(left, right, bottom, top);
}
void drawTile()
{
	glBegin(GL_LINE_LOOP);
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		glVertex2f(250 * cos(angle), 250 * sin(angle));
	}
	glEnd();
	glFlush();

	glBegin(GL_LINE_LOOP);
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		glVertex2f(500+ 250 * cos(angle) , 500 + 250 * sin(angle));
	}
	glEnd();

	glFlush();
}
float random()
{
	float lc = 0.0f;
	srand(time(NULL));
	lc = ((double)rand() / (RAND_MAX));
	return lc;
}
void screen()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			srand(time(NULL));
			if (rand() % 2 == 0)
			{
				setWindow(500.0, 0.0, 0.0, 500.0);
		    }
			else
			{
				setWindow(0.0, 500.0, 0.0, 500.0);
			}
			
			glViewport(i * 50, j * 50, 50, 50);
			 
			drawTile();
			for (int i = 0; i < 99999999; i++);
		}
	}
}
void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);     // clear the screen 
	
	screen();
}

I tried to convert it to modern opengl but had no success, here is my attempt


void setWindow(float lft, float rght, float bttom, float tp)
{
		// Compute the MVP matrix
		glm::mat4 ProjectionMatrix = glm::ortho(lft, rght, bttom, tp, -1.0f, 1.0f);
		glm::mat4 ViewMatrix = glm::mat4(1.0f);
		glm::mat4 ModelMatrix = glm::mat4(1.0f);
		MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
		ndcT = vp * MVP;
		// Send our transformation to the currently bound shader, 
		// in the "MVP" uniform
		//glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
	
}

float random()
{
	float lc = 0.0f;

	srand(time(NULL));
	lc = ((double)rand() / (RAND_MAX));
	return lc;
}

void drawTile()
{
	int c=0;
	int b = num_loops;
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(250 * cos(angle), 250 * sin(angle)));
		c++;
	}
	if (num_loops==0)
		first.push_back(0);
	else
		first.push_back(first[first.size()-1]+count[count.size()-1]);
	count.push_back(c);
	num_loops++;

	c = 0;
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(500+ 250 * cos(angle) , 500 + 250 * sin(angle)));
		c++;
	}
	first.push_back(first[first.size()-1]+count[count.size()-1]);
	count.push_back(c);
	num_loops++;	
	for (int i=first[b]; i<first[num_loops-1]+count[num_loops-1]; i++) {
		fprintf(dbg, "%f\t%f\n", g_vertex_buffer_data[i][0], g_vertex_buffer_data[i][1]);
		vec4 nw = MVP * vec4(g_vertex_buffer_data[i][0], g_vertex_buffer_data[i][1], 0.0f, 1.0f);
		fprintf(dbg, "%f\t%f\n", nw[0], nw[1]);
		nw = vp * nw;
		g_vertex_buffer_data[i][0] = nw[0];
		g_vertex_buffer_data[i][1] = nw[1];
		fprintf(dbg, "%f\t%f\n\n", g_vertex_buffer_data[i][0], g_vertex_buffer_data[i][1]);
	}
	fprintf(dbg, "\n\n");
}

void screen()
{

	//int v1 = rand() % 10;
	// set a fixed window 

	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			srand(time(NULL));
			
			//glViewport(i * 50, j * 50, 50, 50);			
			vp = glm::translate(glm::scale(glm::translate(mat4(1.0f), vec3(0.1f*i, 0.1f*j, 0.0f)), vec3(0.1f, 0.1f, 1.0f)), vec3(1.0f, 1.0f, 0.0f));
			if (rand() % 2 == 0)
			{
				setWindow(500.0, 0.0, 0.0, 500.0);
		    }
			else
			{
				setWindow(0.0, 500.0, 0.0, 500.0);
			}
			
			drawTile();
			
			//for (int i = 0; i < 99999999; i++);
			
		}
	}	
	glBufferStorage( GL_ARRAY_BUFFER, g_vertex_buffer_data.size()*sizeof(glm::vec2), &g_vertex_buffer_data[0], 0);						
}

void setup(void)
{
	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

	// Create and compile our GLSL program from the shaders
	GLuint programID = LoadShaders( "VertexShaderTruchet.vertexshader", "FragmentShaderTruchet.fragmentshader" );

	// Get a handle for our "MVP" uniform
	//MatrixID = glGetUniformLocation(programID, "MVP");
		//glViewport(0, 0, 500, 500);
				// Use our shader
		glUseProgram(programID);

	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

	// 1rst attribute buffer : vertices
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	    glVertexAttribPointer(
		0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
		2,                  // size
		GL_FLOAT,           // type
		GL_FALSE,           // normalized?
		0,                  // stride
		(void*)0            // array buffer offset
				  );	
	screen();
}


//<<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>
// the redraw function
void myDisplay(void)
{
    static const float white[] = { 1.0f, 1.0f, 1.0f, 0.0f };

    glClearBufferfv(GL_COLOR, 0, white);
	glFlush();
	glMultiDrawArrays(GL_LINE_LOOP, &first[0], &count[0], num_loops); // indices starting at 0
	glFlush();
}

As clear from my code I print out the vertices and most of them are out of the rangle [-1,1]
I do not understand how calling glortho with left>right effects rendering.
Any lead to what is wrong with my MVP, viewport explicit matrix. Also I tried theMVP matrix
passed as uniform to vertex shader and use glviewport but still didn’t work.

You didn’t print the values correctly. Cos and Sin give value in this range.

Rather than converting everything then finding it doesn’t work, consider doing it in stages. First, replace the glBegin/glEnd with client-side vertex arrays (glVertexPointer) while leaving everything else unchanged. If that doesn’t work, there’s a problem with your vertex array construction. If that works, try using a vertex shader which uses compatibility variables (gl_Vertex, gl_ModelViewProjectionMatrix). Then replace those with generic attributes and uniforms. That way, when it stops working you have a reasonable idea of where the problem lies.

1 Like

There is a factor of 250 multiplied and in another loop 500 is added.

Anyway by trial and error, I changed calculation of vp into:
vp = glm::translate(glm::scale(glm::translate(mat4(1.0f), vec3((i-5)/5.0f, (j-5)/5.0f, 0.0f)), vec3(0.1f, 0.1f, 1.0f)), vec3(1.0f, 1.0f, 0.0f));

and it seems to give values in NDC [-1,1] and obtained whole circles tiled instead of the truchet tiles, so it seems they were not clipped as would if using glViewport.

Well, any idea how glOrtho behaves when left>right. Could not find any info on internet. I try to change it but the program didn’t work correctly. Does it mean that everything drawn get clipped?

The rendered image will be flipped left-right. Any vertex whose eye-space X coordinate is equal to left will be aligned with the left edge of the viewport, any vertex whose eye-space X coordinate is equal to right will be aligned with the right edge of the viewport.

You can see the documentation for glOrtho here. gluOrtho2D is just glOrtho with near=-1 and far=1.

Note that transformations with a negative determinant (i.e. which include an odd number of reflections) will invert the orientation of primitives, so clockwise becomes counter-clockwise and vice versa. This doesn’t matter for lines, but if you’re rendering triangles/quads/polygons with culling enabled, you have to bear this in mind when selecting front/back faces.

Thanks, following your advice and changing as little as possible at a time, I got the code to work, except that it does not give random patterns, only same regular pattern all tiles in same orientation, but can’t figure out why?

void setup(void)
{
	glClearColor(1.0, 1.0, 1.0, 0.0);      // set the bg color to a bright white

	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

	// Create and compile our GLSL program from the shaders
	GLuint programID = LoadShaders( "VertexShaderTruchet.vertexshader", "FragmentShaderTruchet.fragmentshader" );

	// Get a handle for our "MVP" uniform
	MatrixID = glGetUniformLocation(programID, "MVP");
				// Use our shader
		glUseProgram(programID);

			glGenBuffers(1, &vertexbuffer);
			glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

			// 1rst attribute buffer : vertices
		    glEnableVertexAttribArray(0);
		    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
		    glVertexAttribPointer(
			0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
			2,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
					  );	
	screen();
}

//<<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>
// the redraw function
void setWindow(float left, float right, float bottom, float top)
{
		// Compute the MVP matrix
		glm::mat4 ProjectionMatrix = glm::ortho(left, right, bottom, top, -1.0f, 1.0f);
		glm::mat4 ViewMatrix = glm::mat4(1.0f);
		glm::mat4 ModelMatrix = glm::mat4(1.0f);
		MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
		// in the "MVP" uniform
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
}
void drawTile()
{
	int c = 0;
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(250 * cos(angle), 250 * sin(angle)));
		c++;
	}
	if (num_loops==0)
		first.push_back(0);
	else
		first.push_back(first[first.size()-1]+count[count.size()-1]);
	count.push_back(c);
	num_loops++;

	c = 0;
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(500+ 250 * cos(angle) , 500 + 250 * sin(angle)));
		c++;
	}
	first.push_back(first[first.size()-1]+count[count.size()-1]);
	count.push_back(c);
	num_loops++;
}

void screen()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			srand(time(NULL));	
			if (rand() % 2 == 0)
			{
				//setWindow(500.0, 0.0, 0.0, 500.0);
				flip.push_back(1);
		    }
			else
			{
				//setWindow(0.0, 500.0, 0.0, 500.0);
				flip.push_back(0);
			}
			//glViewport(i * 50, j * 50, 50, 50);
			 
			drawTile();
			//for (int i = 0; i < 99999999; i++);
		}
	}
	glBufferStorage( GL_ARRAY_BUFFER, g_vertex_buffer_data.size()*sizeof(glm::vec2), &g_vertex_buffer_data[0][0], 0);	
	glutPostRedisplay();	
}
void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);     // clear the screen 
	int k =0;
	for (int i=0; i<10; i++) {
		for (int j=0; j<10; j++) {
			glViewport(i*50, j*50, 50, 50);
			if (flip[k/2]) setWindow(500.0, 0.0, 0.0, 500.0);
			else setWindow(0.0, 500.0, 0.0, 500.0);
			glMultiDrawArrays(GL_LINE_LOOP, &first[k], &count[k], 2);
			k += 2;
			glFlush();
			for (int t = 0; t < 99999999; t++);
		}
	}
}

The immediate mode original version gives tiles with random orientations. Don’t know why this is lost in this new version.

Never mind I caught the bug. I took out the seed initialization (srand(time(NULL)) out of the double i,j loop and everything worked fine. The reason is that in the original version the seed initialization was inside loop but there were long enough delay to change the seed value used in generating the random number.
In my modified version I commented out the delay and moved it to the display call back after the MultiDrawArrays, therefore, the double i,j loop in my modified version was running too fast to allow a change in the seed value generated by time(NULL) and hence the same value was used for all values and same orientation was used for all tiles instead of random flipping of orientation.
Thanks again for the help and nice advice about changing as little as possible at a time. Actually this was more of an exercise in converting legacy immediate mode (of which I have so many old programs) to Modern opengl.

Now that it is working, to finish the exercise I need to cut down the memory, the vertices making up all the tiles are more than 70000 points. We need only to store enough points to draw one tile (once), then loop to flip or not the next tile until all 100 are done. Drawing one tile in display call call back and calling glutPostRedisplay() inside double i,j loop didn’t work. Also moving the display call back code inside the double i,j loop of screen including the glFlush didn’t work, so don’t know how to do it…

Here is my first attempt:

int vpi, vpj;

void setWindow(float left, float right, float bottom, float top)
{
		// Compute the MVP matrix
		glm::mat4 ProjectionMatrix = glm::ortho(left, right, bottom, top, -1.0f, 1.0f);
		glm::mat4 ViewMatrix = glm::mat4(1.0f);
		glm::mat4 ModelMatrix = glm::mat4(1.0f);
		glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
		// in the "MVP" uniform
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
}

void drawTile()
{
	int c=0;
	if (!g_vertex_buffer_data.empty()) g_vertex_buffer_data.clear();
	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(250 * cos(angle), 250 * sin(angle)));
		c++;
	}
	first[0] = 0;
	count[0] = c;

	for (float angle = 0.0; angle < 360 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(500+ 250 * cos(angle) , 500 + 250 * sin(angle)));
	}
	first[1] = c;
	count[1] = c;
	glDeleteBuffers(1, &vertexbuffer);
	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);	
	glBufferStorage(GL_ARRAY_BUFFER, g_vertex_buffer_data.size()*sizeof(vec2), &g_vertex_buffer_data[0][0], 0);
	
}

void screen()
{
	for (int i = 0; i < 10; i++)
	{
		vpi = i;
		for (int j = 0; j < 10; j++)
		{
			vpj = j;
			drawTile();
			glutPostRedisplay();		
		}
	}	
}

void setup(void)
{
	srand(time(NULL));
	GLuint VertexArrayID;
	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

	// Create and compile our GLSL program from the shaders
	GLuint programID = LoadShaders( "VertexShaderTruchet.vertexshader", "FragmentShaderTruchet.fragmentshader" );

	// Get a handle for our "MVP" uniform
	MatrixID = glGetUniformLocation(programID, "MVP");
	// Use our shader
		glUseProgram(programID);

			// 1rst attribute buffer : vertices
		    glEnableVertexAttribArray(0);
		    glVertexAttribPointer(
			0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
			2,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
					  );	

    static const float white[] = { 1.0f, 1.0f, 1.0f, 0.0f };
    glClearBufferfv(GL_COLOR, 0, white);
	glFlush();

	screen();
}


//<<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>
// the redraw function
void myDisplay(void)
{
	if (rand() % 2 == 0) setWindow(500.0, 0.0, 0.0, 500.0);
	else setWindow(0.0, 500.0, 0.0, 500.0);
	glViewport(vpi*50, vpj*50, 50, 50);
	cerr << "Multidraw: " << "i= " << vpi << "\tj= " << vpj << "\n";
	glMultiDrawArrays(GL_LINE_LOOP, &first[0], &count[0], 2); // indices starting at 0
	glFlush();
	for (int t = 0; t < 99999999; t++);	
}

OK I figured it out. I need to make setup call drawTile() instead of screen() which serves no purpose now, and its body is moved to display call back without the drawTile() call which is called only once (by setup) to draw a single tile. Then this tile is either flipped or not in different viewports…
Thanks again for Clements who made me think twice before making any single change in converting from legacy immediate mode to modern opengl…

If you have at least OpenGL 3.1 (preferably 3.3), you can use instanced rendering (glDrawElementsInstanced needs 3.1, glVertexAttribDivisor needs 3.3).

I read about them in the red book 9th ed. but need a bit of clarification: A single tile consists of 2 primitives, one quarter circle and its reflection; so I need to draw the first half of all tiles in one path and remember the original seed used in random number generation used in deciding to flip or not each tile.
Then have another drawArraysInstanced to draw the second half of all tiles.
If I draw as in the code posted here, where full circles are drawn and get clipped by an appropriate glViewport, then how do I change the viewport for each instance, the red book talks about uniforms only being changed per instance but does not mention viewports, so it seems that here we need to use glClipplanes. Is that right??

I forgot to ask why did you mention glDrawElements, while it seems to me that glDrawArrays is more appropriate since the vertices are sequential.

Why are you changing the viewport per tile? It should only be necessary to change the transformation.

The original code had two line loops. Those could be rendered in a single draw call with glDrawElements (or with glDrawArrays using primitive restart).

Yes, I see, the second half of the tile is the same as the first one but with different transformation. Thanks…

Well, I tried glDrawArraysInstanced and nothing appeared in the blank window. I was very careful, by first writing a code that used glMultiDrawArrays in a for loop to draw the individual tiles while uploading the MVP matrix into uniform block with each new tile and it worked fine.

Next step was simply instead of passing the MVP matrix into uniform buffer is to store in GL_ARRAY_BUFFER and at the end my display callback is simply the one call to glDrawArraysInstanced.

So, I wrote a simple program to test glDrawArraysInstanced and also got a blank screen. But saw a flash of the 10 red diamonds when I closed the window. So I introduced a timer function to refresh the screen every 50 ms. And finally I got my picture.
Here is the simple program:

// Include GLEW
#include <GL/glew.h>

#include <GL/freeglut.h>

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include "shader.hpp"
GLuint meshVAO, vertexVBO, instanceVBO;

void setup(void) {
// List of 10 triangle x-offsets (translations)
GLfloat translations[10];
GLint index = 0;
for (GLint x = 0; x < 10; x++)
{
    translations[index++] = (GLfloat)x / 10.0f;
}

// vertices
GLfloat vertices[] = {
     0.0f,   0.05f,
     0.05f, -0.05f, 
    -0.05f, -0.05f,
     0.0f,  -0.1f,
};

	// Create and compile our GLSL program from the shaders
	GLuint programID = LoadShaders( "vshader.vshader", "fshader.fshader" );
	// Use our shader
		glUseProgram(programID);

// Setting VAOs and VBOs
glGenVertexArrays(1, &meshVAO);    
glGenBuffers(1, &instanceVBO);
glGenBuffers(1, &vertexVBO);

glBindVertexArray(meshVAO);

    glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);

    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(translations), translations, GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat), (GLvoid*)0);
    glVertexAttribDivisor(1, 1); // This sets the vertex attribute to instanced attribute.

    glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);
glutPostRedisplay();
}

void timer(int value)
{	
	glutPostRedisplay();
	glutTimerFunc(50, timer, 0);  //call hexdraw draw fuction with a gap of 50 miliseconds	
}

void myDisplay(void) {
glBindVertexArray(meshVAO);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 10); // 10 diamonds, 4 vertices per instance
glFlush();
glBindVertexArray(0);
}

//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char **argv)
{
	glutInit(&argc, argv);          // initialize the toolkit
	glutInitContextVersion(3, 3);
	glutInitContextProfile(GLUT_CORE_PROFILE);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set the display mode
	glutInitWindowSize(500, 500);     // set the window size
	glutInitWindowPosition(100, 100); // set the window position on the screen
	glutCreateWindow("Truchet Tile Hill Instanced"); // open the screen window(with its exciting title)
	glutDisplayFunc(myDisplay);     // register the redraw function
	glutTimerFunc(0, timer, 0);	
	
	glewExperimental = GL_TRUE;
	glewInit();

	setup();
	glutMainLoop(); 		     // go into a perpetual loop
	return 0;
}

Now, I didn’t have to refresh the screen in my first running program while passing MVP matrix into uniform. Is that a weird behavior in my graphics driver, or is it typical in glDrawArraysInstanced, or there is something wrong with the code?

Well, it seems the problem is with glutPostRedisplay in freeglut. When I rewrote the program using glfw and glad as done in the red book instead of freeglut and glew, it worked fine…

Well freeglut with double buffering. The problem is that glDrawArraysInstanced requires double buffering to work correctly…

Now I got the simple example of glDrawArraysInstanced to work correctly, but still not for the truchet tiles. Here are the main parts, if anyone can guess what is wrong. After spending half a day starring at it I am stuck…

void generateHalfTile()
{
	for (float angle = 180.0 * 0.01745329; angle < 270.0 * 0.01745329; angle += 0.01745329)
	{
		g_vertex_buffer_data.push_back(vec2(rad + rad * cos(angle), rad + rad * sin(angle)));
	}
}

void generateTilesTransforms(void)		
{
	side = sqrt(INSTANCES);
	mat4 reflct = scale(mat4(1.0f), vec3(-1.0f, -1.0f, 1.0f));

	MV = new mat4[2*INSTANCES];
	for (int i = 0; i < side; i++)
	{
		mat4 vcurrent = current;
		for (int j = 0; j < side; j++)
		{
			if ((rand() % 2) == 0)
			{
				MV[2*(i*side + j)] = current;
				MV[2*(i*side + j)+1] = current * reflct;
		    }
			else
			{
				mat4 current1 = current;
				current = rotate(current1, 90.0f * 0.01745329f, vec3(0.0f, 0.0f, 1.0f));
				MV[2*(i*side + j)] = current;
				MV[2*(i*side + j)+1] = current * reflct;				
				current = current1;
			}
			current = translate(vcurrent, vec3((float) (j+1)*width, 0.0f, 0.0f));
		}
		current = translate(mat4(1.0f), vec3(0.0f, (float) (i+1)*width, 0.0f));
	}
}

void setup(void)
{
	srand(time(NULL));
    static const float white[] = { 1.0f, 1.0f, 1.0f, 0.0f };
    glClearBufferfv(GL_COLOR, 0, white);
	glutSwapBuffers();
    glClearBufferfv(GL_COLOR, 0, white);
	glutSwapBuffers();
	
	GLuint VertexArrayID;
	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

	// Create and compile our GLSL program from the shaders
	GLuint programID = LoadShaders( "VertexShaderTruchetHillInstanced.vertexshader", "FragmentShaderTruchetHillInstanced.fragmentshader" );
	// Use our shader
		glUseProgram(programID);
	
	// Get a handle for our "MVP" uniform
	MatrixID = glGetUniformLocation(programID, "Projection_Matrix");
	GLuint MV_loc = glGetAttribLocation(programID, "mv");
	GLuint g_loc = glGetAttribLocation(programID, "vertexPosition_modelspace");
	// Compute the MVP matrix
	ProjectionMatrix = ortho(0.0f, 500.0f, 0.0f, 500.0f, -1.0f, 1.0f);
	glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &ProjectionMatrix[0][0]);
	current = mat4(1.0f);
	
	generateHalfTile();
	generateTilesTransforms();	

	GLuint vertexbuffer;
	glGenBuffers(1, &vertexbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);	
	glBufferStorage(GL_ARRAY_BUFFER, g_vertex_buffer_data.size()*sizeof(vec2)+2*INSTANCES*sizeof(mat4), NULL, GL_DYNAMIC_STORAGE_BIT);
	glBufferSubData(GL_ARRAY_BUFFER, 0, g_vertex_buffer_data.size()*sizeof(vec2), &g_vertex_buffer_data[0][0]);
	glBufferSubData(GL_ARRAY_BUFFER, g_vertex_buffer_data.size()*sizeof(vec2), 2*INSTANCES*sizeof(mat4), &MV[0][0][0]);
			// 1rst attribute buffer : vertices
    glEnableVertexAttribArray(g_loc);
    glVertexAttribPointer(
			g_loc,              // attribute. No particular reason for 0, but must match the layout in the shader.
			2,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
					  );
	for (int i = 0; i<4; i++) {
		glVertexAttribPointer(MV_loc + i,
			4, GL_FLOAT, GL_FALSE,
			sizeof(mat4), (void *)(g_vertex_buffer_data.size()*sizeof(vec2)+sizeof(vec4)*i));
		glEnableVertexAttribArray(MV_loc + i);
		glVertexAttribDivisor(MV_loc + i, 1);
	}
	glutPostRedisplay();
}

void myDisplay(void)
{
	glDrawArraysInstanced(GL_LINE_STRIP, 0, g_vertex_buffer_data.size(), 2*INSTANCES);
	glutSwapBuffers();
}

Never mind, I found the bug. In my vertex shader, the projection matrix was called Projection_matrix. In my app. I used Projection_Matrix in glGetUniformLocation. Now everything is fine. Nothing like a fresh start…