PDA

View Full Version : OpenGL 3.1 glLinkProgram not working properly



fiodis
09-11-2012, 10:57 AM
Following this (http://openglbook.com/the-book/chapter-2-vertices-and-shapes/) tutorial, and making small adjustments for compatibility with OpenGL 3.1, I've managed to set up a window with freeGLUT and initialize GLEW, but I cannot draw any shapes. For some reason glUseProgram always returns GL_INVALID_OPERATION, which according to this tutorial (http://people.freedesktop.org/~idr/OpenGL_tutorials/02-GLSL-hello-world#id2966213) means the program is not linked correctly. My source code is almost exactly that which works in the first tutorial, though:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gl\glew.h>
#include <GL\freeglut.h>
#define WINDOW_TITLE_PREFIX "OpenGL Context"

int numberInput;
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
unsigned FrameCount = 0;
GLuint
VertexShaderId,
FragmentShaderId,
ProgramId,
VaoId,
VboId,
ColorBufferId;
const GLchar* VertexShader =
{
"#version 130\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"
};
const GLchar* FragmentShader =
{
"#version 130\n"\

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

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


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();

//numberInput = getchar();

exit(EXIT_SUCCESS);
}

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

InitWindow(argc, argv);

glewExperimental = GL_TRUE;
GlewInitResult = glewInit();

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

void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);

glutInitContextVersion(3, 1);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);

glutInitWindowSize(CurrentWidth, CurrentHeight);

glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);

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

glutReshapeFunc(ResizeFunction);
glutDisplayFunc(RenderFunction);
glutIdleFunc(IdleFunction);
glutTimerFunc(0, TimerFunction, 0);
glutCloseFunc(Cleanup);
}

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

void RenderFunction(void) // Render the scene here
{
++FrameCount;

//CreateShaders();
//CreateVBO();

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glDrawArrays(GL_TRIANGLES, 0, 3);

glutSwapBuffers();
glutPostRedisplay();
}

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,
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(1, 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); // This is the problem, but why?

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

numberInput = getchar();

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

If I comment out glUseProgram, I get the triangle displayed properly, but it's all white. I don't understand how the shader program could be failing to link; it's just a few lines. Can anyone see anything off with my code?

Alfonse Reinheart
09-11-2012, 11:43 AM
This:


layout(location=0)

is not legal GLSL 1.30 syntax. You'll have to make more than a few changes to get around this. You have to use glBindAttribLocation (http://www.opengl.org/wiki/GLAPI/glBindAttribLocation) on the program before linking to assign the vertex attributes to attribute indices.

fiodis
09-11-2012, 12:38 PM
Is 1.30 the highest version compatible with OGL 3.1? Or does a higher version of GLSL, that supports the (location=#) syntax, work with OGL 3.1?

EDIT - Got it to work with glBindAttribLocation; thanks Alfonse! :) The newer GLSL syntax would've been nice, but that's what I get for having an Intel GPU.