近来有想弄弄有趣的东西,3D的页面效果,自然会想到webGL,但是介于以前一直没用过,这次也算是初体验了。
初体验的话总是让人有激情,但是这次让我太难受了。。。。。。
为什么呢?因为webGL的初始化太蛋疼了,入门就要比canvas麻烦很多,而且如果用原生api的话各种不会看不懂啊!!!!!。好吧,抱怨完了,写在我们如果要开始webGL之旅需要一些什么
- 创建一个canvas元素
- 获取canvas的上下文
- 初始化视口(viewport)
- 创建一个或者多个包含渲染数据的数组(通常为顶点数组)
- 创建一个或者多个矩阵,将顶点数组变换到屏幕空间中
- 创建一个或者多个着色器来实现绘制算法
- 使用参数初始化着色器
- 绘制
这些看起来还不是很难,但是,着色器对于webGL是非常重要的一部分,而着色器不使用javascript编写,而是一门类似C语言的高级语言编写,并且以字符串的形式插入到代码之中。而且挺麻烦的(应该是我水平太低的原因,以后需要多多学习)
目前在学习的书籍是《WebGL:Up and Running》的中文版(汗),原著作者为Tony Parisi,根据授权,应该是可以使用其中的一部分代码作为回答问题或者学习资料,所以我就把最原本的webGL方式调用粘贴下啦,学习一下(我预计我应该记不住,也看不太懂这些参数要怎么弄)
<html> <head> <title>WebGL Up And Running — Example 1</title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <script type="text/javascript"> function initWebGL(canvas) { var gl; try { gl = canvas.getContext("experimental-webgl"); } catch (e) { var msg = "Error creating WebGL Context!: " + e.toString(); alert(msg); throw Error(msg); } return gl; } function initViewport(gl, canvas) { gl.viewport(0, 0, canvas.width, canvas.height); } var projectionMatrix, modelViewMatrix; function initMatrices() { // The transform matrix for the square - translate back in Z for the camera modelViewMatrix = new Float32Array( [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -3.333, 1]); // The projection matrix (for a 45 degree field of view) projectionMatrix = new Float32Array( [2.41421, 0, 0, 0, 0, 2.41421, 0, 0, 0, 0, -1.002002, -1, 0, 0, -0.2002002, 0]); } // Create the vertex data for a square to be drawn function createSquare(gl) { var vertexBuffer; vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); var verts = [ .5, .5, 0.0, -.5, .5, 0.0, .5, -.5, 0.0, -.5, -.5, 0.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW); var square = {buffer:vertexBuffer, vertSize:3, nVerts:4, primtype:gl.TRIANGLE_STRIP}; return square; } function createShader(gl, str, type) { var shader; if (type == "fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } else if (type == "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; } var vertexShaderSource = " attribute vec3 vertexPos; " + " uniform mat4 modelViewMatrix; " + " uniform mat4 projectionMatrix; " + " void main(void) { " + " // Return the transformed and projected vertex value " + " gl_Position = projectionMatrix * modelViewMatrix * " + " vec4(vertexPos, 1.0); " + " } "; var fragmentShaderSource = " void main(void) { " + " // Return the pixel color: always output white " + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); " + "} "; var shaderProgram, shaderVertexPositionAttribute, shaderProjectionMatrixUniform, shaderModelViewMatrixUniform; function initShader(gl) { // load and compile the fragment and vertex shader //var fragmentShader = getShader(gl, "fragmentShader"); //var vertexShader = getShader(gl, "vertexShader"); var fragmentShader = createShader(gl, fragmentShaderSource, "fragment"); var vertexShader = createShader(gl, vertexShaderSource, "vertex"); // link them together into a new program shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); // get pointers to the shader params shaderVertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPos"); gl.enableVertexAttribArray(shaderVertexPositionAttribute); shaderProjectionMatrixUniform = gl.getUniformLocation(shaderProgram, "projectionMatrix"); shaderModelViewMatrixUniform = gl.getUniformLocation(shaderProgram, "modelViewMatrix"); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Could not initialise shaders"); } } function draw(gl, obj) { // clear the background (with black) gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // set the vertex buffer to be drawn gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer); // set the shader to use gl.useProgram(shaderProgram); // connect up the shader parameters: vertex position and projection/model matrices gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0); gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix); gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix); // draw the object gl.drawArrays(obj.primtype, 0, obj.nVerts); } function onLoad() { var canvas = document.getElementById("webglcanvas"); var gl = initWebGL(canvas); initViewport(gl, canvas); initMatrices(); var square = createSquare(gl); initShader(gl); draw(gl, square); } </script> </head> <body onload="onLoad();"> <canvas id="webglcanvas" style="border: none;" width="500" height="500"></canvas> </body> </html>
恩,最后画出来的效果应该是一个黑框里面有一个白色的正方形(什么?这么长一堆设置连一点点的3d效果都没有?)