webgl入门-基础三角形绘制

背景

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

开始

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

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

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

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

代码实践

着色器创建流程

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

下面代码不包含glsl代码

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:规定数据如何读取

代码体现

// 找出顶点着色器中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不知道你是要画三个点还是一个三角形,还有程序执行次数。

代码体现

// 设置图元类型为三角形
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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/156813.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数式接口详解(Java)

函数式接口详解(Java)_函数式接口作为参数_凯凯凯凯.的博客-CSDN博客 函数式接口:有且仅有一个抽象方法的接口 Java中函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口 只有确保接口中仅有一个抽…

oracel处理XML时,报ORA-31011、ORA-19202。

原字段为clob, 查询 SELECT XMLTYPE(字段) FROM TABLE_A报错如下: ORA-31011: XML 语法分析失败 ORA-19202: XML 处理 LPX-00217: invalid character 12 (U000C) Error at line 1559时出错 ORA-06512: 在 "SYS.XMLTYPE", line 272 ORA-0651…

【AI视野·今日Sound 声学论文速览 第三十二期】Tue, 24 Oct 2023

AI视野今日CS.Sound 声学论文速览 Tue, 24 Oct 2023 Totally 20 papers 👉上期速览✈更多精彩请移步主页 Interesting: 📚nvas3d, 基于任意录音和室内3D信息合成重建不同听角(位置)处的新的声音。(from apple cmu) website: htt…

Jupyter notebook如何加载torch环境

默认你已经安装了anaconda 和 pytorch 环境。 1,必须要以管理员身份打开 Anaconda prompt终端, 2,进入pytorch环境中: conda activate pytorch_393,安装必要插件: (1)conda inst…

flutter之bloc使用详解

flutter中一切皆为Widget,因此在我们开发中,往往业务和UI逻辑写在一起,这样不利于代码维护,因此状态管理框架久诞生了,这篇就开始讲一讲Bloc。 对于Bloc库有两个,如下图: flutter_bloc其实是对…

[云原生案例1.] 构建LNMP架构并运行Wordpress个人博客平台

文章目录 1. 当前需求2. 前置准备3. 搭建过程3.1 创建自定义网络3.2 部署并配置nginx3.2.1 创建工作目录并上传相关软件包3.2.2 解压缩相关软件包3.2.3 编写Dockerfile文件3.2.4 编写nginx.conf文件3.2.5 创建nginx镜像3.2.6 运行容器 3.3 部署并配置mysql3.3.1 创建工作目录3.…

USART HMI串口屏+GPS模块显示时间和经纬度

USART HMI串口屏GPS模块显示时间和经纬度 📍相关篇《基于u-box GPS模块通过串口指令调整输出信息》 📋在不使用其他单片机做数据中转处理情况下,利用USART HMI串口屏主动解析模式,来接收并解析GPS模块数据并显示,功能包…

chorme安装esay scholar及chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案

问题描述 如题,博主想安装easy scholar用于查询论文的分区,结果安装了半天一直出现chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案的问题。 解决方案 先从这个网址下载:https://www.easyscholar.cc/download 然后对下载好的文…

Linux进程概念(1)

📟作者主页:慢热的陕西人 🌴专栏链接:Linux 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 本博客主要内容为进程的概念做铺垫,主要介绍冯诺依曼体系结…

TCP 协议

文章目录 协议格式1面向连接:1.1三次握手(建立连接)1.2包序管理1.2四次挥手(断开连接) 2可靠传输:一。保证数据可靠有序的到达对端:确认应答机制超时重传机制 二。提高传输效率:1.提升自身发送数据量滑动窗口机制 rwnd滑动窗口丢包…

ARM 版 OpenEuler 22.03 部署 KubeSphere v3.4.0 不完全指南续篇

作者:运维有术 前言 知识点 定级:入门级KubeKey 安装部署 ARM 版 KubeSphere 和 KubernetesARM 版 KubeSphere 和 Kubernetes 常见问题 实战服务器配置 (个人云上测试服务器) 主机名IPCPU内存系统盘数据盘用途ks-master-1172.16.33.1661650200KubeSp…

PostGIS轨迹分析——简化轨迹

需求 对轨迹线进行简化,并将原始轨迹上的两个特征点拉取到简化后的轨迹上 简化线 红色线是简化后的轨迹线,蓝色线是原始轨迹,有两个特征点 知识点: st_makeline函数将点连成线st_simplify简化线函数,其中第二个参数为坐标系的单位,0.002度大概代表0.002x1.11x10^5≈22…