所有示例代码均可在我的gitee码云上,读者可自行下载:https://gitee.com/babyogl/learnWebGL,本文示例代码在chapter-01里面,引用文件都在libs文件夹下;为了让读者不至于枯燥乏味,这一篇文章我们不讲计算和理论,相关的矩阵运算和理论留在后面,现在只是单纯的介绍WebGL一些接口和用法,从一个简单的示例开始:绘制一个带颜色的三角形。

在开始之前,需要知道着色器的相关知识,可以参考:webgl介绍里面的着色器介绍,本文的demo 用到的着色器为:

    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 a_position;
        void main() {
            gl_Position = a_position;
        }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
        precision mediump float;//将精度设置为中等精度
        void main() {
            gl_FragColor = vec4(1, 0, 0.5, 1);
        }
    </script>

其中的attribute定义了一个vec4四维变量,用于表示每个顶点的位置信息,gl_Position代表顶点的位置, a_position是着色器用于接收来自JavaScript代码的顶点位置信息的入口。gl_FragColor代表每个片元的颜色,通俗的理解是用于设置顶点颜色。其中的vec4(1, 0, 0.5, 1)代表颜色信息(r, g, b, a),及(红,蓝,绿,透明度),它们的取值都在0-1之间,可以搭配出任意你想要的颜色;

首先,创建HTML文档,并在HTML文档的<body></body>里创建一个用于画图的canvas(画布),并引用相关的js文件,和创建相关的着色器脚本:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>triangle</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        canvas {
            border: 3px solid blue;
            display: block;
        }
    </style>
</head>
<body>
<canvas id="triangle" width="800" height="600"></canvas>
<script type="text/javascript" src="../libs/webgl-utils.js"></script>
<script type="text/javascript" src="../libs/shader.js"></script>
<script id="vertex-shader" type="x-shader/x-vertex">
      attribute vec4 a_position;
      void main() {
          gl_Position = a_position;
      }
 </script>

 <script id="fragment-shader" type="x-shader/x-fragment">
      precision mediump float;//将精度设置为中等精度
      void main() {
          gl_FragColor = vec4(1, 0, 0.5, 1);
      }
 </script>
<script type="text/javascript">
.......//用于实现主要功能的脚本代码
</script>
</body>
</html>

主要功能的实现脚本如下:

获取canvas元素:

 let canvas = document.getElementById('triangle');

判断浏览器是否支持WebGL,其中,antialias表示是否开启抗锯齿, depth表明绘制缓冲区包含一个深度至少为16位的缓冲区:

let gl = canvas.getContext('webgl', {antialias: true, depth: false});
 if (!gl) {
    console.log("您的浏览器不支持webgl!");
 }

根据id获取着色器文本,并创建、编译和链接着色器:

//获取GLSL文本
let vShaderSource = document.getElementById('vertex-shader').text;
let fShaderSource = document.getElementById('fragment-shader').text;
//创建、编译和链接着色器
 let program = initShader(gl, vShaderSource, fShaderSource);

在着色器中寻找attribute变量的位置:

let positionAttributeLocation = gl.getAttribLocation(program, 'a_position');

创建缓冲区,并绑定数据:

//创建缓冲区
 let positionBuffer = gl.createBuffer();

 //将它绑定到ARRAY_BUFFER(将其视为ARRAY_BUFFER = positionBuffer)
 //绑定缓冲区
 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

 //三个顶点构成一个三角形
  let positions = [
       -0.25, 0,
        0, 0.5,
        0.25, 0
      ];

//通过绑定点向缓冲区绑定数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

 最后进行画图:

//使画布的像素数和显示大小匹配
 webglUtils.resizeCanvasToDisplaySize(gl.canvas);

 //设置视口
 gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

 //清除canvas
 gl.clearColor(0, 0, 0, 1);//设置背景颜色
 gl.clear(gl.COLOR_BUFFER_BIT);

 //应用着色器
 gl.useProgram(program);

 //建立着色器中attribute变量与缓冲区之间的连接
 gl.enableVertexAttribArray(positionAttributeLocation);
 const size = 2;//2维坐标:每次迭代运行提取两个单位数据
 const type = gl.FLOAT;//每个单位的数据类型是32位浮点型
 const normalize = false;//不需要归一化数据
 const stride = 0;//每次迭代前进大小* sizeof(类型)以获得下一个位置
 const offset1 = 0;//从缓冲起始位置开始读取

 //从缓冲区取出数据
  gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset1);

  let primitiveType = gl.TRIANGLES;//绘制三角形
  let offset2 = 0;//从第一个顶点开始
  let count = 3;//画图所顶点次数
  gl.drawArrays(primitiveType, offset2, count);//画图

对于WebGL的画图接口gl.drawArrays和gl.drawElements的用法,可以参考这篇文章:https://blog.csdn.net/qq_37338983/article/details/78556091

在一开始我们加了一个<style></style>,主要是利用CSS对页面元素的一些格式进行设置,主要是对canvas和body进行设置:

<style>
        body {
            margin: 0;<!--外边距-->
            overflow: hidden;<!--隐藏溢出页面的元素-->
        }

        canvas {
            border: 3px solid blue;<!--边界线设置-->
            display: block;<!--生成的框的类型-->
        }
 </style>

 

显示效果:

原生webgl学习(二) 用WebGL绘制一个三角形

从下一节开始,将结合实例讲解矩阵的一些运算、例如平移、旋转和缩放等。 

相关文章: