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

相關文章
相關標籤/搜索