为啥这个在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 个float
s 的向量)类型的vertex shader(即顶点属性)的用户定义输入值,名称为position
。在示例中,每个顶点都有一个position
,在将其最终传递给光栅化器之前需要在顶点着色器中正确转换(分配给gl_Position
)。
3.
layout(location = 0) out vec4 color
vec4
类型的fragment shader 的用户定义输出值(4 个float
s 的向量),名称为color
。在示例中,片段着色器为每个要最终写入后台缓冲区的片段输出恒定颜色(例如,红色)。
参考文献
一些有用的 OpenGL/GLSL 参考:
Learn OpenGL如果您想跳过所有 CPU 样板并只关注着色器本身,您可以查看 ShaderToy 以方便原型设计。
【讨论】:
ok 那么什么是输出值,什么是输入值,输出值和输入值有什么区别? @adamtheguy762 图形管道由不同的连接阶段组成,其中一个阶段的输出大致是下一个阶段的输入。其中一些阶段称为着色器,可由用户编程。用户需要定义这些着色器所需的输入和输出值。最常见和基本的设置包括顶点和片段着色器。用户需要指定这两个着色器的输入和输出值。管道将传递输入值,着色器将根据这些输入值生成一些输出值。 好吧,所以我想了想,然后我意识到位置将是顶点着色器的输入,但也是输出,因为它会被传递给光栅化器,但仅用于位置.还有片段着色器中的颜色,为什么是输出? 顶点着色器将通过分配给gl_Position
来输出一个位置,这是一个内置的(即非用户定义的)GLSL值,用于表示同质空间中的位置。光栅化器总是需要每个顶点有这样的值(例如,剔除、裁剪等)。为了知道在哪里找到它,使用了一个特殊的内置变量。示例中片段着色器中的红色是一个输出,因为您想绘制一个红色三角形。以上是关于为啥这个在opengl中绘制三角形的着色器不会多次运行的主要内容,如果未能解决你的问题,请参考以下文章
无法获得简单的 2D 着色器以在 C++ openGL 中绘制红色三角形(无编译器错误)
片段着色器不会在 OpenGL GLSL 中创建像光一样的渐变