【问题标题】:Does OpenGL eliminate a vertex shader with no bound vertex buffer?OpenGL 是否消除了没有绑定顶点缓冲区的顶点着色器?
【发布时间】:2014-01-19 07:16:35
【问题描述】:

OpenGL SuperBible 第 6 版(适用于 OpenGL 4.3)包含使用顶点着色器的示例,这些顶点着色器没有顶点属性输入,但顶点是硬编码的,例如

#version 420 core
void main(void) 
{                                                                 
    const vec4 vertices[] = vec4[](vec4( 0.4, -0.4, 0.5, 1.0), 
                                   vec4(-0.4, -0.4, 0.5, 1.0),    
                                   vec4( 0.4,  0.4, 0.5, 1.0));   
    gl_Position = vertices[gl_VertexID];  
 }

当我运行示例时,窗口被清除,但没有其他任何反应。

通过实验,我发现在将空缓冲区绑定到上下文时,程序会按预期运行。下面是示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h> /
#include <GLFW/glfw3.h> 
#define GLM_MESSAGES
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/vector_angle.hpp>

int main(int argc, char* argv[]) {
    GLuint program;
    GLuint vao;
    GLuint vbo;

    glfwInit();
    GLFWwindow* window = glfwCreateWindow(640, 480, "gl_InstanceID", NULL, NULL);
    glfwMakeContextCurrent(window);

    glewInit();
    program = glCreateProgram();
    GLuint vs = load("vertex.glsl", GL_VERTEX_SHADER, true);
    GLuint fs = load("frag.glsl", GL_FRAGMENT_SHADER, true);
    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program); 
    glDeleteShader(vs);
    glDeleteShader(fs);

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

//**************************************
//no triangle drawn when below these lines commented out
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, 4, NULL, GL_DYNAMIC_COPY);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0);
//***************************************

    do {
        static const GLfloat green[] = { 0.0f, 0.2f, 0.0f, 1.0f };
        glClearBufferfv(GL_COLOR, 0, green);
        glUseProgram(program);
        glDrawArrays(GL_TRIANGLES, 0, 3); //OR glDrawArraysInstanced(GL_TRIANGLES, 0, 3,1);
        glfwSwapBuffers(window);

        glfwPollEvents();
        if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
            glfwSetWindowShouldClose(window, 1);
        }
    } while (!glfwWindowShouldClose(window));
    glfwTerminate();
    return 0;
}

之间添加代码时,会绘制三角形。如果没有缓冲区,则不会绘制三角形。

另外,当顶点数组对象(VAO)被移除(或如上使用)时,三角形也不会显示。只有 VAO 和(空)VBO 才绘制三角形。 移除 VAO 但有缓冲区显示三角形。没有缓冲区没有三角形。 VAO似乎没有什么不同。

还要注意顶点着色器没有输入。

发生了什么?

  1. 编译器/显卡认为顶点着色器什么都不做并删除它?我感觉是显卡(驱动)。
  2. 这是 OpenGL 的预期还是因为显卡?
  3. 我对缓冲区、VAO 和着色器的理解有些欠缺?

其他可能有用的信息

  • GLEW 1.10.0
  • GLFW 3.0.3

片段着色器:

#version 420 core
out vec4 color;
void main(void)
{
color = vec4(1.0);
}

操作系统详情:

  • Linux:3.2.0-4-amd64
  • 发行版:Debian 7.3 Wheezy
  • uname -m: x86_64

编译器细节

  • g++ --version: g++ (Debian 4.7.2-5) 4.7.2

OpenGL 细节:

  • OpenGL 提供程序:Advanced Micro Devices(来自 AMD Catalyst Control Center)
  • OpenGL 渲染器:AMD Radeon HD 7600M 系列(来自 AMD Catalyst Control Center)
  • OpenGL 版本:4.2.11762 兼容性配置文件上下文(来自 AMD Catalyst Control Center)
  • glxinfo:
  • 服务器 glx 版本字符串:1.4
  • 客户端 glx 版本字符串:1.4
  • GLX 版本:1.4
  • OpenGL 版本字符串:4.2.11762 兼容性配置文件上下文
  • OpenGL 着色语言版本字符串:4.20
  • 服务器 glx 供应商字符串:ATI
  • 客户端 glx 供应商字符串:ATI

在使用与 Linux 相同的显卡的 Windows 中也会出现此问题,即

  • Windows 8
  • 64 位
  • 在 ATI Technologies Inc. 的 AMD Radeon HD 7670M 上运行
  • 支持 OpenGL 版本 4.2.11762 兼容性配置文件上下文

AMD 有一个适用于 Linux 的新版本 13.12 驱动程序(我使用的是 13.4)。有时间我会尝试一下,因为上次安装并不容易。

我还登录了issue 984 on Unofficial AMD Bugzilla。但也许它已在 13.12 中修复。


但是,程序可以正常运行(无论是不使用空缓冲区还是使用空缓冲区),都在运行

  • Windows 7 专业版
  • 64 位
  • NVIDIA GeForce GT 520M(驱动日期:2013/10/15,驱动版本:9.18.13.3158)

继续

  • Windows 8
  • 64 位
  • 在英特尔的 Intel(R) HD Graphics 4000 上运行,
  • OpenGL 版本 4.0.0 - 内部版本 9.17.10.2849

【问题讨论】:

  • :( 将#version 420 core 添加到片段着色器没有帮助。

标签: opengl


【解决方案1】:

不,信不信由你glDrawArrays (...) 与绑定哪个顶点缓冲区无关。顶点缓冲区绑定仅在您设置顶点指针时才重要,因为它定义了您传递的指针相对的地址空间。从那时起,绑定的 VBO 就无关紧要了。 顺便说一句,如果您在严格的 GLSL 实现上运行此片段着色器,它将警告/拒绝工作,因为没有#version 指令,它应该假定片段着色器是针对 GLSL 1.10 编写的规范,不支持out阶段变量(你需要gl_FragData [0]代替)。

或者,只需像在顶点着色器中一样添加#version 420 core...版本指令实际上比您想象的更重要,特别是因为在没有它的情况下发生的行为在供应商之间差异很大。这样做可能不会解决您的问题,但它仍然是您应该解决的问题。

至于移除 VAO 的问题,这是意料之中的。在核心 OpenGL 3.2+ 上下文中,您必须有一个非零 VAO 边界才能使 glDrawArrays (...) 工作。实际上,VAO 成为顶点绘制命令的上下文。没有一个界限,你就没有他们可以操作的上下文。

【讨论】:

  • 经过更多实验:移除 VAO 但有缓冲区显示三角形。 VAO似乎没有什么不同。它需要缓冲区才能工作。感谢版本提示。
  • 那么您没有使用核心配置文件上下文。在兼容性上下文(默认)中,这将起作用。还值得一提的是,如果您启用一个没有绑定任何 VBO 的顶点属性数组,则结果将是未定义的。现在,所有属性数组一开始都是禁用的,所以如果这是你的整个程序,那么我不得不想象这是一个驱动程序错误。
  • 如何判断我是否在使用核心配置文件上下文? glxinfo 仅提及核心配置文件的兼容性。
  • 您会知道您是否使用了核心配置文件。您必须执行额外的步骤才能获得核心配置文件,我无法准确告诉您使用 GLFW 时它们是什么,但在设置上下文时通常涉及“窗口提示”。每个框架都有稍微不同的处理方式,但在所有情况下,除非你做这些额外的工作,否则默认情况下你会得到一个兼容性配置文件。兼容性配置文件不一定是坏事,它们的限制比核心更宽松,因此对于刚开始的人来说更容易。但是,某些平台不支持它们(例如 OS X)。
  • 可能我应该在Windows下运行同一个程序,看看Linux和Windows的驱动是否不同。
【解决方案2】:

请记住,顶点着色器只能操作现有顶点。它不能创造它们。即使该位置在着色器中是硬编码的,您仍然必须为其提供一些东西来进行变换。

【讨论】:

  • 这不是真的,你实际上可以在桌面 OpenGL 中运行这种东西。 glDrawArrays (...) 将为每个顶点隐式生成连续的 gl_VertexID 值,即使没有(启用的)数组指针可以从中提取数据。 GLES 是另一回事,但在桌面 GL 中,您始终可以使用 gl_VertexID 索引一些硬编码点。
【解决方案3】:

不,看起来这是 AMD Radeon HD 7600M 系列 (13.4) 驱动程序中的错误

我安装了latest AMD driver,它解决了 Windows 和 Linux 中的问题。

Linux:已安装 amd-catalyst-13.12-linux-x86.x86_64.zip

Windows:已安装 amd_catalyst_13.11_mobility_betav9.5.exe


要在 Linux 上重新安装 AMD 驱动程序,我首先卸载 AMD 安装 (amd-catalyst-previous-version.run --uninstall),删除所有包含名称 fglrx 的软件包(使用 aptitude),将符号链接调整为/usr/lib64(见下文),然后运行新的 amd-catalyst-13.12-linux-x86.x86_64.run。

我看到了这个页面 AMD 13.1 64 bit drivers and the libGL.so.1 error,它解释了 AMD 安装程序将 libGL.so 文件放在哪里

安装程序将 lib 文件放在 /usr/lib64 中。但是,如果您有 Ubuntu,则 64 位库位于 /usr/lib 中。我执行了以下操作来解决我的问题。

卸载驱动程序 sudo ./amd-driver-installer-catalyst-13.1-legacy-linux-x86.x86_64.run --uninstall

删除 /usr/lib64 文件夹 sudo rm -Rf /usr/lib64

创建一个指向 /lib/usr 的符号链接 /usr/lib64 sudo ln -s /usr/lib /usr/lib64

重新安装驱动 sudo ./amd-driver-installer-catalyst-13.1-legacy-linux-x86.x86_64.run --force

重启 须藤重启

【讨论】:

  • 你能在装有 AMD 硬件的机器上运行 Windows 吗?通常来自 NV/AMD 的专有 Linux 驱动程序与 Windows 驱动程序共享大致相同的代码库(尽管通常有更长的发布时间表),但你永远不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多