webgl 纹理贴图
webgl 纹理贴图
在三维图形学中,有一项很重要的技术就是:就是将一张图像(就像一张贴纸)映射(贴)到一个几何图形的表面上去。这就是纹理映射(texture mapping)。此时,这张图片又可以称为纹理图像(texture image)或纹理(texture)。
纹理坐标 纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色。WebGL 系统中的纹理坐标系统是二维的。为了将纹理坐标和广泛使用的x坐标和y坐标区分开来,WebGL 使用s和t命名纹理坐标(st坐标系统)
纹理图像四个角的坐标为左下角(0.0,0.0),右下角(1.0,0.0),右上角(1.0,1.0)和左上角(0.0,1.0)。纹理坐标与图像自身的尺寸无关,不管是128×128还是128×256的图像,其纹理坐标始终是左下角(0.0,0.0),右下角(1.0,0.0),右上角(1.0,1.0)和左上角(0.0,1.0)
纹理贴图的过程
1 |
|
完整代码:
1 |
|
Y轴反转
纹理也有一套自己的坐标系统,为了和顶点坐标加以区分,通常把纹理坐标称为 UV
,U
代表横轴坐标,V
代表纵轴坐标。
在使用图像之前,必须对它进行Y轴反转。
1 |
|
纹理参数
1 |
|
target
- gl.TEXTURE_2D 二维纹理贴图
- gl.TEXTURE_CUBE_MAP_POSITIVE_X:立方体映射纹理的正X面。
- gl.TEXTURE_CUBE_MAP_NEGATIVE_X: 立方体映射纹理的负X面。
- gl.TEXTURE_CUBE_MAP_POSITIVE_Y: 立方体映射纹理的正Y面。
- gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: 立方体映射纹理的负Y面
- gl.TEXTURE_CUBE_MAP_POSITIVE_Z: 立方体映射纹理的正Z面。
- gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: 立方体映射纹理的负Z面。
level
人眼距离这个纹理越近,图片的精度就越高,使用级别高的纹理。反之精度越小,使用级别低的纹理。
0级是基本图像等级,
n级是第n个金字塔简化级。LOD 层次结构,值越小,人眼距离这个纹理越近,看到的图片越精细,使用精度高的纹理。值越大,人眼距离这个纹理越远,看到的图片越模糊,使用精度低的纹理。
width、height
图片的宽高,如果不指定,就使用 ImageData 自带的宽高
border
纹理的边框宽度。必须为 0。
internalformat
这张纹理存储的格式
format
这张图片文件(也就是image)是什么格式
type
每个分量的精度
WebGLRenderingContext.texImage2D() - Web API 接口参考 | MDN (mozilla.org)
1 |
|
target gl.TEXTURE_2D 二维纹理 gl.TEXTURE_CUBE_MAP 立方体纹理.
pname 纹理参数
- 放大方法(gl.TEXTURE_MAG_FILTER)∶这个参数表示,当纹理的绘制范围比纹理本 身更大时,如何获取纹素颜色。比如说,你将 16×16的纹理图像映射到32×32 像素的空间里时,纹理的尺寸就变成了原始的两倍。WebGL 需要填充由于放大而造成的像素间的空隙,该参数就表示填充这些空隙的具体方法。
- 缩小方法(gl.TEXTURE_MIN_FILTER)∶这个参数表示,当纹理的绘制范围比纹理本 身更小时,如何获取纹素颜色。比如说,你将32×32的纹理图像映射到16×16 像素的空间里,纹理的尺寸就只有原始的一半。为了将纹理缩小,WebGL 需要剔除纹理图像中的部分像素,该参数就表示具体的剔除像素的方法。
- 水平填充方法(g1.TEXTURE_WRAP_S )∶这个参数表示,如何对纹理图像左侧或右侧的区域进行填充。
- 垂直填充方法(g1.TEXTURE_WRAP_T)∶这个参数表示,如何对纹理图像上方和下 方的区域进行填充。
param 纹理参数的值
默认值 |
---|
| gl.TEXTURE_MAG_FILTER
| 纹理放大时的算法法 | gl.LINEAR
(默认值), gl.NEAREST
. | 这个参数表示,当纹理的绘制范围比纹理本
身更大时,如何获取纹素颜色。比如说,你将 16×16的纹理图像映射到32×32 像素的空间里时,纹理的尺寸就变成了原始的两倍。WebGL 需要填充由于放大而造成的像素间的空隙,该参数就表示填充这些空隙的具体方法。
|
| gl.TEXTURE_MIN_FILTER
| 缩小方法 | gl.LINEAR
, gl.NEAREST
, gl.NEAREST_MIPMAP_NEAREST
, gl.LINEAR_MIPMAP_NEAREST
, gl.NEAREST_MIPMAP_LINEAR
(默认值), gl.LINEAR_MIPMAP_LINEAR
. | 这个参数表示,当纹理的绘制范围比纹理本
身更小时,如何获取纹素颜色。比如说,你将32×32的纹理图像映射到16×16 像素的空间里,纹理的尺寸就只有原始的一半。为了将纹理缩小,WebGL 需要剔除纹理图像中的部分像素,该参数就表示具体的剔除像素的方法。 |
| gl.TEXTURE_WRAP_S
| 水平填充方法 | gl.REPEAT
(默认值),gl.CLAMP_TO_EDGE
, gl.MIRRORED_REPEAT
. | 这个参数表示,如何对纹理图像左侧或右侧的区域进行填充。 |
| gl.TEXTURE_WRAP_T
| 垂直填充方法 | gl.REPEAT
(默认值),gl.CLAMP_TO_EDGE
, gl.MIRRORED_REPEAT
. | 这个参数表示,如何对纹理图像上方和下
方的区域进行填充。 |
g1.NEAREST | 使用原纹理上距离映射后像素(新像素)中心最近的那个像素的颜色值,作为新像素的值(使用曼哈顿距离’。) |
gl.LINEAR | 使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值(与 g1.NEAREST 相比.该方法图像质量更好,但是会有较大的开销。) |
gl.REPEAT | 平铺式的重复纹理 |
gl.MIRRORED_REPEAT | 镜像对称式的重复纹理 |
gl.CLAMP_TO_EDGE | 使用纹理图像边缘值 |
例子
1 |
|
纹理过渡的方法
在使用纹理贴图的过程中,纹理的大小和WebGL绘制的图形的大小并不能完全一致,,可能纹理对象大,也可能纹理对象小。
- 当纹理图像大于WebGL图形时,WebGL图形的一个片元与许多纹理像素映射。
- 当纹理图像小于WebGL图形时,WebGL图形的许多个片元会和同一纹理的像素映射。
当以上情况发生时,纹理的像素点并不能和图形的像素点一一对应。对于缺失或者多余的像素点,WebGL提供了几种处理方法。
gl.NEAREST (最近点采样)
当纹理被放大或者缩小时,WebGL会在原始图像上根据片元着色器中的纹理坐标来寻找最近的像素点来决定片元的颜色。
优点
- 算法简单,计算量也小
缺点
- 当纹理被放大多倍时,容易产生明显的锯齿。
- 纹理缩小很多时,图像会变得模糊不清。
gl.LINEAR (线性采样)
线性采样时,WebGL会使用原始图像上距离纹理坐标最近的多个像素点的颜色的加权平均值作为片元的颜色。比如,在一个白的和一个黑的像素之间的像素会被输出为灰色。
优点:
- 不会出现锯齿,而是平滑过渡
**Mipmaps 多重细节纹理 **(缩小时的纹理过滤方法)
- gl.NEAREST_MIPMAP_NEAREST。 从一系列纹理中找到尺寸最接近的一个,然后采用gl.NEAREST方式从该纹理中获取像素点
- gl.NEAREST_MIPMAP_LINEAR。 从一系列纹理中找到尺寸最接近的一个,然后采用gl.LINEAR方式从该纹理中获取像素点
- gl.LINEAR_MIPMAP_NEAREST。 从一系列纹理中找到尺寸最接近的两个,然后采用gl.NEAREST方式从两个纹理中获取像素点颜色,然后通过加权平均获取两个像素点颜色的平均值。
- gl.LINEAR_MIPMAP_LINEAR。 从一系列纹理中找到尺寸最接近的两个,然后采用gl.LINEAR方式从两个纹理中获取像素点颜色,然后通过加权平均获取两个像素点颜色的平均值。
填充方法
gl.REPEAT
超出纹理范围的坐标整数部分被忽略,形成重复效果。这是默认的填充方式
gl.CLAMP_TO_EDGE(边缘值填充)
超出纹理范围的坐标被截取成0(昨面)和1(右面),形成纹理边缘延伸的效果。
gl.MIRRORED_REPEAT
超出纹理范围的坐标整数部分被忽略,但当整数部分为奇数时进行取反,形成镜像效果