资讯动态

The Book of Shaders 第三章:理解 uniform 变量与 gl_FragCoord 坐标的着色器编程

发布时间:2026/10/15 1:55:16 来源:尧图企业网站定制
【免费下载链接】thebookofshadersStep-by-step guide through the abstract and complex universe of Fragment Shaders.项目地址https://gitcode.com/gh_mirrors/th/thebookofshaders点击查看免费下载导读本文以《The Book of Shaders》第 03 章仓库 03/README.md 及其波兰语译本 03/README-pl.md为骨架系统讲解片段着色器中 CPU 与 GPU 之间的数据通道uniform变量与内置输入gl_FragCoord。你将掌握u_time、u_resolution、u_mouse三个核心 uniform 的声明方式与使用场景学会用gl_FragCoord归一化坐标驱动 RGB 颜色并通过仓库内的 03/time.frag 与 03/space.frag 两个可运行示例完成动手练习。一、为什么片段着色器需要 uniform在前一章中我们已经看到 GPU 如何管理数量庞大的并行线程——每个线程负责为最终图像的一小块区域计算颜色。尽管每个并行线程彼此看不见对方我们依然需要一种机制把来自 CPU 的输入数据发送给所有线程。由于显卡的硬件架构这种输入必须满足两个硬性条件对所有线程完全一致uniform每个线程拿到的数据必须完全相同严格只读read-only线程可以读取这些数据但绝不能改写它们。换句话说每个线程接收同一份数据只能读、不能改。这份数据就是 GLSL 中的uniform变量。从数据流角度看可以把 uniform 想象成 CPU 与 GPU 之间的一座座单向小桥——数据只从 CPU 流向 GPU仓库作者在 03/notes.md 中也强调它是 one-way bridges。二、uniform 的声明类型、位置与命名规范uniform变量可以拥有 GLSL 支持的大多数数据类型包括类别类型标量float向量vec2、vec3、vec4矩阵mat2、mat3、mat4采样器sampler2D、samplerCube按照惯例uniform 通常声明在着色器最顶部紧跟在默认浮点精度设置之后#ifdef GL_ES precision mediump float; #endif uniform vec2 u_resolution; // 画布尺寸宽高 uniform vec2 u_mouse; // 鼠标位置以屏幕像素为单位 uniform float u_time; // 着色器加载后经过的秒数2.1 命名约定u_前缀本书系列示例统一传递三个 uniformu_time着色器启动以来的秒数、u_resolution着色器所绘制的画布/公告板尺寸、u_mouse画布内部鼠标位置以像素为单位。作者遵循在 uniform 名前加u_前缀的约定目的是让读者一眼看出这是 uniform 而非普通局部变量。不过这只是一种风格偏好实际项目中你还会见到各式各样的命名。例如 ShaderToy 使用同语义的 uniform但采用i前缀命名uniform vec3 iResolution; // 视口分辨率像素 uniform vec4 iMouse; // 鼠标像素坐标xy 为当前位置zw 为点击状态 uniform float iTime; // 着色器播放时间秒注意两个平台的细微差别iResolution是vec3额外携带了像素宽高比信息iMouse是vec4xy 保存当前位置、zw 保存鼠标按键按下/按住的状态。这也印证了原文的提示——uniform 的名字在不同实现中千差万别但语义是一致的。三、实战一用 u_time 驱动颜色动画让我们用 03/time.frag 看看 uniform 的实际效果。这段代码用u_time着色器运行秒数配合正弦函数让画布在红色与黑色之间来回过渡#ifdef GL_ES precision mediump float; #endif uniform float u_time; void main() { gl_FragColor vec4(abs(sin(u_time)),0.0,0.0,1.0); }核心逻辑只有一行abs(sin(u_time))将u_time的连续增长值映射到0.01.0的周期区间作为红色通道强度绿色与蓝色通道恒为0.0alpha 恒为1.0。于是画布在全红与纯黑之间平滑脉动。3.1 GLSL 硬件加速的内置函数这段代码还引出了 GLSL 的另一个惊喜GPU 在硬件层面加速实现了大量角度、三角函数与指数函数无需软件模拟。本书涉及的核心内置函数如下仓库glossary目录收录了它们的详细说明sin()、cos()、tan()、asin()、acos()、atan()、pow()、exp()、log()、sqrt()、abs()、sign()、floor()、ceil()、fract()、mod()、min()、max()、clamp()。以sin()为例词条给出了完整的函数重载签名float sin(float angle)、vec2 sin(vec2 angle)、vec3 sin(vec3 angle)、vec4 sin(vec4 angle)参数以弧度为单位返回值即角度的三角正弦——因此它也天然支持向量化运算。3.2 动手练习在仓库的交互式页面由 src/main.js 中的GlslEditor加载datatime.frag实现中反复调参降低频率把u_time的系数调小例如sin(u_time * 0.4)见 03/notes.md 中的读者记录直到颜色变化几乎不可察觉提高频率把系数调大直到你看到单一颜色且不再闪烁多通道调制为红、绿、蓝三个通道分别配置不同频率的正弦函数观察叠加出的有趣色彩行为gl_FragColor vec4( abs(sin(u_time * 1.0)), abs(sin(u_time * 2.0)), abs(sin(u_time * 3.0)), 1.0 );四、gl_FragCoord默认的输入 varyingGLSL 不仅提供了默认输出vec4 gl_FragColor还提供了默认输入vec4 gl_FragCoord它保存当前活动线程正在处理的像素或称屏幕片段的屏幕坐标。借助gl_FragCoord每个线程都能知道自己工作在画布的哪个位置。这里有一个关键概念区分uniform对所有线程取值相同gl_FragCoord对每个线程取值不同每个像素坐标都不同因此它被称为varying变化值。也正因如此gl_FragCoord不需要你在着色器中显式声明——它是 GLSL 内置的保留字由运行时隐式提供这一点在 03/notes.md 中作者专门提醒读者these are reserved names。五、实战二用 gl_FragCoord 归一化坐标驱动颜色03/space.frag 演示了gl_FragCoord的典型用法——归一化坐标#ifdef GL_ES precision mediump float; #endif uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; void main() { vec2 st gl_FragCoord.xy/u_resolution; gl_FragColor vec4(st.x,st.y,0.0,1.0); }5.1 归一化的原理gl_FragCoord.xy是像素坐标系下的坐标例如画布为 500×500 时取值范围是0.0500.0。将它除以画布尺寸u_resolution后得到的就是0.01.0区间的归一化坐标st// 左下角 (0,0) → 归一化后 (0.0, 0.0) // 右上角 (500,500) → 归一化后 (1.0, 1.0) vec2 st gl_FragCoord.xy / u_resolution; // ST 范围: vec2(0.0,0.0) ~ vec2(1.0,1.0)这正是 GLSL 向量运算的便利之处vec2除以vec2会逐分量相除一步同时完成 X 与 Y 两个维度的归一化03/notes.md 中读者感叹同样的操作在 Processing 里需要调用vector.divide()之类的方法。5.2 把坐标画成颜色归一化之后坐标映射到颜色通道变得异常直接——把st.x送入红色通道、st.y送入绿色通道gl_FragColor vec4(st.x, st.y, 0.0, 1.0); // RED GREEN BLUE ALPHA于是屏幕从左到右呈现红色渐强、从下到上呈现绿色渐强画布左下角为黑色(0,0,0)、右上角为黄色(1,1,0)对角线方向则是红绿等比例混合的过渡色带效果正如下方示意图5.3 用颜色调试着色器在着色器世界里调试手段非常有限最常见的做法就是把变量赋成醒目的颜色再根据看到的图像反推行为。正如原书所言用 GLSL 编程常常像把船装进瓶子里——同样艰难同样美丽同样令人满足。5.4 理解自测对照 03/space.frag 的运行结果检验你的理解归一化坐标(0.0, 0.0)对应画布的哪个位置答案左下角颜色为纯黑(1.0, 0.0)、(0.0, 1.0)、(0.5, 0.5)、(1.0, 1.0)又分别对应哪里依次是右下角纯红、左上角纯绿、中心暗黄、右上角亮黄能否利用u_mouse注意它的值是以像素为单位的未归一化坐标需要先除以u_resolution才能与st处于同一量纲。试试用鼠标移动驱动颜色vec2 ms u_mouse / u_resolution; gl_FragColor vec4(ms.x, ms.y, 0.0, 1.0);能否把u_mouse与u_time结合起来设计一种随鼠标与时间共同变化的颜色图案六、uniform 在运行环境中由谁赋值uniform 的桥需要 CPU 端主动放行数据。本书第四章 04/README.md 展示了在浏览器与主流框架中如何为这些 uniform 赋值浏览器/glslCanvas直接用canvas classglslCanvas>uniforms { u_time: { type: f, value: 1.0 }, u_resolution: { type: v2, value: new THREE.Vector2() }, u_mouse: { type: v2, value: new THREE.Vector2() } }; // 渲染循环中 uniforms.u_time.value clock.getDelta();并在onWindowResize中把画布宽高同步给u_resolution、在onmousemove中把鼠标位置同步给u_mouseProcessingshader.set(u_resolution, float(width), float(height))、shader.set(u_mouse, ...)、shader.set(u_time, millis() / 1000.0)openFrameworksshader.setUniform1f(u_time, ofGetElapsedTimef())、shader.setUniform2f(u_resolution, ofGetWidth(), ofGetHeight())。这证实了一个重要事实uniform 的名字是你自己在 GLSL 中声明的CPU 端必须按相同名字调用对应的 set 接口才能把数据送进着色器03/notes.md 中读者提出的疑问正是这一点。当你在框架中换用不同的 uniform 名时务必同步修改两端的引用。七、小结本章的核心收获可以概括为三条uniform 是 CPU→GPU 的只读广播通道对所有并行线程取值一致声明位置在着色器顶部、精度设置之后支持float、vec、mat、sampler等类型u_time/u_resolution/u_mouse是本书贯穿始终的三大 uniform分别代表时间、画布尺寸与鼠标位置对应 ShaderToy 中的iTime/iResolution/iMousegl_FragCoord是默认的 varying 输入保存当前像素坐标除以u_resolution即可归一化到0.01.0从而直接映射为颜色通道——这是所有基于坐标的图案渐变、分形、程序化纹理的起点。掌握 uniform 与坐标归一化之后就可以进入后续章节用第三章的u_time、u_mouse与gl_FragCoord组合出形状、噪声与更加复杂的程序化艺术。赞分享【免费下载链接】thebookofshadersStep-by-step guide through the abstract and complex universe of Fragment Shaders.项目地址https://gitcode.com/gh_mirrors/th/thebookofshaders点击查看免费下载相关推荐The Book of Shaders 第三章精读GLSL Uniform 变量与 gl_FragCoord 坐标调试实战The Book of Shaders 第三章精读GLSL Uniform 变量与 gl_FragCoord 坐标调试实战 本篇技术指南聚焦于开源 GLSLThe Book of Shaders 第三章精讲GLSL uniform 与 gl_FragCoord 的片元着色器实战The Book of Shaders 第三章精讲GLSL uniform 与 gl_FragCoord 的片元着色器实战 本篇文章以《The Book ofThe Book of Shaders 第三章Uniform 变量与 gl_FragCoord——打通 CPU 与 GPU 的着色器数据通道The Book of Shaders 第三章Uniform 变量与 gl_FragCoord——打通 CPU 与 GPU 的着色器数据通道 本章是 The上一篇【亲测免费】 太吾绘卷游戏模组(Taiwu_mods) 安装与使用教程下一篇Adobe Illustrator批量替换终极指南用ReplaceItems.jsx提升10倍工作效率创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑