Only last set of vertices render

Alright here goes, I am in the middle of porting our rendering from fixed-function to fully programmable with a 3.2 core context and glsl 1.5. Whenever we wish to render to the screen (image, text, shapes) we call a function that fills an array with our vertices and writes that to the VBO (Only have 1 VAO and 1 VBO). After that I bind the shaders and the VAO and then glDrawArrays.

This results in only the last set of vertices being rendered on screen. In the particular test I have, there is a box near the lower left corner that renders and when you click the mouse another box appears at the cursor (like a gunshot). When the shot comes on screen for a second the lower left box disappears and reappears.

I can’t seem for the life of me to render multiple 2d objects onto the screen at once. I have gone so far as changed the fillArray function to create a new VAO and VBO each time it is called to no avail.

Does this problem standout to anyone? I can provide code samples if needed.

Here is a screencast of the behavior I have: - YouTube

Any and all ideas/thoughts/comments/flames are welcome.

You will need to post some code

void OGL_Renderer_3_2::drawVertexArray(GLuint textureId, bool defaultTextureCoords){
    clearScreen(0, 0, 0);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    glUseProgram(mShaderManager->getShaderProgram());
    getError();
    
    mModelViewMatrix = glGetUniformLocation(mShaderManager->getShaderProgram(), "mvp");
    getError();
    
    glUniformMatrix4fv(mModelViewMatrix, 1, GL_FALSE, glm::value_ptr(ModelViewMatrix));
    getError();
        
    glBindVertexArray(mVertexArray);
    getError();


    glDrawArrays(GL_TRIANGLES, 0, 6);
    getError();


    glBindVertexArray(0);
    getError();
    glUseProgram(0);
    getError();
    glDisable(GL_BLEND);
}


/**
 * Used internally to fill the vertex array with quad vertex information.
 */
void OGL_Renderer_3_2::fillVertexArray(GLfloat x, GLfloat y, GLfloat w, GLfloat h)
{


    float *mVertexArrayData = new float[18];
    
    mVertexArrayData[0] = static_cast<GLfloat>(x); mVertexArrayData[1] = static_cast<GLfloat>(y + h); mVertexArrayData[2] = 0;
    mVertexArrayData[3] = static_cast<GLfloat>(x); mVertexArrayData[4] = static_cast<GLfloat>(y); mVertexArrayData[5] = 0;
    mVertexArrayData[6] = static_cast<GLfloat>(x + w); mVertexArrayData[7] = static_cast<GLfloat>(y); mVertexArrayData[8] = 0;
    mVertexArrayData[9] = static_cast<GLfloat>(x + w); mVertexArrayData[10] = static_cast<GLfloat>(y); mVertexArrayData[11] = 0;
    mVertexArrayData[12] = static_cast<GLfloat>(x + w);    mVertexArrayData[13] = static_cast<GLfloat>(y + h); mVertexArrayData[14] = 0;
    mVertexArrayData[15] = static_cast<GLfloat>(x);    mVertexArrayData[16] = static_cast<GLfloat>(y + h); mVertexArrayData[17] = 0;
    
    glGenVertexArrays(1, &mVertexArray); // Create our Vertex Array Object
    glBindVertexArray(mVertexArray); // Bind our Vertex Array Object so we can use it
    
    glGenBuffers(1, &mVertexBufferObject); // Generate our Vertex Buffer Object
    glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferObject); // Bind our Vertex Buffer Object
    glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), mVertexArrayData, 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 [] mVertexArrayData;

}

First fillVertexArray() is called passing in an x and y coordinate where we want the object to draw and usually pass in an image width and height (or box width and height).

drawVertexArray() is called right after.

The shaders that are used are basic, just getting vertices and assigning a color to the whole thing.

If your clear the screen in drawVertexArray, then each call you make to it will clear the screen of previous contents.

Thanks Dan I completely overlooked that! Without clearing the screen though the graphics stay on the screen when moving the mouse around and such and I have intense flashing right now. Should there be a clearScreen call somewhere?

Second issue revealed is my matrix doesn’t seem to be correct… It should be a ortho projection against a viewport size of 800x600. Here is the code:

	int w, h;	SDL_GetWindowSize(mWindow, &w, &h);
	projection = glm::mat4(1.0f);
	projection = glm::ortho(0.0f, static_cast<float>(w), static_cast<float>(h), 0.0f);
	view = glm::lookAt(
				glm::vec3(0,0,0), // Camera is at (0,0,5), in World Space
				glm::vec3(0,0,1), // and looks at the origin
				glm::vec3(0,-1,0)  // Head is up (set to 0,-1,0 to look upside-down)
	);
	model = glm::mat4(1.0f);
	ModelViewMatrix = projection * view * model;

You typically clear the screen at the start of the frame, render all the objects that need rendering, then swap the back and front buffers using SwapBuffers() / SDL_GL_SwapBuffers() or equivalent. Some common reasons for flashing/flickering are:

  1. When using single buffering you can sometimes see each new object being drawn which causes flashing as objects appear + are drawn over quickly
  2. Using double-buffering without clearing the screen (or without drawing to every pixel) each frame, which can result in contents of previous frames re-appearing when you swap buffers
  3. Drawing objects with very similar depth values can give z-fighting that causes flickering as the camera moves (when depth testing is enabled)

I can’t see anything immediately wrong with the matrix code, although it’s a little unusual to have up=(0,-1,0). What do you mean by “doesn’t seem to be correct”? If you have resized the window after the context was created, you will probably want to call glViewport afterwards.

Well this is all 2D rendering so we don’t make use of depth values, but I will double check that I have that turned off. Also I thought glViewport was gone in 3.2 Core?

glViewport is still part of core OpenGL, as the transformation into window coordinates is still needed.

Wow, then I was sorely wrong… The reason I had the view as (0, -1, 0) is because if I don’t, the mouse y orientation is upside down (move mouse up it goes down or at least renders that way).

glViewport should be called when setting up opengl and if the window is resized correct?

The initial size of the viewport is set to the size of the window used for rendering so not strictly needed then (but won’t hurt), but when resizing you’ll want to adjust it.

You may also want to adjust the viewport for drawing things like mini-maps, multiple views etc. but remember to set the scissor rectangle too if you do this since it’s possible to draw on pixels outside the viewport. A simple example of when this can happen is when drawing large points near the edge of the viewport; it will produce pixels drawn outside the viewport. Once the centre of the point leaves the viewport the entire point will be clipped by the clip volume, in which case you might want a viewport larger than the window (extended by half the max point size in each direction) so that it gradually disappears off screen rather than suddenly vanishing when half visible.

In the most recent versions of OpenGL there are also multiple viewports/scissor rects available, so if for example you wanted to view something from multiple angles (eg. for stereo or design work) could set multiple different viewports/scissor rects and in the geometry shader emit a copy of the primitives to each viewport resulting in multiple copies in a single pass.

There must still be something wrong with my coordinates…Again here is my Init code:

void OGL_Renderer_3_2::initGL(){
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	
	glDisable(GL_DEPTH_TEST);
	
	glViewport(0, 0, width(), height());


	// Spit out system graphics information.
	cout << "	- OpenGL System Info -" << endl;


	driverName((char*)glGetString(GL_RENDERER));


	cout << "	Vendor: " << glGetString(GL_VENDOR) << endl;
	cout << "	Renderer: " << driverName() << endl;
	cout << "	Driver Version: " << glGetString(GL_VERSION) << endl;
	cout << "	GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;


//	if(!checkExtensions())
//		throw Exception(0, "Graphics Requirements Not Met", "Your graphics driver does not meet the minimum requirements.");


	glGenVertexArrays(1, &mVertexArray);
	getError();
	glBindVertexArray(mVertexArray);
	getError();


	glGenBuffers(1, &mVertexBufferObject);
	getError();
	glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferObject);
	getError();
	glBufferData(GL_ARRAY_BUFFER, 4 * 6 * sizeof(GLfloat), DEFAULT_VERTEX_COORDS, GL_DYNAMIC_DRAW);
	getError();


	glGenBuffers(1, &mTextureBufferObject);
	getError();
	glBindBuffer(GL_ARRAY_BUFFER, mTextureBufferObject);
	getError();
	glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(DEFAULT_TEXTURE_COORDS), DEFAULT_TEXTURE_COORDS, GL_STATIC_DRAW);
	getError();
	glEnableVertexAttribArray(0);
	getError();


	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	getError();
}




void OGL_Renderer_3_2::initVideo(unsigned int resX, unsigned int resY, unsigned int bpp, bool fullscreen, bool vsync)
{
	// Initialize SDL's Video Subsystems.
	if(SDL_Init(SDL_INIT_VIDEO) < 0)
		throw Exception(701, "Error starting SDL Video Library", SDL_GetError());




	// Setup OpenGL parameters
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);


	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);	/// 	odo	Add checks to determine an appropriate depth buffer.


	if(vsync)
		SDL_GL_SetSwapInterval(1);


	// Anti-aliasing... need to test this.
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);


	Uint32 sdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;


	if(fullscreen)
		sdlFlags = sdlFlags | SDL_WINDOW_FULLSCREEN;


	mWindow = SDL_CreateWindow(title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, resX, resY, sdlFlags);


	if(!mWindow)
	{
		cout << "EXCEPTION: Could not create a Window: " << SDL_GetError() << endl;
		throw Exception(0, "Window Creation Failed", "Unable to create a window.");
	}


	_window = mWindow;


	mContext = SDL_GL_CreateContext(mWindow);


	if(!mContext)
	{
		cout << "EXCEPTION: Could not create an OpenGL Context: " << SDL_GetError() << endl;
		throw Exception(0, "Can't create OGL Context", "Unable to create an OpenGL Context.
" + string(SDL_GetError()));
	}




	void* ptr = SDL_GL_GetProcAddress("glDrawArrays");




	SDL_ShowCursor(false);


	buildDisplayModeList();
	initGL();
	mShaderManager = new ShaderManager();
	
	int w, h;
	SDL_GetWindowSize(mWindow, &w, &h);
	projection = glm::ortho(0.0f, static_cast<float>(w), static_cast<float>(h), 0.0f);
	view = glm::lookAt(
					   glm::vec3(0,0,-1), // Camera is at (0,0,5), in World Space
					   glm::vec3(0,0,0), // and looks at the origin
					   glm::vec3(0,-1,0)  // Head is up (set to 0,-1,0 to look upside-down)
					   );
	model = glm::mat4(1.0f);
	ModelViewMatrix = projection * view * model;
}

This is the image I get when I don’t clear the screen and tell the VertShader not to use my MVP uniform:
[ATTACH=CONFIG]379[/ATTACH]

If I use the MVP uniform still without clearing the screen I get:
[ATTACH=CONFIG]380[/ATTACH]

if I don’t multiply the view and model from INIT and just send the projection, again without clearing the screen I get:
[ATTACH=CONFIG]381[/ATTACH]
*Note the above image has a background image command commented out so I can see the rest of the calls to draw other things.

And if I add in a clear screen command at the start of an update, the screen just doesn’t seem to have anything on it.

Alright I actually fixed the flickering finally! However my mouse y-axis is upside down. In OpenGL 3.2 Core how do I invert that?