webgl入门-基础三角形绘制

背景

最近工作上频繁接触webgl,因为不熟悉每每看到shader中的语法总感觉脑袋大,所以打算开始从零学习一下webgl,文章只做记录学习历程,那就直接开始吧!

开始

可以配合着这个文章食用。

我还是对webgl有一些概念的,说一下我的理解就是用来对图元进行光栅化的程序,首先说光栅化是什么,我的理解是将看到的东西画到屏幕上,那这个过程会经历什么比如画一个三角形,首先我要确定三角形画在哪里也就是顶点的位置,然后确认顶点后填充颜色,颜色其实就是一个个像素组成的,gpu做的就是将一个个gpu渲染上颜色这个过程叫光栅化。

ok,总结一下,一个webgl着色器程序,它需要有两部分组成:

  1. 顶点着色器(VertexShader)
  2. 片元着色器(FragmentShader)

好,以上两个着色器即可组成一个着色器程序。

代码实践

着色器创建流程

  1. 首先获取webgl的上下文
  2. 编写顶点和片元着色器代码
  3. 实例创建顶点和片元shader
  4. 创建着色器程序Program,并注入两个shader

下面代码不包含glsl代码

javascript 复制代码
function initWebgl() {
    const canvas = document.getElementById('canvas');
    const gl = canvas.getContext('webgl');
    // 平面空间大小
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    // 清空画布
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    return gl;
}
const gl = initWebgl();

// 创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
function createShader(gl, type, source) {
    const shader = gl.createShader(type); // 创建着色器对象
    gl.shaderSource(shader, source); // 提供数据源
    gl.compileShader(shader); // 编译 -> 生成着色器
    const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (success) {
        return shader;
    }

    console.log(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
}

const vertexShaderSource = document.querySelector('#vertex-shader-2d').text;
const fragmentShaderSource = document.querySelector('#fragment-shader-2d').text;

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

// 创建着色器程序
function createProgram(gl, vertexShader, fragmentShader) {
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    const success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (success) {
        return program;
    }

    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
}

// 着色器创建成功
const program = createProgram(gl, vertexShader, fragmentShader);

至此准备工作已做好

数据传递流程

现在我想画一个三角形就需要用到顶点着色器,传递给它三个顶点的位置

  1. 首先先寻找要赋值的顶点着色器变量
  2. 创建一个缓冲区
  3. 再创建一个buffer,绑定在缓冲区中
  4. 将数据写入buffer
  5. enableVertexAttribArray:开启属性,这时变量和缓冲区建立好链接了
  6. vertexAttribPointer:规定数据如何读取

代码体现

javascript 复制代码
// 找出顶点着色器中a_position变量
// 这要注意:寻找属性值位置(和全局属性位置)应该在初始化的时候完成,而不是在渲染循环中。
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
// 创建一个缓冲
const positionBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// 三个顶点坐标
const positions = [0, 0, 0, 0.5, 0.7, 0];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// 告诉gl是用那个着色器程序
gl.useProgram(program);

// 启用属性
gl.enableVertexAttribArray(positionAttributeLocation);

// 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)
const size = 2; // 每次迭代运行提取两个单位数据
const type = gl.FLOAT; // 每个单位的数据类型是32位浮点型
const normalize = false; // 不需要归一化数据
const stride = 0; // 0 = 移动单位数量 * 每个单位占用内存(sizeof(type))
// 每次迭代运行运动多少内存到下一个数据开始点
const offset = 0; // 从缓冲起始位置开始读取
gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);

附一些语法规则定义:

开始绘制

需要制定绘制规则,因为gl不知道你是要画三个点还是一个三角形,还有程序执行次数。

代码体现

javascript 复制代码
// 设置图元类型为三角形
const primitiveType = gl.TRIANGLES;
const drawArraysOffset = 0;
// 程序执行次数
const count = 3;
gl.drawArrays(primitiveType, drawArraysOffset, count);

在顶点绘制完成后,gl能够知道哪些像素是需要通过片元着色器进行上色的,至此基础的三角形绘制完毕!

ok,总结一下

一个基础的着色器程序主要流程是:

  1. 创建webgl上下文
  2. 创建顶点着色器和片元着色器组成一个完整的着色器程序
  3. 数据传递,今天的demo只进行了顶点数据传递
  4. 执行着色器程序(可配置执行规则)

本人对数据传递有些模糊,特画了个流程图清晰一下

附文章:

https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-fundamentals.html

相关推荐
丫丫72373411 小时前
Three.js 模型树结构与节点查询学习笔记
javascript·webgl
allenjiao3 天前
WebGPU vs WebGL:WebGPU什么时候能完全替代WebGL?Web 图形渲染的迭代与未来
前端·图形渲染·webgl·threejs·cesium·webgpu·babylonjs
mapvthree3 天前
mapvthree Engine 设计分析——二三维一体化的架构设计
webgl·数字孪生·mapvthree·jsapi2d·jsapigl·引擎对比
GISer_Jing4 天前
3D Cesium渲染架剖析
javascript·3d·webgl
Swift社区5 天前
用 Chrome DevTools 深度分析 Vue WebGL 内存泄漏(进阶篇)
vue.js·webgl·chrome devtools
GISer_Jing7 天前
3DThreeJS渲染核心架构深度解析
javascript·3d·架构·webgl
ThreePointsHeat7 天前
Unity 关于打包WebGL + jslib录制RenderTexture画面
unity·c#·webgl
GISer_Jing8 天前
Three.js核心技术解析:3D开发指南
javascript·3d·webgl
l***O52011 天前
免费的WebGL性能优化,纹理压缩与实例化
性能优化·webgl
二川bro12 天前
第38节:WebGL 2.0与Three.js新特性
开发语言·javascript·webgl