Search code examples
cvisual-studio-2010openglglslpdb-files

Cannot create shaders OpenGL 4.x


I am using this tutorial. I have the correct hardware to run this (AMD 6870). I have followed the tutorial but I only get a flashing of the window before it exits. When I build the code, it builds fine, but lists a load of DLLs that cannot find a PDB. I stepped through my code (Im using Visual Studio 2010 prof) and it exited on my CreateShaders function with the error that they could not be created. I've checked the tutorial on that function and I have it copied.

Here is the code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define WINDOW_TITLE_PREFIX "Chapter Two - A Triangle"

    //Global variable dclerations
 int CurrentWidth  = 800;
int CurrentHeight = 600;
int WindowHandle  = 0;

unsigned FrameCount = 0;

GLuint 
vertexShaderId,
fragmentShaderId,
programId,
vaoId,
vboId,
colorBufferId;


//contents of GLSL vertexshader
const GLchar* vertexShader =
{
"version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\

"void main(void)\n"\
"{\n"\
"   gl_Position = in_Position;\n"\
"   ex_Color = in_Color;\n"\
"}\n"

};

 //contents of fragment shader

 const GLchar* fragmentShader =
{
"#version 400\n"\

"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\

"void main(void)\n"\
"{\n"\
"   out_Color = ex_Color;\n"\
"}\n"
 };

//prototypes
 void Initialize(int,char*[]);
void InitWindow(int, char*[]);
void ResizeFunction(int, int);
void RenderFunction(void);
void TimerFunction(int);
void IdleFunction(void);
void CleanUp(void);
void CreateVBO(void);
void DestroyVBO(void);
void CreateShaders(void);
void DestroyShaders(void);


int main(int argc, char* argv[])
{
Initialize(argc, argv);

glutMainLoop();

exit(EXIT_SUCCESS);
}


void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;

InitWindow(argc, argv);

//glew is initialised after the openGL context is created,
//it needs an active context to implement calls
GlewInitResult = glewInit();

//if glew did not init correctly, print errors
if(GLEW_OK != GlewInitResult)
{
    fprintf(
        stderr,
        "ERROR: %s\n",
        glewGetErrorString(GlewInitResult)
        );
    exit(EXIT_FAILURE);
}

fprintf(
    stdout,
    "INFO: OpenGL Version: %s\n",
    glGetString(GL_VERSION));

CreateShaders();
CreateVBO();
glClearColor(0.0f, 0.0f, 0.0f,0.0f);

}

//uses freeglut to create a window
void InitWindow(int argc, char* argv[]) 
{
//initialises freeglut library
glutInit(&argc, argv);

//creates a forward compatible OpenGL 4.0 core profile
glutInitContextVersion(4,0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);

//when window closes, return to main loop
glutSetOption(
    GLUT_ACTION_ON_WINDOW_CLOSE,
    GLUT_ACTION_GLUTMAINLOOP_RETURNS
    );

glutInitWindowSize(CurrentWidth,CurrentHeight);

// enables depth buffer, double buffering, makes RGBA mode
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

//makes window, passes it the value of defined window
WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);

if(WindowHandle < 1)
{
    fprintf(
        stderr,
        "ERROR: Could not create a new rendering window.\n"
        );
    exit(EXIT_FAILURE);
}

//called when window is resized
glutReshapeFunc(ResizeFunction);
//called when scene is to be drawn on screen
glutDisplayFunc(RenderFunction);
glutIdleFunc(IdleFunction);
//(ms passed before func is called, func to call, value to pass)
glutTimerFunc(0,TimerFunction,0);
glutCloseFunc(CleanUp);
}

void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0,0,CurrentWidth,CurrentHeight);
}

 void RenderFunction(void)
{
FrameCount++;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,3);
glutSwapBuffers();
glutPostRedisplay();
}

 //redraws as soon as possible
void IdleFunction(void)
{
glutPostRedisplay();
}

void TimerFunction(int Value)
{
if(0 != Value)
{
    char* TempString = (char*)
        malloc(512 + strlen(WINDOW_TITLE_PREFIX));

    sprintf(
        TempString,
        "%s: %d Frames Per Second @ %d x %d",
        WINDOW_TITLE_PREFIX,
        //update every quarter of a second
        FrameCount * 4,
        CurrentWidth,
        CurrentHeight
        );

    glutSetWindowTitle(TempString);
    free(TempString);
}

FrameCount = 0;
glutTimerFunc(250, TimerFunction,1);
}


void CleanUp (void)
{
DestroyShaders();
DestroyVBO();
}

void CreateVBO(void)
{
GLfloat vertices[] = {
    -0.8f, -0.8f, 0.0f, 1.0f,
    0.0f,   0.8f, 0.0f, 1.0f,
    0.8f,   -0.8f, 0.0f, 1.0f
};

GLfloat colors[] = {
    1.0f, 0.0f, 0.0f, 1.0f,
    0.0f, 1.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f
};

GLenum ErrorCheckValue = glGetError();

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

glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);

glGenBuffers(1, &colorBufferId);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(1);

ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not create a VBO: %s \n",
        gluErrorString(ErrorCheckValue)
        );

    exit(-1);
}


 }

 void DestroyVBO(void)
 {
GLenum ErrorCheckValue = glGetError();

glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER,0);

glDeleteBuffers(1, &colorBufferId);
glDeleteBuffers(1, &vboId);

glBindVertexArray(0);
glDeleteVertexArrays(1, &vaoId);

ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not Destroy the VBO: %s \n",
        gluErrorString(ErrorCheckValue)
        );
    exit(-1);
}
}

void CreateShaders(void)
{
GLenum ErrorCheckValue = glGetError();

vertexShaderId =glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderId, 1, &vertexShader, NULL);
glCompileShader(vertexShaderId);

fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
glCompileShader(fragmentShaderId);

programId = glCreateProgram();
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId,fragmentShaderId);
glLinkProgram(programId);
glUseProgram(programId);

ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not create the shaders: %s \n",
        gluErrorString(ErrorCheckValue)
        );

    exit(-1);
}
 }

 void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();

glUseProgram(0);

glDetachShader(programId,vertexShaderId);
glDetachShader(programId,fragmentShaderId);


glDeleteShader(fragmentShaderId);
glDeleteShader(vertexShaderId);

glDeleteProgram(programId);


ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "Error: Could not destroy the shaders %s\n",
        gluErrorString(ErrorCheckValue)
        );
    exit(-1);
}

}

Solution

  • The DLL/PDB thing is normal, I don't think it has any effect on your code (I believe it involves loading debug information from DLLs, which is not required).

    Shaders have their own error reporting mechanism that is outside of glGetError, you should add it to your code.

    After compiling each individual shader, you want to call:

    glGetShaderiv with option GL_COMPILE_STATUS (this returns true/false if compile was successful).

    If compile failed, you can get the error message with glGetShaderInfoLog.

    Then after linking the program, you want to call glGetProgramiv to get GL_LINK_STATUS, and again get the error message with glGetProgramInfoLog.