当前位置: 首页 > news >正文

(三)通过WebGL绘制一个简单的三角形来理解渲染管线

理解 WebGL 绘图原理的关键是了解它的渲染管线。WebGL 渲染管线实际上是由多个阶段组成的,每个阶段都有特定的任务,最终输出的是屏幕上的图像。为了让你能轻松理解这些原理,我将通过一个简单的例子来详细解释。

绘制一个简单的三角形

我们将以绘制一个简单的 2D 三角形为例,通过 WebGL 的渲染管线一步步讲解其中的每个阶段。

1. 准备顶点数据

首先,我们需要一些顶点数据,WebGL 使用这些数据来定义要绘制的图形(比如三角形、矩形等)。在 WebGL 中,顶点是通过数组来表示的。

假设我们的三角形顶点数据如下:

const vertices = [-0.5, -0.5,  // 左下角0.5, -0.5,  // 右下角0.0,  0.5   // 顶部
];

这些顶点会定义一个简单的 2D 三角形。

2. 初始化 WebGL 环境

接下来,我们需要初始化 WebGL 环境,并创建一个 顶点缓冲区,用于存储顶点数据。WebGL 的渲染流程是由 GPU 执行的,我们将这些数据上传到 GPU 内存中。

const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

通过 gl.createBuffer()gl.bufferData(),我们将顶点数据传输到 GPU。

3. 编写着色器(Shader)

WebGL 使用 着色器(Shader) 来处理顶点和像素(片段)的数据。着色器程序运行在 GPU 上,它们分为两类:

  • 顶点着色器(Vertex Shader):处理顶点数据。
  • 片段着色器(Fragment Shader):处理像素数据。
顶点着色器

顶点着色器的作用是对传入的顶点数据进行变换,输出位置坐标和其他信息。对于我们的三角形,顶点着色器的作用只是简单地传递顶点坐标。

const vertexShaderSource = `attribute vec2 a_position;  // 顶点位置void main(void) {gl_Position = vec4(a_position, 0.0, 1.0);  // 输出坐标}
`;

在顶点着色器中,我们定义了一个 a_position 属性,它会接收每个顶点的坐标,然后使用 gl_Position 输出最终的位置。

片段着色器

片段着色器的作用是为每个像素计算颜色。我们将颜色设置为白色(也可以为其他颜色)。

const fragmentShaderSource = `void main(void) {gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);  // 白色}
`;

4. 编译和链接着色器

一旦我们编写了顶点着色器和片段着色器,我们需要将它们编译并链接到一起,生成一个可供 WebGL 使用的 着色器程序

// 编译顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);// 编译片段着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);// 创建并链接着色器程序
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);// 使用该程序
gl.useProgram(shaderProgram);

5. 设置顶点属性

接下来,我们需要将顶点数据传递给着色器。通过 attribute 变量,顶点着色器能够接收到这些数据。我们要告诉 WebGL 如何从缓冲区中提取数据并将其传递到着色器。

const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position');
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionAttributeLocation);

这段代码告诉 WebGL 从 vertexBuffer 中提取数据并传递给 a_position,它表示顶点的坐标。

6. 绘制三角形

最后一步是绘制三角形。我们调用 gl.drawArrays() 来绘制图形,它的作用是将顶点数据按照定义的方式绘制到屏幕上。

gl.clear(gl.COLOR_BUFFER_BIT);  // 清空画布
gl.drawArrays(gl.TRIANGLES, 0, 3);  // 绘制三角形,0表示从第一个顶点开始,3表示使用3个顶点

7. WebGL 渲染过程总结

以上步骤就是一个 WebGL 渲染过程的完整流程。为了帮助你更好地理解,下面是 WebGL 渲染管线的主要步骤:

  1. 准备顶点数据:我们创建一个顶点缓冲区,存储图形的顶点信息。
  2. 编写着色器:通过顶点着色器和片段着色器,定义如何处理顶点和像素。
  3. 编译和链接着色器:将编写的着色器代码编译并链接成一个可用的程序。
  4. 传递顶点数据:将顶点数据传递到着色器中,并告诉 WebGL 如何使用这些数据。
  5. 绘制图形:通过调用 gl.drawArrays() 绘制图形,最终在画布上显示出三角形。

8. 渲染管线的关键原理

  • 顶点着色器:负责处理和变换顶点数据(如坐标、颜色、法线等)。它的输出通常是变换后的顶点位置,传递给管线的下一个阶段。
  • 光栅化:将顶点数据转化为片段(像素)。这时图形的形状被“切割”成许多小块。
  • 片段着色器:计算每个像素的最终颜色,例如进行光照计算、纹理映射等。
  • 帧缓冲:片段的输出会被存储到帧缓冲中,最终在屏幕上显示出来。

希望通过这个简单的例子,你能对 WebGL 的渲染管线有一个清晰的认识。

相关文章:

(三)通过WebGL绘制一个简单的三角形来理解渲染管线

理解 WebGL 绘图原理的关键是了解它的渲染管线。WebGL 渲染管线实际上是由多个阶段组成的,每个阶段都有特定的任务,最终输出的是屏幕上的图像。为了让你能轻松理解这些原理,我将通过一个简单的例子来详细解释。 绘制一个简单的三角形 我们将…...

医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件

3D Slicer 是一款功能全面的开源医学影像分析软件,广泛应用于影像处理、三维建模、影像配准和手术规划等领域。它支持多种医学影像格式(如 DICOM、NIfTI)和丰富的插件扩展,是神经科学、放射学和生物医学研究中不可或缺的工具。 在…...

Ollama VS LocalAI:本地大语言模型的深度对比与选择指南

随着人工智能技术的快速发展,大语言模型逐渐成为多个行业的重要工具。从生成内容到智能问答,大模型展现了强大的应用潜力。然而,云端模型的隐私性、使用成本和网络依赖等问题也促使更多用户关注本地化解决方案。Ollama 和 LocalAI 是近年来备…...

虚表 —— 隐藏行(简单版)

因为隐藏行改变了listview内部行号处理机制,需要处理大量细节,如listview内部用于传递行号的各种消息、通知等、封装的各种读取行号的函数等。 所以在工作量很大,一处纰漏可能导致重大bug的情况下,仅对隐藏行功能进行了简单封装&…...

CAD批量打印可检索的PDF文件

本文虽介绍CAD使用方法,但还是劝告大家尽早放弃使用CAD软件。。。。太TM难用了 当你打开CAD时发现如下一堆图纸,但是不想一个一个打印时。你可以按照下面操作实现自动识别图框实现批量打印。 1.安装批量打印插件 2.安装后打开CAD,输入命令Bp…...

2025.1.7(c++基础知识点)

作业(练习) 练习:要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩,分别完成空间的申请、成绩的录入、升序排序、成绩输出函数以及空间释放函数,并在主程序中完成测试 要求使用new和delete完成 #include &…...

jenkins入门12-- 权限管理

Jenkins的权限管理 由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,我们使用Role-based Authorization Strategy 插件 只有项目读权限 只有某个项目执行权限...

Edge SCDN高效防护与智能加速

当今数字化时代,网络安全和内容分发效率已成为企业业务发展的关键因素。酷盾安全推出了Edge SCDN解决方案,为企业提供全方位的安全防护和高效的内容分发服务。 一、卓越的安全防护能力 1.DDoS攻击的精准防御:Edge SCDN具备强大的DDoS攻击检测…...

Ubuntu22.04配置静态ip

1. 编辑网络配置文件 sudo vim /etc/netplan/00-installer-config.yaml 2.输入下面配置 将静态ip设置为192.168.3.200 ,并设置路由器地址192.168.3.1,以及dns地址 223.5.5.5和223.6.6.6 dhcp4: false 表示取消动态分配ip network:ethernets:e…...

[Linux]线程的互斥与同步

目录 一、互斥 1.互斥的概念 2.互斥锁接口 3.线程加锁解锁本质 4.死锁 二、同步 1.同步的概念 2.条件变量 3.条件变量接口 一、互斥 1.互斥的概念 互斥指的是任何时刻,互斥保证有且只有一个执行流进入临界区,进行临界资源的访问,通…...

Java:缓存:LinkedHashMap实现Lru

文章目录 Lru源码分析 ​​​​​​​​​​​​​​LinkedHashMap维护一个LinkedHashMapEntry<K,V>的双向链表对LinkedHashMap的增删查操作,也会对链表进行相同的操作并改变链表的链接顺序小结使用方法​​​​​​​​​​​​​​应用总结Lru Least Recently Used,…...

【形式篇】年终总结怎么写:PPT如何将内容更好地表现出来

——细节满满&#xff0c;看完立马写出一篇合格的PPT 总述 形式服务于内容&#xff0c;同时合理的形式可以更好地表达和彰显内容 年终总结作为汇报型PPT&#xff0c;内容一定是第一位的&#xff0c;在内容篇(可点击查看)已经很详细地给出了提纲思路&#xff0c;那如何落实到…...

自定义字典转换器用于easyExcel 导入导出

文章目录 引言I 字典转换器、注解、序列化器注解定义自定义字典转换器用于easyExcel 导入导出自定义字典序列化器II 字典存储设计数据库表结构redis缓存引言 需求导入Excel时,根据字典内容或者字段编码转换 导出Excel时,根据字典内容或者字段编码转换 接口响应数据序列化时,…...

0 Token 间间隔 100% GPU 利用率,百度百舸 AIAK 大模型推理引擎极限优化 TPS

1. 什么是大模型推理引擎 大模型推理引擎是生成式语言模型运转的发动机&#xff0c;是接受客户输入 prompt 和生成返回 response 的枢纽&#xff0c;也是拉起异构硬件&#xff0c;将物理电能转换为人类知识的变形金刚。 大模型推理引擎的基本工作模式可以概括为&#xff0c…...

js:事件流

事件流 事件流是指事件完整执行过程中的流动路径 一个事件流需要经过两个阶段&#xff1a;捕获阶段&#xff0c;冒泡阶段 捕获阶段是在dom树里获取目标元素的过程&#xff0c;从大到小 冒泡阶段是获取以后回到开始&#xff0c;从小到大&#xff0c;像冒泡一样 实际开发中大…...

Linux对比Windows

1. 性能和资源占用 Linux 更轻量级&#xff1a;Linux 内核设计简洁&#xff0c;占用系统资源&#xff08;如内存、CPU&#xff09;较少&#xff0c;适合高负载的服务器环境。 高效的多任务处理&#xff1a;Linux 在多任务处理和并发请求方面表现优异&#xff0c;适合处理大量并…...

Excel 技巧03 - 如何对齐小数位数? (★)如何去掉小数点?如何不四舍五入去掉小数点?

这几个有点儿关联&#xff0c;我都给放到一起了&#xff0c;不影响大家分别使用。 目录 1&#xff0c;如何对齐小数位数&#xff1f; 2&#xff0c;如何去掉小数点&#xff1f; 3&#xff0c;如何不四舍五入去掉小数点&#xff1f; 1&#xff0c;如何对齐小数位数&#xff…...

Vue3国际化多语言的切换

参考链接: link Vue3国际化多语言的切换 一、安装 vue-i18n 和 element-plus vue-i18n 是一个国际化插件&#xff0c;专为 Vue.js 应用程序设计&#xff0c;用于实现多语言支持。它允许你将应用程序的文本、格式和消息转换为用户的首选语言&#xff0c;从而提供本地化体验。…...

使用XAML语言仿写BiliBil登录界面

实现步骤 实现左右布局 使用了Grid两列的网格布局&#xff0c;第一列宽度占35%&#xff0c;第二列宽度占65%。使用容器布局Border包裹左右布局内容&#xff0c;设置背景色、设置圆角 <!-- 定义两列--> <Grid.ColumnDefinitions><ColumnDefinition Width &quo…...

机器学习和深度学习

机器学习&#xff08;Machine Learning&#xff0c;简称 ML&#xff09;和深度学习&#xff08;Deep Learning&#xff0c;简称 DL&#xff09;都是人工智能&#xff08;AI&#xff09;领域的重要技术&#xff0c;它们的目标是使计算机通过数据学习和自主改进&#xff0c;从而完…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...