OpenGL广告牌插值问题

Posted

技术标签:

【中文标题】OpenGL广告牌插值问题【英文标题】:OpenGL billboard interpolation issue 【发布时间】:2010-04-04 16:38:25 【问题描述】:

我有一个贴有纹理的广告牌四边形。

这基本上是一些具有透明度的文本。

广告牌从相机的角度向前和向后浮动。

随着广告牌移开(并且看起来更小),会出现闪烁效果 在实际纹理上有笔触边框的文本边缘周围。

我认为这是因为需要插值,因为通常 X 像素宽的图像现在仅显示为 X 的百分比,并且需要将一些像素合并在一起。我猜它是在做最近的邻居还是什么?谁能指出我正确的方向来控制opengl设置,我猜有一些方法可以通过调整处理纹理的方法来防止这种效果发生?

我认为这与以下内容有关:

GL_NEAREST_MIPMAP_NEAREST

但是当我尝试为 MIN 过滤器设置它并启用 mip 映射时,我的纹理变得非常块状和模糊......

我也试过了:

GL_LINEAR_MIPMAP_LINEAR

这显然是 MIN 过滤器的三次过滤,但我的图像在显示时非常模糊。 (看起来它是一个非常低分辨率的纹理)任何想法我做错了什么?

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // trilinear

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

更多代码:

// Allocated memory needed for the bitmap context
spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
// Uses the bitmap creation function provided by the Core Graphics framework. 
spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
// After you create the context, you can draw the sprite image to the context.
CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage);
// You don't need the context at this point, so you need to release it to avoid memory leaks.
CGContextRelease(spriteContext);

// Use OpenGL ES to generate a name for the texture.
glGenTextures(1, &spriteTexture[textureCount-1]); 

// Bind the texture name. 
glBindTexture(GL_TEXTURE_2D, spriteTexture[textureCount-1]);


glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);



// Specify a 2D texture image, providing the a pointer to the image data in memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
// Release the image data
free(spriteData);

纹理为 512 x 512。

使用 MIN 滤镜时的模糊示例:

当只使用 GL_NEAREST 作为最小过滤器时更清晰但令人讨厌的双线性和闪烁,当动画收缩时如上所述:

【问题讨论】:

你能显示一些截图吗? 另外,你需要在上传纹理之前设置这些参数(使用glTexImage2d左右)。这样,当你调用glTexImage2d 时,mipmap 就会生成。如果没有剩下的代码,我看不出你在做什么。 普通的 'ole GL_LINEAR 会发生什么? 用 GL_LINEAR 也一样模糊 @PeanutPower:希望能够平滑 1px 文本边框,使其不会像缩小一样闪烁。 【参考方案1】:

如果您使用的是 glu,我建议您尝试使用 gluBuild2DMipmaps 来创建 mipmap,看看其他人是如何做到这一点的。

为了避免使用 glu 函数,我有时会查看 Mesa 的 OpenGL 实现以获得一些想法(我通常会尝试在自己的项目中保留很多代码。我在 OpenGL、D3D 和其他平台)。您可以尝试查看 gluBuild2DMipmaps 的 Mesa 实现 (MesaLib) 的源代码,看看如何获​​得类似的效果。它出现在 MesaLib 的 mipmap.c 中,您可能最终会跳转到 bitmapBuild2DMipmaps 的实现。

我不能保证这会带来好的结果,但这是一个值得探索的途径。对于正在发生的事情的一般调试,您可以尝试的另一件事是将您的 mipmap 纹理输出到文件以供外部查看。所有这一切当然是在您用尽了随机切换标志和谷歌搜索其他人的代码以查看您是否错过任何状态函数的选项之后。

【讨论】:

【参考方案2】:

Mipmapping 由正在绘制的片段的纹素与像素的比率控制(希望我的术语在那里是正确的)。你在屏幕上画多大?

如果您在(例如)128x128 上绘制它,您将获得 mipmap 级别 2,因此会出现模糊。

应该按照它们将在屏幕上显示的大小创建纹理,或者尽可能接近,而不是产生太多像素并让 GPU 选择不合适的 mipmap 级别...

【讨论】:

以上是关于OpenGL广告牌插值问题的主要内容,如果未能解决你的问题,请参考以下文章

在相机后面的位置进行广告牌时的伪影

OpenGL着色器没有将变量从顶点传递到片段着色器

OpenGL 颜色插值

使用余弦函数的OpenGL颜色插值?

OpenGL 缺陷 - 不需要的插值

SceneKit + ARKit:无需相机滚动的广告牌