当顶点属性数组零被禁用时,为什么 OpenGL 绘制会失败?

2024-01-18

我在让我的顶点着色器在 ATI 驱动程序上的 OpenGL 3.3 核心下运行时遇到了极大的困难:

#version 150

uniform mat4 graph_matrix, view_matrix, proj_matrix;
uniform bool align_origin;

attribute vec2 graph_position;
attribute vec2 screen_position;
attribute vec2 texcoord0;
attribute vec4 color;
varying vec2 texcoord0_px;
varying vec4 color_px;

void main() {
    // Pick the position or the annotation position
    vec2 pos = graph_position;

    // Transform the coordinates
    pos = vec2(graph_matrix * vec4(pos, 0.0, 1.0));

    if( align_origin )
        pos = floor(pos + vec2(0.5, 0.5)) + vec2(0.5, 0.5);

    gl_Position = proj_matrix * view_matrix * vec4(pos + screen_position, 0.0, 1.0);
    texcoord0_px = texcoord0;
    color_px = color;
}

我使用 glVertexAttrib4f 指定颜色属性,并关闭属性数组。根据 3.3 核心规范第 33 页,这应该有效:

如果未启用与顶点着色器所需的通用属性相对应的数组,则从当前通用属性状态中获取相应的元素(参见第 2.7 节)。

但是(大多数时候,取决于配置文件和驱动程序)如果我访问禁用的颜色属性,着色器要么根本不运行,要么使用黑色。用常量替换它就可以运行了。

大量搜索结果本页有关 WebGL 的提示 https://developer.mozilla.org/en-US/docs/WebGL/WebGL_best_practices,其中有以下内容:

始终启用顶点属性 0 数组。如果您在禁用顶点属性 0 数组的情况下进行绘制,则在桌面 OpenGL(例如在 Mac OSX 上)上运行时,您将强制浏览器进行复杂的模拟。这是因为在桌面 OpenGL 中,如果顶点属性 0 未启用数组,则不会绘制任何内容。您可以使用bindAttribLocation()强制顶点属性使用位置0,并使用enableVertexAttribArray()使其启用数组。

果然,不仅颜色属性被分配给索引零,而且如果我将另一个启用数组的属性强制绑定为零,代码就会运行并产生正确的颜色。

我在任何地方都找不到任何其他提及此规则的内容,当然在 ATI 硬件上也找不到。有谁知道这个规则从何而来?或者这是 Mozilla 人员注意到并警告过的实现中的错误?


tl;dr:这是一个驱动程序错误。核心 OpenGL 3.3 应该允许您不使用属性 0,但兼容性配置文件不允许,并且某些驱动程序无法正确实现该开关。只需确保使用属性 0 即可避免出现任何问题。

实际内容:

让我们上一堂历史课,了解 OpenGL 规范是如何诞生的。

在 OpenGL 最古老的时代,只有一种渲染方式:立即模式(即:glBegin/glVertex/glColor/glEtc/glEnd)。显示列表是存在的,但它们始终被定义为简单地再次发送捕获的命令。因此,虽然实现实际上并未进行所有这些函数调用,但实现的行为仍然就像它们进行了一样。

在 OpenGL 1.1 中,客户端顶点数组被添加到规范中。现在记住:规范是指定的文档behavior,而不是实施。因此,ARB 简单地定义客户端数组的工作方式与进行立即模式调用完全相同,使用对当前数组指针的适当访问。显然,实现实际上不会这样做,但它们的行为却好像这样做了。

基于缓冲区对象的顶点数组以相同的方式定义,但由于从服务器存储而不是客户端存储中提取,语言稍微复杂一些。

然后发生了一些事情:ARB_vertex_program(不是ARB_vertex_shader。我说的是汇编程序)。

看,一旦有了着色器,您就希望能够开始定义自己的属性,而不是使用内置属性。这一切都是有道理的。然而,有一个问题。

立即模式的工作原理如下:

glBegin(...);
glTexCoord(...);
glColor(...);
glVertex(...);
glTexCoord(...);
glColor(...);
glVertex(...);
glTexCoord(...);
glColor(...);
glVertex(...);
glEnd();

每次你打电话glVertex,这会导致所有当前属性状态都用于单个顶点。所有其他立即模式函数只是将值设置到上下文中;这个功能实际上sendsOpenGL 中要处理的顶点。这在即时模式下非常重要。由于每个顶点都必须在固定功能区域中拥有一个位置,因此使用此函数来决定何时应处理顶点是有意义的。

一旦不再使用 OpenGL 的固定功能顶点语义,立即模式就会出现问题。也就是说,你如何决定何时真正send顶点?

按照惯例,他们将其粘贴到属性 0 上。因此,所有立即模式渲染必须使用属性 0 或 glVertex 来发送顶点。

然而,因为所有其他渲染基于立即模式渲染的语言,所有其他渲染都有相同的局限性立即模式渲染。立即模式需要属性 0 或 glVertex,因此客户端数组等也是如此。尽管这对他们来说没有意义,但他们需要它,因为规范如何定义他们的行为。

然后 OpenGL 3.0 出现了。他们不赞成立即模式。弃用并不意味着removed;规范中仍然包含这些函数,并且所有顶点数组渲染仍然被定义in terms其中。

OpenGL 3.1 实际上删除了旧的东西。这带来了一些语言问题。毕竟,每个数组绘制命令总是根据立即模式定义的。但是一旦即时模式不再存在......你如何定义它?

因此他们必须为核心 OpenGL 3.1+ 开发新的语言。在这样做的同时,他们删除了需要使用属性 0 的毫无意义的限制。

但兼容性配置文件did not.

因此,OpenGL 3.2+的规则是这样的。如果您有核心 OpenGL 配置文件,则不必使用属性 0。如果您有兼容性 OpenGL 配置文件,则必须使用属性 0(或glVertex)。规范就是这么说的。

但这不是实现所实现的。

一般来说,NVIDIA 从来不太关心“必须使用属性 0”规则,只是按照您的预期行事,即使在兼容性配置文件中也是如此。从而违反了规范的规定。 AMD 通常更有可能遵守该规范。然而,他们忘记了实施core行为正确。所以NVIDIA对兼容性太宽容,而AMD对核心太限制。

要解决这些驱动程序错误,只需始终使用属性 0。

顺便说一句,如果您想知道的话,NVIDIA 赢了。在 OpenGL 4.3 中,兼容性配置文件对其数组渲染命令使用与核心相同的措辞。因此,您可以在核心和兼容性上不使用属性 0。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当顶点属性数组零被禁用时,为什么 OpenGL 绘制会失败? 的相关文章

  • wglCreateContextAttribsARB 函数崩溃

    我尝试写下代码 我有InitializeOGL 的代码 bool Ogl InitializeOGL bool vSync cout lt lt Init OpenGL lt
  • 帧缓冲区和在 opengl 中使用着色器

    我对帧缓冲区有点困惑 我想要做的是使用附加了多个纹理的帧缓冲区 填充每个纹理 然后使用着色器组合 混合 所有纹理以创建新的输出 听起来很容易 是的 我也是这么想的 但我不明白 如何将当前绑定的纹理传递给着色器 您需要的是将纹理放入特定的槽中
  • GLSL 中统一浮点行为和常量浮点行为的不同

    我正在尝试在 GLSL 中实现模拟双精度 并且观察到一种奇怪的行为差异 导致 GLSL 中出现细微的浮点错误 考虑以下片段着色器 写入 4 浮点纹理以打印输出 layout location 0 out vec4 Output unifor
  • GL_COLOR_ATTACHMENT 有什么作用?

    我现在正在学习帧缓冲区 但我只是不明白颜色附件的作用 我了解帧缓冲区 第二个参数的意义是什么 glFramebufferTexture2D GL FRAMEBUFFER GL COLOR ATTACHMENT0 GL TEXTURE 2D
  • glDeleteTextures在Windows上似乎没有释放纹理内存,有没有解决办法?

    我的 openGL 应用程序内存不足 遇到一些问题 我正在尝试找出我的问题 为此 我创建了一个小型测试程序 它基本上只是从调用 glDeleteTextures 的文件中加载一个巨大的纹理 然后再次加载它 如果我在 OSX 上运行这个测试程
  • OpenGL什么时候完成函数中指针的处理?

    OpenGL有多项功能 http www opengl org wiki GLAPI glTexSubImage2D直接获取指针 他们中有一些从这些指针读取数据 http www opengl org wiki GLAPI glBuffer
  • GLSL聚光投影体积

    在我的开源项目中 我使用 Qt3D 设置了延迟渲染管道 到目前为止一切顺利 但现在我想通过添加聚光灯投影量来继续前进 例如场景中好像有烟雾 像这样 我正在使用的片段着色器位于问题的末尾 我读过 对于每个片段 我应该从光位置进行光线行进并找到
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • 按像素值偏移 gl_Position 或 gl_Vertex

    我的属性包含像素值 我想用这个属性值来偏移我的 gl vertex 问题是我的 gl vertex 以世界单位为单位 而 offset attribute 以像素为单位 如果我将屏幕尺寸作为统一发送 然后将像素转换为 1 到 1 值 并将其
  • 在 OpenGL 中实例化数百万个对象:提高每秒帧数

    我的最终目标是以 60 fps 渲染 100 万个不同尺寸和颜色的球体 我也希望能够在屏幕上移动相机 我已经修改了代码我正在学习的教程的这一页 http learnopengl com Advanced OpenGL Instancing尝
  • 如何在OpenGL中像这样绘制连接的带状线

    我想用以下方式绘制一系列连接线 GL LINE STRIP 我尝试过自己编写代码 但没有得到想要的结果 所以我来到这里 帮助我找出我错在哪里 这里我只给出我的draw 函数 glBegin GL LINE STRIP glVertex2f
  • WGL:没有双缓冲 + 多重采样 = 失败?

    我通常使用创建像素格式wglChoosePixelFormatARB 与这些论点 除其他外 WGL DOUBLE BUFFER ARB GL TRUE WGL SAMPLE BUFFERS ARB GL TRUE WGL SAMPLES A
  • Retina 显示屏中具有 QOpenGLWIdget 的 Qt MainWindow 显示错误大小

    我有一个 Qt 应用程序MainWindow 我嵌入一个QOpenGLWidget在里面 一切正常 直到我开始使用 Apple Retina 显示屏并在高 DPI 模式下运行我的应用程序 我的QOpenGLWidget只是它应该具有的大小的
  • 开启TK onRenderFrame和onUpdateFrame的区别?

    我目前正在使用 OpenTK 框架和 OpenGL 用 C 编写 Jump n Run 游戏 Open TK 提供预设功能 例如GameWindow Run or GameWindow onUpdateFrame onRenderFrame
  • 新显卡上的 nvoglv32.dll 中的绘制调用崩溃

    几天前 由于一些硬件更改 我设置了计算机并安装了新的 Windows 8 副本 其中 我将显卡从 Radeon HD 7870 更改为 Nvidia GTX 660 再次设置 Visual Studio 11 后 我从 Github 下载了
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态
  • glClipPlane - webGL 中有等效的吗?

    我有一个 3D 网格 是否有可能像这样呈现剖面图 剪辑 glClipPlane在OpenGL中 我正在使用 Three js r65 我添加的最新着色器是 片段着色器 uniform float time uniform vec2 reso
  • OpenGL 计算着色器调用

    我有一个与新计算着色器相关的问题 我目前正在研究粒子系统 我将所有粒子存储在着色器存储缓冲区中 以便在计算着色器中访问它们 然后我派遣一个一维工作组 define WORK GROUP SIZE 128 shaderManager gt u
  • 3D 图形批处理

    很多网站 文章都说 批量 批 批 有人可以解释一下着色器中的 批处理 代表什么吗 即 是否 改变纹理 更改任意着色器变量 意味着某些东西不能 批处理 最简单的总结方法就是尝试尽可能少地调用 API 来绘制您需要绘制的内容 使用顶点数组或 V
  • sRGB 纹理。它是否正确?

    我最近阅读了一些有关 sRGB 格式以及它们如何允许硬件自动对典型显示器执行色彩校正的文章 作为我阅读的一部分 我发现您可以使用普通纹理和返回结果上的 pow 函数来模拟此步骤 无论如何 我想问两个问题 因为我以前从未使用过此功能 首先 有

随机推荐

  • 分组算法

    我试图帮助某人编写一个我认为很容易的程序 但当然它从来都不是 我正在尝试制定一个班级名册 通常有 10 20 名学生 并有效地将每个同学与另一个同学有效地唯一配对 以形成独特的小组 因此 一个10人的班级 可以分成9组 它也需要能够处理奇数
  • 来自 java 的 libxml2

    这个问题有点相关用于 Java 中小型 简单文档的最快 XML 解析器 https stackoverflow com questions 530064 fastest xml parser for small simple documen
  • Postgres 生成_系列

    我想要的是对表格进行统计 为此我正在使用generate series 这是我正在做的事情 SELECT x month amount FROM SELECT generate series min date trunc month dat
  • 在 docker 上运行 conda 的 jupyter

    我正在使用 docker 镜像 Continumio anaconda3 并希望通过浏览器使用 conda 启动 jupyter 笔记本服务器 docker run i t p 8888 8888 continuumio anaconda3
  • 在未使用的默认成员初始值设定项中使用仍然是 odr 使用吗?

    即使任何构造函数都没有使用默认成员初始值设定项 在默认成员初始值设定项中使用仍然是 odr 使用吗 例如 这个程序是否格式错误 因为g a 是否使用了 odr 因此其定义被隐式实例化 template a
  • 加密 SQL 数据库中的密码列

    我的数据库名称密码中有一列 我只想在发布到数据库之前对密码进行哈希或加密 我的 php 提交文件中有这样的代码
  • 在 Python 中处理字符串中的转义序列

    有时 当我从文件或用户获取输入时 我会得到一个带有转义序列的字符串 我想处理转义序列与 Python 处理字符串文字中的转义序列的方式相同 https docs python org 3 reference lexical analysis
  • 在 jQuery 中创建新的(永久)CSS 样式

    我想创建一种新样式 而不仅仅是更改元素的样式属性 下面是一些示例代码来演示该问题 Create 1st element var element1 div div text element1 addClass blue body append
  • ASP.NET c# 修复函数库内自定义ConfirmMessagebox 的 OK 事件

    我们创建了一个从 C 通过 javascript 动态显示模态弹出消息的函数 它工作正常 但我们想添加一个参数 以便我们可以传递一个函数委托 或事件处理程序 如果用户按下 确定 按钮 该函数将被调用 有什么建议么 Postdata 我们不需
  • 函数调用之外的星号

    我正在尝试 python 我有一个关于星号的问题 我知道它们用于函数调用中的参数 但我见过在函数卡之外使用它们的代码片段 例如 在 5 个等级的元组中 将它们解压到变量中 例如 first middle last grades 每当我尝试在
  • Chart.js stepSize 不适用于 min

    StepSize 不考虑 min 包括小提琴 https jsfiddle net 4p93aew7 10 https jsfiddle net 4p93aew7 10 var options type line data labels R
  • 在 CSS 中为 div 使用多个 ID

    我的网站上有 3 个 DIV 元素和这个 CSS box left box middle box right a text decoration none color 000000 它似乎只致力于 box right虽然元素 有任何想法吗
  • 将动态内容放入 mail() $message 中

    我只是想整理一封简单的 HTML 电子邮件 以确认我的数据库的订单 我的 message 看起来有点像 message etc etc 我想要在 message HTML 中执行的操作是调用我的数据库 该数据库将返回类似以下内容的行 ema
  • 使用 Facelets 标记文件时出现 FileNotFoundException

    我正在尝试运行 Core JavaServer Faces 书中的示例 ch05 http horstmann com corejsf http horstmann com corejsf 登录后我收到以下消息 sections plane
  • 实现 std::basic_streambuf 子类来操作输入

    我有一个std basic streambuf导致所有输出都以大写形式写入的子类 如下所示 class upper streambuf public std streambuf public upper streambuf std stre
  • 如何从相机拍摄的照片制作缩略图?

    在我的应用程序中 我使用外部相机应用程序来制作照片并将其保存到 SD 卡 我需要这张照片的方形缩略图 我已经设法将相机发送回的缩略图裁剪成正方形 但由于我将照片保存到磁盘 因此意图是空的 而我的旧方法使图片成为正方形Bitmap cropp
  • Spring单例bean的这种设计是线程安全的吗?

    考虑以下 Spring 服务类 spring定义的作用域是Singleton 在下面的类中自动连接为字段的两个服务 bean 具有相似的结构 它们也由以下字段之一组成 春豆本身 无状态类 不可变类 等等 该模式在应用程序设计中总体采用 Se
  • AjaxControlToolkit.CommonToolkitScripts 错误

    我在我的 ASP NET 应用程序中得到以下代码
  • 回复 Gmail 线程会向我自己发送电子邮件

    文档 https developers google com apps script reference gmail gmail message replybody options https developers google com a
  • 当顶点属性数组零被禁用时,为什么 OpenGL 绘制会失败?

    我在让我的顶点着色器在 ATI 驱动程序上的 OpenGL 3 3 核心下运行时遇到了极大的困难 version 150 uniform mat4 graph matrix view matrix proj matrix uniform b