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;
}