Reputation: 13
I have recently started learning OpenGL, using GLEW, SDL, and C++ together in Code Blocks. I have looked at multiple sources on how to setup GLEW, they are all very similar. I followed them to my understanding of all and I need to get OpenGL working.
I copied the exact code from this tutorial, then fiddled with it trying to get it work after finding out that it didn't. The only things I added where:
#define GLEW_STATIC
glewInit(); // This returns true
glewExperimental = GL_TRUE;
Whenever I compile the program, I get no errors. But whenever I run the program, a windows error message saying "GLEW_Program has stopped working"
. That happens if I link the static library. I just get a bunch of undefined references if I link it dynamically.
These are my linker options:
-lglew32s -lopengl32
-lglu32 -lfreeglut
-lmingw32 -lSDL2main -lSDL2
I put the DLL's in the executable folder, and I've tried 32 bit and 64 bit. I'm using Windows 10. I've also tried the exact procedure on another computer, which is Windows 7 and I got the exact same problem, so I have definitely done something wrong.
I've tried commenting out some snippets of code, and when I don't use the mesh class, it runs fine, but with out the graphics of course. It seems to be handling the buffers that doesn't do any good.
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
I am aware of other posts made about this problem, but the answers did not apply to mine.
I've worn myself out on figuring out how to fix the problem, so I'm now asking for help. I kind of hope it's an obvious mistake by me. This is my first post, so feel free to ask for any clarifications.
// main.cpp
#include "display.h"
#include "mesh.h"
int main(int argc, char** argv)
{
Display display(800, 600, "OpenGL Window");
Vertex vertices[] =
{
Vertex(glm::vec3(-0.5, -0.5, 0)),
Vertex(glm::vec3(0, 0.5, 0)),
Vertex(glm::vec3(0.5, -0.5, 0)),
};
Mesh mesh(vertices, sizeof(vertices)/sizeof(vertices[0]));
while(!display.IsClosed())
{
display.Clear(.2f,.8f,1.f,1.f); //r g b a
// mesh.Draw();
display.Update();
}
return 0;
}
// display.h
#ifndef DISPLAY_H
#define DISPLAY_H
#define GLEW_STATIC
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <iostream>
#include <string>
class Display
{
public:
Display(int width, int height, const std::string& title);
void Clear(float r, float g, float b, float a);
void Update();
bool IsClosed();
virtual ~Display();
protected:
private:
Display(const Display& other) {}
void operator=(const Display& other) {}
SDL_Window* m_window;
SDL_GLContext m_glContext;
bool m_isClosed;
};
#endif // DISPLAY_H
// display.cpp
#include "display.h"
Display::Display(int width, int height, const std::string& title)
{
SDL_Init(SDL_INIT_EVERYTHING);
glewInit();
glewExperimental = GL_TRUE;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_glContext = SDL_GL_CreateContext(m_window);
}
Display::~Display()
{
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
void Display::Clear(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
bool Display::IsClosed()
{
return m_isClosed;
}
void Display::Update()
{
SDL_GL_SwapWindow(m_window);
SDL_Event e;
while(SDL_PollEvent(&e))
{
if(e.type == SDL_QUIT) m_isClosed = true;
}
}
// mesh.h
#ifndef MESH_H
#define MESH_H
#define GLEW_STATIC
#include <glm/glm/glm.hpp>
#include <iostream>
#include <GL/glew.h>
class Vertex
{
public:
Vertex(const glm::vec3& pos)
{
this->pos = pos;
}
protected:
private:
glm::vec3 pos;
};
class Mesh
{
public:
Mesh(Vertex* vertices, unsigned int numVertices);
void Draw();
virtual ~Mesh();
protected:
private:
Mesh(const Mesh& other);
void operator=(const Mesh& other);
enum
{
POSITION_VB,
NUM_BUFFERS
};
GLuint m_vertexArrayObject;
GLuint m_vertexArrayBuffers[NUM_BUFFERS];
unsigned int m_drawCount;
};
#endif // MESH_H
// mesh.cpp
#include "mesh.h"
Mesh::Mesh(Vertex* vertices, unsigned int numVertices)
{
m_drawCount = numVertices;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glBindVertexArray(0);
}
Upvotes: 1
Views: 665
Reputation: 213228
The code initialized GLEW incorrectly.
glewInit(); // Wrong
...
m_window = SDL_CreateWindow(...);
m_glContext = SDL_GL_CreateContext(...);
Here, glewInit()
is called without an OpenGL context. You must initialize the OpenGL context first, before initializing GLEW. In other words, you must do this:
m_window = SDL_CreateWindow(...);
m_glContext = SDL_GL_CreateContext(...);
...
glewInit(); // Correct
The reason you must do it this way is because the OpenGL function entry points are simply not available until you actually have an OpenGL context. In other words, only a few entry points are located in opengl32.dll
/ libgl.so
, and most entry points are in a device-specific OpenGL library which is loaded when you first create a context. Once the context has been created, wglGetProcAddress()
/etc will work, which is what GLEW uses to load function pointers at initialization.
Also note that there are better GL loading libraries out there. In its current state, GLEW is almost completely useless on OS X, for example.
Upvotes: 4