The Book of Shaders 第 08 章:GLSL 二维矩阵变换实战指南 —— 平移、旋转、缩放与 YUV 色彩空间
【免费下载链接】thebookofshadersStep-by-step guide through the abstract and complex universe of Fragment Shaders.项目地址https://gitcode.com/gh_mirrors/th/thebookofshaders点击查看免费下载本章08/README-vi.md的英文原版为08/README.md中文对照见 08/README-ch.md聚焦于 Fragment Shader 中最核心的几何变换问题如何用二维矩阵对坐标空间进行平移、旋转与缩放。本文以仓库中 08/ 目录 下的完整 GLSL 示例为源码依据逐行拆解实现原理与练习步骤并延伸到 3D/4D 矩阵与 YUV 色彩空间等进阶应用。读完你将掌握mat2/mat3/mat4的构造与乘法规则能够写出绕任意中心旋转、缩放坐标的 shader 代码并用矩阵完成 RGB 与 YUV 色彩空间之间的转换。本章定位为什么移动图形要先移动坐标系在上一章第 07 章形状中我们已经学会了在片元着色器里画出十字、圆、矩形等基础形状。本章要解决的是一个更实际的问题如何让这些静态形状动起来、转起来、变大变小直觉上我们会想去移动图形本身但 Fragment Shader 的工作方式完全不同——每个片元fragment的着色位置由归一化坐标st即gl_FragCoord.xy / u_resolution.xy唯一决定你无法像在传统 2D 图形 API 中那样拖拽一个物体。真正可行的思路是反向操作移动整个坐标系。当坐标系平移、旋转或缩放时形状相对于屏幕的位置和姿态自然随之改变。这也是本章标题2D Matrices二维矩阵的由来所有变换最终都归结为对坐标向量施加的矩阵乘法。本章页首还嵌入了一个以 matrix.frag 为片元程序的交互式 canvas 演示雨滴般的字符矩阵滚动效果用它直观地渲染出矩阵这一主题氛围。平移Translate给st加上一个向量平移是所有变换中最直观的一种。如 cross-translate.frag 所示核心代码只有两行// To move the cross we move the space vec2 translate vec2(cos(u_time), sin(u_time)); st translate * 0.35;关键点在于不是移动十字而是给每个片元的位置st加上同一个偏移向量。st本身记录着每个片元在归一化画布中的坐标范围约0.0 ~ 1.0对全体片元统一加上translate * 0.35等价于把整个坐标空间平移了0.35个单位——十字在屏幕上的位置也就随之移动。其中u_time是随时间递增的 uniform 变量cos(u_time)与sin(u_time)组合出的恰好是一个半径为0.35的圆周运动轨迹。文档中的第一个实验对应源码 cross-translate.frag取消第 35 行代码的注释即启用color vec3(st.x, st.y, 0.0);。此时背景会用颜色显示当前坐标空间的实际位置——你会看到整个坐标网格而非仅仅十字都在随u_time做圆周运动从而直观印证移动的是坐标系这一结论。动手练习建议结合u_time与上一章学到的各类造型函数shaping functions为十字设计一种有质感的运动例如海浪的起伏、钟摆的摆动、弹球的落地弹跳、汽车的加速、自行车的减速停止。可以先录下真实世界的运动再逐帧对照。反复调整0.35这个缩放系数观察圆周运动的半径变化把cos/sin换成fract、abs、pow等函数体会不同运动曲线的差异。旋转Rotations二维旋转矩阵的构造旋转无法用简单的加法完成需要引入矩阵。矩阵是按行列组织的一组数字向量与矩阵相乘时遵循精确的运算规则从而按特定方式修改向量的值。GLSL 原生支持 2/3/4 维方阵mat22x2、mat33x3、mat44x4其类型细节可查阅仓库中的 glossary/mat2、glossary/mat3、glossary/mat4。GLSL 还内置了矩阵乘法运算符*以及逐分量相乘的专用函数matrixCompMult()见 glossary/matrixCompMult。需要特别注意的是*执行的是标准矩阵乘法而matrixCompMult()只做对应元素的逐位相乘二者语义完全不同。文档给出的二维旋转矩阵构造函数cross-rotate.frag#define PI 3.14159265359 mat2 rotate2d(float _angle){ return mat2(cos(_angle), -sin(_angle), sin(_angle), cos(_angle)); }mat2按列优先填充第一列为(cos, sin)第二列为(-sin, cos)这正是二维旋转矩阵的标准形式。函数接受弧度角_angle返回的矩阵会将坐标绕原点vec2(0.0)旋转该角度。绕画布中心旋转的三步技巧直接套用上面的矩阵旋转中心是原点(0.0, 0.0)但我们的十字绘制在画布中心vec2(0.5)附近。因此文档给出了经典的三步解法对应 cross-rotate.frag// 1. move space from the center to the vec2(0.0) st - vec2(0.5); // 2. rotate the space st rotate2d(sin(u_time) * PI) * st; // 3. move it back to the original place st vec2(0.5);平移到原点st - vec2(0.5)把画布中心对准坐标原点旋转用rotate2d(...)乘以st角度取sin(u_time) * PI在-π ~ π之间往复摆动十字随之来回旋转平移回原位st vec2(0.5)把旋转后的坐标系搬回画布中央。文档要求的练习对应 cross-rotate.frag取消第 45 行注释color vec3(st.x, st.y, 0.0);观察整个坐标空间绕画布中心旋转的全景注释掉第 37 行st - vec2(0.5)与第 39 行st vec2(0.5)看十字绕画布左下角而非自身中心旋转的效果体会两步平移的意义把旋转角度改成随时间线性增长的u_time或叠加其他函数让旋转与上一节的平移动画相结合。缩放Scale对角矩阵的妙用矩阵不仅能平移、旋转还能缩放物体尺寸——这正是 3D 建模软件与 Processing 中pushMatrix/popMatrix机制背后的原理。二维缩放矩阵的构造cross-scale.fragmat2 scale(vec2 _scale){ return mat2(_scale.x, 0.0, 0.0, _scale.y); }这是一个对角矩阵对角元素分别为x、y方向的缩放系数非对角元素为0。它同样需要配合先移回原点、变换、再移回原位的三步法使用cross-scale.fragst - vec2(0.5); st scale(vec2(sin(u_time) 1.0)) * st; // 缩放系数在 0.0 ~ 2.0 之间周期变化 st vec2(0.5);注意vec2(sin(u_time) 1.0)sin(u_time)取值-1 ~ 1加1后缩放系数在0.0 ~ 2.0间摆动。当系数小于1时是缩小等于1时不变大于1时是放大。文档要求的练习对应 cross-scale.frag取消第 42 行注释观察整个坐标空间被周期性缩放而非只有十字缩放注释第 37、39 行的两次平移观察十字以画布左下角为缩放中心的后果尝试把sin换成其他造型函数体验非对称的缩放节奏。组合变换顺序决定结果文档特别强调变换顺序会直接影响最终结果。矩阵乘法不满足交换律即rotate2d(a) * scale(b)与scale(b) * rotate2d(a)通常得到不同的效果。在 cross-animated.frag 中仓库给出了同时组合旋转与平移的完整示例// move space from the center to the vec2(0.0) st - vec2(0.5); // rotate the space st rotate2d(sin(u_time * 0.5) * PI) * st; // move it back to the original place st vec2(0.5); // To move the cross we move the space vec2 translate vec2(cos(u_time), sin(u_time)); st translate * 0.35;执行顺序是先平移回原点 → 旋转 → 平移回原位 → 整体平移。若颠倒旋转与平移的顺序十字将不再是绕自身中心旋转的同时做圆周运动而会变成绕画布中心公转之类的不同效果。实战建议把多个矩阵先相乘、再统一乘到向量上mat2 m rotate2d(a) * scale(b); st m * st;这样既能减少每片元的运算量也便于推演矩阵的复合语义综合本章技能设计一个假的 UI / HUD平视显示器风格的组合构图绘制多个形状并分别赋予不同的平移、旋转、缩放动画模拟仪表盘、瞄准框、状态面板等界面元素。矩阵的其他应用YUV 色彩空间转换矩阵变换的舞台不止于空间坐标——颜色同样可以视为三维向量用mat3在色彩空间之间迁移。文档以经典模拟视频编码中使用的 YUV 色彩空间为例给出 yuv.frag 这一完整实现。YUV 将颜色拆分为亮度分量Y与两个色度分量U、V依据人眼对亮度敏感、对色度不敏感的特性来压缩色度带宽。两个mat3矩阵在源码中直接定义yuv.frag// YUV to RGB matrix mat3 yuv2rgb mat3(1.0, 0.0, 1.13983, 1.0, -0.39465, -0.58060, 1.0, 2.03211, 0.0); // RGB to YUV matrix mat3 rgb2yuv mat3(0.2126, 0.7152, 0.0722, -0.09991, -0.33609, 0.43600, 0.615, -0.5586, -0.05639);主函数中的变换逻辑yuv.frag展示了把坐标当色度平面使用的技巧void main(){ vec2 st gl_FragCoord.xy / u_resolution; vec3 color vec3(0.0); // UV values goes from -1 to 1 // So we need to remap st (0.0 to 1.0) st - 0.5; // becomes -0.5 to 0.5 st * 2.0; // becomes -1.0 to 1.0 // we pass st as the y z values of // a three dimensional vector to be // properly multiply by a 3x3 matrix color yuv2rgb * vec3(0.5, st.x, st.y); gl_FragColor vec4(color, 1.0); }这段代码有三处值得深挖的细节坐标重映射YUV 的 UV 分量取值范围是-1 ~ 1而st是0 ~ 1因此先st - 0.5再st * 2.0把归一化坐标映射到-1 ~ 1向量维度匹配mat3只能与三维向量相乘所以将(st.x, st.y)作为向量的后两个分量亮度 Y 固定取0.5拼成vec3(0.5, st.x, st.y)颜色即向量yuv2rgb * vec3(...)本质上是把每个像素的 YUV 三元组当作三维向量做矩阵乘法一次运算即完成向 RGB 的线性转换——这正是文档强调的用操作向量的方式操作颜色。屏幕上的最终画面是横轴对应 U色相偏移、纵轴对应 V饱和度方向亮度恒定从而铺展出整个 YUV→RGB 的颜色平面。源码扩展从 2D 到 3D/4D 的矩阵工具箱本章正文聚焦 2D 变换但仓库中的 matrices.frag 提供了一整套可直接复用的矩阵工具函数可作为进阶工具箱继续研读rotate2D(float angle)matrices.frag与正文rotate2d等价的二维旋转矩阵rotateX3D / rotateY3D / rotateZ3Dmatrices.frag分别绕 X、Y、Z 轴旋转的mat3版本绕轴旋转矩阵的特点是对应轴上元素保持1.0、其余非对角元素为0另外两轴构成经典的cos/sin旋转块rotateX4D / rotateY4D / rotateZ4D同文件mat4版本通过扩展为 4x4 齐次坐标矩阵为后续引入透视投影等操作预留了空间scale4D(x, y, z)matrices.frag三维缩放的对角矩阵与本章 2D 缩放矩阵一脉相承translate4D(x, y, z)matrices.frag4x4 齐次平移矩阵平移量落在矩阵的第四行——这是齐次坐标表示法下用矩阵表达平移的标准做法。从 2D 到 4D矩阵变换的规律是统一的旋转矩阵由三角函数构成、缩放矩阵是对角阵、平移矩阵依赖齐次坐标的额外维度。理解本章的mat2用法后向上扩展维度只是照葫芦画瓢。此外glossary/mat2 还给出了mat2的多种初始化方式逐列填充、单个对角线值、向量与标量组合以及按列访问aMat2[0]、按元素访问aMat2[1][1]的语法建议一并查阅。小结与下一步本章的核心方法论可以浓缩为一句话在 Fragment Shader 中变换永远施加在坐标系而非物体上。通过给st加向量实现平移、用mat2旋转矩阵配合移回原点—变换—移回原位三步法实现绕任意中心的旋转、用对角矩阵实现缩放并时刻警惕矩阵乘法的顺序约束——这些能力是组合出复杂构图如 HUD 界面的基础。掌握这些变换后下一步就是把它们应用在程序化纹理procedural patterns的创作中用重复与变化编织出漂亮的图案。事实上本仓库后续章节如 第 09 章图案正是沿着这条路径展开的而 YUV 这类色彩矩阵技巧也将在纹理与色彩处理中反复出现。建议你在本地按 08/index.php 所示的方式加载本章页面通过?lan参数还可以切换 README 的语言版本并配合 glslEditor 等工具逐行取消注释、观察坐标空间的变化把本章的每个练习亲手做一遍。赞分享【免费下载链接】thebookofshadersStep-by-step guide through the abstract and complex universe of Fragment Shaders.项目地址https://gitcode.com/gh_mirrors/th/thebookofshaders点击查看免费下载相关推荐The Book of Shaders 第 8 章实战解读GLSL 二维矩阵变换——平移、旋转、缩放与 YUV 色彩空间The Book of Shaders 第 8 章实战解读GLSL 二维矩阵变换——平移、旋转、缩放与 YUV 色彩空间 本篇技术指南以开源仓库 thebooGLSL 二维矩阵变换实战平移、旋转、缩放与 YUV 色彩空间——The Book of Shaders 第八章深入解析GLSL 二维矩阵变换实战平移、旋转、缩放与 YUV 色彩空间——The Book of Shaders 第八章深入解析 输出文章 GLSL 二维矩阵变换实The Book of Shaders 第 8 章精读用 GLSL 矩阵变换操控二维空间——平移、旋转、缩放与 YUV 色彩空间The Book of Shaders 第 8 章精读用 GLSL 矩阵变换操控二维空间——平移、旋转、缩放与 YUV 色彩空间 本篇对应 thebookof上一篇中国大学MOOC离线学习终极方案mooc-dl完整指南下一篇GoBelieve即时通讯服务教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考