摘要:下面是頂點(diǎn)及片元著色器程序,用字符串表示,它將直接運(yùn)行在瀏覽器之上。最后,使用將和著色器連接。創(chuàng)建著色器對象創(chuàng)建編程對象賦值已創(chuàng)建的著色器對象連接編程對象檢查鏈接結(jié)果鏈接程序失敗使用可用著色器程序這一步主要使用方法告訴使用程序。
該文章于一天前發(fā)表在 github,若有問題可提至 github。
目前,我們有很多方案可以快速的接觸到 WebGL 并繪制復(fù)雜的圖形,但最后發(fā)現(xiàn)我們忽視了很多細(xì)節(jié)性的東西。當(dāng)然,這對初學(xué) WebGL 是有必要的,它能迅速提起我們對 WebGL 的學(xué)習(xí)興趣。當(dāng)學(xué)習(xí)到更加深入的階段時,我們更想了解 WebGL 的工作機(jī)制,這也將對我們編程有極大的幫助。以上也是我想寫這樣一個系列的原因。
簡介用更專業(yè)的描述講,WebGL (Web Graphics Library) 是一個用以渲染交互式 3D 和 2D 圖形的無需插件且兼容下一代瀏覽器的 JavaScript API,通過 HTML5 中
Hello World首先,我們將通過實(shí)現(xiàn)一個簡單的 WebGL 程序(清空繪圖區(qū))叩開 WebGL 的大門。下面將實(shí)現(xiàn)一個最簡單的 WebGL 功能:
創(chuàng)建 canvas 元素WebGL 采用 HTML5 中的
獲取 WebGL 上下文
目前,各瀏覽器基本都實(shí)現(xiàn)了對 WebGL 的支持,但 IE11 及 Edge 瀏覽器稍微有些不同。以下是對初始化 WebGL 的基本封裝:
function initWebGL(canvas) { // 創(chuàng)建全局變量 window.gl = null; try { // 嘗試獲取標(biāo)準(zhǔn)上下文,如果失敗,回退到試驗(yàn)性上下文 gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch(e) { throw "創(chuàng)建失敗。"; } // 如果沒有GL上下文,馬上放棄 if (!gl) { alert("WebGL初始化失敗,可能是因?yàn)槟臑g覽器不支持。"); gl = null; } return gl; }
這里通過采用 canvas 的 getContext(contextType, contextAttributes) 方法判斷瀏覽器是否支持 WebGL,并創(chuàng)建其上下文。當(dāng)返回值是 canvas 的上下文時,瀏覽器可支持 WebGL,為 null 時,則創(chuàng)建失敗。注意,在 IE11 及 Edge 瀏覽器下,需要使用 "experimental-webgl" 創(chuàng)建 WebGL,此處做了兼容處理。
清空繪圖區(qū)下面將背景顏色設(shè)置為黑色,并清空緩存區(qū)。
var gl; // WebGL的全局變量 function start() { var canvas = document.getElementById("glcanvas"); // 初始化 WebGL 上下文 gl = initWebGL(canvas); // 只有在 WebGL 可用的時候才繼續(xù) if (gl) { // 設(shè)置清除顏色為黑色,不透明 gl.clearColor(0.0, 0.0, 0.0, 1.0); // 清除顏色和深度緩存 gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); } }
這樣,我們可以在瀏覽器中看到一塊黑色區(qū)域。你可能已經(jīng)注意到,WebGL 遵循的是傳統(tǒng) OpenGL 顏色分量的取值范圍,從 0.0 到 1.0。RGB 的值越高,顏色越亮。注意,clear() 方法在這里清除顏色和深度緩存,而不是繪制區(qū)域的
上面我們完成了第一個 WebGL 程序,但是我們還未接觸到 WebGL 的核心:可編程著色器。接下來,我們將使用可編程著色器在屏幕上繪制點(diǎn)。可編程著色器是一個較為復(fù)雜的概念,也有自己的編程語言 GLSL,后面將會又專門的文章具體講解可編程著色器。這里我們只需要簡單了解繪制的流程:
編寫著色器程序WebGL 是無法像 OpenGL 利用固定渲染管線,代替它的是可編輯渲染管線中的 GLSL 著色語言。下面是頂點(diǎn)及片元著色器 GLSL 程序,用字符串表示,它將直接運(yùn)行在瀏覽器之上。
// 頂點(diǎn)著色器程序 var VSHADER_SOURCE = "void main() { " + " gl_Position = vec4(0.0, 0.0, 0.0, 1.0); " + // 設(shè)置頂點(diǎn)位置 " gl_PointSize = 10.0; " + // 設(shè)置點(diǎn)的大小 "} "; // 片元著色器程序 var FSHADER_SOURCE = "void main() { " + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); " + // 設(shè)置點(diǎn)的顏色,此處為白色 "} ";
上面程序是不是有中似曾相識的感覺?沒錯,GLSL 語言和 C 語言很類似。著色器程序中包含一個主函數(shù),且返回值為空。其中 vec4() 構(gòu)造函數(shù)用于生成一個四維向量(x,y,z,w)。
編譯著色器首先,需要用 createShader( type ) 方法生成相應(yīng)類型的 WebGLShader。接著,使用 shaderSource( shader, sourceCode ) 作為 GLSL 源碼的鉤子函數(shù)。最后使用 compileShader( shader ) 完成對著色器的編譯。程序中我們做了編譯后的校驗(yàn),當(dāng)著色器編譯失敗時,會報(bào)出失敗并刪除著色器。
function createShader (gl, type, sourceCode) { // 編譯著色器類型:頂點(diǎn)著色器及片元著色器。 var shader = gl.createShader( type ); gl.shaderSource( shader, sourceCode ); gl.compileShader( shader ); if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) { var info = gl.getShaderInfoLog( shader ); console.log( "無法編譯 WebGL 程序。 " + info); gl.deleteShader(shader); return null; } return shader; }連接到可用程序
此時,著色器仍是不可用的,需要將其賦值到 WebGLProgram 上。這里主要進(jìn)行了三步操作,首先,需要使用 createProgram() 方法創(chuàng)建和初始化一個 WebGLProgram 對象。接著,使用 gl.attachShader(program, shader) 將該對象結(jié)合兩個已經(jīng)編譯的著色器。最后,使用 linkProgram(program) 將 WebGLProgram 和著色器連接。
function createProgram(gl, vshader, fshader) { // 創(chuàng)建著色器對象 var vertexShader = createShader(gl, gl.VERTEX_SHADER, vshader); var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fshader); if (!vertexShader || !fragmentShader) { return null; } // 創(chuàng)建編程對象 var program = gl.createProgram(); if (!program) { return null; } // 賦值已創(chuàng)建的著色器對象 gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); // 連接編程對象 gl.linkProgram(program); // 檢查鏈接結(jié)果 var linked = gl.getProgramParameter(program, gl.LINK_STATUS); if (!linked) { var error = gl.getProgramInfoLog(program); console.log("鏈接程序失敗:" + error); gl.deleteProgram(program); gl.deleteShader(fragmentShader); gl.deleteShader(vertexShader); return null; } return program; }使用可用著色器程序
這一步主要使用 useProgram(program) 方法告訴 GPU 使用程序。
function initShaders(gl, vshader, fshader) { var program = createProgram(gl, vshader, fshader); if (!program) { console.log("創(chuàng)建程序失敗。"); return false; } gl.useProgram(program); gl.program = program; return true; }繪制一個點(diǎn)
最后,使用 drawArrays(mode, first, count) 繪制一個點(diǎn),該函數(shù)是一個非常強(qiáng)大的渲染函數(shù),后續(xù)文章會有詳細(xì)介紹。此處只需要知道傳入 "POINTS" 繪制了一個點(diǎn)。
// 繪制一個點(diǎn) gl.drawArrays(gl.POINTS, 0, 1);
至此,我們已經(jīng)完成了繪制一個點(diǎn)的全部程序。當(dāng)運(yùn)行以上程序時,我們會在瀏覽器中看到一個白色的點(diǎn)。
結(jié)束語到現(xiàn)在,我們雖然還沒有使用 WebGL 繪制三維圖形,但我們已經(jīng)進(jìn)入了 WebGL 世界。我們已經(jīng)使用 WebGL 繪制了簡單的圖形。但是這只是 WebGL 的繪制的冰山一角,我們使用 WebGL 當(dāng)然不是為了繪制這樣一個簡單的圖形。為了繪制更復(fù)雜的圖形,我們還有很多的細(xì)節(jié)需要去了解。但是無論如何,我們都已經(jīng)開啟了 WebGL 的第一步,其實(shí)問題也并沒有我們想象的那么難。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/80634.html
摘要:我們的目標(biāo)是將位置信心從程序中傳遞到頂點(diǎn)著色器,而變量就傳輸?shù)氖悄切┖晚旤c(diǎn)相關(guān)的數(shù)據(jù)。緩沖區(qū)對象是中的一塊存儲區(qū)域,其中保存了大量的頂點(diǎn)數(shù)據(jù),可以一次性的向頂點(diǎn)著色器傳入多個頂點(diǎn)到變量。三角形一系列單獨(dú)的三角形。系列文章初探繪制三角形 該文章于一天前發(fā)表在 github,若有問題可提至 github。 在上一篇文章WebGL 初探中,我們熟悉了 WebGL 的簡單背景以及如何繪制一個簡...
摘要:存儲之初探的發(fā)布和定稿為前端界帶來巨大的變化,新增的和特性給業(yè)務(wù)帶來了更多可能性,讓用戶體驗(yàn)擁有了更可能的豐富。只讀返回一個整數(shù),表示存儲在對象中的數(shù)據(jù)項(xiàng)數(shù)量。會在過期時間之后銷毀。安全性方面,中一般不建議存儲敏感信息。 Web存儲之LocalStorage初探 HTML5的發(fā)布和定稿為前端界帶來巨大的變化,新增的API和特性給業(yè)務(wù)帶來了更多可能性,讓用戶體驗(yàn)擁有了更可能的豐富。 · ...
摘要:在文末,我會附上一個可加載的模型方便學(xué)習(xí)中文藝術(shù)字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說是 HTML5 技術(shù)生態(tài)鏈中最為令人振奮的標(biāo)準(zhǔn)之一,它把 Web 帶入了 3D 的時代。 初識 WebGL 先通過幾個使用 Web...
閱讀 1843·2021-09-22 15:55
閱讀 3533·2021-09-07 10:26
閱讀 638·2019-08-30 15:54
閱讀 694·2019-08-29 16:34
閱讀 848·2019-08-26 14:04
閱讀 3271·2019-08-26 11:47
閱讀 2142·2019-08-26 11:33
閱讀 2300·2019-08-23 15:17