我有一个CMake父项目和一个CMake子项目,在cmake父项目中,我可以调用任何OpenGL函数,并且效果很好,但是在子项目中,我不能直接调用任何OpenGL函数,只能通过父项目功能将起作用。
父项目:
cmake_minimum_required (VERSION 3.8)
project(LumiumEngine)
set(CMAKE_DEBUG_POSTFIX "-d")
set(LUMI_DIR "LumiumEngine")
# SDL2
find_package(SDL2 CONFIG REQUIRED)
add_library(${PROJECT_NAME} SHARED "${LUMI_DIR}/System/Window.hpp" "${LUMI_DIR}/System/Window.cpp")
# glad
set(GLAD_DIR "${CMAKE_HOME_DIRECTORY}/external/glad")
add_library("glad" "${GLAD_DIR}/src/glad.c")
target_include_directories("glad" PUBLIC "${GLAD_DIR}/include")
target_include_directories(${PROJECT_NAME} PUBLIC "${SDL2_INCLUDE_DIRS}" "${GLAD_DIR}/include")
target_link_libraries(${PROJECT_NAME} PUBLIC SDL2::SDL2 SDL2::SDL2main "glad" "${CMAKE_DL_LIBS}")
set_target_properties(${PROJECT_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/${PROJECT_NAME}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/${PROJECT_NAME}/bin"
)
install(DIRECTORY bin
DESTINATION "${CMAKE_HOME_DIRECTORY}/Lumin"
FILES_MATCHING
PATTERN "*.dll"
PATTERN "*.ilk" EXCLUDE
PATTERN "*.pdb" EXCLUDE
)
儿童项目:
cmake_minimum_required (VERSION 3.8)
project(Lumin)
set(CMAKE_DEBUG_POSTFIX "-d")
# find OpenGL
find_package(OpenGL REQUIRED)
add_executable(${PROJECT_NAME} "main.cpp" "${CMAKE_HOME_DIRECTORY}/external/glad/src/glad.c")
target_link_libraries(${PROJECT_NAME} PUBLIC "${OPENGL_LIBRARIES}" LumiumEngine)
set_target_properties(${PROJECT_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/${PROJECT_NAME}/bin"
)
子项目依赖于父项目,(在父-父目录中,我只是将这两个项目都添加为子目录和add_dependency(Child Parent),应从我的项目中加载适当的.dll和.libs。了解我将SDL2, SDL2main, glad
加载到父项目中,然后再加载OpenGL
+ Parent中的所有库,因为它们是使用PUBLIC标签添加的。
代码不是问题,因为我在Visual Studio中使用相同的代码创建了一个包含两个子项目的项目。我缺少图书馆吗?编译OpenGL加载程序“ glad”也可能是一个问题。
我认为让我感到困惑的主要问题是,为什么在我的父项目中的抽象层隐藏的OpenGL函数可以正常工作,但是当我在我的子项目中调用OpenGL函数时,却收到“在0x00010处抛出的异常...”在OpenGL调用中。感谢您的帮助或指导。
编辑:添加代码示例:
这是我的父项目LumiumEngine中的Window.cpp
#include "Window.hpp"
#include <glad/glad.h>
lumi::Window::Window()
{
m_shouldClose = true;
}
lumi::Window::~Window()
{
SDL_Quit();
}
bool lumi::Window::createWindow(std::string title, int xPos, int yPos, int width, int height, unsigned int flags)
{
// Set SDL as ready and init SDL
SDL_SetMainReady();
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init Error", "Could not init SDL2", NULL);
SDL_Quit();
return false;
}
SDL_GL_LoadLibrary(NULL); // Default OpenGL is fine.
// Request an OpenGL 4.5 context (should be core)
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
// Also request a depth buffer
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
// create the window
m_pWindow = SDL_CreateWindow(title.c_str(), xPos, yPos, width, height, flags);
if (m_pWindow == nullptr)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Window Error", "Could not create a window", NULL);
SDL_Quit();
return false;
}
// create the openGL context
m_glContext = SDL_GL_CreateContext(m_pWindow);
if (m_glContext == nullptr)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Window Error", "Could not create an openGL context with version 4.5", NULL);
SDL_Quit();
return false;
}
printf("OpenGL loaded\n");
gladLoadGLLoader(SDL_GL_GetProcAddress);
printf("Vendor: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("Version: %s\n", glGetString(GL_VERSION));
m_shouldClose = false;
glViewport(0, 0, width, height);
glClearColor(.2f, .4f, .6f, 1.0f);
return true;
}
bool lumi::Window::isOpen()
{
return !m_shouldClose;
}
子项目main.cpp
#include <LumiumEngine/System/Window.hpp>
#include <glad/glad.h>
int main(int argc, char **argv)
{
lumi::Window window;
if (window.createWindow("Hello World", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL))
{
glClearColor(0.2f, 0.4f, 0.6f, 1.0f); // exception occurs here, as you can see it's after i create a valid OpenGL context
while (window.isOpen())
{
//window.display();
}
}
return 1;
}
请注意我如何在createWindow函数中调用相同的OpenGL函数glClearColor()
,它运行得很好。我可以通过调用window.display来调用glClear(GL_COLOR_BUFFER_BIT); then SDL_GL_SwapBuffers()
侧面说明:我只是尝试摆脱子项目,并使父项目成为可执行文件而不是库,而且工作正常,但我真的很希望能够将LumiumEngine做成一个库,以便我可以调用它将来来自多个项目。此刻我完全迷住了。
答案 0 :(得分:0)
Blahhh!
因此,由于某些原因,您必须在子项目中再次通过happy手动加载OpenGL,即使它已在父项目中被调用并且我们已经验证了我们具有有效的OpenGL上下文。简单的解决方法是添加:
gladLoadGLLoader(SDL_GL_GetProcAddress)
在创建SDL窗口后调用:
#include <LumiumEngine/System/Window.hpp>
#include <glad/glad.h>
int main(int argc, char **argv)
{
lumi::Window window;
if (window.createWindow("Hello World", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL))
{
gladLoadGLLoader(SDL_GL_GetProcAddress);
glClearColor(0.2f, 0.4f, 0.6f, 1.0f); // THIS WORKS NOW!!
while (window.isOpen())
{
window.display();
}
}
return 1;
}
这种简单的解决方法可以解决一个让我非常头疼的简单问题。