标签:webgl
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。
attribute vec3 position; attribute vec3 normal; attribute vec4 color; uniform mat4 mvpMatrix; uniform mat4 mMatrix; varying vec3 vPosition; varying vec3 vNormal; varying vec4 vColor; void main(void){ vPosition = (mMatrix * vec4(position, 1.0)).xyz; vNormal = normal; vColor = color; gl_Position = mvpMatrix * vec4(position, 1.0); }跟上次比较,变更点有两个。
precision mediump float; uniform mat4 invMatrix; uniform vec3 lightPosition; uniform vec3 eyeDirection; uniform vec4 ambientColor; varying vec3 vPosition; varying vec3 vNormal; varying vec4 vColor; void main(void){ vec3 lightVec = lightPosition - vPosition; vec3 invLight = normalize(invMatrix * vec4(lightVec, 0.0)).xyz; vec3 invEye = normalize(invMatrix * vec4(eyeDirection, 0.0)).xyz; vec3 halfLE = normalize(invLight + invEye); float diffuse = clamp(dot(vNormal, invLight), 0.0, 1.0) + 0.2; float specular = pow(clamp(dot(vNormal, halfLE), 0.0, 1.0), 50.0); vec4 destColor = vColor * vec4(vec3(diffuse), 1.0) + vec4(vec3(specular), 1.0) + ambientColor; gl_FragColor = destColor; }着色器中的main函数的第一行,将从点光源到顶点的光向量代入到变量lightVec中。像上面说的一样,使用了单纯的减法,很简单吧。并且,使用这里得到的光向量,和之前平行光源一样求逆矩阵以及半向量,计算扩散光和反射光。
这次细节部分修改的比较多,一点点的开始解说。目前为止的demo都只渲染了一个圆环体,这次在圆环体之外加一个球体,看文章一开始的图片就知道了。圆环体的顶点数据以及球体的顶点数据要另外准备。
球体模型的顶点数据的生成,使用以下的函数。和生成圆环体的顶点数据的函数是比较类似的。// 球体を生成する関数 function sphere(row, column, rad, color){ var pos = new Array(), nor = new Array(), col = new Array(), idx = new Array(); for(var i = 0; i <= row; i++){ var r = Math.PI / row * i; var ry = Math.cos(r); var rr = Math.sin(r); for(var ii = 0; ii <= column; ii++){ var tr = Math.PI * 2 / column * ii; var tx = rr * rad * Math.cos(tr); var ty = ry * rad; var tz = rr * rad * Math.sin(tr); var rx = rr * Math.cos(tr); var rz = rr * Math.sin(tr); if(color){ var tc = color; }else{ tc = hsva(360 / row * i, 1, 1, 1); } pos.push(tx, ty, tz); nor.push(rx, ry, rz); col.push(tc[0], tc[1], tc[2], tc[3]); } } r = 0; for(i = 0; i < row; i++){ for(ii = 0; ii < column; ii++){ r = (column + 1) * i + ii; idx.push(r, r + 1, r + column + 2); idx.push(r, r + column + 2, r + column + 1); } } return {p : pos, n : nor, c : col, i : idx}; }形成球体的顶点,定义了一个用一个大的多边形群组成的膜裹成球的形状方法。这个sphere函数接受四个参数,第一个参数是形成球体的膜状的多边形板的纵向分割数(顶点数),用地球比喻的话就是纬度的方向。第二个参数则是横向分割数,这里用地球来说的话,就是经度的方向。第三个参数是球体的半径。第四个参数是球体的颜色,这个颜色是包含四个元素的数组,如果没有指定颜色,则会自动分配HSV颜色。
// 用球体的顶点数据生成VBO并保存 var sphereData = sphere(64, 64, 2.0, [0.25, 0.25, 0.75, 1.0]); var sPosition = create_vbo(sphereData.p); var sNormal = create_vbo(sphereData.n); var sColor = create_vbo(sphereData.c); var sVBOList = [sPosition, sNormal, sColor]; // 球体用IBO的生成 var sIndex = create_ibo(sphereData.i);上面的代码,生成一个纵向和横向都是64个顶点的球体,半径是2.0,这次指定的颜色是蓝色。需要注意的是,为了后面的处理,将VBO保存到了数组中,这样做了之后,attributeLocation和VBO联系的工作就变的非常的方便了,这个后面会叙述。
// uniformLocationを配列に取得 var uniLocation = new Array(); uniLocation[0] = gl.getUniformLocation(prg, ‘mvpMatrix‘); uniLocation[1] = gl.getUniformLocation(prg, ‘mMatrix‘); uniLocation[2] = gl.getUniformLocation(prg, ‘invMatrix‘); uniLocation[3] = gl.getUniformLocation(prg, ‘lightPosition‘); uniLocation[4] = gl.getUniformLocation(prg, ‘eyeDirection‘); uniLocation[5] = gl.getUniformLocation(prg, ‘ambientColor‘); // 中略 // 点光源的位置 var lightPosition = [0.0, 0.0, 0.0];着色器中进行的uniform修饰符变量的变更在这里都详细的反映出了,而且,demo的电光源的位置设定成了原点。
// カウンタをインクリメントする count++; // カウンタを元にラジアンと各種座標を算出 var rad = (count % 360) * Math.PI / 180; var tx = Math.cos(rad) * 3.5; var ty = Math.sin(rad) * 3.5; var tz = Math.sin(rad) * 3.5; // トーラスのVBOとIBOをセット set_attribute(tVBOList, attLocation, attStride); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tIndex); // モデル座標変換行列の生成 m.identity(mMatrix); m.translate(mMatrix, [tx, -ty, -tz], mMatrix); m.rotate(mMatrix, -rad, [0, 1, 1], mMatrix); m.multiply(tmpMatrix, mMatrix, mvpMatrix); m.inverse(mMatrix, invMatrix); // uniform変数の登録と描画 gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix); gl.uniformMatrix4fv(uniLocation[1], false, mMatrix); gl.uniformMatrix4fv(uniLocation[2], false, invMatrix); gl.uniform3fv(uniLocation[3], lightPosition); gl.uniform3fv(uniLocation[4], eyeDirection); gl.uniform4fv(uniLocation[5], ambientColor); gl.drawElements(gl.TRIANGLES, torusData.i.length, gl.UNSIGNED_SHORT, 0); // 球体のVBOとIBOをセット set_attribute(sVBOList, attLocation, attStride); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sIndex); // モデル座標変換行列の生成 m.identity(mMatrix); m.translate(mMatrix, [-tx, ty, tz], mMatrix); m.multiply(tmpMatrix, mMatrix, mvpMatrix); m.inverse(mMatrix, invMatrix); // uniform変数の登録と描画 gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix); gl.uniformMatrix4fv(uniLocation[1], false, mMatrix); gl.uniformMatrix4fv(uniLocation[2], false, invMatrix); gl.drawElements(gl.TRIANGLES, sphereData.i.length, gl.UNSIGNED_SHORT, 0); // コンテキストの再描画 gl.flush();各种坐标变换矩阵的生成,以及逆矩阵的生成结束后,将点光源的位置和视点向量等一起传入着色器,以及VBO和IBO的绑定处理之后,发出绘图命令。
为了绘制两个模型而进行了一连串的处理,但是要注意不要重复,也没进行特别难的处理。
用点光源来渲染圆环体和球体
转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend
标签:webgl
原文地址:http://blog.csdn.net/lufy_legend/article/details/40029511