Having a lot of trouble getting OpenGL to work

Started by
8 comments, last by Xycaleth 9 years, 2 months ago

In an effort to not lock out OSX/Linux users from things I hope to create, I'm learning OpenGL, using C++ on Windows 8.1. I'm compiling with CL (MSVC++2013 update 3) from the command line, and using VS2013 for debugging. Unfortunately I am having problems even getting to a stage where I can put a few test vertices on screen.

My main problem has been that I keep getting the error "invalid enumerant" when I try to create a vertex shader like so:


auto id = glCreateShader(GL_VERTEX_SHADER);

My initialization code looks like this:


GLFWwindow *window;
if (!glfwInit())
	return 0;

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

window = glfwCreateWindow(width, height, "My App", 0, 0);
if (!window)
{
	glfwTerminate();
	return 0;
}

glfwMakeContextCurrent(window);

glewExperimental = GL_TRUE;
int error = glewInit();

Here's a log dump from my console:


[Graphics] Vendor: NVIDIA Corporation
[Graphics] Renderer: GeForce GTX 670/PCIe/SSE2
[Graphics] Version: 4.1.0 NVIDIA 347.09
[Graphics] GLSL Version: 4.10 NVIDIA via Cg compiler
[Shaders] Compiling shader file: vs-default.glsl
[Shaders] Unable to create shader: invalid enumerant
  • I have the latest driver from NVIDIA
  • My video card supports up to version 4.5, but I have also tried setting 3.2, 3.3, 4.0, 4.1 and 4.4.
  • I'm using GLFW3 and GLEW.
  • I have glewExperimental = GL_TRUE right before glewInit().
  • I have tried setting glewExperimental = GL_FALSE, to no avail

The opengl32.dll in my system32 folder has the following properties:

2015-01-19_2233.png

I found some old thread from 2011 without much in the way of help, but one person said that GLEW wasn't great with core profile stuff, though that's around three years out of date. Nevertheless, I tried using the glbinding project, but I was unable to get it to work with glfw, as glfw defines __gl_h_, which causes glbinding to break on compile, complaining that it's not compatible with __gl_h_, which I find strange given that the glbinding readme file cites glfw as one of the possible opengl libraries that it can be used with.

Anyway, I'm stuck. Roadblocked before I even got a chance to start doing anything with OpenGL. Any help would be appreciated.

Advertisement

Update:

After adding some extra logging code, I've discovered that the error is actually originating here:


glewExperimental = GL_TRUE;
glewInit();
err = glGetError();
if(err != GL_NO_ERROR)
{
    logger("Graphics") << "Unable to initialize glew: " << gluErrorString(err) << endlog;
    return 0;
} 

I still don't understand why it's happening though.

glGetError() gets the last error, this must not be necessary the error state of the last command. In your case the error could be a result of a previously executed OGL command. Best to add the error-checking once before analysing certain code part like this:


// start here, if an error occurres here, something went wrong before
err=glGetError();
if(err!=GL_NO_ERROR) ... 


glCommand1();
..
glCommandN():

// check point, if an error occurres here, glComman1 to glCommandN could be the reason.
err=glGetError();
if(err!=GL_NO_ERROR) ... 

@Ashaman - thanks, I discovered this also in the last few minutes, which has helped me solve the problem... so without further ado...

SOLVED!

Either of these two lines, whether in isolation, or used together, will cause glewInit to fail. I have no idea why.


glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

Instead of using glGetError to check whether GLEW initialization succeeded or failed, you should use the documented and supported way, i.e check the return value from glewInit. This should return GLEW_OK if GLEW initialized successfully.

So, this is basically broken:


glewInit();
err = glGetError();
if(err != GL_NO_ERROR)

And this is the right way:


if (glewInit () != GLEW_OK)

And this is even better again if you want to find out exactly what went wrong:


GLenum err = glewInit();
if (GLEW_OK != err)
{
  /* Problem: glewInit failed, something is seriously wrong. */
  fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  ...
}

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

You should check the return value from glewInit instead of using glGetError. Also, if I remember correctly, there's a bug(?) in glew so that its initialization function uses glGetString or something and it causes a silly error because it's not allowed in the context. You can just ignore that by calling simply glGetError once after glewInit.

Do something like this:


glewExperimental = GL_TRUE;

GLenum error = glewInit();
glGetError(); // ignore the silly error

if(error != GLEW_OK) {
	// glew failed
}

Edit: That GL_INVALID_ENUM thing is mentioned here: https://www.opengl.org/wiki/OpenGL_Loading_Library#GLEW_.28OpenGL_Extension_Wrangler.29

Derp

Thanks for the suggestions guys, but glewInit was not returning any error at all, which is why it took me ages to figure out the problem.

Ok, it really seems like GLEW is doing something weird internally, because there no GL error exists before glewInit() is called, and glewInit() itself doesn't report an error, but after calling it, there's an error.

Here's an excerpt from my code that I used to test this:


log << "Setting window as current context" << endlog;
glfwMakeContextCurrent(window);

// inserted the following to be sure no errors were waiting to be read
auto err = glGetError();
if(err != GL_NO_ERROR)
{
	log << "Unable to make context current: " << gluErrorString(err) << endlog;
	return 0;
}

log << "Initializing GLEW" << endlog;
glewExperimental = GL_TRUE;
int glewError = glewInit();
if(glewError != GLEW_OK)
{
	log << "Failed to initialize glew: " << glewGetErrorString(glewError) << endlog;
	glfwTerminate();
	return 0;
}
err = glGetError();
if(err != GL_NO_ERROR)
{
	log << "Unable to initialize glew: " << gluErrorString(err) << endlog;
	glfwTerminate();
	return 0;
}

Here's the output:


[Graphics] Initializing GLFW
[Graphics] Creating window (1280x768)
[Graphics] Setting window as current context
[Graphics] Initializing GLEW
[Graphics] Unable to initialize glew: invalid enumerant

Quite confused about this, and while I can of course hack around the existence of the error, it bothers me...

It's not unlikely that GLEW encounters OpenGL errors during its initialization which do not influence its own outcome. The obvious way would be to check the return value of glewInit (that call must succeed) and then clear the error state by calling glGetError until GL_NO_ERROR is returned (note that glGetError can always return error codes in a row because each call reports the state of a single error flag, as per the second paragraph of the documentation).

Unless 3rd party libraries document that functionality explicitly you should not assume they will leave the OpenGL state in a specific way.

I believe there's a long-standing bug in GLEW where it uses glGetString(GL_EXTENSIONS) to get a list of all the extensions. This has been deprecated since OpenGL 3.1, and (I believe) is removed from the core context completely. This is what's producing the GL error.

This topic is closed to new replies.

Advertisement