webgl - 3- 绘制三角形(上)

三角形是一个最简单,稳定的面,webgl中的三维模型都是由三角形面组成的。

本章节目标:

1.理解多点绘图原理
2.可以绘制三角形,并将其组合成多边形。

知识点:

  1. 换缓冲区对象
  2. 点,线,面图像

第一章webgl的绘图方式

先看下webgl是怎么绘图的:
1.绘制多点:
请添加图片描述

  1. 如果是线,就连接点成线

请添加图片描述

  1. 如果是面,那就在图形内部,逐便元填色

请添加图片描述
webgl绘图的方式就是这么简单,接下来就说一下这个绘图方式在程序中是如何实现的。

第2章:绘制多点:

在webgl 里所有的图形都是由顶点连接而成的,咱们就先画三个可以构成三角形的点。

现在要画的多点是可以被webgl加工成线,面的。

绘制多点的整体步骤:

  1. 建立着色器源文件
<script id="vertexShader" type="x-shader/x-vertex">
       attribute vec4 a_Position;
       void main(){
   
           gl_Position = a_Position;
           gl_PointSize = 20.0;
       }
   </script>
   <script id="fragmentShader" type="x-shader/x-fragment">
       void main(){
   
           gl_FragColor=vec4(1.0,1.0,0.0,1.0);
       }
   </script>
  1. 获取webgl上下文
  const canvas = document.getElementById('canvas');
   canvas.width=window.innerWidth;
   canvas.height=window.innerHeight;
   const gl = canvas.getContext('webgl');
  1. 初始化着色器
 const vsSource = document.getElementById('vertexShader').innerText;
   const fsSource = document.getElementById('fragmentShader').innerText;
   initShaders(gl, vsSource, fsSource);
  1. 设置顶点点位
  const vertices=new Float32Array([
    // 一行是一个顶点数据(x, y, z)
       0.0,  0.1,
       -0.1,-0.1,
       0.1, -0.1
   ])
   const vertexBuffer=gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
   gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
   const a_Position=gl.getAttribLocation(gl.program,'a_Position');
   gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
   gl.enableVertexAttribArray(a_Position);
  1. 清理画布
   gl.clearColor(0.0, 0.0, 0.0, 1.0);
   gl.clear(gl.COLOR_BUFFER_BIT);
  1. 绘图
   gl.drawArrays(gl.POINTS, 0, 3);

效果如下:
请添加图片描述

接下来对第4步进行详细的讲解:

在用js定点位的时候,肯定是要建立一份顶点数据的,这份顶点数据是给谁的呢?肯定是给着色器的,因为着色器需要这份顶点数据绘图。
然而,我们在js中建立顶点数据,着色器肯定是拿不到的,这是语言不通导致的。

为了解决这个问题,我们在js中建立顶点数据,着色器肯定是拿不到的,这是语言不通导致的。

为了解决这个问题,webgl 系统就建立了一个能翻译双方语言的缓冲区。js 可以用特定的方法把数据存在这个缓冲区中,着色器可以从缓冲区中拿到相应的数据。

接下来就看下这个缓冲区是如何建立的,着色器又是吐核从中拿到数据的。

1.建立顶点数据,两个浮点数据构成一个顶点,分别代表x,y值。

const vertices=new Float32Array([
    //x    y
    0.0,  0.1, //顶点
    -0.1,-0.1, //顶点
    0.1, -0.1  //顶点
])

现在上面的这些顶点数据是存储在js缓冲区里面的,着色器拿不到,所以需要建立一个着色器和js都能进入的公共区。

2.建立缓冲区:

const vertexBuffer=gl.createBuffer();

现在上面这个换成区是独立存在的,它只是一个空着的仓库,和谁都没有关系。解析来咱们就和着色器建立连接。

3.绑定缓冲区对象

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)

gl.bindBuffer(target,buffer) 绑定缓冲区

  • target 要把缓冲区放在webgl 系统中的什么位置
  • buffer 缓冲区

着色器对象在执行initShaders()初始化方法的时候,已经被写入webgl上下文对象的gl中了。

当缓冲区和着色器建立了绑定关系,我们就可以往这块空间写入数据了。

4.往缓冲区对象中写入对象。

gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);

bufferData(target, data, usage) 将数据写入缓冲区。

  • target 要把缓冲区放在webgl 系统中的什么位置
  • data 数据
  • usage 向缓冲区写入数据的方式,咱们在这里先知道 gl.STATIC_DRAW 方式即可,它是向缓冲区中一次性写入数据,着色器会绘制多次。

现在着色器虽然绑定了缓冲区,可以访问里面的数据了,但是我们还得让着色器知道这个仓库是给哪个变量的,比如咱们这里用于控制点位的attribute 变量。这样做是为了提高绘图效率。

5.将缓冲区对象分配给attribute变量

const a_Position=gl.getAttribLocation(gl.program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);

gl.vertexAttribPointer(local,size,type,normalized,stride,offset) 将缓冲区对象分配给attribute 变量

  • local attribute变量
  • size 顶点分量的个数,比如我们的vertices 数组中,两个数据表示一个顶点,那咱们就写2
  • type 数据类型,比如 gl.FLOAT 浮点型
  • normalized 是否将顶点数据归一
  • stride 相邻两个顶点间的字节数,我的例子里写的是0,那就是顶点之间是紧挨着的
  • offset 从缓冲区的什么位置开始存储变量,我的例子里写的是0,那就是从头开始存储变量

到了这里,着色器就知道缓冲区的数据是给谁的了。因为咱们缓冲区里的顶点数据是数组,里面有多个顶点。所以我们得开启一个让着色器批量处理顶点数据的属性。默认着色器只会一个一个的接收顶点数据,然后一个一个的绘制顶点。

6.开启顶点数据的批处理功能。

gl.enableVertexAttribArray(a_Position);
  • location attribute变量

7.绘图:

gl.clearColor(0.0, 0.0, 1.0)
gl.clear()
gl.drawArrays(gl.POINTS, 0, 3)

drawArrays(mode,first,count)

  • mode:绘图模式,比如: gl.POINTS 画点
  • first从哪个顶点开始绘制
  • count要画多少个顶点

完整代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>绘制多点</title>
    <style>
      body {
   
        margin: 0;
        overflow: hidden;
      }
      #canv
WebGL是一种用于在Web浏览器中绘制3D图形的技术。要绘制多边形,你需要定义顶点数据,并使用WebGL绘制函数将其绘制到画布上。 以下是一个使用WebGL绘制三角形的示例: ```javascript // 获取画布元素 var canvas = document.getElementById("myCanvas"); // 获取WebGL上下文 var gl = canvas.getContext("webgl"); // 定义顶点数据 var vertices = [ -0.5, -0.5, 0.0, // 第一个顶点的坐标 0.5, -0.5, 0.0, // 第二个顶点的坐标 0.0, 0.5, 0.0 // 第三个顶点的坐标 ]; // 创建缓冲区对象 var vertexBuffer = gl.createBuffer(); // 绑定缓冲区对象 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 将顶点数据写入缓冲区对象 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // 获取顶点着色器代码 var vertexShaderSource = ` attribute vec3 aPosition; void main() { gl_Position = vec4(aPosition, 1.0); } `; // 创建顶点着色器对象 var vertexShader = gl.createShader(gl.VERTEX_SHADER); // 编译顶点着色器代码 gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); // 获取片元着色器代码 var fragmentShaderSource = ` void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } `; // 创建片元着色器对象 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); // 编译片元着色器代码 gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); // 创建着色器程序对象 var program = gl.createProgram(); // 将顶点着色器和片元着色器附加到着色器程序对象上 gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); // 链接着色器程序对象 gl.linkProgram(program); // 使用着色器程序对象 gl.useProgram(program); // 获取顶点位置属性的位置 var aPosition = gl.getAttribLocation(program, "aPosition"); // 启用顶点属性数组 gl.enableVertexAttribArray(aPosition); // 指定顶点属性数组的数据格式和位置 gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0); // 清空画布 gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // 绘制三角形 gl.drawArrays(gl.TRIANGLES, 0, 3); // 刷新画面 gl.flush(); ``` 这段代码首先获取了画布元素和WebGL上下文,然后定义了三个顶点的坐标数据。接下来,创建了顶点着色器和片元着色器,并编译它们的代码。然后,创建了着色器程序对象,并将顶点着色器和片元着色器附加到着色器程序对象上。之后,启用顶点属性数组,并指定顶点属性数组的数据格式和位置。最后,清空画布,绘制三角形,并刷新画面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值