在纹素中心采样不会得到正确的结果,OpenGL,C++。

10
不久前,我遇到了一个问题,使用texels的边缘作为纹理坐标,而不是texels的中心。这与线性混合相结合,导致颜色平滑而不是纹理所给出的纯色。
感谢在这里给我的建议,我认为我的问题已经解决了,因为我开始使用texels的中心作为坐标,但只在一个情况下起作用,我不知道为什么只有在那个情况下起作用。
再次展示一些图片。
这是我正在使用的纹理(32x32像素),带有2像素的边框:

enter image description here

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

enter image description here

我认为很明显,该四边形的颜色没有根据纹理正确设置。看起来像混合的问题,但是我使用了纹素中心来设置纹理坐标,就像这样:
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();

为了澄清: = 2 = = 2/32 = 0.0625 = 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
@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(); // 重置模型视图矩阵 - Piotr Chojnacki
你不应该尝试将纹素中心分配给顶点。你真正想要的是在光栅化之后,纹素居中于生成的片段上。我在这里写了一个相当详细的答案(附有图片解释),也许阅读这篇文章会帮助你理解:https://dev59.com/Y2gu5IYBdhLWcg3wQE8D#11458037 - Tim
@Tim,根据您的回答,我应该不使用“texelCentersOffset”来解决问题,是吗?但是,正如我在这里写的那样,这会导致混合的问题:https://dev59.com/wWzXa4cB1Zd3GeqPRDSF。而JasonD指出我应该使用这个偏移量...或者我误解了您的文章? - Piotr Chojnacki
@Tim,你的问题在于你没有在纹素中心进行采样,但从哪里采样纹理取决于纹理坐标和顶点位置的函数。为了完美地在纹素中心进行采样,必须考虑两者(以及了解光栅化规则)。确实可能是这种情况,即对于您的情况不需要纹素偏移,但这意味着您必须在精确的像素位置上绘制原语,并且大小恰好正确。 - JasonD
1个回答

3

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

mipmap是通过平均4个texel块创建的。因此,当您采样mipmap时,会从多个texel中获取信息。因此,如果您的四边形比纹理小,则必须采样mipmap,并且会出现纹理溢出的情况。关闭mipmapping,我的猜测是问题会消失。


抱歉回复晚了,但是确实存在问题。谢谢你,Tocs! - Piotr Chojnacki

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