我正在尝试使用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
对于所有渲染过程都是相同的,只是一个正交投影。 textureWidth
和textureHeight
是保存邻居数据的纹理的大小(通常为1024x1024)。
屏幕/纹理位置的计算是否正确?
答案 0 :(得分:0)
屏幕/纹理位置的计算是否正确?
你的视口是什么?这看起来很合适,假设视口大小与纹理相同(您已经说过)和批判性,不包含偏移(例如,其原点是 0 , 0 强>)。
这里唯一真正的问题是使用texelFetch (...)
需要整数坐标,transformedPos
是一个浮点向量。 GLSL没有定义从vecN
到ivecN
的隐式转换,因此您无法使用直接计算的坐标 - 您必须自己构建ivec
。
ivec2 texel_coords = ivec2 (transformedPos.x, transformedPos.y);
幸运的是,因为纹素是以i + 0.5 为中心而不是i + 0.0 ,所以当你将坐标从浮点转换为整数时,它们被截断的事实证明了在这种情况下无关紧要。也就是说,像素坐标 511.9 明显更接近 512 而 511 。如果纹素是以整数边界为中心,那么当你试图找到最近的邻居时, 511.9 在转换为整数时变为 511 的事实真的会搞乱。