WebGL学习 | 青训营笔记

129 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第6天

1.什么是WebGL?

定义:WebGL是帮助你在浏览器上创建和渲染三维图形的一个API集,专门用于Web页的OpenGL,底层还是JavaScript API

现代图形系统

image.png

  • 光栅 (Raster) :几乎所有现代图形系统都是基于光栅来绘制图形的,光栅是指构成图像的像素阵列
  • 像素 (Pixel) :一个像素对应图像上的一个点,通常保存图像上的某个具体位置的颜色等信息
  • 帧缓存 (Frame Buffer) :在绘图过程中,像素信息被存放帧缓存中,帧缓存是一块内存地址
  • CPU :中央处理单元,负责逻辑计算
  • GPU :图形处理单元,负责图形计算

CPU与GPU的设计区别

CPU和GPU之所以大不相同,是由于其设计目标的不同,它们分别针对了两种不同的应用场景。CPU需要很强的通用性来处理各种不同的数据类型,同时又要逻辑判断又会引入大量的分支跳转和中断的处理。这些都使得CPU的内部结构异常复杂。而GPU面对的则是类型高度统一的、相互无依赖的大规模数据和不需要被打断的纯净的计算环境。

CPU的工作原理像一个管道,每个管道我们叫做一个CPU内核,CPU的工作能力,与管道本身的处理速度(频率)合管道的数量(内核数)有关系
与CPU不同,GPU可以看成是由数量非常多的微小管道构成的结构。如果对于一张600像素x800像素的图片,有48万个管道组成的GPU,就可以同时处理这48万个像素点了。

image.png

工作原理

  • 轮廓提取 CPU
  • 光栅化 GPU
  • 帧缓存
  • 渲染

image.png

WebGL利用JavaScript来准备数据,将数据通过共享数据结构(ArrayBuffer) 传递给GPU,由GPU进行着色处理,然后再将处理后的数据输出到帧缓冲区,最后再渲染出来。

准备数据: 通过JavaScript的类型数组(TypedArray)
着色处理:通过WebGL Program执行一种特殊的glsl语言来实现。顶点着色片段着色

WebGL Startup

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

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

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);
  }
`
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);

const program=gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);

gl.useProgram(program);

const points=new Float32Array([
  -1,-1,
  0,1,
  1,-1,
]);
const BufferId=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,BufferId);
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW);

const vPosition=gl.getAttribLocation(program,'position'); // 顶点着色器position变量
gl.vertexAttribPointer(vPosition,2,gl.FLOAT,false,0,0); // 给变量设置长度和类型
gl.enableVertexAttribArray(vPosition);// 激活变量

gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,points.length/2);