WebGL学习笔记(六):纹理贴图

只能够绘制纯色的模型是不够的,为了呈现出更真实的模型,咱们还须要经过纹理贴图给模型进行上色。html

丢失上下文

GPU做为一种公用资源,是会被多个进程同时使用的,在资源不足的状况下(好比PC或手机系统进入休眠状态前或被唤醒后),咱们持有的上下文会出现丢失的状况,为了保证程序运行的健壮性,咱们必须在丢失上下文以后作出处理。git

Canvas为咱们提供了两个事件来监听,上下文的丢失和恢复,具体使用看下面的代码:github

 1 var canvas = document.getElementById("myGLCanvas");
 2 // 监听上下文丢失的事件
 3 canvas.addEventListener("webglcontextlost", function (event) {
 4     // 取消默认行为
 5     event.preventDefault();
 6     // 中止继续绘图的代码
 7 }, false);
 8 // 监听上下文恢复的事件
 9 canvas.addEventListener("webglcontextrestored", function () {
10     // 从新初始化的代码
11     // 须要注意的是 Canvas 经过 getContext 方法得到的上下文对象不须要从新获取, 还能够继续使用以前获取的上下文对象
12     // 开始继续绘图的代码
13 }, false);

模拟丢失上下文

咱们要测试丢失上下文的处理代码是否正常,就须要触发丢失上下文,咱们可使用下面的js库来模拟上下文的丢失:web

https://github.com/KhronosGroup/WebGLDeveloperToolscanvas

能够参考其目录下的src\debug\lost-context-simulator-test.html示例来使用。less

2D映射和立方体映射

咱们须要将2D图片贴到3D模型上,须要使用到2D的图片,采用UV坐标来肯定3D的面上的一个点能够对应2D图片上的一个像素或多个像素(采样),下面是uv坐标的坐标系:工具

(s对应u、t对应v),范围[0-1]。测试

立方体映射,是一个包含了6个2D图片的映射,通常用来实现环境映射,或者实现环境反射,下面的示例能够很好的展示环境反射的应用:webgl

https://threejs.org/examples/#webgl_materials_envmapsspa

另外立方体映射还经常使用于建立天空盒(SkyBox)。

纹理大小

咱们提交到GPU的图片尺寸的高和宽必须是2的n次方,即(二、四、八、1六、3二、6四、12八、256...),不过在OpenGL ES 2.0和WebGL中,咱们也可使用高宽非2的n次方的图片,即NPOT(Non Power Of Two);

若是咱们使用了非2的n次方的图片,会有下面的一些限制:

  • 不能使用MipMap映射;
  • 在着色器中采样纹理贴图时:纹理过滤方式只能用最近点或线性, 不能使用重复模式。

具体请看:https://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences

关于y轴翻转

咱们先看看DOM里的Image对象的坐标系和WebGL纹理的坐标系的区别:

能够发现,两个坐标系的y轴恰好是相反的,因此为了使坐标系一致,咱们须要使用下面的代码来翻转y轴:

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

纹理过滤

咱们的纹理图片和将要渲染的区域尺寸是不必定彻底一致的,当纹理小于渲染区域时须要纹理伸展,当纹理大于渲染区域时须要纹理收缩;

MipMap

当纹理进行伸展过大和收缩过大时,会出现模糊和锯齿,为了解决这个问题,咱们可使用多套尺寸的纹理,来对应不一样尺寸的渲染区域,GPU会根据渲染区域的大小自动选择;

优势

  • 模型不管是远离仍是离摄像机较近时,显示都会比较天然;
  • 渲染效率更高;

缺点

  • 内存使用会增大为单张图片的1/3;

建立MipMap的方法

  • 提交纹理以后,调用gl.generateMipmap方法WebGL会自动生成指定纹理的MipMap;
  • 经过外部工具,直接将全部的MipMap生成好以后,手动进行提交,该方法通常用于比较特殊的状况,好比不一样级别的MipMap纹理图像不一致的状况;

纹理坐标包装

  • GL_REPEAT: 超出纹理范围的坐标整数部分被忽略,造成重复效果。
  • GL_MIRRORED_REPEAT: 超出纹理范围的坐标整数部分被忽略,但当整数部分为奇数时进行取反,造成镜像效果。
  • GL_CLAMP_TO_EDGE:超出纹理范围的坐标被截取成0和1,造成纹理边缘延伸的效果。

activeTexture和bindTexture

gl.activeTexture

激活当前的操做贴图,指定后续代码操做的贴图是哪个,参数是枚举gl.TEXTURE0到gl.TEXTURE7(最大值请查看gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS,最少是8);

后面会调用bindTexture来绑定当前的操做贴图,若是没有调用activeTexture就调用了bindTexture,则默认激活0号纹理单元(能够理解为默认调用了gl.activeTexture(gl.TEXTURE0)代码);

gl.bindTexture

绑定指定纹理到activeTexture激活的纹理单元中,同时能够指定该纹理的类型;

更多详细信息能够参考这里:https://www.jianshu.com/p/1829b4acc58d

示例

https://hammerc.github.io/dou3d-ts/examples/learningNotes/lesson_4/index.html

相关文章
相关标签/搜索