手动计算gl_FragCoord

时间:2014-05-27 23:12:45

标签: c++ opengl graphics glsl

我正在尝试使用OpenGL和GLSL着色器实现最近邻搜索点。 NN计算正常工作,结果被绘制到大小为1024x1024的纹理中(使用当前屏幕大小的视口)。 结果只包含一个保存邻居位置的vec4。

现在重要的部分是: 持有vec4的纹素正好位于投影点的位置(我正在寻找邻居的点)。因此,理论上,为了访问任意点的邻居,我将其世界位置投影到屏幕坐标并使用它们来访问纹理(例如,使用texelFetch)。

如果我在顶点着色器中进行点投影并使用gl_FragCoord访问片段程序中的纹理,则此方法有效。但是现在我遇到了一个新的情况,即只能在片段着色器中使用这些点(通过纹理/缓冲区访问),因此我必须手动计算屏幕位置。

我尝试了以下来自行计算gl_FragCoord,但它不起作用(仅限空白结果):

vec4 pointPos = ... //texture lookup
vec4 transformedPos = matProjectionOrtho * pointPos;
transformedPos.xy /= transformedPos.w;
transformedPos.xy = transformedPos.xy * 0.5f + 0.5f;
transformedPos.xy = vec2(transformedPos.x * textureWidth, 
                         transformedPos.y * textureHeight);

投影矩阵matProjectionOrtho对于所有渲染过程都是相同的,只是一个正交投影。 textureWidthtextureHeight是保存邻居数据的纹理的大小(通常为1024x1024)。

屏幕/纹理位置的计算是否正确?

1 个答案:

答案 0 :(得分:0)

屏幕/纹理位置的计算是否正确?

你的视口是什么?这看起来很合适,假设视口大小与纹理相同(您已经说过)和批判性,不包含偏移(例如,其原点是 0 0 )。

这里唯一真正的问题是使用texelFetch (...)需要整数坐标,transformedPos是一个浮点向量。 GLSL没有定义从vecNivecN的隐式转换,因此您无法使用直接计算的坐标 - 您必须自己构建ivec

有效的事情:

ivec2 texel_coords = ivec2 (transformedPos.x, transformedPos.y);

幸运的是,因为纹素是以i + 0.5 为中心而不是i + 0.0 ,所以当你将坐标从浮点转换为整数时,它们被截断的事实证明了在这种情况下无关紧要。也就是说,像素坐标 511.9 明显更接近 512 511 。如果纹素是以整数边界为中心,那么当你试图找到最近的邻居时, 511.9 在转换为整数时变为 511 的事实真的会搞乱。