只能夠繪製純色的模型是不夠的,爲了呈現出更真實的模型,咱們還須要經過紋理貼圖給模型進行上色。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