CMake子项目无法调用OpenGL函数,但父项目可以

时间:2018-07-19 08:40:15

标签: c++ opengl cmake

我有一个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做成一个库,以便我可以调用它将来来自多个项目。此刻我完全迷住了。

1 个答案:

答案 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;
}

这种简单的解决方法可以解决一个让我非常头疼的简单问题。