【免费下载链接】thebookofshaders
Step-by-step guide through the abstract and complex universe of Fragment Shaders.
本篇技术指南以 The Book of Shaders 仓库的 vec2 词条文档(本仓库亦提供 越南语版本 等多语言版本)为核心,系统讲解 GLSL 中二维浮点向量vec2的类型定义、四种典型声明方式与初始化规则,并结合仓库内各章节真实着色器源码,展示它在坐标归一化、形状绘制、噪声与 Voronoi 算法中的高频用法。读完本文,你将能熟练声明与操作vec2,看懂 The Book of Shaders 教程中几乎所有基于二维坐标运算的示例代码。
一、vec2是什么:着色器世界的最小坐标单元
vec2是 GLSL 内置的二维浮点向量(2 dimensional floating point vector),由两个float分量组成,分别用x、y访问。在片段着色器(Fragment Shader)中,屏幕上的每一个像素坐标、UV 坐标、方向向量、位移向量,几乎都以vec2为基本载体。
在 The Book of Shaders 的示例中,vec2最常见的三个用途是:
- 接收
uniform输入:几乎所有.frag示例都会声明uniform vec2 u_resolution;和uniform vec2 u_mouse;,分别保存画布分辨率与鼠标位置(如 circle.frag)。 - 归一化像素坐标:用
vec2 st = gl_FragCoord.xy / u_resolution.xy;把像素坐标映射到0.0~1.0区间(见 space.frag)。 - 参与向量运算:
vec2支持与标量、向量进行算术与比较运算,是绘制形状、生成噪声的基础数据类型。
需要说明的是,本仓库所有示例均采用 GLSL ES(WebGL)风格编写,文件开头通常有:
#ifdef GL_ES precision mediump float; #endif这意味着vec2及其分量在该环境下默认使用mediump精度,但在桌面 GLSL 中则遵循更严格的浮点精度约定。精度限定符(highp、mediump、lowp)可以单独作用于vec2分量,例如highp vec2。
二、vec2的声明与四种初始化方式
根据 vec2 词条文档 的声明示例,vec2可以通过以下方式构造:
vec2 aVec2 = vec2(1.0, 1.0); // 逐分量指定:x = 1.0, y = 1.0 vec2 bVec2 = vec2(1.0); // 单一标量:x = 1.0, y = 1.0(广播) vec2 cVec2 = vec2(aVec3); // 从更高维向量截取前两个分量 vec2 dVec2 = vec2(aVec3.x, aVec3.y); // 从高维向量的分量组合1. 逐分量指定(Per-Component Scalar)
为每个分量分别提供一个float标量,最直观也最常用:
vec2 aVec2 = vec2(1.0, 1.0); vec2 st = vec2(0.25, 0.75); // x = 0.25, y = 0.752. 单一标量广播(Single Scalar)
只传一个标量时,该值会被同时赋给所有分量:
vec2 bVec2 = vec2(1.0); // 等价于 vec2(1.0, 1.0)这在需要「两个分量相同」的常量场景中非常简洁,例如 circle.frag 中的_st - vec2(0.5),即把坐标原点平移到画布中心。
3. 从更高维向量截取(Higher-Dimension Vector)
传入一个维度更高的向量(如vec3、vec4),构造器会按分量顺序取前两个分量来初始化:
vec2 cVec2 = vec2(aVec3); // 取 aVec3.x、aVec3.y4. 从分量组合构造(Component Combination)
除上述三种外,GLSL 还允许将向量与标量任意组合传入构造器,只要提供的分量总数不少于目标向量的分量数即可。该规则在仓库的 vec3 词条 与 vec4 词条 中表述得更明确,对vec2同样适用:
vec2 dVec2 = vec2(aVec3.x, aVec3.y); // 两个标量 vec2 eVec2 = vec2(1.0, 2.0); // 两个标量 vec2 fVec2 = vec2(aVec4.xy); // 一个二维向量 vec2 gVec2 = vec2(aVec2.x, aFloat); // 标量 + 标量关键约束:构造参数的分量总和必须恰好等于(或至少达到)目标向量的分量数。多于所需时按顺序截取,少于所需时编译报错。
三、分量访问:点号.xy与 Swizzle 重排
vec2的两个分量可以通过.x、.y单独读写,也可以像.xy、.yx、.xx这样进行swizzle(分量重排),甚至用颜色语义.rg(红、绿通道)。仓库源码中的典型证据:
- space.frag 直接把两个分量当作 R、G 颜色输出:
vec2 st = gl_FragCoord.xy/u_resolution; gl_FragColor = vec4(st.x,st.y,0.0,1.0);- shapes.frag 先归一化再缩放并校正宽高比:
vec2 st = gl_FragCoord.xy/u_resolution.xy; st = st *2.-1.; // 映射到 -1.0 ~ 1.0 st.x *= u_resolution.x/u_resolution.y; // 分量级运算校正宽高比- hsb.frag 用
st.x、st.y分别映射色相(Hue)与亮度(Brightness):
vec2 st = gl_FragCoord.xy/u_resolution; color = hsb2rgb(vec3(st.x,1.0,st.y));swizzle 操作既可用于读取(st.xy),也可用于赋值(st.yx = vec2(1.0, 2.0)),是构建向量与重排通道时最常用的语法。
四、仓库实战:vec2在教程各章节中的典型应用
The Book of Shaders 的每个章节示例都离不开vec2,以下是几类可验证的核心模式。
1. 坐标归一化与二维空间映射(第 03 章)
片段着色器的输入坐标gl_FragCoord是vec4类型,取.xy即可得到当前像素坐标,再除以u_resolution归一化:
vec2 st = gl_FragCoord.xy/u_resolution.xy;time.frag 则展示了用vec2与标量混合构造vec4输出的写法:gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0);,这正是「标量 + 标量构造向量」的实例。
2. 形状绘制:距离场与几何变换(第 07 章)
circle.frag 中,vec2同时承担了参数类型、坐标平移与点积运算:
float circle(in vec2 _st, in float _radius){ vec2 dist = _st-vec2(0.5); // 平移坐标系 return 1.-smoothstep(_radius-(_radius*0.01), _radius+(_radius*0.01), dot(dist,dist)*4.0); // vec2 点积 → 标量 }第 08 章矩阵示例 matrices.frag 展示了vec2与mat2的配合——旋转矩阵作用于二维向量:
mat2 rotate2D(float angle){ return mat2(cos(angle),-sin(angle), sin(angle),cos(angle)); }3. 平铺与网格(第 09 章)
grid.frag 中的tile()与box()函数展示了vec2的运算、单标量构造与 swizzle 组合:
vec2 tile(vec2 _st, float _zoom){ _st *= _zoom; return fract(_st); // 返回分数部分 } float box(vec2 _st, vec2 _size){ _size = vec2(0.5)-_size*0.5; vec2 uv = smoothstep(_size,_size+vec2(1e-4),_st); uv *= smoothstep(_size,_size+vec2(1e-4),vec2(1.0)-_st); return uv.x*uv.y; // 分量相乘 }4. 随机与噪声:vec2作为哈希键(第 11、12 章)
二维随机函数通常把vec2坐标点积映射到标量再取小数部分:
- 2d-noise.frag:
float random (in vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123); }- 2d-voronoi.frag 用
vec2返回二维随机偏移:
vec2 random2( vec2 p ) { return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); }- 2d-gnoise.frag 中
floor(st)、fract(st)、i + vec2(0.0,0.0)等操作体现了vec2与标量、向量相加以及分量级函数调用的通用性。
这些模式反复印证了vec2的三个核心能力:分量级标量运算、与高维向量的互转、作为哈希/随机键参与数学计算。
五、与相关类型的转换与区别
vec2只是 GLSL 向量家族的一员,理解它需要同时掌握其近邻类型:
| 类型 | 分量类型 | 分量数 | 说明 |
|---|---|---|---|
vec2 | float | 2 | 本文主角,二维浮点向量 |
bvec2 | bool | 2 | 二维布尔向量,见 bvec2 |
ivec2 | int | 2 | 二维整数向量,常用于循环计数与网格索引,见 ivec2 |
vec3 | float | 3 | 三维浮点向量,可经vec2(aVec3)截取,见 vec3 |
vec4 | float | 4 | 四维浮点向量,gl_FragCoord即为该类型,见 vec4 |
mat2 | float | 2×2 | 二维矩阵,可与vec2相乘实现变换,见 mat2 |
类型之间可以显式转换:vec2(float)由标量广播、vec2(ivec2)将整数向量转为浮点向量、vec2(bvec2)把布尔值转为0.0/1.0。反过来,vec3(aVec2, 1.0)可以把vec2扩维成vec3,这一写法在 hsb.frag 中已实际使用。底层标量类型(float、int、bool)的构造规则同样适用于向量构造器。
六、词条关联与延伸阅读
vec2并非孤立概念,它与 GLSL 类型体系紧密相连。原词条文档列出的关联词条在本仓库均有对应文档,可继续深入阅读:
- 标量基础:bool、int、float
- 布尔向量:bvec2、bvec3、bvec4
- 整数向量:ivec2、ivec3、ivec4
- 浮点向量:vec2、vec3、vec4
- 矩阵:mat2、mat3、mat4
如果想在真实示例中检验vec2的各种用法,建议按章节顺序阅读 第 03 章坐标归一化、第 07 章形状绘制、第 09 章平铺与网格、第 11 章噪声 与 第 12 章 Voronoi 的着色器源码,每一份.frag文件都是vec2的活教材。
【免费下载链接】thebookofshaders
Step-by-step guide through the abstract and complex universe of Fragment Shaders.
相关推荐
《The Book of Shaders》GLSL 类型精讲:vec2 二维浮点向量详解
《The Book of Shaders》GLSL 类型精讲:vec2 二维浮点向量详解 导读 vec2 是 GLSL(OpenGL Shading Langu
MagicalDanmaku 崩溃报告集成指南:Breakpad 架构、Minidump 全流程与 QBreakpad 实战
MagicalDanmaku 崩溃报告集成指南:Breakpad 架构、Minidump 全流程与 QBreakpad 实战 本指南以仓库内 Google Br
VueUse useIDBKeyval 深入指南:用 IndexedDB 实现响应式持久化与跨标签页同步
VueUse useIDBKeyval 深入指南:用 IndexedDB 实现响应式持久化与跨标签页同步 useIDBKeyval 是 VueUse 集成包(
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考