使用WebGL绘制一只平面小鸡

本文介绍了如何使用WebGL绘制一只平面小鸡,通过分解成三角形、圆形等基本图形,结合JavaScript和数学方法实现。详细讲解了从顶点着色器到片元着色器,再到图形绘制的全过程,包括鸡的嘴巴、头部和身体各部分的绘制细节。
摘要由CSDN通过智能技术生成

这学期选修了计算机图形学这门课,最近刚开始接触WebGL,目前只学到二维的部分,尝试绘制一只平面的小鸡。

效果图

首先上效果图:
可爱的小鸡

下面直接进入代码部分:

drawCircle.html

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>DrawCircle</title>

        <script id="vertex-shader" type="x-shader/x-vertex">
            attribute vec4 vPosition;
            uniform mat4 u_transMat;
            void main(){
    
              gl_Position = u_transMat * vPosition;
            }
        </script>
        <script id="fragment-shader" type="x-shader/x-fragment">
            precision mediump float;
            uniform vec4 u_FragColor;
            void main(){
    
                gl_FragColor = u_FragColor;
            }
        </script>

        <script type="text/javascript" src="../Common/webgl-utils.js"></script>
        <script type="text/javascript" src="../Common/initShaders.js"></script>
        <script type="text/javascript" src="drawCircle.js"></script>

    </head>
    <body>
        <canvas id="gl-canvas" width="512" height="512">
            Oops ... your browser doesn't support the HTML5 canvas element
        </canvas>
    </body>
</html>

在html文件中,声明了两个着色器。
顶点着色器内,设置了attribute变量vPosition用于记录顶点的属性,uniform变量u_transMat为变换矩阵,用于对绘制出的图案进行旋转平移操作。
片元着色器内,首先设置精度为中低精度,uniform变量u_FragColor用于记录片元颜色。
body中,声明一个canvas画布,所有的绘制都在画布上进行。
需要注意的是,gl_Position的值是用变换矩阵 * 顶点坐标向量得到的,变换矩阵和顶点坐标向量的位置不能交换,因为我们最终需要得到的gl_Position是一个四阶行向量。

drawCircle.js

js代码部分比较长,让我分解为多个部分。
通过对小鸡的分析,不难得知,组成该图形的图形为三角形、圆形、线段。

1. 我们首先来介绍绘制圆的函数getCircleVertex。
// 画圆
// 半径r 面数m 度数c
function getCircleVertex(r, m, c) {
   
    var arr = [];
    var addAng = c / m;
    var angle = 0;
    for (var i = 0; i < m; i++) {
   
        arr.push(Math.sin(Math.PI / 180 * angle) * r, Math.cos(Math.PI / 180 * angle) * r, 0, 1.0);
        arr.push(0.0, 0.0, 0.0, 1.0);
        angle = angle + addAng;
        arr.push(Math.sin(Math.PI / 180 * angle) * r, Math.cos(Math.PI / 180 * angle) * r, 0, 1.0);
    }
    return arr;
}

由于WebGL没有提供圆这个基本图形,于是我们把圆细分,通过绘制多个三角形来达到圆的效果。该函数它有三个参数:r表示圆的半径,m表示绘制该圆需要的三角形面数(即个数,数字越大,圆的效果越好),c表示需要绘制的度数(c取360时为整圆,取180时为半圆,以此类推),函数返回值为存储了构成圆的每个三角形的三个顶点的数组(有点绕)。

观察for循环内部,我们使用JavaScript内置的Math.sin()和Math.cos()来计算三角形(可看做扇形)圆心角的正余弦,但这两个方法必须接收弧度值,所以要先把角度转换为弧度值。
由于最后我们使用gl.TRIANGLES来绘制三角形,因此每一次for循环就将三角形的三个角的坐标加入到arr数组中。

2. 接着进入js主体代码部分
	window.onload = function init () {
   
    var canvas = document.getElementById( "gl-canvas" );

    var gl = WebGLUtils.setupWebGL( canvas );
    if ( !gl ) {
    alert( "WebGL isn't available" ); }

    // 设置窗口大小
    gl.viewport( 0, 0, canvas.width, canvas.height );
    gl.clearColor( 0.0
使用 WebGL 绘制正方形需要进行以下步骤: 1. 获取 WebGL 上下文对象 ```javascript const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); ``` 2. 设置顶点着色器和片元着色器 ```javascript const vertexShaderSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0, 1); } `; const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(1, 0, 0, 1); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); ``` 3. 创建着色器程序并链接顶点着色器和片元着色器 ```javascript const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); ``` 4. 创建缓冲区并绑定数据 ```javascript const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); const positions = [ -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); ``` 5. 设置顶点属性指针并启用 ```javascript const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); gl.enableVertexAttribArray(positionAttributeLocation); gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); ``` 6. 清空画布并绘制正方形 ```javascript gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); ``` 完整的 WebGL 绘制正方形的代码如下: ```javascript const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); const vertexShaderSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0, 1); } `; const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(1, 0, 0, 1); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); const positions = [ -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); gl.enableVertexAttribArray(positionAttributeLocation); gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); ``` 这样就可以在 canvas 中绘制一个红色的正方形了。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值