调用OpenGL函数时程序崩溃
我正在尝试设置一个游戏引擎项目。我的视觉工作室项目的设置是为了让我的'引擎'项目与我的'游戏'项目分开。然后将引擎项目编译为一个dll供游戏项目使用。我已经下载并设置了glfw和glew开始使用openGL。我的问题是,当我打我的第一个openGL函数时,程序崩溃。我知道这与glewinit有关,即使glew成功初始化(没有控制台错误)。在我的发动机项目,我有一个窗口类,其中,在窗口建设,GLEW应设置:调用OpenGL函数时程序崩溃
在window.h
#pragma once
#include "GL\glew.h"
#include "GLFW\glfw3.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) {}
};
}
Window.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);
}
}
这是这是我的游戏项目,我现在有我的OpenGL功能在全局函数(只是现在)内发现了我的main.cpp文件:
的main.cpp
#include <iostream>
#include <array>
#include <fstream>
#include "GL\glew.h"
#include "GLFW\glfw3.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;
}
现在,如果我是在我的main.cpp这里移动glewinit()代码:
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中初始化glew导致程序崩溃?谢谢你的帮助。
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
导致程序崩溃GLEW初始化?
因为你的engine.dll
和你的主应用程序每个都有一个单独的所有这些全局变量的集合。您必须从您的引擎DLL中导出所有__glew*
变量,以便能够访问您在engine.dll
中呼叫的glewInit
呼叫的结果。
谢谢你的一些澄清。确保导出游戏项目中使用的所有glew变量的最佳方法是什么?动态链接glew而不是静态链接到引擎中会有诀窍吗? – Jason
@Jason:老实说:你可能不应该那样做,因为函数指针在上下文之间可能会有所不同。从技术上讲,每次切换上下文时都必须调用'glewInit'。正确的解决方案是拥有一个结构或类,它包含所有的函数指针,并通过它完成调用。然后你可以在DLL之间传递一个指向该结构的指针。 - 当然,大多数OpenGL加载程序的设计不允许它轻松地完成此操作。我建议你在每个需要它的模块中调用'glewInit'。 – datenwolf
哇真的吗?这很有趣。我永远不会认为这是事实。感谢datenwolf的领导 – Jason
桌面。我不小心添加了opengl-es标记,现在删除它 – Jason
只有当你的OpenGL上下文已经创建时,你才可以调用'glewInit',否则你会碰壁...我没有看到任何OpenGL初始化...可能是隐藏的在BlazeGraphics :: Window窗口内(1280,720,“MyGame”);'。此外''glewInit'和所有OpenGL的东西应该从同一个线程调用... – Spektre