OpenGL ES 纹理坐标略有偏差

发布于 2024-11-07 11:00:21 字数 948 浏览 0 评论 0原文

我试图通过指定我想要的坐标来在 OpenGL 中绘制纹理的子区域。但发生的情况是,根据图像的大小,选择纹理坐标的原点似乎有轻微的偏移。偏移量似乎小于像素的大小&输出是相邻像素的模糊组合。

这是我所描述的一个想法。在本例中,我想要选择 6x5 绿色/白色区域,但 OpenGL 渲染的内容包括顶部和底部的轻微粉红色调。左像素。 Offset Illustration

输出的样子:

结果输出纹理

我可以通过在将纹理坐标传递给 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);

I'm trying to draw a subregion of a texture in OpenGL by specifying the coordinates I want. What's happening though is that, depending on the size of the image, it seems there's a slight offset in the origin of where it selects the texture coordinates. The offset amount seems to be less than the size of a pixel & the output is is blurred combination of neighboring pixels.

Here's an idea of what I'm describing. In this case I'd want to select the 6x5 green/white region but what OpenGL is rendering includes a slight pink tint to the top & left pixels.
Offset Illustration

What the output would look like:

Resulting Output Texture

I can fix it by adding an offset to the texture coordinates before passing them to glTexCoordPointer but the problem is that I have no way to calculate what the offset is and it seems different for different textures.

Pseudocode:

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦途 2024-11-14 11:00:21

请记住,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],其中 x0.5/widthy 为 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;

Keep in mind, that OpenGL samples textures at the texel centers. So when using linear filtering (like GL_LINEAR or GL_LINEAR_MIPMAP_LINEAR) the exact texel color is only returned if sampled at the texel center. Thus, when you only want to use a sub-region of a texture, you need to indent your texture coordinates by half a texel (or 0.5/width and 0.5/height). Otherwise the filtering will blend the border of the texture with neigbouting texels outside of your intended region. This causes your slightly pinkish border. If you use up the whole texture this effect is compensated by the GL_CLAMP_TO_EDGE wrapping mode, but when using a subregion, GL does not know where it's edge is and that filtering should not cross it.

So when you got a subregion of the texture in the range [s1,s2]x[t1,t2] (0 <= s,t <= 1), the real valid texCoord interval should be [s1+x,s2-x]x[t1+y,t2-y] with x being 0.5/width and y being 0.5/height (the width and height of the whole texture corresponding to [0,1]x[0,1]).

Therefore try

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;
海风掠过北极光 2024-11-14 11:00:21

这可能与环绕有关。创建源图像时尝试此操作:

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP )
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP )

Propably this has to do with the wrap around. Try this when you create the source image:

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP )
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文