增加一個2D 物件到WebGL 環境- Web APIs | MDN

文章推薦指數: 80 %
投票人數:10人

當你建立了WebGL的context後,便可開始渲染。

最簡單的例子就是加入一個 ... 每次迭代時,vertex shader 從buffer 得到下一個值並傳入到attribute。

SkiptomaincontentSkiptosearchSkiptoselectlanguage給開發者的網頁技術文件WebAPIsWebGLWebGLtutorial增加一個2D物件到WebGL環境ArticleActions正體中文(繁體)ThispagewastranslatedfromEnglishbythecommunity.LearnmoreandjointheMDNWebDocscommunity.畫場景建立正方形平面渲染場景矩陣運算RelatedTopics WebGLAPI WebGLtutorial GettingstartedwithWebGL Adding2DcontenttoaWebGLcontext UsingshaderstoapplycolorinWebGL AnimatingobjectswithWebGL Creating3DobjectsusingWebGL UsingtexturesinWebGL LightinginWebGL AnimatingtexturesinWebGL Examplesandarticles Matrixmathfortheweb WebGLmodelviewprojection WebGLbestpractices UsingWebGLextensions Abasic2DWebGLanimationexample WebGLbyexample Interfaces WebGLRenderingContext(en-US) WebGL2RenderingContext(en-US) WebGLActiveInfo(en-US) WebGLBuffer(en-US) WebGLContextEvent(en-US) WebGLFramebuffer(en-US) WebGLProgram(en-US) WebGLQuery(en-US) WebGLRenderbuffer(en-US) WebGLSampler(en-US) WebGLShader(en-US) WebGLShaderPrecisionFormat(en-US) WebGLSync(en-US) WebGLTexture(en-US) WebGLTransformFeedback(en-US) WebGLUniformLocation(en-US) WebGLVertexArrayObject(en-US) Documentation: Contribute TheMDNproject 畫場景建立正方形平面渲染場景矩陣運算增加一個2D物件到WebGL環境 «前頁 次頁» 當你建立了WebGL的context後,便可開始渲染。

最簡單的例子就是加入一個普通的正方形。

接下來,我們會介紹如何畫一個正方形。

畫場景首先我們需要知道雖然這個範例只是要畫一個正方形,但我們還是在3D的空間裡作圖。

基本上,我們就是畫一個正方形並把它放在相機前面,使正方形與使用者的視角垂直。

我們要定義一個shader,透過它來渲染我們的物件。

接下來,我們會展示如何在螢幕前顯示一個正方形。

ShaderWebGLShader使用OpenGLESShadingLanguage。

這邊不討論shader的細節的,但簡而言之,我們需要定義兩個shader(GPU上可執行的函數):vertexshader和fragmentshader。

這兩個shader會以字串的形式傳入WebGL,編譯後在GPU上執行。

Vertexshader Vertexshader是用來定義一個變數gl_Position的值來控制畫布空間的值(-1到+1),下面的範例,我們設了一個變數aVertexPosition用來記錄vertex的位置。

接下來我們將該位置乘上兩個4x4的矩陣(uProjectionMatrix和uModelMatrix),並將結果設定為gl_Position的值。

如果想要了解更多關於Projection和其他矩陣可以參閱這篇文件。

//Vertexshaderprogram constvsSource=` attributevec4aVertexPosition; uniformmat4uModelViewMatrix; uniformmat4uProjectionMatrix; voidmain(){ gl_Position=uProjectionMatrix*uModelViewMatrix*aVertexPosition; } `; Fragmentshader 每次vertexshader給gl_Position1到3個值的時候,它會分別畫出點、線、三角形。

畫圖的時候,會呼叫fragmentshader來詢問每個pixel的顏色。

在這個範例中,我們對於每次詢問都回傳白色。

gl_FragColor是GL預設的變數用來定義每個fragment的顏色,透過設定該變數的值來定義每個pixel的顏色,如下: constfsSource=` voidmain(){ gl_FragColor=vec4(1.0,1.0,1.0,1.0); } `; 初始化shader現在我們已經定義了兩個shader,我們接下來要將它們傳入WebGL,編譯並連結。

下面的程式碼呼叫了loadShader來建立兩個shader。

接下來,我們要新增一個程式,並將shader加入該程式,並將程式連結起來。

如果編譯或連接失敗,程式碼會顯示錯誤訊息。

  // //初始化shader來告知WebGL怎麼畫 // functioninitShaderProgram(gl,vsSource,fsSource){ constvertexShader=loadShader(gl,gl.VERTEX_SHADER,vsSource); constfragmentShader=loadShader(gl,gl.FRAGMENT_SHADER,fsSource); //建立shader程式 constshaderProgram=gl.createProgram(); gl.attachShader(shaderProgram,vertexShader); gl.attachShader(shaderProgram,fragmentShader); gl.linkProgram(shaderProgram); //錯誤處理 if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){ alert('Unabletoinitializetheshaderprogram:'+gl.getProgramInfoLog(shaderProgram)); returnnull; } returnshaderProgram; } // //createsashaderofthegiventype,uploadsthesourceand //compilesit. // functionloadShader(gl,type,source){ constshader=gl.createShader(type); //Sendthesourcetotheshaderobject gl.shaderSource(shader,source); //Compiletheshaderprogram gl.compileShader(shader); //Seeifitcompiledsuccessfully if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){ alert('Anerroroccurredcompilingtheshaders:'+gl.getShaderInfoLog(shader)); gl.deleteShader(shader); returnnull; } returnshader; }   我們可以透過呼叫initShaderProgram來建立shader程式 constshaderProgram=initShaderProgram(gl,vsSource,fsSource); 接下來我們需要找到WebGL生成出的位置。

這個例子中我們有一個attribute、兩個uniform。

Attributes從buffer獲得值。

每次迭代時,vertexshader從buffer得到下一個值並傳入到attribute。

Uniform則像是Javascript的全域變數。

每次迭代,他們的值不會改變。

為了之後方便,我們將shader程式與attribute和uniform存放在同一個物件中。

constprogramInfo={ program:shaderProgram, attribLocations:{ vertexPosition:gl.getAttribLocation(shaderProgram,'aVertexPosition'), }, uniformLocations:{ projectionMatrix:gl.getUniformLocation(shaderProgram,'uProjectionMatrix'), modelViewMatrix:gl.getUniformLocation(shaderProgram,'uModelViewMatrix'), }, }; 建立正方形平面在我們渲染前,我們要建立一個buffer用來儲存頂點的座標。

在此我們宣告一個函數initBuffers(),隨著之後建立更多複雜的物件,這個動作會重複見到很多次。

functioninitBuffers(gl){ //建立一個buffer來儲存正方形的座標 constpositionBuffer=gl.createBuffer(); //SelectthepositionBufferastheonetoapplybuffer //operationstofromhereout. gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer); //Nowcreateanarrayofpositionsforthesquare. constpositions=[ 1.0,1.0, -1.0,1.0, 1.0,-1.0, -1.0,-1.0, ]; //NowpassthelistofpositionsintoWebGLtobuildthe //shape.WedothisbycreatingaFloat32Arrayfromthe //JavaScriptarray,thenuseittofillthecurrentbuffer. gl.bufferData(gl.ARRAY_BUFFER, newFloat32Array(positions), gl.STATIC_DRAW); return{ position:positionBuffer, }; } 這個步驟非常簡單,一開始呼叫gl物件的函數createBuffer()(en-US)來產生一個儲存座標的buffer,並將將該buffer綁定WebGL的context。

完成後,我們宣告一個陣列來儲存正方形平面各頂點的座標,並轉型為浮點數陣列並用bufferData()(en-US)函數傳入gl物件。

渲染場景Shader建立好了、位置也確定好了、正方形平面頂點的位置也已經放到buffer後,我們就可以實際來渲染場景了。

因為這個例子沒有任何的動畫,drawScene()函數非常單純。

functiondrawScene(gl,programInfo,buffers){ gl.clearColor(0.0,0.0,0.0,1.0);//設定為全黑 gl.clearDepth(1.0);//清除所有東西 gl.enable(gl.DEPTH_TEST);//Enable深度測試 gl.depthFunc(gl.LEQUAL);//Nearthingsobscurefarthings //開始前先初始化畫布 gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); //Createaperspectivematrix,aspecialmatrixthatis //usedtosimulatethedistortionofperspectiveinacamera. //Ourfieldofviewis45degrees,withawidth/height //ratiothatmatchesthedisplaysizeofthecanvas //andweonlywanttoseeobjectsbetween0.1units //and100unitsawayfromthecamera. constfieldOfView=45*Math.PI/180;//inradians constaspect=gl.canvas.clientWidth/gl.canvas.clientHeight; constzNear=0.1; constzFar=100.0; constprojectionMatrix=mat4.create(); //note:glmatrix.jsalwayshasthefirstargument //asthedestinationtoreceivetheresult. mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); //Setthedrawingpositiontothe"identity"point,whichis //thecenterofthescene. constmodelViewMatrix=mat4.create(); //Nowmovethedrawingpositionabittowherewewantto //startdrawingthesquare. mat4.translate(modelViewMatrix,//destinationmatrix modelViewMatrix,//matrixtotranslate [-0.0,0.0,-6.0]);//amounttotranslate //TellWebGLhowtopulloutthepositionsfromtheposition //bufferintothevertexPositionattribute. { constnumComponents=2;//pullout2valuesperiteration consttype=gl.FLOAT;//thedatainthebufferis32bitfloats constnormalize=false;//don'tnormalize conststride=0;//howmanybytestogetfromonesetofvaluestothenext //0=usetypeandnumComponentsabove constoffset=0;//howmanybytesinsidethebuffertostartfrom gl.bindBuffer(gl.ARRAY_BUFFER,buffers.position); gl.vertexAttribPointer( programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset); gl.enableVertexAttribArray( programInfo.attribLocations.vertexPosition); } //TellWebGLtouseourprogramwhendrawing gl.useProgram(programInfo.program); //Settheshaderuniforms gl.uniformMatrix4fv( programInfo.uniformLocations.projectionMatrix, false, projectionMatrix); gl.uniformMatrix4fv( programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix); { constoffset=0; constvertexCount=4; gl.drawArrays(gl.TRIANGLE_STRIP,offset,vertexCount); } } 第一步,我們先將畫布背景設定為黑色,並設定相機的視角。

我們將角度設為45°,並設定成與畫布的長寬比相同。

另外我們指定我們只要渲染離相機0.1~100單位遠的物件。

接下來,我們讀入正方形的位置,並把它擺在離相機6單位遠的位置。

然後我們將正方形頂點的buffer綁定到gl上。

最後我們呼叫drawArrays()(en-US)函數來渲染物件。

檢視完整程式碼|開啟新頁面來檢視結果矩陣運算矩陣的運算看起來很複雜,但其實一步一步運算其實不會那麼困難。

大部分使用者不會寫自己的運算函數,多半是使用現成的矩陣函數庫,這個例子中我們用的是glMatrixlibrary。

可參考以下資料 MatricesonWebGLFundamentals MatricesonWolframMathWorld MatrixonWikipedia «前頁 次頁» Foundaproblemwiththispage?EditonGitHubSourceonGitHubReportaproblemwiththiscontentonGitHubWanttofixtheproblemyourself?SeeourContributionguide.Lastmodified:Dec8,2020,byMDNcontributors



請為這篇文章評分?