增加一個2D 物件到WebGL 環境- Web APIs | MDN
文章推薦指數: 80 %
當你建立了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
延伸文章資訊
- 1WebGLRenderingContext.bufferData() - Web APIs | MDN
The WebGLRenderingContext.bufferData() method of the WebGL API initializes and creates the buffer...
- 2WebGL How It Works
Buffers are the way of getting vertex and other per vertex data onto the GPU. gl.createBuffer cre...
- 35.3 - A Primer on Buffer Objects — LearnWebGL
Buffer objects provide the data for attribute variables in vertex shader programs. Remember that ...
- 4WebGL/uniform-buffers.html at main - GitHub
Contribute to KhronosGroup/WebGL development by creating an account on GitHub. ... <title>WebGL U...
- 5WebGL2 Fundamentals
Buffers are arrays of binary data you upload to the GPU. ... This tells WebGL we want to get data...