片段着色器究竟如何用于纹理?

Posted

技术标签:

【中文标题】片段着色器究竟如何用于纹理?【英文标题】:How exactly does fragment shader work for texturing? 【发布时间】:2017-07-14 23:45:23 【问题描述】:

我正在学习 opengl,我认为我非常了解片段着色器。我的直觉是片段着色器对每个像素应用一次,但最近在处理纹理时,我对它们的工作原理感到困惑。

首先,片段着色器通常采用一系列纹理坐标,因此如果我有一个四边形,片段着色器将采用四边形 4 个角的纹理坐标。现在我不明白的是采样过程,它是获取纹理坐标并在该纹理坐标处获取适当颜色值的过程。具体来说,由于我只提供 4 个纹理坐标,opengl 怎么知道对颜色值之间的坐标进行采样。

当您考虑到顶点着色器直接进入片段着色器并且顶点着色器适用于每个顶点的事实时,这项任务变得更加混乱。这意味着在任何给定时间,片段着色器只知道对应于单个顶点的纹理坐标,而不是构成四边形的全部 4 个坐标。因此,当它一次只有一个纹理坐标可用时,它如何知道对适合屏幕上形状的值进行采样?

【问题讨论】:

"顶点着色器直接进入片段着色器" 你真的看过diagram of the OpenGL rendering pipeline吗?因为在VS结束和FS开始之间发生了很多事情。 【参考方案1】:

所有varying 变量都是自动插值的。

因此,如果您将每个顶点的纹理坐标放入varying,之后您无需对它们进行任何特殊处理。

可以这么简单:

// Vertex
#version 330 compatibility
attribute vec2 a_texcoord;
varying vec2 v_texcoord;

void main()

    v_texcoord = a_texcoord;


// Fragment
uniform vec2 u_texture;
varying vec2 v_texcoord;

void main()

    gl_FragColor = texture2D(u_texture, v_texcoord);

免责声明:我使用了旧的 GLSL 语法。在较新的 GLSL 版本中,attribute 将替换为 invarying 将替换为顶点着色器中的out 和片段着色器中的ingl_FragColor 将替换为自定义 out vec4 变量。 texture2D() 将替换为 texture()

请注意此片段着色器如何不进行任何手动插值。它只接收一个vec2 v_texcoord,它是从v_texcoords 的底层插入的,这些顶点包含一个当前片段所属的基元1

1. primitive 表示点、线、三角形或四边形。

【讨论】:

在什么和什么之间插值?那么in/out变量呢?这些是如何工作的? 感谢您的回答,我只是快速澄清一下,看看我是否理解正确。基本上发生的事情是顶点坐标在引擎盖下转换为图元,并且该纹理坐标的纹理坐标也绑定到该图元。因此,opengl 可以在这些纹理坐标之间进行插值,这意味着如果您的图元是三角形,它必须以三角形模式进行插值。因此,它将产生正确的颜色。我的解释正确吗? @NicolBolas 在 "v_texcoords 的顶点之间插值,其中包含一个原始当前片段所属的"。好的,我添加了关于新 in/out 语法的免责声明。 @Wowzer 是的,听起来不错。图元中的每个顶点都有自己的纹理坐标,然后为该图元的每个片段进行插值。 最后一件事在您的免责声明中似乎有点矛盾。您说 in 将是属性,而 out 会有所不同。这意味着改变 vec2 v_texcoord;会出 vec2 v_texcoord 但那不可能,因为您正在接受 texcoord。【参考方案2】:

首先:在核心上下文中,您仍然可以使用 gl_FragColor。

second : 你有 texel ,fragment 和 real_monitor_pixel。这些是不同的 事物。 说这一行是关于将 texel 转换为片段(或转换为像素 idk 的作用):

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

当纹素小于片段(像素)时

【讨论】:

以上是关于片段着色器究竟如何用于纹理?的主要内容,如果未能解决你的问题,请参考以下文章

如何在片段着色器中平铺部分纹理

片段着色器中未使用纹理数据 - OpenGL

如何将浮点矩阵作为 2D 纹理传递给片段着色器?

纹理中的 OpenGL 片段着色器

纹理上的片段着色器

为啥片段着色器比渲染纹理更快?