只能够绘制纯色的模型是不够的,为了呈现出更真实的模型,咱们还须要经过纹理贴图给模型进行上色。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图片贴到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次方的图片,会有下面的一些限制:
具体请看:https://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences
咱们先看看DOM里的Image对象的坐标系和WebGL纹理的坐标系的区别:
能够发现,两个坐标系的y轴恰好是相反的,因此为了使坐标系一致,咱们须要使用下面的代码来翻转y轴:
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
咱们的纹理图片和将要渲染的区域尺寸是不必定彻底一致的,当纹理小于渲染区域时须要纹理伸展,当纹理大于渲染区域时须要纹理收缩;
当纹理进行伸展过大和收缩过大时,会出现模糊和锯齿,为了解决这个问题,咱们可使用多套尺寸的纹理,来对应不一样尺寸的渲染区域,GPU会根据渲染区域的大小自动选择;
激活当前的操做贴图,指定后续代码操做的贴图是哪个,参数是枚举gl.TEXTURE0到gl.TEXTURE7(最大值请查看gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS,最少是8);
后面会调用bindTexture来绑定当前的操做贴图,若是没有调用activeTexture就调用了bindTexture,则默认激活0号纹理单元(能够理解为默认调用了gl.activeTexture(gl.TEXTURE0)代码);
绑定指定纹理到activeTexture激活的纹理单元中,同时能够指定该纹理的类型;
更多详细信息能够参考这里:https://www.jianshu.com/p/1829b4acc58d
https://hammerc.github.io/dou3d-ts/examples/learningNotes/lesson_4/index.html