webgl 纹理进阶(一) MipMap与RipMap(各向异性过滤)

一.简介

在我们使用纹理的过程中,经常会遇到纹理过大或者过小的情况,纹理过大会使得一个pixel内对应多个tixel,会生成摩尔纹,如下图所示,而纹理过小则会产生马赛克,本节先记录纹理过大时的解决情况

二.在webgl中如何设置

2.1.创建一个纹理

js 复制代码
 function initTexture(gl,image){
    var texture=gl.createTexture()
    //获取纹理存储位置
    var u_Sampler=gl.getUniformLocation(gl.program, 'u_Sampler')
    //y轴翻转
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)

    // //设置一次读取一字节
    // const alignment =1;
    // gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);
    //开启0号纹理单元
    gl.activeTexture(gl.TEXTURE0)
    //想target绑定纹理单元
    gl.bindTexture(gl.TEXTURE_2D, texture)
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image)
    //当纹理过大时采样方法设置
    
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
    //当纹理过小时采样方法设置
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
    //将纹理传递给着色器
    gl.uniform1i(u_Sampler,0)

}

在webgl1中要求纹理图片宽高为2的n次幂,在webgl2中无此要求

这儿使用了一个2048*2048分辨率的图片,效果如下:

可以看到,已经产生了摩尔纹

2.2. MipMAP(多级渐远纹理)

采样会引起走样,那么我们不采样,只得到一定范围的平均值。

这是点查询与范围查询的问题

  • 点查询,给出一个点,得到一个点的值
  • 范围查询,不采样,给出一个区域,得到区域的(平均)值

Mipmap 多级渐远纹理 可以进行快速的范围查询,但是是近似的,并且只有方形

2.3 在webgl中产生MipMap

js 复制代码
gl.generateMipmap(gl.TEXTURE_2D)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR)

在webgl1中,gl.TEXTURE_MIN_FILTER默认值为gl.NEAREST_MIPMAP_LINEAR,即要求默认打开MipMap,因此在上面2.1代码中,如果不设置为gl.LINEAR,会出不来效果

pname Description param
Available in WebGL 1
gl.TEXTURE_MAG_FILTER Texture magnification filter gl.LINEAR (default value), gl.NEAREST.
gl.TEXTURE_MIN_FILTER Texture minification filter gl.LINEAR, gl.NEAREST, gl.NEAREST_MIPMAP_NEAREST, gl.LINEAR_MIPMAP_NEAREST, gl.NEAREST_MIPMAP_LINEAR (default value), gl.LINEAR_MIPMAP_LINEAR.

效果如下:

2.4 各向异性过滤

Mipmap会把远处的细节都模糊掉 因为它只能查询方块的区域内,以及插值毕竟只是近似

  • 解决三线性插值的方法就是各向异性过滤

  • 方块的近似有时候太过勉强,如下图纹理映射后奇形怪状的

  • Mipmap做的是方块的 也就是下图左上角的图,但是不方正的压缩做不了
  • 各向异性过滤允许我们对长条的区域进行范围查询,但是对于斜着的区域,不行 生成各向异性过滤的图(Ripmaps)的开销是原本的三倍 各向异性的意思是,在不同的方向上它的表现各不相同 各向异性的几X是压缩几倍,也就是从左上角往右下角多几层

  • EWA过滤,把任意不规则的形状拆成很多不同的圆形,去覆盖这个形状 多次查询自然可以覆盖,但是耗时大

2.5 webgl启用各向异性过滤

  • 获取扩展
js 复制代码
// 获取扩展对象
var ext = gl.getExtension('EXT_texture_filter_anisotropic');
if (!ext) {
    console.log("Anisotropic filtering extension is not available.");
}

......
// 设置纹理参数,启用各向异性过滤
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 16); // 设置各向异性级别,可以是任意正数

效果如下:

3.MipMap可视化

下面使用自定义设置层级,将MipMap可视化,从1级到11级从蓝色到红色,可以查看mipMap层级,代码如下:

js 复制代码
function initTexture(gl,image){
    var texture=gl.createTexture()
    //获取纹理存储位置
    var u_Sampler=gl.getUniformLocation(gl.program, 'u_Sampler')
    //y轴翻转
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)

    // //设置一次读取一字节
    // const alignment =1;
    // gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);
    //开启0号纹理单元
    gl.activeTexture(gl.TEXTURE0)
    //想target绑定纹理单元
    gl.bindTexture(gl.TEXTURE_2D, texture)
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image)

    gl.generateMipmap(gl.TEXTURE_2D)
    //配置纹理图像

    gl.texImage2D(gl.TEXTURE_2D, 1, gl.RGBA,1024,1024,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(1024,lerpColor(1)))
    gl.texImage2D(gl.TEXTURE_2D, 2, gl.RGBA,512,512,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(512,lerpColor(2)))
    gl.texImage2D(gl.TEXTURE_2D, 3, gl.RGBA,1256,1256,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(256,lerpColor(3)))
    gl.texImage2D(gl.TEXTURE_2D, 4, gl.RGBA,128,128,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(128,lerpColor(4)))
    gl.texImage2D(gl.TEXTURE_2D, 5, gl.RGBA,64,64,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(64,lerpColor(5)))
    gl.texImage2D(gl.TEXTURE_2D, 6, gl.RGBA,32,32,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(32,lerpColor(6)))
    gl.texImage2D(gl.TEXTURE_2D, 7, gl.RGBA,16,16,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(16,lerpColor(7)))
    gl.texImage2D(gl.TEXTURE_2D, 8, gl.RGBA,8,8,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(8,lerpColor(8)))
    gl.texImage2D(gl.TEXTURE_2D, 9, gl.RGBA,4,4,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(4,lerpColor(9)))
    gl.texImage2D(gl.TEXTURE_2D, 10, gl.RGBA,2,2,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(2,lerpColor(10)))
    gl.texImage2D(gl.TEXTURE_2D, 11, gl.RGBA,1,1,0, gl.RGBA,gl.UNSIGNED_BYTE,createColorArray(1,lerpColor(11)))

    //配置纹理参数
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR)
    // gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    //设置纹理参数,启用各向异性过滤
    gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, 16); // 设置各向异性级别,可以是任意正数

    //将纹理传递给着色器
    gl.uniform1i(u_Sampler,0)

}

使用了各向异性之后:

不使用:

由此看出,各向异性使用之后只有在压缩很严重的情况下才会使用较小纹理采样

相关推荐
DT——5 小时前
Vite项目中eslint的简单配置
前端·javascript·代码规范
学习ing小白7 小时前
JavaWeb - 5 - 前端工程化
前端·elementui·vue
真的很上进7 小时前
【Git必看系列】—— Git巨好用的神器之git stash篇
java·前端·javascript·数据结构·git·react.js
胖虎哥er7 小时前
Html&Css 基础总结(基础好了才是最能打的)三
前端·css·html
qq_278063717 小时前
css scrollbar-width: none 隐藏默认滚动条
开发语言·前端·javascript
.ccl7 小时前
web开发 之 HTML、CSS、JavaScript、以及JavaScript的高级框架Vue(学习版2)
前端·javascript·vue.js
小徐不会写代码7 小时前
vue 实现tab菜单切换
前端·javascript·vue.js
2301_765347548 小时前
Vue3 Day7-全局组件、指令以及pinia
前端·javascript·vue.js
ch_s_t8 小时前
新峰商城之分类三级联动实现
前端·html
辛-夷8 小时前
VUE面试题(单页应用及其首屏加载速度慢的问题)
前端·javascript·vue.js