WebGL学习系列-多边形绘制原理

前言

前面学习了通过缓冲区对象来绘制多个点的原理,在实际的3D世界里,有好多复杂的模型,但细化分解后又是由一个个基础的几何图形构成的,掌握了基础图形的绘制才能够理解更加复杂的模型。本节将会讲解三角形,矩形以及利用三角函数绘制圆。

WebGL几何图形绘制

之前的篇章我们通过 drawArrays 这个api绘制过单个点以及多个点,然而,它的功能不仅仅如此,它也是绘制多边形的基石。先来看下面这张熟悉的图:

基本图形

drawArrays 支持多种类型的基本图形,可以画点、线段、折线图,三角形,扇形等,不过要注意顶点的顺序性。

在上一小节画三个点的示例上,只要稍微把绘制方法改一下,即可绘制一个三角形。

// 第一个参数改为: context.TRIANGLES
context.drawArrays(context.TRIANGLES, 0, n);

效果图如下:
三角形

是不是非常的简单,同时注意到,WebGL绘制出来的是填充好了的三角形,还记得我们在片元着色器中定义的顶点颜色为: gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0),也就是三个顶点都是红色,结果整个三角形都为红色的。(后续章节会解释颜色的绘制,这跟片元着色器的工作原理相关)

现在,我们已经知道了,要绘制一个几何图形,只需要按照规定定义好图形的顶点,再调用drawArrays方法便可以自行绘制出几何图形了,这便是WebGL几何图形的绘制原理,只需要指定顶点信息即可。

接着,我们再接再厉,绘制一个四边形。四边形跟三角形不一样的地方在于多了一个顶点,我们重新定义顶点的信息:

var vertices = new Float32Array([
        -0.5,0.5, -0.5,-0.5, 0.5,0.5, 0.5,-0.5
      ]);

这一次,我们使用 context.TRIANGLE_STRIP 这种类型进行绘制,参考图示,定义的顶点顺序为:左上角(V0),左下角(V1),右上角(V2),右下角(V3)。

最后修改绘制方法即可:

// 绘制矩形
context.drawArrays(context.TRIANGLE_STRIP, 0, n);

效果图如下:
矩形

绘制一个圆

从上面几何绘制图形来看,似乎没有办法可以直接绘制一个圆,事实上,的确没有直接的api可以绘制一个圆,但这难不倒我们,借助 context.TRIANGLE_FAN 这种类型,我们便可以绘制一个近乎圆的多边形(肉眼来看的确就是一个圆)。

为了说明圆的绘制原理,咱们先来看两张几何图
八边形示意图

十六边形示意图

我们在一个圆形上面画一个八边形和一个十六边形,所有的顶点都落在圆形上面,从以上两幅图可以看到,只要遵循顶点在圆形上,而且顶点均匀分布,那么随着顶点数越多,所有顶点连结起来就越接近一个圆。

思路有了,接下来,我们的任务就转化为怎么去求这些点的坐标。

顶点位置计算

假设p1就是我们的点V0,现在我们要求出其他点的坐标,设点p2(x’,y’)是接下去的顶点,与p1(x,y) 相隔了θ度(θ = 360/n,n为顶点数量),

由三角函数知识 ,可得
sinθ = y’/ r ; cosθ = x’/ r

也即:
p2(x’ , y’) = (r * cosθ , r * sinθ)

现在,我们使用的是角度 ,js中计算三角函数使用的是弧度,所以要转换一下,
θ = 360/n * (Math.PI/180); (n为顶点的数量)

有了这些基础,我们便可以编写画圆的程序了,初始化顶点的代码如下:

function initVertexBuffers(context) {
      // 画n个点
      var n = 64;
      var vertices = new Float32Array(n*2);
      var angle = 0; // 开始的弧度 
      var r = 0.5; // 圆的半径
      // θ值
      var stepAngle = 360/n * (Math.PI/180);
      for(var i=0; i<n*2; i+=2){
        // 计算顶点x坐标
        vertices[i] = r * Math.cos(angle);
        // 计算顶点y坐标
        vertices[i+1] = r * Math.sin(angle);
        angle += stepAngle;
      }

      // 创建一个缓存对象,用于存放顶点数据
      var vertexBuffer = context.createBuffer();
      // 绑定缓存对象
      context.bindBuffer(context.ARRAY_BUFFER, vertexBuffer);
      // 把数据写到缓冲对象中
      context.bufferData(context.ARRAY_BUFFER, vertices, context.STATIC_DRAW);
      // 获取顶点着色器代码中的顶点变量
      var a_Position = context.getAttribLocation(context.program, 'a_Position');
      // 设置变量获取数据规则
      context.vertexAttribPointer(a_Position, 2, context.FLOAT, false, 0, 0);
      // 允许变量从 ARRAY_BUFFER目标上绑定的缓冲区对象获取数据
      context.enableVertexAttribArray(a_Position);

      return n;
    }

然后,我们使用 TRIANGLE_FAN 进行绘制即可。

// 绘制扇形
context.drawArrays(context.TRIANGLE_FAN, 0, n);

最后我们来看看当n=8,16,64时的效果图:
n=8
n=16
n=64

小结

多边形的绘制是非常基础的知识,但也是非常重要的,只有知道了怎么绘制基础的图形,才能够理解各种更加复杂的模型,通过一些数学知识,我们最后绘制了一个圆。大家可以凭自己的想象尝试绘制更多的图形。

源码下载

点击下载(多边形绘制原理)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值