WebGL texture 贴图 采样计算方式 mipmap计算方式

1,329 阅读2分钟

zhuanlan.zhihu.com/p/144332091

纹理过小

  • 直接采取最近的点是不合理的 image.png

  • 解决方案:双线性过滤(Bilinear Filtering)

  • image.png

  • image.png

  • image.png

  • image.png

  • 双三次插值(Bicubic),是利用三次方程来进行两次插值,效果可能更好,但是计算速度很低

纹理过大

  • 直接用大的像素块是不合理的 image.png
  • 解决方案:多级渐远纹理(Mipmap) 各向异性过滤Mipmap
  • 随着level的提升,每提升一级将4个相邻像素点求均值合为一个像素点
  • 那么如何去确定使用哪个level的texture呢?利用屏幕像素的相邻像素点估算footprint大小再确定level
tex2D(sampler2D tex, float2 uv)
{
    float dx=ddx(uv);
    float dy=ddy(uv);
    // texSize.xy为纹理tex的纹素大小
    // texSize.xy=1.0/float2(texWidth,texHeight)
    float px = texSize.x * dx;
    float py = texSize.y * dy;
    float lod = 0.5 * log2(max(dot(px, px), dot(py, py)));
    uv.w= lod;
    return tex2Dlod(tex, uv);
}

在屏幕空间中取当前像素点的右方和上方的两个相邻像素点(4个全取也可以),分别查询得到这3个点对应在Texture space的坐标,计算出当前像素点与右方像素点和上方像素点在Texture space的距离,二者取最大值,计算公式如图中所示,那么level D就是这个距离的log2值 (D = log2L) ! 这不难理解,读者可以具体取几个例子比如L = 1,L = 2,L = 4,看看是否符合这样的计算即可。

  • image.png image.png

纹理过大 各向异性Mipmap

  • 它只能针对正方形纹理进行Mip分层
  • 可以看出不同screen space的像素点所对应的footprint是不同的,有长方形,甚至是不规则图形,那么针对这种情况,有的所需要的是仅仅是水平方向的高level,有的需要的仅仅是竖直方向上的高level,因此这也就启发了各向异性的过滤: image.png
  • 「各项异性过滤」的特性,例如OpenGL中可以通过 GL_TEXTURE_MAX_ANISOTROPY_EXT 来设置纹理中各项异性过滤的数值。 image.png