webGL——2

首先,我们有个名词:“渲染器”

渲染器是这样一些代码,在一个场景开始绘制之前,它能对场景的任何部分做任何处理。这的确十分有用,由于它运行在图形卡上,所以它能很快运行且能很便利地做各种变换。

渲染器运行在图形卡上获得WebGL系统,它把模型视图矩阵和投影矩阵应用到场景中,而不需要使用相对较慢的JavaScript来移动场景中的每一个点和每一个三角形顶点。这相当有用并且值得额外的开销。

下面我们来看一个简单的例子:

functioninitShaders(){

varfragmentShader=getShader(gl,"shader-fs");//获取片段渲染器

varvertexShader=getShader(gl,"shader-vs");//获取顶点渲染器

shaderProgram=gl.createProgram();//创建渲染器对象

gl.attachShader(shaderProgram,vertexShader);//绑定顶点渲染器

gl.attachShader(shaderProgram,fragmentShader);//绑定片段渲染器

gl.linkProgram(shaderProgram);//和webGL关联shaderProgram

if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){

alert("Couldnotinitialiseshaders");

}

gl.useProgram(shaderProgram);//告诉webGLass使用shaderProgram

shaderProgram.vertexPositionAttribute=gl.getAttribLocation(shaderProgram,"aVertexPosition");//获取属性vertexPositionAttribute

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);//使能

shaderProgram.pMatrixUniform=gl.getUniformLocation(shaderProgram,"uPMatrix");//获取属性pMatrixUniform

shaderProgram.mvMatrixUniform=gl.getUniformLocation(shaderProgram,"uMVMatrix");//获取属性pMatrixUniform

}

至此,初始化渲染器完成。其中有个自定义函数,需要特别解释:

/**

*这是一个比看起来要简单的函数。我们要做的是在HTML网页中寻找一个元素,其具有与传入参数匹配的ID,取出其内容并基于其类型创建一个片段渲染器或者一个顶点渲染器(以后我们将更多地解释它们的区别),接着将其传入到WebGL中编译成可以在图形卡上运行的形式。接下来,代码进行出错处理,最后完成整个处理。当然,我们只能在JavaScript中将渲染器定义为字符串而不能从HTML中提取——通过这样做,我们使其更易读,因为它们被定义为网页中的脚本,就像它们本身就是JavaScript一样.

事实上,他动态的创建了渲染器语言编写的代码,推送给图形显卡执行,它们使

用一种特殊的与C语言有很大关系的渲染器语言所写。

*/

functiongetShader(gl,id){

varshaderScript=document.getElementById(id);

if(!shaderScript){

returnnull;

}

varstr="";

vark=shaderScript.firstChild;

while(k){

if(k.nodeType==3){

str+=k.textContent;

}

k=k.nextSibling;

}

alert(str);

varshader;

if(shaderScript.type=="x-shader/x-fragment"){

shader=gl.createShader(gl.FRAGMENT_SHADER);

}elseif(shaderScript.type=="x-shader/x-vertex"){

shader=gl.createShader(gl.VERTEX_SHADER);

}else{

returnnull;

}

gl.shaderSource(shader,str);

gl.compileShader(shader);

if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){

alert(gl.getShaderInfoLog(shader));

returnnull;

}

returnshader;

}

至此,创建渲染器对象完成,(实际上他实在拼接渲染器代码之后,和webGL绑定的)。

最后,贴上完整的JS代码,如果不出意外(当然HTML自己写)页面上就能看见三角形和正方形了(合适的浏览器):

<scripttype="text/javascript"src="glMatrix-0.9.5.min.js"></script>

<scriptid="shader-fs"type="x-shader/x-fragment">

precisionmediumpfloat;

voidmain(void){

gl_FragColor=vec4(1.0,1.0,1.0,1.0);

}

</script>

<scriptid="shader-vs"type="x-shader/x-vertex">

attributevec3aVertexPosition;

uniformmat4uMVMatrix;

uniformmat4uPMatrix;

voidmain(void){

gl_Position=uPMatrix*uMVMatrix*vec4(aVertexPosition,1.0);

}

</script>

<scripttype="text/javascript"charset="UTF-8">

vargl;

vartriangleVertexPositionBuffer;

varsquareVertexPositionBuffer;

varshaderProgram;//渲染器对象

varmvMatrix=mat4.create();//模型矩阵

/**

mat4.create=function(a){

varb=newglMatrixArrayType(16);

if(a)

{

b[0]=a[0];

b[1]=a[1];

b[2]=a[2];

b[3]=a[3];

b[4]=a[4];

b[5]=a[5];

b[6]=a[6];

b[7]=a[7];

b[8]=a[8];

b[9]=a[9];

b[10]=a[10];

b[11]=a[11];

b[12]=a[12];

b[13]=a[13];

b[14]=a[14];

b[15]=a[15]

}

returnb

};*/

varpMatrix=mat4.create();//投影矩阵

functioninitGL(canvas){

try{

canvas.width=screen.width;

canvas.height=screen.height;

gl=canvas.getContext("experimental-webgl");

gl.viewportWidth=canvas.width;

gl.viewportHeight=canvas.height;

}catch(e){

}

if(!gl){

alert("CouldnotinitialiseWebGL,sorry:-(");

}

}

/**

*这是一个比看起来要简单的函数。我们要做的是在HTML网页中寻找一个元素,其具有与传入参数匹配的ID,取出其内容并基于其类型创建一个片段渲染器或者一个顶点渲染器(以后我们将更多地解释它们的区别),接着将其传入到WebGL中编译成可以在图形卡上运行的形式。接下来,代码进行出错处理,最后完成整个处理。当然,我们只能在JavaScript中将渲染器定义为字符串而不能从HTML中提取——通过这样做,我们使其更易读,因为它们被定义为网页中的脚本,就像它们本身就是JavaScript一样.

事实上,他动态的创建了渲染器语言编写的代码,推送给图形显卡执行,它们使

用一种特殊的与C语言有很大关系的渲染器语言所写。

*/

functiongetShader(gl,id){

varshaderScript=document.getElementById(id);

if(!shaderScript){

returnnull;

}

varstr="";

vark=shaderScript.firstChild;

while(k){

if(k.nodeType==3){

str+=k.textContent;

}

k=k.nextSibling;

}

alert(str);

varshader;

if(shaderScript.type=="x-shader/x-fragment"){

shader=gl.createShader(gl.FRAGMENT_SHADER);

}elseif(shaderScript.type=="x-shader/x-vertex"){

shader=gl.createShader(gl.VERTEX_SHADER);

}else{

returnnull;

}

gl.shaderSource(shader,str);

gl.compileShader(shader);

if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){

alert(gl.getShaderInfoLog(shader));

returnnull;

}

returnshader;

}

functioninitShaders(){

varfragmentShader=getShader(gl,"shader-fs");//获取片段渲染器

varvertexShader=getShader(gl,"shader-vs");//获取顶点渲染器

shaderProgram=gl.createProgram();//创建渲染器对象

gl.attachShader(shaderProgram,vertexShader);//绑定顶点渲染器

gl.attachShader(shaderProgram,fragmentShader);//绑定片段渲染器

gl.linkProgram(shaderProgram);//和webGL关联shaderProgram

if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){

alert("Couldnotinitialiseshaders");

}

gl.useProgram(shaderProgram);//告诉webGLass使用shaderProgram

shaderProgram.vertexPositionAttribute=gl.getAttribLocation(shaderProgram,"aVertexPosition");//获取属性vertexPositionAttribute

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);//使能

shaderProgram.pMatrixUniform=gl.getUniformLocation(shaderProgram,"uPMatrix");//获取属性pMatrixUniform

shaderProgram.mvMatrixUniform=gl.getUniformLocation(shaderProgram,"uMVMatrix");//获取属性pMatrixUniform

}

functionsetMatrixUniforms(){

gl.uniformMatrix4fv(shaderProgram.pMatrixUniform,false,pMatrix);//将渲染器和投影矩阵绑定

gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform,false,mvMatrix);//将渲染器和模型矩阵绑定

}

/**

*初始化图形缓存区缓冲区实际上是图形卡上的内存

*/

functioninitBuffers(){

triangleVertexPositionBuffer=gl.createBuffer();//创建三角形顶点数组

gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);//绑定数值

varvertices=[

0.0,1.0,0.0,

-1.0,-1.0,0.0,

1.0,-1.0,0.0

];//定义三角形

gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(vertices),gl.STATIC_DRAW);//vertices填充缓存区

triangleVertexPositionBuffer.itemSize=3;//缓存区的列

triangleVertexPositionBuffer.numItems=3;//缓存区的行三个独立的顶点位置(numItems),其中每一个由三个数(itemSize)组成

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,newFloat32Array(vertices),gl.STATIC_DRAW);

squareVertexPositionBuffer.itemSize=3;

squareVertexPositionBuffer.numItems=4;

}

//将两个对象的顶点位置放置到图形卡上————————绘制图形

functiondrawScene(){

gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);//告诉WebGL画布的大小

gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);//清除画布

//mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;returnmat4.frustum(-b,b,-a,a,c,d,e)};

mat4.perspective(45,gl.viewportWidth/gl.viewportHeight,0.1,100.0,pMatrix);//为场景设置透视参数

//mat3.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=1;a[5]=0;a[6]=0;a[7]=0;a[8]=1;returna};

mat4.identity(mvMatrix);//

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

gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);

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

setMatrixUniforms();//把矩阵参数传到图形卡,这个函数将模型视图矩阵和投影矩阵从JavaScript中转移到WebGL中,并与渲染器相关

gl.drawArrays(gl.TRIANGLES,0,triangleVertexPositionBuffer.numItems);//从顶点数组的第0项开始一直到第numItems个元素,将顶点数组绘制成三角形

//alert("triangleFinish!");

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

gl.bindBuffer(gl.ARRAY_BUFFER,squareVertexPositionBuffer);

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

setMatrixUniforms();

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

}

functionwebGLStart(){

varcanvas=document.getElementById("lesson01-canvas");

initGL(canvas);

initShaders();

initBuffers();

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

gl.enable(gl.DEPTH_TEST);

drawScene();

}

</script>

希望您有所收获,也希望我有所进步!

夜深了,当所有离你远去的时候,你选择了编程,无所谓成功或者成就,只为真实的向梦想靠近,孤独并快乐着!晚上下班时,看见地铁站两个年轻人,忘情地抱着吉他,唱着歌,他们贫穷却快乐着!有时候人生或许就是这样,坚强地活着,并快乐!我没有能力给他们钱,但我却有跟唱歌者同样的心情,或是爱,或是情,那些远去的,那些我们真正在乎的东西!

相关推荐