OpenGL 渲染在 Linux 机器上不起作用(Windows 渲染)---可能与 cmake 脚本有关(参见更新)

Posted

技术标签:

【中文标题】OpenGL 渲染在 Linux 机器上不起作用(Windows 渲染)---可能与 cmake 脚本有关(参见更新)【英文标题】:OpenGL rendering not working on Linux machine (windows renders) --- probably related to cmake script (See Updates) 【发布时间】:2016-12-03 16:15:32 【问题描述】:

我正在使用 OpenGL 开发自制图形引擎。我使用 c++、cmake、glew 和 wxWidgets。到目前为止,我只是在 Windows 机器上工作,一切都很好。现在我尝试移植到linux。现在的问题是,除了渲染之外,一切似乎都正常工作。我使用了一个非常简单的着色器:

#VERTEX // ----------------------------------------------
#version 430 core

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
layout (location = 2) in vec2 VertexTexCoord;

void main()

    gl_Position         = vec4(VertexPosition,1.0);




#FRAGMENT // --------------------------------------------

#version 430 core

out vec4 FragColor;

void main()

    FragColor = vec4(1.0,0.0,0.0,1.0);  

在 Windows 上,我可以毫无问题地渲染一个简单的红色方块。在 Linux 上,什么都没有,只有清晰的颜色(禁用背面剔除)。我还尝试每帧切换清除颜色以查看上下文是否正确绑定并且交换是否正常工作。我得到了预期的闪烁屏幕,所以上下文和丢失的交换不是问题。我还插入了 GLErrors 的检查,但没有得到任何结果。着色器的编译似乎按预期工作,程序运行没有任何异常或其他问题,除了丢失的输出。我还阅读了另一个线程,其中在操作系统上发生了同样的问题。问题是,在没有 VAO 限制的情况下调用了 glEnableVertexAttribArray。但对我来说不是这样。这是我如何生成对象的代码 sn-p:

// Create VAO
    glGenVertexArrays(1, &pVAOHandle_r);
    glBindVertexArray(pVAOHandle_r);

    // Create VBO
    glGenBuffers(1, &pVBOHandle_r);
    glBindBuffer(GL_ARRAY_BUFFER, pVBOHandle_r);

    // Transfer data
    glBufferData(GL_ARRAY_BUFFER, NumVertexAttribFloats * pVertices_cr.size() * sizeof(F32), VertexArray.data(), GL_STATIC_DRAW);


    // Set Attributes
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          NumVertexAttribFloats * sizeof(GLfloat),
                          0);

    U16 AttribNumber = 1;
    GLuint Offset = 12;

    if(pVertices_cr[0]->HasNormal())
    
        glEnableVertexAttribArray(AttribNumber);
        glVertexAttribPointer(AttribNumber,
                              3,
                              GL_FLOAT,
                              GL_FALSE,
                              NumVertexAttribFloats * sizeof(GLfloat),
                              (void*)Offset);
        ++AttribNumber;
        Offset += 12;
    
    if(pVertices_cr[0]->HasColor())
    
        glEnableVertexAttribArray(AttribNumber);
        glVertexAttribPointer(AttribNumber,
                              4,
                              GL_FLOAT,
                              GL_FALSE,
                              NumVertexAttribFloats * sizeof(GLfloat),
                              (void*)Offset);
        ++AttribNumber;
        Offset += 16;
    
    if(pVertices_cr[0]->HasTexCoord())
    
        glEnableVertexAttribArray(AttribNumber);
        glVertexAttribPointer(AttribNumber,
                              2,
                              GL_FLOAT,
                              GL_FALSE,
                              NumVertexAttribFloats * sizeof(GLfloat),
                              (void*)Offset);
        ++AttribNumber;
        Offset+=8;
    

这里是渲染调用:

    glBindVertexArray(mVertexMeshReference.GetVAO());
//  glBindBuffer(GL_ARRAY_BUFFER,mVertexMeshReference.GetVBO());
    glBindTexture(GL_TEXTURE_2D, mTextureReference.GetHandle());

    glDrawArrays(mVertexMeshReference.GetGLPrimitiveType(),
                 0,
                 mVertexMeshReference.GetNumPrimitives() * mVertexMeshReference.GetNumPrimitiveVertices());

我不确定是否必须再次绑定VBO,所以我测试了它,没有任何区别。

还有一个区别:我在 Windows 上构建静态而在 linux 上动态构建。我不确定它是否与使用的库有关。也许有些丢失了,但我希望链接器会抱怨它。我还检查了哪个 GPU OpenGL 正在使用,因为我也有一个板载芯片组,但输出显示的是正确的。到目前为止,我不知道可能是什么问题。也许有人发现了一个错误,这与 Windows 无关,但在 linux 上。如果您需要其他代码 sn-ps,请告诉我。希望你能帮助我。

------- 更新 --------------

我将在此处列出任何建议解决方案的结果,这样您就无需阅读所有帖子及其 cmets。

来自 OpenGL 的输出:

   glGetString(GL_VENDOR) = NVIDIA Corporation
   glGetString(GL_RENDERER) = GeForce GTX 980M/PCIe/SSE2
   glGetString(GL_SHADING_LANGUAGE_VERSION) = 4.50 NVIDIA
   glGetString(GL_VERSION) = 4.5.0 NVIDIA 370.28

发现样品有同样的问题! 在其中一个 cmets 中,我说样品正在工作。我错了。当我使用自己构建的 wxWidgets 时,它们起作用了。但是我的 wxWidgets 设置和 cmake 遇到了其他问题,这些问题通过使用 ubuntu 存储库中的库得到了解决。现在我复制了企鹅示例并编写了一个 cmake 文件。我在这里遇到了完全相同的问题,除了缺少企鹅之外,一切似乎都正常。所以我想问题出在我的 cmake 脚本中,与程序本身无关。

这是脚本(忽略最小 wxWidgets 示例的 2 个命令):

 PROJECT(Sample)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(CMAKE_VERBOSE_MAKEFILE ON)


SET(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=gnu++14 -Wall  -Wno-long-long -pedantic -D__WXGTK__")

find_package(wxWidgets COMPONENTS gl core base REQUIRED)
FIND_PACKAGE(OpenGL)
include($wxWidgets_USE_FILE)

add_executable(Minimal
   minimal.cpp)

target_link_libraries(Minimal $wxWidgets_LIBRARIES)

add_executable(Penguin
   opengl/penguin/penguin.cpp
   opengl/penguin/dxfrenderer.cpp
   opengl/penguin/penguin_trackball.o)

LINK_DIRECTORIES(opengl/penguin)

target_link_libraries(Penguin
    $wxWidgets_LIBRARIES
    $OPENGL_gl_LIBRARY
    $OPENGL_glu_LIBRARY)

更新 2

现在我 99% 确定它与我的 cmake 脚本有关。我切换回我自己的构建 wxWidgets。有了它(版本 3.1),我可以使用提供的 makefile 构建企鹅示例,如果我运行程序,我可以看到企鹅。如果我使用上面显示的 cmake 脚本构建相同的文件,一切都会编译,但企鹅不见了!

那么我在我的 cmake 文件中做错了什么?少了什么东西?也许有人可以复制脚本并在自己的机器上尝试?

【问题讨论】:

对不起,我的错。但是我为我的着色器编写了一个小型预处理器,它允许我通过使用包含等重用代码。它还自动包含版本指令。我将它添加到原始帖子中以避免将来的刺激。对不起。 嗯,不用担心。核对我现在已经过时的评论。 【参考方案1】:

如果它在 Windows 上运行但不在 Linux 上运行,则您的驱动程序可能无法运行该 OGL 版本。

您使用哪个 wxWidgets 版本?在 wx 3.0 之前,只有 OGL 2.1 可用。对于 wx 3.1,OGL 版本仅受操作系统驱动程序的限制,但您应该询问您计划使用的版本。

您是否测试过 wxWidgets OGL 示例?

【讨论】:

wxWidgets 的当前版本是 3.0.2。 (Ubuntu)。我运行的唯一示例是企鹅示例,它很好。但我认为这是一个基于旧 OGL 版本的安静的旧样本。如果您认为其中一个依赖于当前的 OGL 版本,我将尝试其他的。当我使用 OpenGL 命令获取当前着色语言版本时,它显示为 4.5。我不完全确定,但我认为如果驱动程序无法正常工作,它应该显示旧版本,还是不显示? 在您的 wxWidgets 应用程序中获取当前的 OGL 版本。返回的版本取决于上下文创建。 Wx 3.1 中更改了 OGL 上下文创建及其选项 使用 glGetString(GL_VERSION) 并返回 4.5.0 NVIDIA 370.28。在原始帖子中添加了更新部分,您可以在其中查看我尝试过的内容以及结果。那里也列出了一些其他结果。【参考方案2】:

这真的是顶点着色器的全部吗?我自己没有使用过 Glew 或 wxWidgets,所以我不知道他们是否在编译之前在某处插入了额外的代码,但我假设某处有一个“in vec3 VertexPosition”。

永远不要期望您的顶点属性的位置总是相同的,除非您在链接之前使用glBindAttribLocation 或在顶点着色器中使用布局限定符将它们放置在固定位置。使用glGetAttribLocation 让 glEnableVertexAttribArray 和 glVertexAttribPointer 确定它们在哪里。如果您尝试渲染的任何内容都可以在 Windows 上运行,那么这可能就是问题所在。

【讨论】:

嗨,不,不是整个着色器,我已经编写了一个处理包含的小型预处理器,因此我不必在每个着色器中重复代码。懒得复制包含的东西。我将对其进行编辑并将包含的行放入起始帖子中。对不起

以上是关于OpenGL 渲染在 Linux 机器上不起作用(Windows 渲染)---可能与 cmake 脚本有关(参见更新)的主要内容,如果未能解决你的问题,请参考以下文章

Flask-Login:在本地机器上不起作用,但在托管上很好

为啥clock()在集群机器上不起作用

截图功能在其他机器上不起作用

OpenGL第一个立方体渲染不起作用

Angular5服务调用在ngOnInit上不起作用

Crystal Report 的 ODBC 连接报告在其他机器上不起作用