black flicker at triangle edges

This is the cube I am trying to render (24 vertices with 12 tris):

I couldn’t get a screen shot of it, but whenever I move the camera (or I guess more precisely move the whole scene around the camera), I get a black flicker at the edges between the sides of the cube. I think it might be that the sides are being drawn too slow and can’t keep up with the camera movement. I know that I could render it more efficiently with 8 vertices but then the cube will look weird once I light it (not enough normals). Here is my code (about 230 lines long):

#define BUFFER_OFFSET(i)((char*)NULL+(i))

#include <GLTools.h>            // OpenGL toolkit
#include <GLShaderManager.h>    // Shader Manager Class
#include <GLFrustum.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#include <GL/glut.h>            // Windows FreeGlut equivalent
#include <vector>

struct vertexType
{
	GLfloat xPos,yPos,zPos;
	GLfloat rColor,bColor,gColor,aColor;
};

GLShaderManager	shaderManager;
std::vector<vertexType> vertexArray;
std::vector<GLushort> vertexIndex;

GLuint vdataBufferID; //vertex data
GLuint viBufferID; //vertex index buffer
GLFrame cameraFrame;
GLFrame modelFrame;
bool rightMouseDown;
int oldMouseX,oldMouseY;
int deltaMouseX,deltaMouseY;

GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrustum frustum;
GLGeometryTransform transformPipeline;

void loadVertexArray(GLfloat x,GLfloat y,GLfloat z,GLfloat r,GLfloat g,GLfloat b,GLfloat a)
{
	vertexType tempVertex;
	tempVertex.xPos=x;
	tempVertex.yPos=y;
	tempVertex.zPos=z;
	tempVertex.rColor=r;
	tempVertex.gColor=g;
	tempVertex.bColor=b;
	tempVertex.aColor=a;
	vertexArray.push_back(tempVertex);
}
void initTriCube(float xPos,float yPos,float zPos)
{
	loadVertexArray(-0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f,1.0f); //0 (0.0) RED
	loadVertexArray(-0.5f,0.5f,0.0f, 0.0f,0.0f,1.0f,1.0f); //1 (0.1) GREEN
	loadVertexArray(-0.5f,0.5f,0.0f, 0.0f,0.0f,0.5f,1.0f); //2 (0.2) DARK GREEN
	loadVertexArray(-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f,1.0f); //3 (1.0) RED
	loadVertexArray(-0.5f,-0.5f,0.0f, 1.0f,0.0f,1.0f,1.0f); //4 (1.1) YELLOW
	loadVertexArray(-0.5f,-0.5f,0.0f, 0.0f,0.0f,0.5f,1.0f); //5 (1.2) DARK GREEN
	loadVertexArray(0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f,1.0f); //6 (2.0) RED
	loadVertexArray(0.5f,-0.5f,0.0f, 1.0f,0.0f,1.0f,1.0f); //7 (2.1) YELLOW
	loadVertexArray(0.5f,-0.5f,0.0f, 0.0f,1.0f,0.0f,1.0f); //8 (2.2) BLUE
	loadVertexArray(0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f,1.0f); //9 (3.0) RED
	loadVertexArray(0.5f,0.5f,0.0f, 0.0f,0.0f,1.0f,1.0f); //10 (3.1 GREEN
	loadVertexArray(0.5f,0.5f,0.0f, 0.0f,1.0f,0.0f,1.0f); //11 (3.2) BLUE
	loadVertexArray(-0.5f,0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //12 (4.0) BLUE
	loadVertexArray(-0.5f,0.5f,1.0f, 0.0f,0.0f,1.0f,1.0f); //13 (4.1) GREEN
	loadVertexArray(-0.5f,0.5f,1.0f, 0.0f,0.0f,0.5f,1.0f); //14 (4.2) DARK GREEN
	loadVertexArray(-0.5f,-0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //15 (5.0) BLUE
	loadVertexArray(-0.5f,-0.5f,1.0f, 1.0f,0.0f,1.0f,1.0f); //16 (5.1) YELLOW
	loadVertexArray(-0.5f,-0.5f,1.0f, 0.0f,0.0f,0.5f,1.0f); //17 (5.2) DARK GEEN
	loadVertexArray(0.5f,-0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //18 (6.0) BLUE
	loadVertexArray(0.5f,-0.5f,1.0f, 1.0f,0.0f,1.0f,1.0f); //19 (6.1) YELLOW
	loadVertexArray(0.5f,-0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //20 (6.2) BLUE
	loadVertexArray(0.5f,0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //21 (7.0) BLUE
	loadVertexArray(0.5f,0.5f,1.0f, 0.0f,0.0f,1.0f,1.0f); //22 (7.1) GREEN
	loadVertexArray(0.5f,0.5f,1.0f, 0.0f,1.0f,0.0f,1.0f); //23 (7.2) BLUE

	//front
	vertexIndex.push_back(12);	vertexIndex.push_back(15);	vertexIndex.push_back(18);
	vertexIndex.push_back(18);	vertexIndex.push_back(21);	vertexIndex.push_back(12);
	//back
	vertexIndex.push_back(6);	vertexIndex.push_back(3);	vertexIndex.push_back(0);
	vertexIndex.push_back(0);	vertexIndex.push_back(9);	vertexIndex.push_back(6);
	//top
	vertexIndex.push_back(22);	vertexIndex.push_back(10);	vertexIndex.push_back(1);
	vertexIndex.push_back(1);	vertexIndex.push_back(13);	vertexIndex.push_back(22);
	//bottom
	vertexIndex.push_back(7);	vertexIndex.push_back(19);	vertexIndex.push_back(16);
	vertexIndex.push_back(16);	vertexIndex.push_back(4);	vertexIndex.push_back(7);
	//left side
	vertexIndex.push_back(17);	vertexIndex.push_back(14);	vertexIndex.push_back(2);
	vertexIndex.push_back(2);	vertexIndex.push_back(5);	vertexIndex.push_back(17);
	//right side
	vertexIndex.push_back(8);	vertexIndex.push_back(11);	vertexIndex.push_back(23);
	vertexIndex.push_back(23);	vertexIndex.push_back(20);	vertexIndex.push_back(8);

	glGenBuffers(1,&vdataBufferID);
	glBindBuffer(GL_ARRAY_BUFFER,vdataBufferID);
	glBufferData(GL_ARRAY_BUFFER,sizeof(vertexType)*vertexArray.size(),&(vertexArray[0]),GL_STATIC_DRAW);

	glGenBuffers(1,&viBufferID);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,viBufferID);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*vertexIndex.size(),&(vertexIndex[0]),GL_STATIC_DRAW);

	modelFrame.SetOrigin(xPos,yPos,zPos);
	modelFrame.SetUpVector(0.0f,1.0f,0.0f);
	modelFrame.SetForwardVector(0.0f,0.0f,1.0f);
}
void drawTriCube()
{
	glBindBuffer(GL_ARRAY_BUFFER,vdataBufferID);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(vertexType),BUFFER_OFFSET(0));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1,4,GL_FLOAT,GL_FALSE,sizeof(vertexType),BUFFER_OFFSET(12));
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,viBufferID);
	glDrawElements(GL_TRIANGLES,vertexIndex.size(),GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
}
void MouseMoved(int x,int y)
{
	float cameraAngularX=0.0f;
	float cameraAngularY=0.0f;
	if(rightMouseDown)
	{
		deltaMouseX=x-oldMouseX;
		deltaMouseY=y-oldMouseY;
		cameraAngularX=float(m3dDegToRad(deltaMouseX))*0.01f;
		cameraAngularY=float(m3dDegToRad(deltaMouseY))*0.01f;
		cameraFrame.RotateWorld(cameraAngularX,0.0f,1.0f,0.0f);
		cameraFrame.RotateWorld(cameraAngularY,1.0f,0.0f,0.0f);
	}
}
void MouseClicked(int button, int state, int x, int y)
{
	if(state==GLUT_DOWN)
	{
		if(button==GLUT_RIGHT_BUTTON)
		{
			rightMouseDown=true;
			oldMouseX=x;
			oldMouseY=y;
		}
		else
			rightMouseDown=false;
	}
}
void SpecialKeys(int key, int x, int y)
{
	switch(key)
	{
	case GLUT_KEY_UP:		modelFrame.RotateLocalX(0.1f);
							break;
	case GLUT_KEY_DOWN:		modelFrame.RotateLocalX(-0.1f);
							break;
	case GLUT_KEY_LEFT:		modelFrame.RotateLocalY(-0.1f);
							break;
	case GLUT_KEY_RIGHT:	modelFrame.RotateLocalY(0.1f);
							break;
	default:				break;
	}
}
void ChangeSize(int w, int h)
{
	glViewport(0, 0, w, h);
	frustum.SetPerspective(35.0f,float(w)/float(h),1.0f,100.0f);
	projectionMatrix.LoadMatrix(frustum.GetProjectionMatrix());
	transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}

void SetupRC()
{
	glClearColor(255.0f, 255.0f, 255.0f, 1.0f );
	glCullFace(GL_BACK);
	glFrontFace(GL_CCW);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);

	shaderManager.InitializeStockShaders();
	initTriCube(0.0f,0.0f,-8.0f);
}
void RenderScene(void)
{
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	
	modelViewMatrix.PushMatrix(); //save identity matrix
	M3DMatrix44f cameraMatrix;
	cameraFrame.GetCameraMatrix(cameraMatrix);
	modelViewMatrix.PushMatrix(cameraMatrix);

	modelViewMatrix.PushMatrix();
	modelViewMatrix.MultMatrix(modelFrame);
	shaderManager.UseStockShader(GLT_SHADER_SHADED,transformPipeline.GetModelViewProjectionMatrix());
	drawTriCube();
	modelViewMatrix.PopMatrix();

	modelViewMatrix.PopMatrix();
	modelViewMatrix.PopMatrix(); //restore identity matrix

	glutSwapBuffers();
	glutPostRedisplay();
}
int main(int argc, char* argv[])
{
	gltSetWorkingDirectory(argv[0]);
	rightMouseDown=false;
	oldMouseX=0;
	oldMouseY=0;
	deltaMouseX=0;
	deltaMouseY=0;

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Triangle");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
	glutSpecialFunc(SpecialKeys);
	glutMotionFunc(MouseMoved);
	glutMouseFunc(MouseClicked);

	GLenum err = glewInit();
	if (GLEW_OK != err) 
	{
		fprintf(stderr, "GLEW Error: %s
", glewGetErrorString(err));
		return 1;
	}
	SetupRC();

	glutMainLoop();
	//delete VBO
	glDeleteBuffers(1,&vdataBufferID);
	glDeleteBuffers(1,&viBufferID);
	return 0;
}

Suggestions? Thanks for any help.

You upload vertex data every time you draw, because your draw function contains:


glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(vertexType),BUFFER_OFFSET(0));

Unless the data changes you only want to do the upload once and then only bind the buffer and draw from it.

You upload vertex data every time you draw, because your draw function contains:

glVertexAttribPointer does no data uploading.

Oops, sorry, got confused :frowning:

I’d really like to make up for that mistake by spotting the real issue, but I can’t seem to see any problem with the code, sorry.

Thanks for looking at the code. It might just be the video card driver or the shader. Sorry to use up your time. I’m going to push ahead with lighting the cube and applying textures.