vlambda博客
学习文章列表

WebGL可视化基础(一)

图形是如何绘制的

一个通用的计算机图形系统主要包括6个设备,分别是输入设备/中央处理单元/图形处理单元/存储器/帧缓存/输出设备

首先,数据经过CPU处理,转换为特定结构的几何信息,然后将这些信息送到GPU中进行处理。在GPU中要经过两个步骤生成光栅信息。这些光栅信息会输出到缓存中,最后渲染到屏幕上。

WebGL可视化基础(一)


这个绘图过程主要做了2件事情,一是对给定的数据结合绘图的场景要素(例如相机/光源/遮挡物体等等)进行计算,最终将图形变为屏幕空间的2D坐标。二是为屏幕空间的每个像素点进行着色,把最终完成的图形输出到显示设备上。这整个过程是一步一步进行的,前一步的输出就是后一步的输入,所以我们也把这个过程叫做渲染管线(RenderPipelines)

如何用WebGL绘制三角形

浏览器提供的WebGL API是IpenGL ES的 JavaScript绑定版本,它赋予开发者操作GPU的能力。

  1. 创建WebGL 上下文
  2. 创建WebGL 程序
  3. 将数据存入缓冲区
  4. 将缓冲区的数据读取到GPU
  5. GPU执行WebGL程序,输出结果

步骤一:创建WebGL上下文

 const canvas = document.querySelector("canvas");
 const gl = canvas.getContext("webgl");

步骤二:创建WebGL 程序

  • 这里需要创建一个WebGLProgram 对象,它是给GPU最终运行着色器的程序。

  • 这里首先要编写两个着色器(Shader)。

const vertex = `
attribute vec2 position;

void main() {
gl_PointSize = 1.0;
gl_Position = vec4(position. 1.0, 1.0)
}
`;

const fragment = `
precision mediump float;

void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

为什么需要两个着色器呢?这就需要理解顶点和图元的概念。在绘图的时候,WebGL是以顶点和四个图元来描述图形几何信息的。顶点就是几何图形的顶点,比如,三角形有三个顶点,四边形有四个顶点。图元是WebGL可直接处理的图形单元,由WebGL的糊涂模式决定,有点/线/三角形等等。

所以,顶点和图元是绘图过程中必不可少的。因此,WebGL绘制一个图形的过程,一般都需要用到两段着色器。一段叫顶点着色器负责处理图形的顶点信息,另一段叫片元着色器负责处理图形的像素信息。

我们可以把顶点着色器理解为处理顶点的GPU程序代码。他可以改变顶点的信息(如顶点的坐标/法线方向/材质等等),从而改变我们绘制出来的图形的形状或者大小等

顶点处理完之后,WebGL就会根据顶点和绘图模式指定的图元,计算出需要着色的像素点,然后对它们进行执行片元着色器程序。

这里其实很好理解,顶点是为了帮助我们绘制出图形,图元是为了帮助我们上色。

  • 开始绘制三角形
// 创建成shader对象
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);

// 创建WebGLProgram对象,并且将这两个shader关联到WebGL程序上。
// 再将WebGL程序链接到WebGL上下文对象上。
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgrram(program);

// 最后通过useProgram 选择启动这个WebGLPrame对象。
gl.useProgram(program);

// 接下来将数据存入缓冲区,也就是将数据送入GPU
// 定义三角形的三个顶点
const points = new Float32Array([
  -1-1,
  01,
  1-1,
]);

// 将数据送入WebGL的缓冲区 三步走,创建一个缓存对象,绑定为当前操作对象,再把当亲的数据写入缓存对象。
const bufferId = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);

// 将缓存区数据读取到GPU,把数据绑定给顶点着色器的position变量
// 在GLSL中, attribute 表示声明变量,vec2是变量的类型,它表示一个二维向量,position是变量名。

const vPosition = gl.getAttribLocation(program, 'position');
// 获取顶点着色器中的position
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false00); //给变量设置长度和类型
gl.enableVertextAttribArray(vPosition); //激活变量

// 执行着色器程序完成绘制
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);

// 至此我们的三角形就绘制完成了
  • WebGL 绘图过程流程图

参考文章

极客时间:跟月影学和石化