在 OpenGL 3.2 中绘制全屏四边形的最佳方法是什么?

2024-03-28

我正在片段着色器中进行光线投射。我可以想出几种方法来为此目的绘制全屏四边形。要么在剪辑空间中绘制一个四边形,并将投影矩阵设置为单位矩阵,要么使用几何着色器将点变成三角形带。前者使用立即模式,在 OpenGL 3.2 中已弃用。我使用后者是出于新奇,但它仍然使用立即模式来画点。


我认为最有效的方法是绘制一个single“全屏”triangle。为了让三角形覆盖整个屏幕,它需要比实际视口大。在 NDC 中(还有剪辑空间,如果我们设置w=1),视口将始终是[-1,1]正方形。为了使三角形完全覆盖该区域,我们需要两条边的长度是视口矩形的两倍,以便第三条边将穿过视口的边缘,因此我们可以使用以下坐标(在逆时针顺序):(-1,-1), (3,-1), (-1,3).

我们也不需要担心文本坐标。为了得到通常的标准化[0,1]在整个可见视口的范围内,我们只需要使顶点的相应纹理坐标变大,并且重心插值对于任何视口像素都会产生与使用四边形时完全相同的结果。

这种方法当然可以与无属性渲染相结合,如德曼泽的回答 https://stackoverflow.com/a/51625078/2327517:

out vec2 texcoords; // texcoords are in the normalized [0,1] range for the viewport-filling quad part of the triangle
void main() {
        vec2 vertices[3]=vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3));
        gl_Position = vec4(vertices[gl_VertexID],0,1);
        texcoords = 0.5 * gl_Position.xy + vec2(0.5);
}

为什么单个三角形会更有效?

This is not关于保存一个顶点着色器调用,以及在前端处理的少一个三角形。使用单个三角形最显着的效果是更少的片段着色器调用

一旦图元的单个像素落入 2x2 像素大小的块(“四边形”),真正的 GPU 总是会调用该块的片段着色器。这对于计算窗口空间导函数 https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/dFdx.xhtml(纹理采样也隐含需要这些,请参见这个问题 https://stackoverflow.com/questions/52975878/what-is-in-simple-terms-texturegrad/52977548#52977548).

如果基元没有覆盖该块中的所有 4 个像素,则剩余的片段着色器调用将不会执行任何有用的工作(除了提供用于导数计算的数据之外),并且将被称为辅助调用(甚至可以通过gl_HelperInvocationGLSL功能 https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/gl_HelperInvocation.xhtml)。也可以看看Fabian“ryg”Giesen 的博客文章 https://fgiesen.wordpress.com/2011/07/10/a-trip-through-the-graphics-pipeline-2011-part-8/更多细节。

如果您渲染具有两个三角形的四边形,则两个三角形的一条边都会对角地穿过视口,并且在两个三角形上,您将在对角边生成大量无用的辅助调用。对于完美的正方形视口(纵横比 1),效果最差。如果您绘制单个三角形,则不会有这样的对角线边缘(它位于视口之外,根本不关心光栅化器),因此不会有额外的帮助器调用。

等一下,如果三角形延伸穿过视口边界,它不会被剪切并实际放置吗more在 GPU 上工作?

如果您阅读有关图形管道(甚至 GL 规范)的教科书材料,您可能会有这样的印象。但现实世界的 GPU 使用一些不同的方法,例如保护带削波。我不会在这里详细介绍(这将是一个单独的主题,请查看Fabian“ryg”Giesen 的精彩博客文章 https://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/详细信息),但总体思路是,无论如何,光栅化器只会为视口(或剪刀矩形)内的像素生成片段,无论图元是否完全位于其中,因此我们可以简单地向其抛出更大的三角形,如果以下两项均属正确:

  • a) 三角形仅延伸 2D 顶部/底部/左/右剪裁平面(与 z 维度近/远剪裁平面相反,后者处理起来更棘手,特别是因为顶点也可能位于behind相机)

  • b) 实际的顶点坐标(以及光栅化器可能对其执行的所有中间计算结果)可以用 GPU 硬件光栅化器使用的内部数据格式表示。光栅化器将使用特定于实现的宽度的定点数据类型,而顶点坐标是 32 位单精度浮点数。 (这基本上就是定义保护带大小的)

我们的三角形只比视口大 3 倍,所以我们可以非常确定根本不需要裁剪它。

但是这值得吗?

嗯,片段着色器调用的节省是真实的(特别是当您有复杂的片段着色器时),但在现实场景中总体效果可能几乎无法衡量。另一方面,该方法并不比使用全屏四边形更复杂,并且使用数据较少,所以即使可能不会产生巨大的差异,也不会造成伤害,所以为什么not使用它?

这种方法是否可以用于各种轴对齐矩形,而不仅仅是全屏矩形?

理论上,您可以将其与剪刀测试结合起来绘制一些任意轴对齐的矩形(剪刀测试将非常有效,因为它只是限制首先生成哪些片段,这不是真正的“测试” “在丢弃片段的硬件中)。但是,这需要您更改要绘制的每个矩形的剪刀参数,这意味着大量的状态更改并限制您每次绘制调用只能使用单个矩形,因此在大多数情况下这样做并不是一个好主意。

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

在 OpenGL 3.2 中绘制全屏四边形的最佳方法是什么? 的相关文章

  • glBufferSubData什么时候返回? [复制]

    这个问题在这里已经有答案了 我想将一个非常大的内存块的内容传输到足够大的 GPU 缓冲区 然后立即更改 CPU 上的内存内容 伪代码是这样的 glBindBuffer very large buffer glBufferSubData ve
  • 任何图像文件格式是否支持负浮点数?

    我正在使用 OpenGL 来实现一些屏幕空间过滤器 出于调试目的 我想保存一堆纹理 以便可以比较各个像素值 问题是这些 16 位浮点纹理具有负值 您知道有哪些支持负值的图像文件格式吗 我怎样才能导出它们 是的 有一些这样的格式 您需要的是使
  • 我如何知道我正在使用哪个版本的 OpenGL?

    我开始使用 GLFW 和 OpenGL 用 C 目前 编写程序 我的问题是 我如何知道我的程序将使用哪个版本的 OpenGL 我的笔记本电脑显示我的显卡支持 OpenGL 3 3 输入 glxinfo grep i opengl 返回 Op
  • 包含原始数据的头文件的用途是什么?

    决定检查一些除了我自己的代码之外的代码 Quake I https github com id Software Quake就是选择 我点击的第一个文件只包含原始数据 唯一的注释是 GP L 我猜它是一个包含法向量的数组 不管它的目的是什么
  • 如何减慢从BVH文件读取opengl动画的速度?

    使用 GLFW3 我目前制作了一个 bvh 文件解析器 它读取文件并将其转换为我在 opengl 中制作的人体模型 然而 每当我启动它时 移动速度太快 以至于眼睛看不到动画 所以我想把动画速度调低一点 这是我的渲染循环 while glfw
  • 使用 xscreensaver 编写屏幕保护程序的提示和技巧? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 几个月来我一直在做一些简单的 Ope
  • 您应该如何有效地批处理复杂的网格?

    渲染复杂网格的最佳方法是什么 我在下面写了不同的解决方案 想知道您对它们有何看法 让我们举个例子 如何渲染 Crytek Sponza 网格 PS 我不使用Ubershader 只使用单独的着色器 如果您通过以下链接下载网格 http gr
  • 使用 gldrawpixels 进行 opengl 旋转

    我的团队目前仅限于在 opengl 1 4 平台上绘制图像 这意味着我们无法使用任何漂亮的纹理映射来绘制图像 是的 我们仅限于使用 intel 集成图形平台 这非常烦人 到目前为止 我们能够绘制 缩放和翻转图像 但是制作图形的人声称在使用
  • 对数/线性 Z 缓冲区阴影贴图

    问题在于 伪影出现在距离很远的阴影中 我想尝试制作一个对数深度缓冲区 但我不明白应该在哪里完成以及如何完成 我对全向阴影贴图使用点光源方法 顶点着色器 version 460 core layout location 0 in vec3 a
  • 如何在 WebGL 中创建合适的圆角矩形?

    我试图实现答案这个问题 https stackoverflow com questions 43970170 bordered rounded rectangle in glsl但似乎有点问题 如果您打开他们的 ShaderToys 并尝试
  • QGLWidget 比 QWidget 慢

    问题主要是在标题中确定的 我尝试了 Qt 的示例 二维绘画 http harmattan dev nokia com docs library html qt4 opengl 2dpainting html 并注意到 如果我尝试在 QGLW
  • 无法将简单的无符号字节 RGB 纹理映射到四边形:

    我有一个非常简单的程序 将虚拟红色纹理映射到四边形 下面是 C 中的纹理定义 struct DummyRGB8Texture2d uint8 t data 3 4 int width int height DummyRGB8Texture2
  • 如何用SDL2和OpenGL画三角形?

    我正在使用 C 中的 SDL2 和 OpenGL 开发一个简单的应用程序 问题是我的程序没有绘制三角形 Rect hpp 绘制三角形的类 ifndef Rect hpp define Rect hpp include
  • 尝试 glUseProgram 时出现 Opengl 错误 1281

    我有什么想法可以调试这个opengl进一步错误 1281 我正在从文件加载源代码 编译 链接 然后尝试检查错误glUseProgram 在我的对象的绘制方法中 log info gl2 glIsProgram shaderProgram t
  • 从活动顶点数组生成平滑法线

    我正在尝试通过挂钩 OpenGl 调用来破解和修改旧版 opengl 固定管道游戏的多个渲染功能 而我当前的任务是实现着色器照明 我已经创建了一个适当的着色器程序 可以正确照亮大部分对象 但该游戏的地形是在没有提供正常数据的情况下绘制的 游
  • 如何创建一个 numpy 数组来描述三角形的顶点?

    我喜欢使用 Numpy 创建要传递到的顶点数组glsl Vertices将是一个包含 3 个顶点信息的 numpy 数组 Each vertex包括 pos x y 具有 32 位的 64 位有符号浮点格式 R 分量位于字节 0 3 中 3
  • VBO - 没有指数化的指数化

    我正在尝试将 VBO 与元素数组缓冲区一起用于我的三角形 如下所示 glBindBuffer GL ARRAY BUFFER g Buffer 0 glVertexPointer 3 GL FLOAT 0 BUFFER OFFSET 0 g
  • 如何将 3D 图像输出到 3D 电视?

    我有一台 3D 电视 如果我不至少尝试让它显示我自己创作的漂亮 3D 图像 我就会逃避我的责任 作为一个极客 我之前已经完成了非常基本的 OpenGL 编程 因此我了解所涉及的概念 假设我可以为自己渲染一个简单的四面体或立方体并使其旋转一点
  • 使用 Opengl 绘制立方体 3D

    我想使用 OpenGL 绘制 3D 立方体这是我的代码如何纠正错误 float ver 8 3 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  • (定义一个宏)方便OpenGL命令调试?

    有时插入条件打印和检查需要很长时间glGetError 使用二分搜索的形式来缩小范围 其中第一个函数调用是 OpenGL 首先报告错误 我认为如果有一种方法可以构建一个宏 我可以包装所有可能失败的 GL 调用 并有条件地调用 那就太酷了gl

随机推荐