当前位置: 首页 > 知识库问答 >
问题:

顶点和片段着色器如何在OpenGL中通信?

茅昀
2023-03-14

我真的不明白片段着色器是如何工作的。

我知道

  • 顶点着色器每个顶点运行一次
  • 片段着色器对每个片段运行一次

由于片段着色器不是按顶点而是按片段工作,它如何将数据发送到片段着色器?顶点的数量和片段的数量不相等。

它如何决定哪个碎片属于哪个顶点?

共有2个答案

沈建柏
2023-03-14

答案是他们不会——至少不会直接这么做。还有一个叫做“光栅化器”的东西,它位于管道中的顶点处理器和片段处理器之间。光栅化器负责收集来自顶点着色器的顶点,将它们重新组合为基本体(通常为三角形),将这些三角形分解为(部分)覆盖器像素的“光栅”,并将这些片段发送到片段着色器。

这是一个(大部分)固定功能的硬件,你不直接编程。有一些配置调整可以影响它作为基本体处理的内容,以及它作为片段生成的内容,但在大多数情况下,它只是在顶点着色器和片段着色器之间进行。

翟源
2023-03-14

要理解这一点,需要考虑整个渲染管道。顶点着色器的输出(除了特殊输出gl_Position)作为顶点的“关联数据”传递到管道中的下一个阶段。

虽然顶点着色器一次只处理一个顶点,根本不关心基本体,但管道的后续阶段确实会考虑基本体类型(以及顶点连接信息)。这就是通常所说的“原始装配”。现在,我们仍然有单个顶点和VS生成的相关数据,但我们也知道哪些顶点被组合在一起,以定义一个基本基本图元,如点(1个顶点)、线(2个顶点)或三角形(3个顶点)。

在光栅化过程中,将为属于原语的输出像素光栅中的每个像素位置生成片段。这样,定义基本体的顶点的关联数据可以在整个基本体上插值。在一行中,这是相当简单的:一个线性插值完成。让我们调用endpointA和B,每个endpoint都有一些相关的输出向量v,这样我们就有了v_A和v_B。通过这条线,我们得到v的插值为v(x)=(1-x)*v_A x*v_B,其中x在0(在点A)到1(在点B)的范围内。对于三角形,在所有3个顶点的数据之间使用重心插值。因此,虽然顶点和片段之间没有1:1的映射,但VS的输出仍然定义了FS对应输入的值,只是不是以直接的方式,而是通过使用的基本体类型的插值间接地定义。

到目前为止,我给出的公式有点简化。实际上,默认情况下,通过修改公式以考虑透视的失真影响,有效地应用了透视校正。这只是意味着插值应该在对象空间中线性应用(在应用投影失真之前)。例如,如果您有一个透视投影和一些与图像平面不平行的基元,在屏幕空间中向右移动1个像素确实意味着在真实对象上移动可变距离,具体取决于实际点到相机平面的距离。

您可以使用GLSL中in/out变量的noperspective限定符来禁用透视校正。然后,如我所述,使用线性/重心插值。

您还可以使用flat限定符,它将完全禁用插值。在这种情况下,只有一个顶点(所谓的“激发顶点”)的值用于整个基本体的所有片段。整数数据永远不能由GL自动插值,并且在发送到片段着色器时必须限定为平面

 类似资料:
  • WebGL的着色器代码分为顶点着色器代码和片元着色器代码两部分,顶点着色器代码会在GPU的顶点着色器单元执行,片元着色器代码会在GPU的片元着色器单元执行,在WebGL渲染管线流程中,或者说GPU的渲染流程中,顶点着色器代码先执行处理顶点,得到一系列片元,然后再执行片元着色器代码处理片元。 main()函数 顶点着色器和片元着色器代码都有一个唯一的主函数main(),attribute、varyi

  • 在一个简单的hello world OpenGL程序中,它只是在窗口上绘制一个静态三角形,当我将三角形的3个顶点设置为红色、绿色和蓝色时,三角形将填充渐变。 但是当我使用这样的着色器时: 顶点着色器: 其中属性和来自顶点缓冲区,通过的调用传递。 片段着色器: 三角形仍然充满了梯度,问题来了: 如果顶点着色器是按顶点计算的,则应为的每个实例指定顶点的颜色。顶点颜色应为红色、绿色或蓝色,如顶点缓冲区中

  • 我对OpenGL有点生疏,我已经实现了一个场景的照明,场景中有小行星围绕行星旋转的实例。出于某种原因,我得到的唯一输出似乎是场景的环境照明。我无法使漫反射或镜面反射工作。 这是现场的一张照片(很难看到…)仅限环境 片段着色器代码如下所示。FragPos、Normal和TexCoords都是你所期待的。纹理_diffuse1是行星/小行星纹理,具体取决于使用的着色器。LightPos可以移动,它由图

  • 我正在学习使用OpenGL制作图形引擎。我想知道,重复操作是否应该从顶点着色器移动到片段着色器,因为据我所知,顶点着色器每个顶点只运行一次? 例如,当规格化灯光方向的向量时,由于该灯光在整个顶点中相同,是否应将其移动到顶点着色器,而不是为每个像素计算它?在着色器中保留片段有什么特别的原因?

  • 我希望在2D OpenGL应用程序上实现着色器。我的计划是将场景渲染到帧缓冲区对象,然后使用着色器将该帧缓冲区对象渲染到屏幕。 这是我绘制到帧缓冲区对象的场景,然后从那里绘制到屏幕。使用箭头键可以让月亮四处移动(我很自豪!) 但是,当我尝试使用着色器程序将帧缓冲区对象渲染到屏幕上时,我得到以下结果: 这是非常可悲的。这个片段着色器是我从一个教程中得到的,我相信问题一定是统一变量。 以下是片段着色器