Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenGL 4.1 GL\u ARB\u单独的\u程序\u对象有用性_Opengl - Fatal编程技术网

OpenGL 4.1 GL\u ARB\u单独的\u程序\u对象有用性

OpenGL 4.1 GL\u ARB\u单独的\u程序\u对象有用性,opengl,Opengl,我一直在阅读OpenGL4.1新特性评论。我不太理解GL_ARB_单独的_程序_对象使用背后的想法,至少根据文章作者的说法: 它允许独立使用着色器阶段,而无需更改其他阶段 着色器阶段。我认为这有两个主要原因:Direct3D、Cg和even 旧的OpenGL ARB程序可以做到这一点,但更重要的是,它带来了一些 软件设计的灵活性允许在任何时候都可以看到图形管道 较低的粒度。例如,我最好的敌人VAO是 链接缓冲区数据、顶点布局数据和GLSL的容器对象 程序输入数据。如果没有专门的软件设计,这意味着

我一直在阅读OpenGL4.1新特性评论。我不太理解GL_ARB_单独的_程序_对象使用背后的想法,至少根据文章作者的说法:

它允许独立使用着色器阶段,而无需更改其他阶段 着色器阶段。我认为这有两个主要原因:Direct3D、Cg和even 旧的OpenGL ARB程序可以做到这一点,但更重要的是,它带来了一些 软件设计的灵活性允许在任何时候都可以看到图形管道 较低的粒度。例如,我最好的敌人VAO是 链接缓冲区数据、顶点布局数据和GLSL的容器对象 程序输入数据。如果没有专门的软件设计,这意味着 当我改变一个对象的材质(一个新的片段着色器)时, 我需要不同的VAO。。。幸运的是,可以保持相同的VAO 只有通过定义一个关于如何 在C++程序与GLSL程序之间进行通信。它起作用了 即使还有一些缺点

现在,这一行:

例如,我最大的敌人VAO是一个链接缓冲区数据、顶点布局数据和GLSL程序输入数据的容器对象。如果没有专用的软件设计,这意味着当我更改对象的材质(新的片段着色器)时,我需要不同的VAO…

我想知道。在我的OpenGL程序中,我使用VAO对象,我可以在不同的着色器程序之间切换,而无需对VAO本身做任何更改。那么,我是否误解了整个想法?也许他的意思是我们可以在不重新链接的情况下切换同一程序的着色器

我可以在不同的着色器程序之间切换

是的,但是你必须完全替换整个程序。单独的着色器对象允许您仅替换一个阶段(例如,仅替换顶点着色器)


例如,如果有N个顶点着色器和M个顶点着色器,则使用常规链接可以有N*M个程序对象(覆盖所有可能的组合)。使用单独的着色器对象,它们彼此分离,因此只需要保留N+M着色器对象。在复杂的场景中,这是一个显著的改进。

我将这个答案分解为多个部分

ARB_separate_shader_对象的用途是什么 此功能的目的是能够在顶点/碎片/几何体/细分着色器之间轻松混合和匹配

目前,必须将所有着色器阶段链接到一个单片程序中。因此,我可以对两个不同的片段着色器使用相同的顶点着色器代码。但这导致了两个不同的项目

每个节目都有自己的一套制服和其他状态。这意味着,如果我想更改顶点着色器中的一些统一数据,我必须在两个程序中都更改它。我必须在每个位置上使用
glGetUniformLocation
(因为它们可能有不同的位置)。然后,我必须分别设置每一个的值

这是一个很大的痛苦,而且完全没有必要。使用单独的着色器,您不必这样做。您有一个仅包含顶点着色器的程序和两个包含两个片段着色器的程序。更改顶点着色器统一不需要两次调用。实际上,缓存数据更容易,因为只有一个顶点着色器

此外,它还处理着色器组合的组合爆炸

假设您有一个顶点着色器,可以执行简单的刚性变换:它将模型转换为摄影机矩阵,将摄影机转换为剪辑矩阵。也可能是法线的矩阵。还有一个片段着色器,它将从一些纹理中采样,根据法线进行一些照明计算,并返回一种颜色

现在,假设您添加了另一个片段着色器,该着色器使用额外的照明和材质参数。它没有来自顶点着色器的任何新输入(没有新的纹理坐标或任何东西),只有新的制服。可能是投影照明,顶点着色器不涉及。不管怎样

现在,假设我们添加了一个新的顶点着色器,该着色器执行顶点加权蒙皮。它提供与旧顶点着色器相同的输出,但它有一系列用于蒙皮的统一和输入权重

这为我们提供了2个顶点着色器和2个片段着色器。共有4个程序组合

当我们再添加两个兼容的片段着色器时会发生什么?我们有8种组合。如果我们有3个顶点和10个片段着色器,我们总共有30个程序组合

使用单独的着色器,3个顶点和10个片段着色器需要30个程序管道对象,但只需要13个程序对象。这比非独立情况下的程序对象少了50%以上

为什么引用的文本是错误的 现在,这句话[…]让我感到奇怪

它应该让你感到惊讶;这在几个方面都是错误的。例如:

VAO是链接缓冲区数据、顶点布局数据和GLSL程序输入数据的容器对象

不,没有。它将提供顶点数据的缓冲区对象绑定到该数据的顶点格式。它还指定要访问的顶点属性索引。但这与“GLSL程序输入数据”的紧密耦合程度完全取决于您

没有一个专门的软件设计,这意味着当我改变一个对象(一个新的片段着色器)的材料,我需要不同的VAO

除非这一行将“专用软件设计”等同于“合理的编程实践”,否则这完全是胡说八道

这就是我的意思。您将看到在线示例代码,这些代码在设置顶点数据时执行以下操作:

glBindBuffer(GL_ARRAY_BUFFER, buffer_object);
glEnableVertexAttribArray(glGetAttribLocation(prog, "position"));
glVertexAttribPointer(glGetAttribLocation(prog, "position"), ...);
这里有一个术语:糟糕的代码。执行此操作的唯一原因是如果
prog
指定的着色器不在您的直接控制之下。如果是这样的话。。。您怎么知道
prog
有一个名为“position”的属性

着色器的合理编程实践是使用co
GLuint prog = glCreateProgram();
glAttachShader(prog, ...); //Repeat as needed.
glBindAttribLocation(prog, 0, "position");
#version 330
layout(location = 0) in vec4 position;