Brian Yeh
Brian Yeh

Reputation: 3267

glCreateShader throwing exception on OSX, why?

I have some code where i'm directly following a tutorial to generate a triangle. The author is writing his code in windows but he says this can be done in OSX as well. I was able to get the program to compile but it's throwing an exception when it hits glCreateShader. I've looked everywhere but I can't figure out what's wrong. It must be some newbie mistake. Does anyone know what could be wrong?

#include <iostream>
#include <string>
#include <Dunjun/Common.hpp>
#include <GL/glew.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl.h>
#include <GLFW/glfw3.h>

#define GLOBAL static
#define internal static
#define LOCAL_PERSIST static

#define float32 float
#define float64 double

GLOBAL const int g_windowWidth = 854;
GLOBAL const int g_windowHeight = 480;
GLOBAL const char* g_gameTitle = "Dunjun";

GLFWwindow *toggleFullScreenWindow(GLFWwindow *window, int key);

void setColor(float32 red, float32 blue, float32 green, float32 alpha);

bool toggleExit(GLFWwindow *window, bool isRunning);

GLFWwindow* initialize_window(int width, int height, const char* title);

void init_glfw();

void init_glew();

void glfwHints();

int main(int argc, char **argv) {

    GLFWwindow *window = initialize_window(g_windowWidth, g_windowHeight, g_gameTitle);

    float vertices[] = {
            +0.0f, -0.5f, //vertex 1
            -0.5f, -0.5f, //vertex 2
            +0.5f, -0.5f  //vertex 3
    };

    const char* vertexShaderText = {
            "version 120\n"
            "\n"
            "attribute vec2 position"
            "void main()"
            "{"
            "    gl_position = vec4(position, 0.0, 1.0);"
            "}"
    };

    const char* framentShaderText = {
        "version 120\n"
        "\n"
        "void main()"
        "{"
        "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
        "}"
    };

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderText, nullptr);
    glCompileShader(vertexShader);

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &vertexShaderText, nullptr);
    glCompileShader(vertexShader);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    glBindAttribLocation(shaderProgram, 0, "position");

    glLinkProgram(shaderProgram);

    glUseProgram(shaderProgram);




    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    /*
     * GL_STATIC_DRAW      Things that are static
     * GL_DYNAMIC_DRAW     Things that are changed but not to often
     * GL_STREAM_DRAW      THings that change all the time.
     */

    bool running = true;
    /* Loop until the user closes the window */
    while (running) {

        /* Render here */
        setColor(0.5f, 0.69f, 1.0f, 1.0f);

        //draw things
        {
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
            glDrawArrays(GL_TRIANGLES, 0, 3);
            glDisableVertexAttribArray(0);
        }

        /*Swap front and back buffers */
        glfwSwapBuffers(window);

        /*poll for and process events*/
        glfwPollEvents();

        running = toggleExit(window, running);

        window = toggleFullScreenWindow(window, GLFW_KEY_F11);
    }

    glfwTerminate();
    return EXIT_SUCCESS;
}




void glfwHints(){
    glfwWindowHint(GLFW_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_VERSION_MINOR, 1);
}


void setColor(float32 red, float32 blue, float32 green, float32 alpha){
    glClearColor(red, green, blue, alpha);
    glClear(GL_COLOR_BUFFER_BIT);
}

bool toggleExit(GLFWwindow *window, bool isRunning) {
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) ||
        glfwWindowShouldClose(window)) {
        isRunning = false;
    }

    return isRunning;
}

GLFWwindow* initialize_window(int width, int height, const char* title){

    init_glfw();

    /* Create a windowed mode window and its OpenGL context */
    glfwHints();
    GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window);
    init_glew();
    return window;
}

GLFWwindow *toggleFullScreenWindow(GLFWwindow *window, int key) {
    if (glfwGetKey(window, key)) {
        LOCAL_PERSIST bool isFullScreen = false;
        isFullScreen = !isFullScreen;

        GLFWwindow *newWindow;
        if (isFullScreen) {
            int count;
            const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
            int monitorHeight = modes[count - 1].height;
            int monitorWidth = modes[count - 1].width;
            newWindow = glfwCreateWindow(monitorWidth, monitorHeight, g_gameTitle, glfwGetPrimaryMonitor(), window);
        } else {
            newWindow = glfwCreateWindow(g_windowWidth, g_windowHeight, g_gameTitle, nullptr, window);
        }
        glfwDestroyWindow(window);
        glfwMakeContextCurrent(newWindow);
        return newWindow;


    }
}

void init_glew(){
    if(!glewInit()){
        std :: cout << "glew failed to init!";
        exit(EXIT_FAILURE);
    }
}

void init_glfw(){
    if (!glfwInit()) {
        std :: cout << "glfw failed to init!";
        exit(EXIT_FAILURE);
    }
}

UPDATE: I've edited the code to include the suggested changes but glewInit() returns with a falsey value. What could still be wrong.

Upvotes: 1

Views: 997

Answers (2)

Reto Koradi
Reto Koradi

Reputation: 54602

You have to decide if you want to use GLEW or not, and then stick to it consistently. It's not needed for Mac OS, and I would recommend avoiding it. But some people still like using it, so it's your choice.

What you have right now is this:

#include <GL/glew.h>
#ifndef __APPLE__
    #include <OpenGL/glext.h>
    #include <OpenGL/gl.h>
#endif
...
#ifndef __APPLE__
    if(!glewInit()){
        exit(EXIT_FAILURE);
    }
#endif

You're including the GLEW header, but not initializing GLEW. The GLEW header will contain declarations for OpenGL entry points, but they are function pointers, which will be null until GLEW is initialized. So if you're calling glCreateShader() afterwards, it will be a null function pointer.

To correct this, you need to include the native OpenGL header, which contains declarations of the actual OpenGL entry points, and not just function pointers:

#ifdef __APPLE__
    #include <OpenGL/gl.h>
#else
    #include <GL/glew.h>
#endif

Upvotes: 5

Alex
Alex

Reputation: 3181

glfwMakeContextCurrent(window); has to be called before initializing GLEW. If you swap the order of glewInit() and initialize_window() in your main() then everything should work

Upvotes: 1

Related Questions