如何在glsl中计算gl_FragCoord

15

在我的GLSL片段着色器中,我想要能够计算碎片距离空间中特定直线的距离。

为此,我首先尝试使用在顶点着色器中设置的可变vec2来反映最终出现在gl_FragCoord中的内容:

varying vec2 fake_frag_coord;
//in vertex shader:
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
fake_frag_coord=(gl_ModelViewProjectionMatrix * gl_Vertex).xy;

现在在片元着色器中,我期望:

gl_FragCoord.xy==fake_frag_coord

但是它不工作。管线对 gl_Position 执行了什么操作,将其转换为 gl_FragCoord,我在处理 fake_frag_coord 时忽略了什么操作?

4个回答

11

gl_FragCoord是屏幕坐标,因此您需要有关屏幕大小等信息才能根据位置生成它。您生成的fake_frag_coord将对应于标准化设备坐标中的屏幕点(我想是-1到1)。因此,如果您在特定维度上乘以半个屏幕大小,然后添加该大小,您将获得实际的屏幕像素。


1
我之前对你的错误评判是错误的,但是关于使用 gl_ModelViewProjectionMatrix * gl_Vertex 可能会引入计算错误这一点是正确的。 - Razzupaltuff
2
吹毛求疵一下:实际上,这将为您提供剪辑空间坐标,而不是标准化设备坐标,因为您没有执行光栅化过程(在顶点着色器和片段着色器之间)中发生的透视除法。http://www.glprogramming.com/red/chapter03.html#name1 - Pike65
@Pike65 这不仅仅是一个小问题,它应该会导致透视投影的完全不同的值。 - Christian Rau
gl_FragCoord.xy==gl_Position.xy/gl_Position.w这段代码是否会进行透视除法? - toolchainX

0

我希望我有更多的声望,这样我也可以吹毛求疵。 这是我知道的。 OpenGL会自动为您执行除法运算,因此当一个位置到达片段着色器时,它已经处于NDC坐标系中,此时W将为1.0,唯一需要除以W的时间是如果您想在CPU端执行相同的数学运算并获得相同的结果,或者出于某种奇怪的原因,您想在顶点着色器中获取NDC坐标。


2
gl_FragCoord 不在标准化设备坐标系中,而是在窗口坐标系中。 - Reto Koradi

0
你遇到的问题是在着色器中计算的 gl_ModelViewProjectionMatrix * gl_Vertex 并不总是与固定功能管线产生的结果相同。为了获得相同的结果,请使用 fake_frag_coord = ftransform()。
编辑:
然后根据屏幕尺寸进行缩放。

ftransform生成位置,而不是fragcoord。问题并不是在问如何获取位置。 - Jay Kominek
我的答案并不完全错误。你需要根据屏幕尺寸来缩放fake_frag_coord,但是使用fake_frag_coord = gl_ModelViewProjectionMatrix * gl_Vertex或者=ftransform()可能会得到不同的结果。 - Razzupaltuff

-2
varying vec2 fake_frag_coord;
//in vertex shader:

fake_frag_coord=(gl_ModelViewMatrix * gl_Vertex).xy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接