【问题标题】:OpenGL Mipmapping: how does OpenGL decide on map level?OpenGL Mipmapping:OpenGL 如何决定地图级别?
【发布时间】:2010-05-25 16:51:56
【问题描述】:

我无法在 OpenGL 中实现 mipmapping。我正在使用 OpenFrameworks 并修改了 ofTexture 类以支持 mipmap 的创建和渲染。

以下代码是该类的原始纹理创建代码(为清楚起见稍作修改):

  glEnable(texData.textureTarget);
      glBindTexture(texData.textureTarget, (GLuint)texData.textureID);
      glTexSubImage2D(texData.textureTarget, 0, 0, 0, w, h, texData.glType, texData.pixelType, data);
      glTexParameteri(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glDisable(texData.textureTarget);

这是我的支持 mipmap 的版本:

  glEnable(texData.textureTarget);
       glBindTexture(texData.textureTarget, (GLuint)texData.textureID);
       gluBuild2DMipmaps(texData.textureTarget, texData.glTypeInternal, w, h, texData.glType, texData.pixelType, data);
       glTexParameteri(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
       glTexParameteri(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  glDisable(texData.textureTarget);

代码不会产生错误(gluBuild2DMipmaps 返回“0”)并且纹理渲染没有问题。但是,我看不出有什么不同。

我渲染的场景由 z=0 处的“平面方形图块”组成。它基本上是一个 2D 场景。在绘制瓷砖之前,我使用“glScale()”放大和缩小。当我缩小时,平铺纹理的像素开始“跳舞”,表明(据我所知)未过滤的纹理查找。请参阅:http://www.youtube.com/watch?v=b_As2Np3m8A 25 秒。

我的问题是:由于我不移动相机位置,而只使用整个场景的缩放,这是否意味着 OpenGL 无法决定适当的 mipmap 级别并使用完整的纹理大小(级别 0)?

保罗

【问题讨论】:

    标签: opengl filter textures mipmaps


    【解决方案1】:

    除了透视距离之外,Mipmapping 还将补偿场景比例。顶点着色器输出(即使您不使用自己的着色器,驱动程序仍会创建)指定每个顶点的屏幕空间坐标和这些顶点的纹理坐标。 GPU 将根据将要生成的片段的纹理像素比来决定使用哪个 mip 级别。

    您在渲染图块时是否也在设置GL_LINEAR_MIPMAP_LINEAR?仅在渲染事物时才重要,而不是在创建/加载纹理时。您的包围 glEnable/glDisable 调用也可能需要移动,具体取决于您实际传入的状态。

    【讨论】:

    • 感谢您的回复。我已将 glTexParamateri() 调用移至对 gluBuild2DMipmaps() 的调用之上,甚至将它们添加到绘图函数中。我也打电话给 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) ,但我仍然看不出有什么区别。至少,多亏了你,我现在明白了 OpenGL 如何决定 mipmap 级别。
    • @Droozle:当您将 glTexParameter 移动到渲染代码时,您是在 glDraw* 调用之前还是之后放置它?它必须在之前。当你调用 glTexParameter 或 glEnable 之类的东西时,你是在 gl 驱动程序中设置一个状态。驱动程序会记住这些状态,直到您将其设置为其他状态。这些状态中的大多数仅在您调用 glDrawSomething 时由驱动程序使用。
    • 感谢您的回复。我知道 OpenGL 是一个状态机,我认为我按照书本做了所有事情。在查看了至少 20 个不同的代码示例之后,我现在已经放弃了。也许这与我的纹理具有 Alpha 通道这一事实有关,但到目前为止我运气不佳。这很奇怪。
    【解决方案2】:

    如果您的目标是 OpenGL >= 1.4,您可能应该切换到 automatic mipmap generation

    您可以尝试更改 GL_TEXTURE_MIN/MAX_LOD 以强制使用特定的 mip 级别。

    【讨论】:

    • 谢谢,我尝试了 MIN/MAX_LOD 选项,但还是没有效果。不过,我注意到 glTexSubImage2D() 不支持 mipmapping。我已将其更改为 glTexImage2D() 调用,并遵循有关自动生成 mipmap 的建议。仍然没有成功,没有视觉差异,像素仍然闪烁。我的驱动程序支持 OpenGL2.1,所以它应该可以工作。我很困惑,呵呵。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    相关资源
    最近更新 更多