WebGL系列教程二(环境搭建及初始化Shader)
目录
- 1 前言
- 2 新建html页面
- 3 着色器介绍
- 3.1 顶点着色器、片元着色器与光栅化的概念
- 3.2 声明顶点着色器
- 3.3 声明片元着色器
- 4 坐标系(右手系)介绍
- 5 着色器初始化
- 5.1 给一个画布canvas
- 5.2 获取WebGL对象
- 5.3 创建着色器对象
- 5.4 获取着色器对象的源
- 5.5 绑定着色器的源
- 5.6 编译着色器
- 5.7 创建并关联项目
- 6 绘制
- 6.1 声明点的位置、大小和颜色
- 6.2 绘制
- 6.3 完整代码
- 7 总结
1 前言
上一篇中我们对WebGL进行了简单的介绍,从本篇开始,正式进入实战。那么我们第一步需要做什么呢?当然是环境的搭建,以及Shader的初始化。废话不多说,咱们直接开整。
2 新建html页面
其实搭建WebGL的环境十分简单,因为WebGL在在浏览里运行的,因此只需要新建一个html页面就行了。
3 着色器介绍
3.1 顶点着色器、片元着色器与光栅化的概念
那么什么是顶点着色器?什么是片元着色器?什么叫做光栅化?这三个概念对我们学习WebGL还是很重要的,在学习WebGL的过程中,我曾经常困惑于片元、光栅化的概念,现在我们就用一张图来解释下。假设我们要在屏幕上画一个三角形。

如图所示,v1 v2 v3 就叫做顶点,三角形内部的一个个红色的点,就叫做片元,也叫片段,其实它的意思就是一个个像素。注意像素应该是密密麻麻占满了整个三角形,这里为了示意只画出来了少部分。屏幕是什么?屏幕是一种光栅设备,因此把任何一种图形,不论是二维三维的,画在屏幕上,就叫做光栅化。光栅化的概念就这么简单。看过很多其他教程,只说光栅化,不说光栅化是什么意思,很令人困惑。
3.2 声明顶点着色器
声明顶点着色器很简单,只需要写一个script标签,注意type
<script id="vertex-shader" type="x-shader/x-vertex"></script>
3.3 声明片元着色器
声明片元着色器也很简单,只需要写一个script标签,同样注意type
<script id="vertex-shader" type="x-shader/x-fragment"></script>
4 坐标系(右手系)介绍
现在我们来做一个最简单的例子,画一个点,这个点的坐标分别是x=0.5,y=0.5,z=0。在此之前我们先明确一下WebGL中的坐标系:X轴向右,Y轴向上,Z轴向外。右手握拳,四指从X到Y转动,大拇指的方向就是Z轴的方向。很明显,WebGL中默认是右手系。因为z=0,因此这个点在xy所形成的平面内。

5 着色器初始化
初始化着色也很简单,我们先给出步骤,然后一步步来说明
- 创建着色器对象
- 获取着色器对象的源代码
- 绑定着色器的源
- 编译着色器
- 创建并关联项目
5.1 给一个画布canvas
<canvas id="canvas" width="1080" height="720"></canvas>
5.2 获取WebGL对象
const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
5.3 创建着色器对象
//创建着色器对象
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
5.4 获取着色器对象的源
//获取着色器对象的源
let vertexSource = document.getElementById("vertex-shader").innerText;
let fragmentSource = document.getElementById("fragment-shader").innerText;
因为这里我们要用的innerText,也就是script标签里的文本,因此也可以不把文本写在script标签里,而是直接手写字符串,这样的不好处就是没有智能提示,比如:
let vertexSource = “…”
let fragmentSource = “…”
5.5 绑定着色器的源
//绑定着色器的源
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);
5.6 编译着色器
//编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
5.7 创建并关联项目
//创建并关联项目
let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
6 绘制
现在我们的准备工作已经完事了,可以开始绘制了。首先需要补齐script标签的内容
6.1 声明点的位置、大小和颜色
<script id="vertex-shader" type="x-shader/x-vertex">//声明一个点,vec2表示2维向量attribute vec2 aPos;void main(){//点的大小10像素gl_PointSize = 10.0;//点的位置,将vec2补齐为vec4gl_Position = vec4(aPos,0.0,1.0); }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">void main(){//点的颜色,rgba形式,红色gl_FragColor = vec4(1.0,0.0,0.0,1.0);}
</script>
6.2 绘制
//绘制
let aPos = gl.getAttribLocation(program,"aPos");
//设置顶点的值,该顶点是用二维坐标表示的,vertexAttrib2f表示vertex中的attribute属性,2个float值
gl.vertexAttrib2f(aPos,0.5,0.5);
//绘制点,从第0个点开始,绘制两个
gl.drawArrays(gl.POINTS,0,2);

改为x=0,y=0看看效果,点回到了正中间。

6.3 完整代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#canvas{border: 1px solid #ccc;}</style>
</head><body><canvas id="canvas" width="1080" height="720"></canvas><script id="vertex-shader" type="x-shader/x-vertex">attribute vec2 aPos;void main(){gl_PointSize = 10.0;gl_Position = vec4(aPos,0.0,1.0); //gl_Position = aPos; }</script><script id="fragment-shader" type="x-shader/x-fragment">void main(){gl_FragColor = vec4(1.0,0.0,0.0,1.0);}</script><script>const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");//创建着色器对象let vertexShader = gl.createShader(gl.VERTEX_SHADER);let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);//获取着色器对象的源let vertexSource = document.getElementById("vertex-shader").innerText;let fragmentSource = document.getElementById("fragment-shader").innerText;//绑定着色器的源gl.shaderSource(vertexShader,vertexSource);gl.shaderSource(fragmentShader,fragmentSource);//编译着色器gl.compileShader(vertexShader);gl.compileShader(fragmentShader);console.log(gl.getShaderInfoLog(vertexShader));//创建并关联项目let program = gl.createProgram();gl.attachShader(program,vertexShader);gl.attachShader(program,fragmentShader);gl.linkProgram(program);gl.useProgram(program);//绘制let aPos = gl.getAttribLocation(program,"aPos");//设置顶点的值,该顶点是用二维坐标表示的gl.vertexAttrib2f(aPos,0.0,0.0);gl.drawArrays(gl.POINTS,0,2);</script>
</body></html>
7 总结
本篇博文中我们梳理了WebGL中整个的绘制流程,右手坐标系的指向,顶点着色器、片元着色器、光栅化等概念的含义,并以一个最简单的示例,点绘制来演示Shader的初始化过程,代码并不复杂,希望读者仔细体会,回见~
相关文章:
WebGL系列教程二(环境搭建及初始化Shader)
目录 1 前言2 新建html页面3 着色器介绍3.1 顶点着色器、片元着色器与光栅化的概念3.2 声明顶点着色器3.3 声明片元着色器 4 坐标系(右手系)介绍5 着色器初始化5.1 给一个画布canvas5.2 获取WebGL对象5.3 创建着色器对象5.4 获取着色器对象的源5.5 绑定着色器的源5.6 编译着色器…...
keepalive和nginx高可用集群
keepalived 和 nginx 高可用集群搭建 主备模式 zyj86主机和zyj87主机安装nginx和keepalived yum install nginx keepalived -y systemctl enable --now nginx.service keepalived.service主调度器配置 编辑zyj86主机(主)配置文件 vi /etc/keepalived…...
二分查找题总结
二分查找题总结 hot100搜索插入位置搜索二维矩阵在排序数组中查找元素的第一个和最后一个位置搜索旋转排序数组寻找旋转排序数组中的最小值寻找两个正序数组的中位数 hot100 搜索插入位置 题目链接: 35.搜索插入位置 代码: class Solution {public in…...
仕考网:公务员面试流程介绍
通知进面信息——资格审查——面试签到——抽签候考 面试形式: 面试分为结构化和无领导小组两种形式 1.在结构化面试中,当轮到某位考生时,引导员将在候考室宣布其编号,随后考生跟随引导人员前往考场入口。考生在开始考试时需回…...
(十五)SpringCloudAlibaba-Sentinel持久化到Nacos
前言 在前面我们已经将Sentinel配置的规则持久化到系统的文件中。本章节我们将Sentinel持久化到Nacos中; 传送门(Sentinel数据持久化到文件)https://blog.csdn.net/weixin_45876411/article/details/140742963 默认情况下 Sentinel 只能接收到 Nacos 推送的消息,但…...
GitHub图床
GitHub图床 文章目录 GitHub图床图床介绍Github访问GitHub手动修改hostsgithub520 加速器创建账户创建仓库创建token PicGoTypora 图床介绍 图床 存放图片的地方 为什么设置图床呢 在我认识图床之前, 有一个问题 [^放在typora上面的图片, 其实是一个链接, 并且将图片存放在本地…...
记一次高版本view-design的组件迁移到自身项目的低版本
背景 npm i -S view-design当前老项目使用view-design这个组件库,但是当我们去官网查看该组件库最新版本,竟然发现没有博主想用的image/ImagePreivew这两个基础组件 说实话,有点离谱了哈!! 自己造轮子? …...
QT运行ROS工程
文章目录 使用QT创建ROS工程项目配置修改cmake环境配置运行设置 运行 使用QT创建ROS工程 工程名字和路径 下一步(直接选择默认选项就可以)->完成 完成之后 是这样的 接下来在工作空间里面创建功能包 鼠标选中src点击右键->添加新文件 name::功能包的名字…...
电脑技巧:如何在Win11电脑上调整设置,让屏幕更加护眼?
目录 一、调整屏幕亮度 二、启用夜间模式 三、调整色彩设置 四、使用第三方护眼软件 五、保持良好的用眼习惯 总结 随着长时间使用电脑的人越来越多,护眼问题也变得越来越重要。Win11作为更新的操作系统,提供了更多的设置选项来帮助我们保护眼睛。本文将详细介绍如何在…...
【数据结构】排序算法篇二
【数据结构】排序算法篇二 1. 快速排序(hoare版本)(1)基本思想:(2)动态图解:(3)代码实现:(4)特性总结: 2. 快速…...
python进阶篇-day09-数据结构与算法(非线性结构与排序算法)
非线性结构(树状结构) 特点: 每个节点都可以有n个子节点(后继节点) 和 n个父节点(前驱节点) 代表: 树, 图...... 概述 属于数据结构之 非线性结构的一种, 父节点可以有多个子节点(后续节点) 特点 有且只有1个根节点 每个节点都可以有1个父节点及任意个子节点, 前提: 根节点除…...
线性代数基础
Base 对于矩阵 A,对齐做 SVD 分解,即 U Σ V s v d ( A ) U\Sigma V svd(A) UΣVsvd(A). 其中 U 为 A A T AA^T AAT的特征向量,V 为 A T A A^TA ATA的特征向量。 Σ \Sigma Σ 的对角元素为降序排序的特征值。显然,U、V矩阵…...
LCR 021
题目:LCR 021 解法一:计算链表长度 遍历两次,第一次获取链表长度 L(包括虚拟节点),第二次遍历到第 L-n 个节点(从虚拟节点遍历) public ListNode removeNthFromEnd(ListNode head, …...
【阿雄不会写代码】全国职业院校技能大赛GZ036第四套
也不说那么多了,要用到这篇博客,肯定也知道他是干嘛的,给博主点点关注点点赞!!!这样博主才能更新更多免费的教程,不然就直接丢付费专栏里了,需要相关文件请私聊...
Vue组件:使用$emit()方法监听子组件事件
1、监听自定义事件 父组件通过使用 Prop 为子组件传递数据,但如果子组件要把数据传递回去,就需要使用自定义事件来实现。父组件可以通过 v-on 指令(简写形式“”)监听子组件实例的自定义事件,而子组件可以通过调用内建…...
数据分析-埋点
1、数据埋点的定义 针对特定用户行为或事件进行捕获、处理何发送的相关技术及其实施过程。 2、数据埋点的原理 埋点是数据采集的重要方式。通过在页面上植入代码,监控用户行为(例:页面加载、按钮点击等)。用户一旦触发了该事件,就会根据埋点信息将相关数…...
【文心智能体】通过工作流使用知识库来实现信息查询输出,一键查看旅游相关信息,让出行多一份信心
欢迎来到《小5讲堂》 这是《文心智能体平台》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 创建灵感基本配置头像名称和简介人物设定角色与目标思考路…...
服务器监控工具都是监控服务器的哪些性能和指标
服务器监控工具通常用于确保服务器及其相关服务的正常运行。这些工具可以帮助管理员快速识别并解决问题,从而减少停机时间和性能下降的风险。以下是服务器监控工具通常会监控的一些主要内容: 系统健康状态: CPU使用率 内存(RAM&…...
不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信
不小心删除了一条短信,或者丢失了所有短信?希望还未破灭,下面介绍如何在 iPhone 上查找和恢复已删除的短信。 短信通常都是非正式和无关紧要的,但短信中可能包含非常重要的信息。因此,如果您删除了一些短信以清理 iPh…...
【skyvern 快速上手】一句话让AI帮你实现爬虫+自动化
目录 skyvern介绍主要特点工作流程 部署(重点介绍源码部署)源码部署docker快速部署 运行(基于源码)后端前端 快速使用示例总结 skyvern介绍 Skyvern 是一款利用大语言模型(LLM)和计算机视觉技术来自动化浏…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
【题解-洛谷】P10480 可达性统计
题目:P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M,接下来 M M M 行每行两个整数 x , y x,y x,y,表示从 …...
