日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【译】Lesson 1: 一个三角形和一个方块

發(fā)布時間:2024/7/19 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【译】Lesson 1: 一个三角形和一个方块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

聲明】:本系列文章譯自:http://learningwebgl.com/blog/?page_id=1217, 感謝Giles Thomas;限于我的英文水平,本文翻譯并不一定嚴格遵從原文,但也不會嚴重背離原文(如果有,請務(wù)必知會我一下,多謝);如果處于非商業(yè)目的,你可以自由轉(zhuǎn)載并修改完善之;一切目的都是促進交流。如果能注明出處就最好不過了~~

-----------------------------------------

歡迎來到我的第一篇WebGL教程。這篇教程基于著名的Nehe Opengl教程的第二課。將向你展示怎樣在網(wǎng)頁中畫一個三角形和一個方塊。這個可能引不起你的多大興趣,但是確實是WebGL的很好的基礎(chǔ)介紹;如果你理解了它怎樣工作,剩下的就非常簡單了。。。

下面是本課運行在支持WebGL的瀏覽器上的效果:

猛擊這里可以看到真實運行的WebGL版本(前提是你有一個支持其運行的瀏覽器);如果沒有,猛擊這里。

更多的關(guān)于其如何工作的在下面。。。

一個小知會:這些教程的目標人群是有適當?shù)木幊探?jīng)驗,但是沒有多少3d圖形編程的經(jīng)驗的人;目標是讓你知其然并能知其所以然的理解代碼里將的是什么,然后你就可以盡快的開發(fā)自己的3D網(wǎng)頁程序。我自己邊學(xué)習(xí)WebGL邊寫這個的,所以可能會有一些錯誤;使用這些代碼你需要自己承擔風(fēng)險。但是我正在修改并修正我所知道的bug和誤解,如果你發(fā)現(xiàn)了任何不對的請留言讓我知道。

有兩種途徑獲取這個例子的代碼:當你觀看實時運行的版本時,通過瀏覽器的”查看源代碼“即可;或者如果你使用GitHub,你就可以從倉庫中克隆一份出來(包括以后的所有課程)。無論哪種方式,當你獲取了代碼之后,用你喜歡的文本編輯器中加載閱讀。初一見的時候難免會覺得代碼不堪入目,即使你以前已經(jīng)有了一些初步的經(jīng)驗,比如:OpenGL。剛一開始我們就定義了兩個Shader,這通常被看做是比較先進的技術(shù)。。。但是不要氣餒,它只是紙老虎。

像很多程序一樣,這個WebGL頁面一開頭就定義了一堆會被后面高層邏輯調(diào)用的底層函數(shù)。為了解釋他們,我將從底下的代碼講起,所以如果你正在順序的跟讀代碼,請?zhí)D(zhuǎn)到最底下。

你將看到如下的HTML代碼:

<body onload="webGLStart();">
<a href="http://learningwebgl.com/blog/?p=28">&lt;&lt; Back to Lesson 1</a><br />

<canvas id="lesson01-canvas" style="border: none;" width="500" height="500"></canvas>

<br/>
<a href="http://learningwebgl.com/blog/?p=28">&lt;&lt; Back to Lesson 1</a><br />
</body>

這個就是整個頁面的body部分 -- 所有其他的東西都用JavaScript實現(xiàn)(但是如果你通過”查看源代碼“來取得代碼,你將看到很多額外的代碼段用來解析我的網(wǎng)站,這些你可以跳過)。顯然我們可以放更多的HTML代碼到<body>標簽中來讓我們的WebGL圖像來構(gòu)建一個常見的網(wǎng)頁,但對于這個簡單的demo我們只需要一個回到本blog文章的鏈接和一個容納3d實時圖形的<canvas>標簽。Canvas 是HTML5的新特性,就是他們在網(wǎng)頁中支持了JavaScript的各種新的繪制元素,包括2D和3D(webGL)。在這個標簽中,除了一些簡單的層級屬性我們不再涉及canvas的其他任何具體東西,取而代之的是將WebGL的初始化代碼集中到一個叫webGLStart的Javascript函數(shù)中,從代碼可以看出這個函數(shù)當頁面加載的時候被調(diào)用。

現(xiàn)在讓我們翻到這個函數(shù)并看一下代碼:

function webGLStart() {
var canvas = document.getElementById("lesson01-canvas");
initGL(canvas);
initShaders();
initBuffers();

gl.clearColor(
0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);

drawScene();
}

代碼中首先調(diào)用函數(shù)初始化WebGL和我之前提到過的shaders,并將我們想繪制3d圖形的canvas元素作為參數(shù)傳遞到前者中,然后用initBuffers初始化一些緩存;所謂緩存就是保存我們將要繪制的三角形和方塊的地方 -- 后面我們將詳述之。然后,執(zhí)行了一些基本的WebGL初始化函數(shù),比如:將畫布清除為黑色并開啟深度測試(即Z-Test),這些步驟都是通過調(diào)用gl對象上的方法實現(xiàn)的 -- 后面我們將看到它是怎樣初始化的。最后,調(diào)用函數(shù)drawScene;就像你看到的名字一樣這個函數(shù)使用buffers繪制出那個三角形和方塊。

因為其對于理解頁面怎樣工作具有很重要的作用,后面我們將講到initGL和initShaders;但是首先,我們先看一下initBuffers和drawScene兩個函數(shù)。

首先initBuffers:

var triangleVertexPositionBuffer;
var squareVertexPositionBuffer;

我們定義兩個全局變量來操作緩存。(真實情況下不可能為每個對象都定義一個全局變量,但是這里因為我們才剛開始,所以一切從簡)

下一步:

function initBuffers() {
triangleVertexPositionBuffer
= gl.createBuffer();

我們?yōu)槿切蔚捻旤c位置創(chuàng)建一個緩沖區(qū),頂點就是3d空間中定義我們需要繪制的形體的點。對于我們的三角形,我們將有三個頂點。這些緩沖區(qū)實際上就是顯卡上的一些顯存;通過在初始化時將頂點位置傳遞到顯卡上,然后當我們繪制場景時,本質(zhì)上講就是告訴WebGL去繪制之前告訴它要繪制的那些東西,這樣我們就可以使得我們的代碼有很高的執(zhí)行效率,特別是當我們開始讓場景動起來時,想通過每秒繪制幾十次來使得物體動起來時。當然,在現(xiàn)在的例子里因為只有三個頂點,所以將他們壓到顯卡里是不會有太多消耗的 -- 但是當我們處理擁有成千上萬頂點的大模型的時候,這樣的處理方式將會顯示出其優(yōu)勢的。接著:

gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);

這一行告訴WebGL接下來所有buffer上的操作都使用我們指定的這個buffer。這里有一個概念“當前數(shù)組緩沖區(qū)”,并且所有函數(shù)操作都是基于這個“當前”緩沖區(qū)而非讓你自己指定哪個你想操作的buffer。奇怪,但是我相信在這個的背后肯定是有性能方面的原因的。

var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
];

接著,我們用javascript的list來定義頂點位置。可以看到這是一個中心點在(0,0,0)的等腰三角形。

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

現(xiàn)在,我們基于前邊的Javascript的list創(chuàng)建一個Float32Array的對象,并且告訴WebGL使用它來填充“當前緩沖”,當然它就是我們的triangleVertexPositionBuffer。我們將在未來的課程里詳細討論Float32Arrays,但是現(xiàn)在你只需要知道我們是有方法可以將Javascript的list轉(zhuǎn)化成WebGL可以用來填充緩沖區(qū)的東西的。

triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems
= 3;

最后關(guān)于buffer的操作時為其設(shè)置兩個新的屬性。這不是WebGL內(nèi)置的什么東西,但是后面將會非常有用。Javascript一個很好的特性是其不需要顯示的聲明一個你想設(shè)置的屬性(對此,褒貶不一)。所以即使buffer之前并不存在itemSize和numItems兩個屬性,現(xiàn)在它也有了。我們稱作這樣的buffer為9元素buffer,實際上表示其右三個獨立的頂點位置(numItems),每個位置有三個數(shù)組成(itemSize)。

現(xiàn)在我們已經(jīng)完整建立了三角形的緩沖區(qū),接著是方塊的:

squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices
= [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array(vertices), gl.STATIC_DRAW);
squareVertexPositionBuffer.itemSize
= 3;
squareVertexPositionBuffer.numItems
= 4;
}

所有這些代碼都是很顯然的 -- 方塊有四個頂點位置而不是三個,所以數(shù)組要大一些并且numItems不一樣。

OK,這就是我們將兩個物體的頂點坐標壓到顯卡所需要做的一切。現(xiàn)在讓我們看看drawScene,這個就是我們使用那些buffer進行繪制的地方。一步一步來:

function drawScene() {
gl.viewport(
0, 0, gl.viewportWidth, gl.viewportHeight);

第一步是用viewport函數(shù)告訴WebGL畫布的大小;很后面的課程里我們將講到為什么這個非常重要;現(xiàn)在,你只需要知道在你繪制之前需要調(diào)用這個函數(shù)就好了。接著,我們清除畫布:

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

…然后:

mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

這里我們設(shè)置好我們要觀察場景的透視角度。默認,WebGL使用正交投影繪制物體(作者單詞拼錯了。。。)。為了使得遠處的物體看起來小一些,我們需要告知WebGL我們使用的透視角度。對于當前場景,我們說我們的FOV是45°,并告訴其我們畫布的長寬比,并且說遠近裁剪面的距離分別是0.1個單位和100個單位。

正如你所看到的,這個透視的東東用的是一個叫mat4的模塊中的函數(shù)設(shè)置的。并且涉及到一個叫pMatrix的變量。(好多廢話)

現(xiàn)在我們設(shè)置好了透視角度,然后我們繼續(xù)到繪制的部分:

mat4.identity(mvMatrix);

【一大段關(guān)于gl矩陣運算的廢話,不翻了。。。】上面這句就是初始化一個矩陣變量留作后面用,identity就是單位陣。

OK,接著講代碼,將我們的三角形繪制到畫布的左手邊:

mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);

通過設(shè)置矩陣為單位陣將物體移動到3d空間的中心,然后我們將三角形向左移1.5個單位(即沿X軸負向移動),并且向里移動7個單位(即,遠離觀察者,沿Z軸負向)。

接下來的就開始了實際的繪制工作:

gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

你應(yīng)該記得為了使用我們的buffer,必須首先調(diào)用gl.bindBuffer來指定一個當前緩沖區(qū),然后調(diào)用其上的操作代碼。這里我們選擇我們的triangleVertexPositionBuffer,然后告訴WebGL緩沖區(qū)里的內(nèi)容用來做頂點位置坐標。這里可以看到我們告訴WebGL緩沖區(qū)里的每個元素都是3個數(shù)字的長途(itemSize)。

接下來,就是:

setMatrixUniforms();

這里讓W(xué)ebGL考慮到我們的WVP矩陣,這個是需要的,因為所有關(guān)于矩陣的東東都不是WebGL內(nèi)置的。可以看出這個的方法是:你可以通過改變mvMatrix的值來移動物體,但是所有這些都是在Javascript私有空間內(nèi)執(zhí)行的,setMatrixUniforms,將計算結(jié)果傳遞到顯卡,此函數(shù)將在文件的后面定義。

一旦這些都搞定,WebGL就擁有了一個被當做頂點坐標的數(shù)組,并且知道要設(shè)置的矩陣。下一步就是告訴它怎么處理這些東東:

gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);

或者,換句話講:從之前我給你的被當做三角形的頂點數(shù)組中的0號元素起至第numItems個元素止,依次畫數(shù)組中的頂點

一旦這個操作完成,WebGL就已經(jīng)畫好了我們的三角形。下一步,繪制方塊:

mat4.translate(mvMatrix, [3.0, 0.0, 0.0]);

我們首先將我們的MV矩陣向右移動3個單位。記得吧,之前我們已經(jīng)向左移動了1.5個單位,并距離屏幕向里移動了7個單位,所以最后我們就向右移動了1.5個單位,并向里移動了7個單位。接著:

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

即,告訴WebGL使用我們的方塊buffer當做其頂點坐標。。。

setMatrixUniforms();

。。。我們將mvp矩陣重新壓入顯卡(這樣就可以使得mvTranslate生效),這樣最后我們就可以:

gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);

畫點。【這里作者自問自答的解釋了一堆為什么使用TRANGLE_STRIP,咱就不廢話了】

不管怎樣,一旦執(zhí)行到這里,我們就完成了我們的drawScene函數(shù)。

}

如果你已經(jīng)走到這里了,那你完全可以準備開始實驗了。復(fù)制代碼到一個本地文件,既可以從GitHub或者直接從實時版本獲取;如果是后者,你需要index.html和glMatrix-0.9.4.min.js兩個文件。先在本地運行確保能工作,然后嘗試修改一些頂點坐標;特別是,現(xiàn)在的場景還很平;嘗試改變方塊的Z坐標為2或者-3,然后看其移動到后邊和前邊變小和變大。或者嘗試改變其中的一個或者2個,在透視角度下觀察期變形。。。。

...

OK,你應(yīng)該回來了,現(xiàn)在讓我們來看那些支持函數(shù)。【后面又有一對廢話。。。】

首先來看initGL這個函數(shù),下面是它的實現(xiàn):

var gl;
function initGL(canvas) {
try {
gl
= canvas.getContext("experimental-webgl");
gl.viewportWidth
= canvas.width;
gl.viewportHeight
= canvas.height;
}
catch(e) {
}
if (!gl) {
alert(
"Could not initialise WebGL, sorry :-(");
}
}

這個函數(shù)非常簡單。你可能已經(jīng)注意到,initBuffersdrawScene函數(shù)經(jīng)常涉及一個叫做gl的對象,很明顯該對象牽涉某種WebGL核心。這個函數(shù)獲取了這一核心——稱為WebGL context,它是通過使用標準的context名稱請求canvas賦予的(你可能猜測,在某個時候context的名字將從“experimental-webgl”變成“webgl”,那時我將更新我的課程和博客)。一旦得到上下文,我們將使用viewport函數(shù)告訴WebGL畫布的大小;在后面的課程中我們會回過來講講這為什么會很重要;現(xiàn)在,你只需知道該函數(shù)調(diào)用時需要畫布的大小。一旦函數(shù)執(zhí)行完,GL的context就設(shè)置好了。

調(diào)用InitGL之后,webGLStart函數(shù)繼續(xù)調(diào)用initShaders。這個函數(shù)用來初始化著色器xu。我們稍后再回來看這個函數(shù),因為我們首先要來看看處理模型視圖矩陣的應(yīng)用函數(shù)。下面是其代碼:

var mvMatrix = mat4.create();var pMatrix = mat4.create();

我們定義mvMatrix變量來保存模型視圖矩陣,接著定義使用該變量的loadIdentitymvTranslate函數(shù)以及multMatrix應(yīng)用函數(shù)。如果你知道JavaScript,你就會明白我們在此使用的矩陣代數(shù)函數(shù)并不是一般的JavaScript的API;事實上它們由先前提到的兩個文件所支持,這兩個文件位于HTML網(wǎng)頁的頂部:

第一個文件,?Sylvester,是一個處理矩陣和矢量代數(shù)的開源JavaScript庫,第二個文件是由Vladimir Vuki?evi?開發(fā)的Sylvester庫的一系列擴展。

總之,在這些簡單函數(shù)和有用的庫文件的幫助下,我們可以維護模型視圖矩陣。這里需要說明另一個矩陣,就是我前面提到的投影矩陣。你也許記得,WebGL不內(nèi)置perspective函數(shù)。但是模型視圖矩陣封裝了像移動和旋轉(zhuǎn)物體這樣的過程,這正是矩陣擅長的事情。你現(xiàn)在肯定已經(jīng)猜到,投影矩陣正是這么一個矩陣。下面是其代碼:
?

var pMatrix;

function perspective(fovy, aspect, znear, zfar) {

  pMatrix = makePerspective(fovy, aspect, znear, zfar);

}

makePerspective函數(shù)是另一個定義在glUtils.js文件中的函數(shù);它返回一個我們需要應(yīng)用在指定的全景透視圖中的特定矩陣。

現(xiàn)在,我們除了setMatrixUniforms函數(shù)外已經(jīng)瀏覽了所有函數(shù),正如我先前所說,這個函數(shù)將模型視圖矩陣和投影矩陣從JavaScript中轉(zhuǎn)移到WebGL中,并與著色器相關(guān)。由于它們相互關(guān)聯(lián),所以我們將從一些背景知識開始。

你也許會問:什么是著色器?在三維圖形的歷史上,著色器曾經(jīng)“名副其實”過:在繪制一個場景之前,它指示系統(tǒng)如何渲染或著色。然而,隨著時間的推移,它的功能日益增強,以至于如今要這樣定義它才更為合適:著色器是這樣一些代碼,在一個場景開始繪制之前,它能對場景的任何部分做任何處理。這的確十分有用,由于它運行在圖形卡上,所以它能很快運行且能很便利地做各種變換,哪怕是在這個簡單的例子中。

我們引入著色器是為了一個簡單的WebGL例子(在OpenGL教程中這至少算是“中級”),該例子能運行在圖形卡上且使用著色器獲得WebGL系統(tǒng)。它把模型視圖矩陣和投影矩陣應(yīng)用到場景中,而不需要使用相對較慢的JavaScript來移動場景中的每一個點和每一個三角形頂點。這相當有用并且值得額外的開銷。

下面是如何設(shè)置它們。正如你所記得的,webGLStart函數(shù)調(diào)用initShaders函數(shù),那么讓我們一步一步地來看一看:
? var shaderProgram;
function initShaders() {
  
var fragmentShader = getShader(gl, "shader-fs");
  
var vertexShader = getShader(gl, "shader-vs");
  shaderProgram
= gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert(
"Could not initialise shaders");
  }
  gl.useProgram(shaderProgram);

正如你所見,它使用getShader函數(shù)來獲得兩個著色器:一個片段著色器和一個頂點著色器,接著將兩者綁定在一個WebGL“程序”上。一個程序是一段放置在系統(tǒng)WebGL上的代碼;你可以把它視作一種運行在圖形卡上的特定方式。正如你所期望的,你可以將它和一些著色器聯(lián)系在一起,每個著色器都可以視為程序中的一個代碼片段;確切地說,每個程序可以擁有一個片段著色器和一個頂點著色器。讓我們簡單地看一下:

shaderProgram.vertexPositionAttribute =?

gl.getAttribLocation(shaderProgram, "aVertexPosition");

?

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

?

一旦設(shè)置好程序并綁定了著色器,函數(shù)將得到一個“屬性”的引用,該屬性存儲在vertexPositionAttribute對象中。我們再次利用JavaScript把任一字段設(shè)置在任一對象上;默認情況下對象沒有vertexPositionAttribute字段,但是對于我們來說將兩個值保留在一起是很方便的,因此我們僅設(shè)置程序中新字段的屬性。

?

那么,vertexPositionAttribute是做什么的呢?也許你還記得,我們在drawScene函數(shù)中使用過它;如果你回過去看一看從適當?shù)木彌_區(qū)設(shè)置三角形頂點位置的那段代碼,你將看到我們所做的就是將緩沖區(qū)與該屬性關(guān)聯(lián)在一起。稍后你將明白這是什么意思。現(xiàn)在,只需注意到我們也使用gl.enableVertexAttribArray函數(shù)來指示WebGL使用一個數(shù)組來為該屬性提供數(shù)值。

?

shaderProgram.pMatrixUniform =?gl.getUniformLocation(shaderProgram, "uPMatrix");

?

shaderProgram.mvMatrixUniform =?gl.getUniformLocation(shaderProgram, "uMVMatrix");

}

initShaders函數(shù)所做的最后一件事就是從程序中獲取兩個多的值,這兩個變量稱作uniform變量,我們很快會再遇見它們,但現(xiàn)在你只需注意到,正如屬性一樣,我們?yōu)榱朔奖愣鴮⑵浯鎯υ趯ο笾小?/p>


現(xiàn)在,我們來看看getShader函數(shù):

function getShader(gl, id) {

  
var shaderScript = document.getElementById(id);
  
if (!shaderScript) {
      
return null;
  }
  
var str = "";
  
var k = shaderScript.firstChild;
  
while (k) {
    
if (k.nodeType == 3)
        str
+= k.textContent;
        k
= k.nextSibling;
    }

  
var shader;
  
if (shaderScript.type == "x-shader/x-fragment") {
      shader
= gl.createShader(gl.FRAGMENT_SHADER);
  }
  
else if (shaderScript.type == "x-shader/x-vertex") {
      shader
= gl.createShader(gl.VERTEX_SHADER);
  }
  
else {
      
return null;
  }

  gl.shaderSource(shader, str);
  gl.compileShader(shader);
  
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert(gl.getShaderInfoLog(shader));
      
return null;
  }
  
return shader;
}

這是另一個比看起來要簡單的函數(shù)。我們要做的是在HTML網(wǎng)頁中尋找一個元素,其具有與傳入?yún)?shù)匹配的ID,取出其內(nèi)容并基于其類型創(chuàng)建一個片段渲染器或者一個頂點渲染器(以后我們將更多地解釋它們的區(qū)別),接著將其傳入到WebGL中編譯成可以在圖形卡上運行的形式。接下來,代碼進行出錯處理,最后完成整個處理。當然,我們只能在JavaScript中將渲染器定義為字符串而不能從HTML中提取——通過這樣做,我們使其更易讀,因為它們被定義為網(wǎng)頁中的腳本,就像它們本身就是JavaScript一樣。

看完這個以后,我們應(yīng)該來看看渲染器的代碼:

關(guān)于這些你要記住的第一件事就是:這些代碼不是用JavaScript所寫,即使這兩種腳本語言的祖先十分相似。事實上,它們使用一種特殊的與C語言有很大關(guān)系的著色器語言(當然,JavaScript也是如此)所寫。第一個著色器——即片段著色器——什么也不做;它簡單地規(guī)定了被繪制的物體將被繪制成白色(怎么給物體著色是下一節(jié)課程的話題)。第二個著色器有點意思,它是一個頂點著色器——還記得吧,它是一段圖形卡上的代碼,能用一個頂點完成它想做的任何事。與之相關(guān)聯(lián)的是,它有兩個uniform變量:uMVMatrix和uPMatrix。uniform變量十分有用,因為它們能在著色器之外獲得——實際上是在包含它們的程序之外,你可能還記得,當時我們從initShaders函數(shù)獲得了它們,它們也可以從將其設(shè)置為模型視圖矩陣和投影矩陣的代碼(我敢肯定你已經(jīng)實現(xiàn)了它)中獲得。你可能認為著色器程序是一個對象(在面向?qū)ο蟮膱鼍爸?#xff09;,而統(tǒng)一變量是對象中的字段。現(xiàn)在,著色器在每個頂點上調(diào)用,頂點作為aVertexPosition參數(shù)傳入到著色器的代碼中,由于在drawScene函數(shù)中使用vertexPositionAttribute,此時,我們將其屬性與緩沖區(qū)關(guān)聯(lián)在一起。著色器主程序中的這部分代碼只是將頂點與模型視圖矩陣和投影矩陣相乘,然后作為頂點最終位置的結(jié)果傳出。webGLStart函數(shù)調(diào)用initShaders函數(shù),在網(wǎng)頁的腳本中使用getShader函數(shù)裝載了片段著色器和頂點著色器,以便它們能被編譯后傳入到WebGL,最終使用WebGL渲染出三維場景。

剩下還沒有說明的代碼是setMatrixUniforms函數(shù),一旦你理解了上面所講的,就很容易理解它。

function setMatrixUniforms() {
  gl.uniformMatrix4fv(shaderProgram.pMatrixUniform,
false,
      
new WebGLFloatArray(pMatrix.flatten()));
  gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform,
false,
      
new WebGLFloatArray(mvMatrix.flatten()));
}

通過引用uniform來表示initShaders中的投影矩陣和模型視圖矩陣,我們將值從JavaScript類型矩陣傳遞給了WebGL。

第一課的內(nèi)容真的很多,但是希望你(也包括我)能夠理解所有這些基本知識,我們將以此為基礎(chǔ)創(chuàng)建更加有趣的模型:五彩繽紛的、可移動的、真正的三維WebGL模型。為了了解更多關(guān)于WebGL的知識,請閱讀第2課。

【發(fā)現(xiàn)翻譯果然是一件很累的事情,尤其是作者寫的廢話較多的時候。。。,翻譯最后一段的時候google了一下發(fā)現(xiàn)譯言網(wǎng)上已經(jīng)有這個系列的譯文了。。。,很汗,然后后面的幾個lesson就不想繼續(xù)了,但是善始善終本篇還是想完成,所以就繼續(xù)參考了一些譯言網(wǎng)的內(nèi)容,糾正了其一些說法的問題,把shader翻譯成渲染器總是不大對勁,我改成”著色器“了】

轉(zhuǎn)載于:https://www.cnblogs.com/konlil/archive/2011/03/06/1971905.html

總結(jié)

以上是生活随笔為你收集整理的【译】Lesson 1: 一个三角形和一个方块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。