gl_FragCoord和归一化设备坐标
# 1. gl_FragCoord和归一化设备坐标解读
在WebGL和GLSL中,gl_FragCoord
是一个特殊的内置变量,它提供了当前片段(fragment)的坐标。这个坐标最初是在屏幕空间(screen space)中给出的,其范围取决于渲染目标(如屏幕或纹理)的分辨率。然而,为了在着色器中实现某些效果,我们经常需要将这些屏幕空间坐标转换为归一化设备坐标(Normalized Device Coordinates, NDC)。
# 屏幕空间坐标到NDC的转换
屏幕空间坐标转换到NDC的公式如下:
- x 的NDC = (
gl_FragCoord.x
/ 屏幕宽度) * 2 - 1 - y 的NDC = (1 -
gl_FragCoord.y
/ 屏幕高度) * 2 - 1
这里,屏幕宽度和高度可以由传入片段着色器的uniform变量提供,例如:
uniform vec2 resolution;
# 转换步骤
归一化:首先,将屏幕空间坐标除以屏幕的宽度和高度,这将把坐标转换到[0, 1]的范围内。
偏移和缩放:然后,通过乘以2并减去1,将坐标范围从[0, 1]转换到[-1, 1]。这样,屏幕的左下角映射到-1,右上角映射到1。
# 示例
假设屏幕分辨率为800x600:
- 屏幕空间坐标 (400, 300) 转换为NDC:
- x的NDC = (400 / 800) * 2 - 1 = 0
- y的NDC = (1 - 300 / 600) * 2 - 1 = 0.5
这意味着屏幕中心点(400, 300)在NDC中位于(0, 0.5)。
# 为什么使用NDC?
- 一致性:NDC提供了一个一致的坐标系统,使得在不同的屏幕分辨率下编写的着色器代码可以更灵活地工作。
- 视口变换:在OpenGL和WebGL中,片段坐标最终会被转换到NDC,然后通过视口变换映射到屏幕空间。
- 跨平台:NDC使得着色器效果在不同设备和分辨率上保持一致,无需针对每个分辨率单独调整。
# 在GLSL中使用NDC
在GLSL中,你可以在片段着色器中直接使用gl_FragCoord
,然后根据上面提供的公式进行转换。例如:
void main() {
vec2 ndc = (gl_FragCoord.xy / resolution.xy) * 2.0 - 1.0;
// 使用ndc坐标进行着色操作...
}
# 2. gl_FragCoord 范围
gl_FragCoord
在 WebGL 和 GLSL 中代表当前片段的屏幕坐标。其坐标范围取决于你是在查看屏幕空间坐标还是归一化设备坐标(Normalized Device Coordinates, NDC)。
屏幕空间坐标:
- 在屏幕空间中,
gl_FragCoord
的 x 和 y 分量的范围通常是从(0, 0)
到(width, height)
,其中(width, height)
是屏幕或渲染目标的分辨率。例如,如果你的渲染目标是 800x600 像素,那么gl_FragCoord
的 x 坐标范围从 0 到 799,y 坐标范围从 0 到 599。
- 在屏幕空间中,
归一化设备坐标 (NDC):
- 在归一化设备坐标中,
gl_FragCoord
的 x 和 y 分量被映射到[-1, 1]
的范围内。这是通过将屏幕空间坐标除以渲染目标的尺寸,然后乘以 2 并减去 1 来实现的。具体转换公式如下: [ \text{NDC_x} = \frac{2 \times \text{gl_FragCoord.x}}{\text{resolution.x}} - 1 ] [ \text{NDC_y} = 1 - \frac{2 \times \text{gl_FragCoord.y}}{\text{resolution.y}} ] - 这种转换使得坐标
(0, 0)
对应于屏幕的中心,(-1, -1)
对应于屏幕的左下角,(1, 1)
对应于屏幕的右上角。
- 在归一化设备坐标中,
深度坐标:
gl_FragCoord
的 z 分量表示片段的深度值,这个值的范围取决于深度测试函数,但通常是从 0 到 1,其中 0 表示最接近观察者,1 表示最远。
视角坐标:
gl_FragCoord
的 w 分量在片段着色器中通常没有直接的用途,因为它与透视除法有关,在顶点着色器中被用来转换坐标到屏幕空间。
在编写着色器时,开发者可能会根据需要在屏幕空间坐标和归一化设备坐标之间转换,以实现不同的视觉效果。
# 1. gl_FragCoord 是什么?
gl_FragCoord
是 GLSL(OpenGL Shading Language)中的一个内置变量,它代表当前片段(fragment)的屏幕坐标。在WebGL(一种基于OpenGL ES的Web标准)中,这个变量用于着色器编程,尤其是片段着色器(fragment shader)中。
以下是 gl_FragCoord
的几个关键点:
内置变量:
gl_FragCoord
是一个 vec4 类型的向量,由 WebGL 引擎自动提供给片段着色器。屏幕坐标:
gl_FragCoord
的前两个分量(即xy
分量)表示当前片段在屏幕坐标系中的位置。屏幕坐标系的原点(0,0)通常位于屏幕的左下角,其中 x 轴向右为正,y 轴向上为正。深度和视角:
gl_FragCoord
的第三个分量(z
分量)表示片段的深度值,可用于深度测试。第四个分量(w
分量)通常用于透视除法,但在片段着色器中很少使用。用途: 在片段着色器中,
gl_FragCoord
可以用来获取片段的位置信息,从而可以根据片段的位置执行不同的着色操作。例如,可以用来实现一些基于屏幕位置的特效,如边缘检测、扭曲效果等。归一化设备坐标: 通过将
gl_FragCoord
除以屏幕尺寸并乘以2,可以将其转换为归一化设备坐标(NDC),范围在 [-1.0, 1.0] 之间。这种转换在处理屏幕空间特效时非常有用。与
resolution
的关系: 通常,会将gl_FragCoord
与一个名为resolution
的 uniform 变量结合使用,resolution
存储了屏幕或渲染目标的宽度和高度。通过这种方式,可以创建与屏幕分辨率无关的着色器效果。
# 3. (gl_FragCoord.xy / resolution.xy * 2.0) 表示什么?
在GLSL(OpenGL Shading Language)中,gl_FragCoord
是一个内置变量,它代表当前片段(fragment)的窗口坐标(window coordinate)。每个片段对应于屏幕或渲染目标上的一个像素点。
下面是对表达式 (gl_FragCoord.xy / resolution.xy * 2.0)
的逐部分解释:
gl_FragCoord.xy
: 这表示gl_FragCoord
的 x 和 y 分量,即当前片段的屏幕坐标。在WebGL中,坐标原点(0,0)通常位于屏幕的左下角,x 轴向右为正方向,y 轴向上为正方向。resolution.xy
: 这表示传入着色器的resolution
uniform 变量的 x 和 y 分量,通常表示屏幕或渲染目标的分辨率,例如resolution
可能是vec2(800, 600)
表示屏幕分辨率为800x600像素。(gl_FragCoord.xy / resolution.xy)
: 这个操作将片段的屏幕坐标除以分辨率,得到归一化设备坐标(Normalized Device Coordinate, NDC),范围通常是[-1.0, 1.0]
。归一化设备坐标是相对于屏幕中心的,其中(-1, -1)
表示屏幕的左下角,(1, 1)
表示屏幕的右上角。* 2.0
: 乘以2将NDC坐标扩展到[-2.0, 2.0]
的范围,这通常用于创建超出屏幕范围的视觉效果,或者在某些着色器效果中提供更多的空间来处理片段。
综上所述,整个表达式 (gl_FragCoord.xy / resolution.xy * 2.0)
将片段的屏幕坐标转换为相对于屏幕中心的标准化坐标,并且扩大了坐标的范围。这在创建全屏着色器效果时非常有用,因为它允许你访问并处理超出屏幕边界的片段。