调用OpenGL函数时程序崩溃



我正在尝试设置一个游戏引擎项目。我的visual studio项目是这样设置的,所以我有一个"引擎"项目与我的"游戏"项目分开。然后将引擎项目编译为游戏项目使用的dll。我已经下载并设置了glfw和glow来开始使用openGL。我的问题是,每当我击中第一个openGL函数时,程序就会崩溃。我知道这与glewinit有关,即使glewinit初始化成功(没有控制台错误)。在我的引擎项目中,我有一个窗口类,在窗口构建时,应该设置glow:

Window.h

#pragma once
#include "GLglew.h"
#include "GLFWglfw3.h"
#if (_DEBUG)
#define LOG(x) printf(x)
#else
#define LOG(x)
#endif
namespace BlazeGraphics
{
    class __declspec(dllexport) Window
    {
    public:
        Window(short width, short height, const char* title);
        ~Window();
        void Update();
        void Clear() const;
        bool Closed() const; 
    private:
        int m_height;
        int m_width;
        const char* m_title;
        GLFWwindow* m_window;
    private:
        Window(const Window& copy) {}
        void operator=(const Window& copy) {}
    };
}

windows .cpp(其中glewinit()被调用)

#include "Window.h"
#include <cstdio>
namespace BlazeGraphics
{
    //Needed to define outside of the window class (not sure exactly why yet)
    void WindowResize(GLFWwindow* window, int width, int height);
    Window::Window(short width, short height, const char* title) :
        m_width(width),
        m_height(height),
        m_title(title)
    {
        //InitializeWindow
        {
            if (!glfwInit())
            {
                LOG("Failed to initialize glfw!");
                return;
            };
            m_window = glfwCreateWindow(m_width, m_height, m_title, NULL, NULL);
            if (!m_window)
            {
                LOG("Failed to initialize glfw window!");
                glfwTerminate();
                return;
            };
            glfwMakeContextCurrent(m_window);
            glfwSetWindowSizeCallback(m_window, WindowResize);
        }
        //IntializeGl
        {
            //This needs to be after two functions above (makecontextcurrent and setwindowresizecallback) or else glew will not initialize
            **if (glewInit() != GLEW_OK)
            {
                LOG("Failed to initialize glew!");
            }**
        }
    }

    Window::~Window()
    {
        glfwTerminate();
    }
    void Window::Update()
    {
        glfwPollEvents();
        glfwSwapBuffers(m_window);
    }
    void Window::Clear() const
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    //Returns a bool because glfwwindowShouldClose returns a nonzero number or zero
    bool Window::Closed() const
    {
        //Made it equal to 1 to take away warning involving converting an int to bool
        return glfwWindowShouldClose(m_window) == 1;
    }
    //Not part of window class so defined above
    void WindowResize(GLFWwindow* window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }
}

这是我的main.cpp文件,它是在我的游戏项目中找到的,我目前在全局函数中有我的openGL功能(只是现在):

main.cpp

#include <iostream>
#include <array>
#include <fstream>
#include "GLglew.h"
#include "GLFWglfw3.h"
#include "../Engine/Source/Graphics/Window.h"
void initializeGLBuffers()
{
    GLfloat triangle[] =
    {
        +0.0f, +0.1f, -0.0f,
        0.0f, 1.0f, 0.0f,
        -0.1f, -0.1f, 0.0f, //1
        0.0f, 1.0f, 0.0f,
        +0.1f, -0.1f, 0.0f, //2
        0.0f, 1.0f, 0.0f,
    };
    GLuint bufferID;
    glGenBuffers(1, &bufferID);
    glBindBuffer(GL_ARRAY_BUFFER, bufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (sizeof(GLfloat)) * 6, nullptr);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (sizeof(GLfloat)) * 6, (char*)((sizeof(GLfloat)) * 3));
    GLushort indices[] =
    {
        0,1,2
    };
    GLuint indexBufferID;
    glGenBuffers(1, &indexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
};

void installShaders()
{
    //Create Shader
    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    //Add source or text file to shader object
    std::string temp = readShaderCode("VertexShaderCode.glsl");
    const GLchar* adapter[1];
    adapter[0] = temp.c_str();
    glShaderSource(vertexShaderID, 1, adapter, 0);
    temp = readShaderCode("FragmentShaderCode.glsl").c_str();
    adapter[0] = temp.c_str();
    glShaderSource(FragmentShaderID, 1, adapter, 0);
    //Compile Shadaer
    glCompileShader(vertexShaderID);
    glCompileShader(FragmentShaderID);
    if (!checkShaderStatus(vertexShaderID) || !checkShaderStatus(FragmentShaderID))
        return;
    //Create Program
    GLuint programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, FragmentShaderID);
    //Link Program
    glLinkProgram(programID);
    if (!checkProgramStatus(programID))
    {
        std::cout << "Failed to link program";
        return;
    }
    //Use program
    glUseProgram(programID);
}
int main()
{
    BlazeGraphics::Window window(1280, 720, "MyGame");
    initializeGLBuffers();
    installShaders();
    while (!window.Closed())
    {
        window.Clear();
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
        window.Update();
    };
    return 0;
}

现在如果我将glewinit()代码移动到main.cpp:

int main()
{
    BlazeGraphics::Window window(1280, 720, "MyGame");
    if (glewInit() != GLEW_OK)
            {
                LOG("Failed to initialize glew!");
            }
    initializeGLBuffers();
    installShaders();
    while (!window.Closed())
    {
        window.Clear();
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
        window.Update();
    };
    return 0;
}

,那么我的程序编译得很好。为什么尝试在engine.dll中初始化glow会导致程序崩溃?谢谢你的帮助。

GLEW通过为每个OpenGL函数定义一个函数指针作为全局变量来工作。让我们以glBindBuffer为例:

#define GLEW_FUN_EXPORT GLEWAPI
typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer;

所以我们只有一个__glewBindBuffer函数指针,它将通过glewInit从您的OpenGL实现设置为正确的地址。

为了实际能够编写glBindBuffer, GLEW简单地定义了将GL函数映射到那些函数指针变量的预处理宏:

#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer);

为什么尝试在engine.dll内初始化glow会导致程序崩溃?

因为你的engine.dll和你的主应用程序都有一个单独的全局变量集。您必须从引擎DLL中导出所有__glew*变量,以便能够访问engine.dllglewInit调用的结果。

最新更新