为啥这个在opengl中绘制三角形的着色器不会多次运行

Posted

技术标签:

【中文标题】为啥这个在opengl中绘制三角形的着色器不会多次运行【英文标题】:Why does this shader to draw a triangle in opengl not get run multiple times为什么这个在opengl中绘制三角形的着色器不会多次运行 【发布时间】:2018-08-14 16:50:56 【问题描述】:

我正在通过一些在线 youtube 教程学习使用 OpenGL。 24:43是我说的代码:https: //www.youtube.com/watch?v=71BLZwRGUJE&list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2&index=7

在该系列的上一个视频中,这家伙说顶点着色器运行 3 次(对于三角形),片段着色器对形状内的每个像素运行一次,但是在我链接的视频中,有没有告诉顶点着色器运行 3 次,也没有告诉片段着色器运行多次。谁能解释一下原因?

我也很难理解所使用的术语。例如,在顶点着色器中是代码:in vec4 position。在片段着色器中有代码out vec4 color。我在谷歌上搜索了很多这意味着什么,但我在任何地方都找不到它的含义。

【问题讨论】:

您至少可以通过发布代码而不是参考大约 30 分钟的 Youtube 视频来显示一些努力。 对不起,我忘了添加代码可见的时间,我现在就这样做 不是我的反对意见,但如果你想知道为什么你被反对,请阅读idownvotedbecau.se/imageofcode。 【参考方案1】:

1.

为需要绘制的图元的每个顶点执行一个顶点着色器。由于在示例中只绘制了一个三角形(即具有三个顶点的图元),因此顶点着色器显然执行了 3 次,该三角形的每个顶点执行一次。顶点着色器的调度由 OpenGL 自己完成。用户不需要关心这个。

为光栅器生成的每个片段执行片段着色器(即光栅器将基元分解为称为片段的离散元素)。一个片段对应一个像素。虽然这不是双射,但对于某些像素,可能没有片段,而对于某些像素,可能有多个片段,具体取决于要绘制的场景。片段的调度由 OpenGL 自己完成。用户不需要关心这个。

用户有效地只配置流水线的可配置阶段,绑定可编程着色器,绑定着色器输入和输出资源,以及绑定几何资源(顶点和索引缓冲区、拓扑)。后者在示例中对应于包含三角形三个顶点的顶点缓冲区,以及GL_TRIANGLES 拓扑。

所以举个例子:

// The buffer ID.
unsigned int buffer;
// Generate one buffer object:
glGenBuffers(1, &buffer);
// Bind the newly created buffer to the GL_ARRAY_BUFFER target:
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Copies the previously defined vertex data into the buffer's memory:
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
// Set the vertex attributes pointers
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

...

// Bind the buffer as a vertex buffer:
glBindVertexArray(buffer);

...

// Draw a triangle list for the triangles with the vertices at indices [0,3) = 1 triangle:
glDrawArrays(GL_TRIANGLES, 0, 3);

类似的很好解释的"How to draw a triangle"-tutorial。

2.

layout(location = 0) in vec4 position;

vec4(4 个floats 的向量)类型的vertex shader(即顶点属性)的用户定义输入值,名称为position。在示例中,每个顶点都有一个position,在将其最终传递给光栅化器之前需要在顶点着色器中正确转换(分配给gl_Position)。

3.

layout(location = 0) out vec4 color

vec4 类型的fragment shader 的用户定义输出值(4 个floats 的向量),名称为color。在示例中,片段着色器为每个要最终写入后台缓冲区的片段输出恒定颜色(例如,红色)。

参考文献

一些有用的 OpenGL/GLSL 参考:

Learn OpenGL

如果您想跳过所有 CPU 样板并只关注着色器本身,您可以查看 ShaderToy 以方便原型设计。

【讨论】:

ok 那么什么是输出值,什么是输入值,输出值和输入值有什么区别? @adamtheguy762 图形管道由不同的连接阶段组成,其中一个阶段的输出大致是下一个阶段的输入。其中一些阶段称为着色器,可由用户编程。用户需要定义这些着色器所需的输入和输出值。最常见和基本的设置包括顶点和片段着色器。用户需要指定这两个着色器的输入和输出值。管道将传递输入值,着色器将根据这些输入值生成一些输出值。 好吧,所以我想了想,然后我意识到位置将是顶点着色器的输入,但也是输出,因为它会被传递给光栅化器,但仅用于位置.还有片段着色器中的颜色,为什么是输出? 顶点着色器将通过分配给gl_Position来输出一个位置,这是一个内置的(即非用户定义的)GLSL值,用于表示同质空间中的位置。光栅化器总是需要每个顶点有这样的值(例如,剔除、裁剪等)。为了知道在哪里找到它,使用了一个特殊的内置变量。示例中片段着色器中的红色是一个输出,因为您想绘制一个红色三角形。

以上是关于为啥这个在opengl中绘制三角形的着色器不会多次运行的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的三角形在镶嵌后不显示? OpenGL

无法获得简单的 2D 着色器以在 C++ openGL 中绘制红色三角形(无编译器错误)

片段着色器不会在 OpenGL GLSL 中创建像光一样的渐变

Opengl为啥这个着色器不起作用?

在 vertexShader 中使用 OpenGl 未声明的标识符,我在顶点着色器中绘制三角形时遇到问题

Android OpenGL学习:最小系统绘制