对纹素中心进行采样不会给出正确的结果,OpenGL,C++

Posted

技术标签:

【中文标题】对纹素中心进行采样不会给出正确的结果,OpenGL,C++【英文标题】:Sampling on the texel centers doesn't give proper results, OpenGL, C++ 【发布时间】:2012-12-18 15:15:07 【问题描述】:

不久前我在显示纹理时遇到了问题,因为我使用纹素的边缘作为纹理坐标而不是纹素的中心。这与线性混合相结合,给出了颜色的平滑结果,而不是纹理给出的纯色。

感谢这里给我的建议,当我开始使用纹素中心作为坐标时,我认为我的问题已经解决,但它只在一种情况下有效,我不知道为什么只在那种情况下有效。

我再展示一些图片。

这是我正在使用的纹理(32x32 像素),边框为 2 像素:

我正在绘制的整个对象由 9 个四边形组成,但它们只使用一个纹理(我展示的那个)。其中之一将作为我的问题的解释:

我认为该四边形的颜色没有根据纹理正确设置是很明显的。

看起来像混合的问题,但是为了设置纹理坐标,我使用了纹素的中心,如下所示:

glBegin(GL_QUADS);
    // Bottom left
    glTexCoord2f(0.0 + texelCentersOffset, maxTexCoordBorderY + texelCentersOffset);
    glVertex2i(pos.x, pos.y + height - m_borderWidth);

    // Top left
    glTexCoord2f(0.0 + texelCentersOffset, (GLfloat)1.0 - maxTexCoordBorderY - texelCentersOffset);
    glVertex2i(pos.x, pos.y + m_borderWidth);

    // Top right
    glTexCoord2f(maxTexCoordBorderX - texelCentersOffset, (GLfloat)1.0 - maxTexCoordBorderY - texelCentersOffset);  
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);

    // Bottom right
    glTexCoord2f(maxTexCoordBorderX - texelCentersOffset, maxTexCoordBorderY + texelCentersOffset);
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
glEnd();

澄清:

m_borderWidth = 2

maxTexCoordBorderX = maxTexCoordBorderY = 2/32 = 0.0625

texelCentersOffset = 1/64 = 0.015625

谁能告诉我我写的东西有什么问题?

编辑1:

这是我的纹理的设置:

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                 GL_LINEAR_MIPMAP_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                    GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                    GL_REPEAT );
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, m_width, m_height,
                   GL_RGBA, GL_UNSIGNED_BYTE, pixmap );

当我从 GL_LINEAR 更改为 GL_NEAREST 时,它可以正常工作,所以这显然是混合的问题,但仍然无法弄清楚为什么会出错。

编辑2:

当我将四边形的高度增加到等于或大于纹理的高度时,它可以正常工作而不会更改任何纹理坐标。

【问题讨论】:

您在哪里设置投影和模型视图矩阵? pos 的值是多少? @genpfault pos.x 和 pos.y 为 0,因此可以省略。矩阵在开头设置如下: glViewport(0, 0, width, height); // 重置当前视口 glMatrixMode(GL_PROJECTION); // 选择投影矩阵 glLoadIdentity(); // 重置投影矩阵 glOrtho(0.0, width, height, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); // 选择模型视图矩阵 glLoadIdentity(); // 重置模型视图矩阵 您不应该尝试将纹素中心分配给顶点。您真正想要的是纹素以 光栅化后的结果片段为中心。我在这里写了一个非常通透的答案(用图片来解释),也许阅读它会帮助你理解:***.com/a/11458037/1236185 @Tim 所以根据你的回答我应该不使用这个“texelCentersOffset”,对吧?但话又说回来,正如我在这里写的那样,这种混合存在问题:***.com/questions/13929160/… JasonD 指出我应该使用这个偏移量......或者我误解了你的文章? @Tim 你的问题你没有在纹素中心采样,但是从哪里采样纹理是纹理坐标和纹理坐标的函数顶点位置。为了在 texel 中心进行完美采样,必须考虑两者(以及了解光栅化规则)。对于您的情况,确实可能不需要 texel-offset,但这意味着您必须在准确的像素位置绘制图元,并且尺寸准确。 【参考方案1】:

在我看来,当您将四边形大小设置为小于纹理大小时。它必须使用 mipmap 对纹理进行采样。

Mipmap 是通过平均 4 个纹素块制成的。因此,当您对 mipmap 进行采样时,您会从多个纹素中获取信息。因此,通过让您的四边形小于纹理,它必须对 mipmap 进行采样,并且您正在获得纹理出血。关闭 mipmapping,我猜它会消失。

【讨论】:

抱歉回复晚了,但是是的,这是个问题。谢谢你,Tocs!

以上是关于对纹素中心进行采样不会给出正确的结果,OpenGL,C++的主要内容,如果未能解决你的问题,请参考以下文章

在OpenGL中采样16位高度图的正确方法是啥

为啥在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮?

在OpenGL中加载图像以用于GIS应用程序

第十二节—关于纹理单元

在opengl中找到旋转的图像中心

点云体素下采样 ❤️(体素质心 | 体素中心)