OpenGL ES纹理略微偏离

Nic*_*tch 11 c++ textures opengl-es

我试图通过指定我想要的坐标在OpenGL中绘制一个纹理的子区域.然而,正在发生的是,根据图像的大小,它似乎在选择纹理坐标的位置有一个轻微的偏移.偏移量似乎小于像素的大小,并且输出是相邻像素的模糊组合.

这是我所描述的想法.在这种情况下,我想要选择6x5绿色/白色区域,但OpenGL渲染的内容包括顶部和左侧像素的浅粉色调. 偏移图

输出结果如下:

产生的输出纹理

我可以通过在将它们传递给glTexCoordPointer之前向纹理坐标添加偏移来修复它,但问题是我无法计算偏移量是什么,并且对于不同的纹理看起来不同.

伪代码:

float uFactor = regionWidth / textureWidth;   // For the example: 0.6f
float vFactor = regionHeight / textureHeight; // For the example: 0.5f

data[0].t[0] = 0.0f * uFactor;
data[0].t[1] = 0.0f * vFactor;
data[1].t[0] = 1.0f * uFactor;
data[1].t[1] = 0.0f * vFactor;
data[2].t[0] = 0.0f * uFactor;
data[2].t[1] = 1.0f * vFactor;
data[3].t[0] = 1.0f * uFactor;
data[3].t[1] = 1.0f * vFactor;

glPushMatrix();

// translate/scale/bind operations

glTexCoordPointer(2, GL_FLOAT, 0, data[0].t);
Run Code Online (Sandbox Code Playgroud)

Chr*_*ica 19

请记住,OpenGL会在纹素中心对纹理进行采样.因此,当使用线性过滤(如GL_LINEARGL_LINEAR_MIPMAP_LINEAR)时,只有在纹素中心采样时才会返回确切的纹素颜色.因此,当您只想使用纹理的子区域时,需要将纹理坐标缩进半个纹素(或0.5/width0.5/height).否则,过滤将混合纹理的边框与您想要的区域之外的邻接纹理.这会使你的边框略带粉红色.如果你用完整个纹理,这个效果会被GL_CLAMP_TO_EDGE包裹模式补偿,但是当使用一个子区域时,GL不知道它的边缘在哪里,并且过滤不应该越过它.

所以,当你在范围内得到了纹理的子区域[s1,s2]x[t1,t2](0 <= s,t <= 1),真正有效的texCoord间隔应[s1+x,s2-x]x[t1+y,t2-y]x正在0.5/widthy being 0.5/height(对应于整个纹理的宽度和高度[0,1]x[0,1]).

所以试试吧

data[0].t[0] = 0.0f * uFactor + 0.5/textureWidth;
data[0].t[1] = 0.0f * vFactor + 0.5/textureHeight;
data[1].t[0] = 1.0f * uFactor - 0.5/textureWidth;
data[1].t[1] = 0.0f * vFactor + 0.5/textureHeight;
data[2].t[0] = 0.0f * uFactor + 0.5/textureWidth;
data[2].t[1] = 1.0f * vFactor - 0.5/textureHeight;
data[3].t[0] = 1.0f * uFactor - 0.5/textureWidth;
data[3].t[1] = 1.0f * vFactor - 0.5/textureHeight;
Run Code Online (Sandbox Code Playgroud)

  • 您可以尝试将顶点坐标与像素中心对齐,这意味着将它们调整半个像素(当然,在视图坐标中).否则它们有点偏离纹理坐标,这意味着你有一个带有cxd纹理的axb rect.如果您想要像素精确纹理,则需要== c和b == d.所以也要对texCoords进行同样的调整.然后尺寸匹配. (2认同)