GLSL纹理坐标转绝对像素?

3

我的问题是关于纹理坐标如何映射到纹素(不考虑滤波)。

例如,(0,0) 是指左上角的顶部左侧像素还是指顶部左侧像素的中心?

如果使用近邻滤波,纹理坐标 (0.5,0.5) 获取了哪个像素?

对于 (1.0,1.0),它是指右下角底部右侧像素的底部右侧角还是指底部右侧像素的顶部左侧角?(我记得几年前一些 ATI 和 NVIDIA 显卡之间存在差异。现在是否已经规范化?)

如果使用 texelFetch() 而不是 textureLod(),访问像素的正确方式是什么?

是这样吗?

ivec2 size = textureSize(sampler,0);
ivec2 iCoords = ivec2(int(uv.x*size.x),int(uv.y*size.y));
vec4 col = texelFetch(sampler,iCoords);

或者可能是
ivec2 iCoords = ivec2(int(uv.x*size.x+0.5f),int(uv.y*size.y+0.5f));

你确定吗?

甚至更好的是

ivec2 iCoords = ivec2(int(uv.x*(size.x+1)),int(uv.y*(size.y+1)));

也许有人可以澄清映射是如何确切工作的?

这是一个常见问题。我在StackOverflow.com上已经多次回答过它。https://dev59.com/dlrUa4cB1Zd3GeqPn9xg#7272871 https://dev59.com/9G025IYBdhLWcg3wqXto#5879551 - datenwolf
1个回答

6
如果您的问题只是出于好奇,那么据我所知,对于这个问题没有标准答案,因为纹理坐标不一定要以1.0结束。此外,图形卡将以不同的方式处理值(例如,某些图形卡今天支持64位FP-Ops)。我认为您应该尽量编写安全的代码,如果适用,可以使用0.999而不是1.0。
否则,如果您正在寻找从渲染的纹理中读取像素的方法,您可以按照dominik göddeke关于gpgpu网站中描述的定义您的视口。如果将视口设置为纹理的大小,则可以简单地在其原始坐标处抓取像素。我真的很推荐这个网站,它帮助了我很多。
更新:当使用GL_REPEAT时,纹理坐标在纹理的第一个和最后一个像素之间插值。因此,在4个纹素纹理中,第一个像素的中心位于0.125,因为每个像素的宽度为0.25或1/4。
这更形象地解释了它: 四个纹素的纹理插值

你可以看到,[0,0]处的纹素是[0.125,0]和[0.875,0]的线性混合,且在此示例中等于[1,1]。

所有这些都在DelphiGL维基英语翻译)中有很好的解释。

对于一开始的混淆我感到很抱歉。


那么,如果它是指像素的中心,那么例如(-0.0001,-0.0001)仍然会指向左上角像素吗?(假设纹理包装已激活且纹理很小) - matthias_buehlmann
嗯,但如果这是真的,并且您使用UV坐标(0,0)到(1,1)在角顶点上创建四边形并对其进行纹理处理,那么您将只看到纹理边框像素的一半... - matthias_buehlmann
这取决于GL_TEXTURE_WRAP_S/T参数。如果您启用了GL_REPEATGL_LINEAR,那么(-0.0001,-0.0001)将与(texsize_x, texsize_y)进行最小插值。如果您启用了GL_NEAREST,它仍将返回(0,0)处的纹理颜色。 - devsnd
好的 - 如果我创建一个3x3的纹理,并将其用于一个四边形,并将插值设置为GL_Linear,那么我总是会看到中间有一个完整的像素和周围被切成一半的像素吗? - matthias_buehlmann
你说得对,我马上会更正我的答案。 - devsnd

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