GLFW+VBO+Shader = black screen?

I’ve created a window with GLFW and can successfully draw some primitive things on it (glBegin/glVertex/glEnd).

Now I took a working tutorial on VBO with vertex and fragment shader and simply copied the relevant code into my GLFW framework. But nothing shows up. The shader files are loaded correctly, no error messages. Just a black window. I’m trying to fix this problem for 3 days.

Here’s the code:


#include "StdAfx.h"
#include "Renderer.h"
#include <GL/GLU.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <math.h>


GLuint vertBuffer, colorBuffer;
GLhandleARB shaderProgram;

PFNGLGENBUFFERSARBPROC		glGenBuffersARB;
PFNGLBINDBUFFERARBPROC		glBindBufferARB;
PFNGLBUFFERDATAARBPROC		glBufferDataARB;
PFNGLDELETEBUFFERSARBPROC	glDeleteBuffersARB;

PFNGLCREATEPROGRAMOBJECTARBPROC		glCreateProgramObjectARB;
PFNGLDELETEOBJECTARBPROC			glDeleteObjectARB;
PFNGLUSEPROGRAMOBJECTARBPROC		glUseProgramObjectARB;
PFNGLCREATESHADEROBJECTARBPROC		glCreateShaderObjectARB;
PFNGLSHADERSOURCEARBPROC			glShaderSourceARB;
PFNGLCOMPILESHADERARBPROC			glCompileShaderARB;
PFNGLGETOBJECTPARAMETERIVARBPROC	glGetObjectParameterivARB;
PFNGLATTACHOBJECTARBPROC			glAttachObjectARB;
PFNGLGETINFOLOGARBPROC				glGetInfoLogARB;
PFNGLLINKPROGRAMARBPROC				glLinkProgramARB;


Renderer::Renderer(void)
{	
}

Renderer::~Renderer(void)
{
}

void Renderer::init(void) 
{
	vertBuffer = NULL;
	colorBuffer = NULL;
	shaderProgram = NULL;

	if(glfwExtensionSupported("GL_ARB_vertex_buffer_object")==GL_FALSE)
		throw std::exception("Vertex Buffer Objects not supported by the current driver");

	// Retrieve the function pointers for each of the extension functions we will be using
	glGenBuffersARB		= (PFNGLGENBUFFERSARBPROC) glfwGetProcAddress("glGenBuffersARB");			
	glBindBufferARB		= (PFNGLBINDBUFFERARBPROC) glfwGetProcAddress("glBindBufferARB");
	glBufferDataARB		= (PFNGLBUFFERDATAARBPROC) glfwGetProcAddress("glBufferDataARB");
	glDeleteBuffersARB	= (PFNGLDELETEBUFFERSARBPROC) glfwGetProcAddress("glDeleteBuffersARB");

	if(glfwExtensionSupported("GL_ARB_shading_language_100")==GL_FALSE)
		throw std::exception("GLSL Shaders not supported by the current driver");

	glCreateProgramObjectARB  = (PFNGLCREATEPROGRAMOBJECTARBPROC)glfwGetProcAddress("glCreateProgramObjectARB");
	glDeleteObjectARB         = (PFNGLDELETEOBJECTARBPROC)glfwGetProcAddress("glDeleteObjectARB");
	glUseProgramObjectARB     = (PFNGLUSEPROGRAMOBJECTARBPROC)glfwGetProcAddress("glUseProgramObjectARB");
	glCreateShaderObjectARB   = (PFNGLCREATESHADEROBJECTARBPROC)glfwGetProcAddress("glCreateShaderObjectARB");
	glShaderSourceARB         = (PFNGLSHADERSOURCEARBPROC)glfwGetProcAddress("glShaderSourceARB");
	glCompileShaderARB        = (PFNGLCOMPILESHADERARBPROC)glfwGetProcAddress("glCompileShaderARB");
	glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glfwGetProcAddress("glGetObjectParameterivARB");
	glAttachObjectARB         = (PFNGLATTACHOBJECTARBPROC)glfwGetProcAddress("glAttachObjectARB");
	glGetInfoLogARB           = (PFNGLGETINFOLOGARBPROC)glfwGetProcAddress("glGetInfoLogARB");
	glLinkProgramARB          = (PFNGLLINKPROGRAMARBPROC)glfwGetProcAddress("glLinkProgramARB");

	// Define the positions for each of the three points of the triangle
	float verts[] = {
						//X      Y     Z
						0.0f,  1.0f, 0.0f,		// Top Middle
						1.0f, -1.0f, 0.0f,		// Bottom Left
						1.0f, -1.0f, 0.0f		// Bottom Right
					};
		
	// Define the colors for each of the three points of the triangle
	float colors[] = {
						//R     G	 B
						1.0f, 0.0f, 0.0f,		// Top Middle - Red
						0.0f, 1.0f, 0.0f,		// Bottom Left - Green
						0.0f, 0.0f, 1.0f		// Bottom Right - Blue
					};
			
	glGenBuffersARB(1, &vertBuffer);
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertBuffer);									// Set the newly created buffer as the current one
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, GL_STATIC_DRAW_ARB);	// Send the vetex position data to the current buffer
	
	glGenBuffersARB(1, &colorBuffer);													// Create a handle for the vertex color buffer
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);								// Set the newly created buffer as the current one
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colors), colors, GL_STATIC_DRAW_ARB);	// Send the vertex color data to the current buffer

	//glEnable(GL_VERTEX_PROGRAM_ARB);
	//glEnable(GL_FRAGMENT_PROGRAM_ARB);
	GLhandleARB vertShader, fragShader;
	ShaderFromFile("Vertex.glsl", GL_VERTEX_SHADER_ARB, vertShader);		// Load "Vertex.glsl" as our Vertex Shader
	ShaderFromFile("Fragment.glsl", GL_FRAGMENT_SHADER_ARB, fragShader);    // Load "Fragment.glsl" as our Fragment Shader
	LinkShaders(vertShader, fragShader, shaderProgram);					// Link the vertex and fragment shaders into the shader program
	
	// Now that the shader program has been linked, we no longer need these two intermediate objects and should delete them
	glDeleteObjectARB(vertShader);
	glDeleteObjectARB(fragShader);

	// init openGL settings
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	// Clear the Screen to Black
	glClearDepth(1.0f);						// Clear the Depth Buffer completely
	glDepthFunc(GL_LEQUAL);					// The method used to determine if one pixel is behind another
	glEnable(GL_DEPTH_TEST);				// Enable Z-Buffering (Depth Testing)
	glShadeModel(GL_SMOOTH);				// When shading, interpolate values between vertices
}

void Renderer::resize(int width, int height)
{
	if(height==0) height = 1;			// Must have a height of at least 1 to prevent divide by 0 errors
		
	glViewport (0, 0, width, height);	// Tell OpenGL the size of our window 	
	glMatrixMode(GL_PROJECTION);		// Notify OpenGL that we are modifying the Projection Matrix																
	glLoadIdentity();					// Set the Projection matrix to the Identiy matrix	
	gluPerspective(45.0f, width/height , 0.1f, 255.0f);	//Set Perspective projection
	glMatrixMode(GL_MODELVIEW);			// Switch the matrix back to ModelView mode 																	
	glLoadIdentity();					// Set the ModelView matrix to the Identity matrix
}

void Renderer::renderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glLoadIdentity();										// Set the ModelView matrix to the Identity matrix to remove any rotation/translation that's already occured											
	glTranslatef(0.0f, 0.0f, -2.0f);						// Move the "camera" back two units, so we can see the triangle

	// Shader Program
	glUseProgramObjectARB(shaderProgram);					// Set the shader program to use for this draw call

	// Vertex Buffer
	glEnableClientState(GL_VERTEX_ARRAY);					// Tell OpenGL that our rendered geometry will contain position information
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertBuffer);		// Set the vertex position buffer as the current buffer 
	glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);			// Set the current buffer as the source of position information
	
	// Color Buffer
	glEnableClientState(GL_COLOR_ARRAY);					// Tell OpenGL that our rendered geometry will contain color information
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);		// Set the vertex color buffer as the current buffer 
	glColorPointer(3, GL_FLOAT, 0, (char*)NULL);			// Set the current buffer as the source of color information
	
	// Draw
	glDrawArrays(GL_TRIANGLES, 0, 3);						// Render three points with the current sources

	glDisableClientState(GL_VERTEX_ARRAY);					// Tell OpenGL that we are done using position data
	glDisableClientState(GL_COLOR_ARRAY);					// Tell OpenGL that we are done using color data

	// Draw "old" stuff
	glTranslatef(0.0f, 0.0f, -4.0f);

	glBegin(GL_QUADS);
		glColor4f(0.0f,0.0f,1.0f,1.0f);
		glVertex3f(-1.0f,-1.0f,-1.0f);
		glVertex3f(1.0f,-1.0f,-1.0f);
		glColor4f(0.0f,1.0f,1.0f,1.0f);
		glVertex3f(1.0f,1.0f,-1.0f);
		glVertex3f(-1.0f,1.0f,-1.0f);
	glEnd();
	
	glFlush();	
}

void Renderer::terminate(void)
{
	if(glDeleteBuffersARB != NULL)
	{ 
		// A note about these two calls: If the buffers were not created properly in the first place
		// OpenGL will silently ignore these calls, so they are safe to make without further error checking
		glDeleteBuffersARB(1, &vertBuffer);		// Delete the vertex position buffer and free it's data from video memory
		glDeleteBuffersARB(1, &colorBuffer);		// Delete the vertex color buffer and free it's data from video memory
	}
		
	// Do the same for shader resources
	if(glDeleteObjectARB != NULL)
		glDeleteObjectARB(shaderProgram);			// Delete the shader program and free it's data from video memory
}

void Renderer::ShaderFromFile(const char* shaderPath, GLenum shaderType, GLhandleARB& handle)
{
	char* shaderSrc = NULL;
	int len = 0;
	int errorFlag = -1;

	if(!FileToString(shaderPath, shaderSrc, len))
	{
		std::string err = "Could not read shader:

" + std::string(shaderPath);
		std::cout << err << std::endl;
		return;
	}
			
	handle = glCreateShaderObjectARB(shaderType);

	glShaderSourceARB(handle, 1, (const char**)&shaderSrc, &len);
	glCompileShaderARB(handle); 
	delete[] shaderSrc;

	glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &errorFlag);
	
	if(!errorFlag)
	{
		std::string err = "Shader Compile Error:

" + std::string(shaderPath) + "

" + GetShaderInfoLog(handle);
		std::cout << err << std::endl;
		return;
	}
}

// Helper function used to create (link) a shader program from a vertex and fragment shader object
void Renderer::LinkShaders(GLhandleARB& vertex, GLhandleARB& fragment, GLhandleARB& handle)
{
	int errorFlag = -1;
	
	handle = glCreateProgramObjectARB();
	glAttachObjectARB(handle, vertex);
	glAttachObjectARB(handle, fragment);
	glLinkProgramARB(handle);

	glGetObjectParameterivARB(handle, GL_OBJECT_LINK_STATUS_ARB, &errorFlag);
	if(!errorFlag)
	{
		std::string err = "Shader Program Link Error:

" + GetShaderInfoLog(handle);
		std::cout << err << std::endl;
		return;
	}
}

// Helper function used to get log info (such as errors) about a shader object or shader program
std::string Renderer::GetShaderInfoLog(GLhandleARB& obj)
{
	int logLength = 0;
	int charsWritten  = 0;
	char *tmpLog;
	std::string log;
		
	glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
		
	if (logLength > 0)
	{
		tmpLog = new char[logLength];
		glGetInfoLogARB(obj, logLength, &charsWritten, tmpLog);
		log = tmpLog;
		delete[] tmpLog;
	}

	return log;
}

// Helper function used to read the contents of a file into a char array
bool Renderer::FileToString(const char* path, char*& out, int& len)
{
	std::ifstream file(path, std::ios::ate | std::ios::binary);
	
	if(!file.is_open()) return false;

	len = file.tellg();
	out = new char[ len+1 ];
	file.seekg (0, std::ios::beg);
	file.read(out, len);
	//std::cout << "Shader Code: 
 " << out << std::endl;
	file.close();
	out[len] = 0;

	return true;
}

And the main class:

#include "stdafx.h"
#include "Renderer.h"

Renderer renderer;

///ENTRY:mainCRTStartup 

void GLFWCALL windowResize(int width, int height)
{
	renderer.resize(width, height);
}

int _tmain(int argc, _TCHAR* argv[])
{
	int running = GL_TRUE;

	// Initialize GLFW
	glfwInit();	
	glfwOpenWindowHint(GLFW_AUX_BUFFERS, 6);
	
	// Open an OpenGL window
	if(!glfwOpenWindow( 740,500, 8,8,8,8,24,8, GLFW_WINDOW))
	{
		glfwTerminate();
		return 0;
	}

	renderer.init();
	glfwSetWindowTitle("RAVE prototype");
	glfwSetWindowSizeCallback(windowResize);

	

	while(running)
	{
		renderer.renderScene();
		glfwSwapBuffers();

		// Check if ESC key was pressed or window was closed
		running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
	}

	// Close window and terminate GLFW
	renderer.terminate();
	glfwTerminate();

	// Exit program
	return 0;
}

First bug, width and height are int, probably you are getting one as result of the division.

gluPerspective(45.0f, width/height , 0.1f, 255.0f);

Second bug

float verts[] = {
  0.0f,  1.0f, 0.0f,
  1.0f, -1.0f, 0.0f,
  1.0f, -1.0f, 0.0f
};

Two point are the same, openGL don’t draw zero area triangles.

Can you see the quad? Maybe is a shader error.