OpenGL ES 3.0编程指南:第九章. Texturing---(三)

[TOC]

Texture Filtering and Mipmapping

到目前为止,我们将2D纹理的解释限制在单独的2D图像上。尽管这样可以允许我们解释纹理的概念,但是在OpenGL ES中,关于纹理的声明和使用还有更多的内容。到目前为止,我们知道纹理坐标会产生纹理贴图的一个索引,用来获取图像数据。当缩小和方法过滤模式设为GL_NEAREST时,将在纹理坐标的位置上读取纹理像素。这被称作点采样或者最近采样。

然而,最近采样可能会产生明显的视觉伪像。只是因为当图像缩小时,在像素之间进行插值时纹理坐标会发生较大的跳跃,部分采样点会丢失,造成视觉伪像和性能损失。用来解决这种视觉伪像的方案就是mipmap。Mipmap的思路是建立一个图像链称为mipmap链,这个mipmap链以原始图像开始,后续的每个图像的每个维度都是它上一个图像大小的一半,直到链底部的一个1x1大小的纹理。Mip图像可以编程生成,一个mip级别图像的每个像素通常根据上一个级别贴图中相同位置的4个像素的平均值计算得到(box filtering)。

下面的例子展示了如何通过盒试过滤生成mipmap链:

glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);

level = 1;
prevImage = &pixel[0];

while (width > 1 && height > 1)
{
    int newWidth, newHeight;

    GenMipMap2D (prevImage, &newImage, width, height, &newWidth, &newHeight);

    glTexImage2D (GL_TEXTURE_2D, level, GL_RGB, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, newImage);

    free(prevImage);

    prevImage = newImage;
    level++;

    width = newWidth;
    height = newHeight;
}

free (newImage);

Mipmap链加载完成后,就可以设置过滤模式来使用mipmap了,从而减少锯齿伪像。
有两种过滤类型会发生:缩小和放大。当在屏幕上的投影多边形的尺寸小于纹理尺寸时发生缩小过滤,反之发生放大过滤。由硬件决定发生哪一种过滤类型,但是API可以控制每种过滤类型采用哪种过滤方法。对于放大过滤,mipmap意义不大,因为我们总是会从最大的级别图像进行取样。对于缩小过滤,有很多种采样模式,采用哪种采样模式基于你需要获得的显示质量以及愿意损失多少性能。

使用下列方法来声明过滤模式:

void glTexParameteri (GLenum target, GLenum pname, GLint param);
void glTexParameteriv (GLenum target, GLenum pname, const GLint * params);
void glTexParameterf (GLenum target, GLenum pname, GLfloat param);
void glTexParameterfv (GLenum target, GLenum pname, const GLfloat * params);

  • target : 可取值为
    GL_TEXTURE_2D,
    GL_TEXTURE_3D,
    GL_TEXTURE_2D_ARRAY,
    GL_TEXTURE_CUBE_MAP
  • pname : 要设置哪一项参数,可取值为
    GL_TEXTURE_BASE_LEVEL,
    GL_TEXTURE_COMPARE_FUNC
    GL_TEXTURE_COMPARE_MODE
    GL_TEXTURE_MIN_FILTER
    GL_TEXTURE_MAG_FILTER
    GL_TEXTURE_MIN_LOD
    GL_TEXTURE_MAX_LOD
    GL_TEXTURE_MAX_LEVEL
    GL_TEXTURE_SWIZZLE_R
    GL_TEXTURE_SWIZZLE_G
    GL_TEXTURE_SWIZZLE_B
    GL_TEXTURE_SWIZZLE_A
    GL_TEXTURE_WRAP_S
    GL_TEXTURE_WRAP_T
    GL_TEXTURE_WRAP_R
  • params :参数值,可取值如下表

| pname | params |
| --- | --- |
| GL_TEXTURE_MAG_FILTER | GL_NEAREST, GL_LINEAR|
| GL_TEXTURE_MIN_FILTER | GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR |
| GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R | GL_REPEAT, GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT |
| GL_TEXTURE_COMPARE_FUNC | GL_LEQUAL, GL_GEQUAL, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER |
| GL_TEXTURE_COMPARE_MODE | GL_COMPARE_REF_TO_TEXTURE, GL_NONE |
| GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G, GL_TEXTURE_SWIZZLE_B, GL_TEXTURE_SWIZZLE_A | GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE |

放大过滤模式可以设置为GL_NEAREST或者GL_LINER:

  • GL_NEAREST :从最靠近纹理坐标的纹理进行点采样
  • GL_LINEAR :从纹理坐标附近的纹理中进行双线性采样(4个样本的平均值)

缩小过滤模式可以设置为如下值:

  • GL_NEAREST : 从最靠近纹理坐标的纹理进行点采样
  • GL_LINEAR :从最靠近纹理坐标的纹理中进行双线性采样(4个样本的平均值)
  • GL_NEAREST_MIPMAP_NEAREST : 从选择的最近的mip级别进行点采样
  • GL_NEAREST_MIPMAP_LINEAR :从两个最近的mip级别进行点采样,然后对采样值进行插值
  • GL_LINEAR_MIPMAP_NEAREST :从选择的最近的mip级别进行双线性采样
  • GL_LINEAR_MIPMAP_LINEAR :从两个最近的mip级别进行双线性采样,然后对采样值进行插值,这种模式也被称为三线性过滤,是所有模式中效果质量最好的。
    注意:在缩小过滤模式中,只有GL_NEAREST和GL_LINEAR不需要完整的mipmap链,其他模式都需要。

值得一提的是,你选择的过滤模式对性能会有一定的影响。如果缩小过滤发生并且性能是关键,那么使用mipmap过滤模式通常是最好的选择。如果没有使用mipmap,那么纹理缓存利用率可能非常低,因为读取发生在贴图的少数位置。然而,如果你选择的过滤模式越高级,那么性能代价也就越大。所以,应该选择一种能够满足质量要求并且不会对性能造成太大影响的过滤模式。

Seamless Cubemap Filtering (无缝立方图过滤)

在OpenGL ES 3.0中,立方图的过滤模式有了一个新的变化。在OpenGL ES 2.0中,当线性过滤核心发生在边缘时,过滤只会发生在立方图的一个面上,这会在立方图各面的边缘产生伪像。而在OpenGL ES 3.0中,立方图过滤是无缝的了,如果过滤核心发生在边缘上时,将会从它覆盖的所有面中获取样本,这样就在各面的边缘形成了更平滑的过滤。在OpenGL ES 3.0中,不需要手动开启无缝过滤,会自动使用。

你可能感兴趣的:(OpenGL ES 3.0编程指南:第九章. Texturing---(三))