蚊章汇 - 着色器
type: channel
link: https://linuxcn.bwsl.wang/tag/%E7%9D%80%E8%89%B2%E5%99%A8/
items: 着色器入门：符号距离函数！

着色器入门：符号距离函数！
type: item
date: 2021-12-23T00:27:53+08:00
description: 大家好！不久前我学会了如何使用着色器制作有趣的闪亮旋转八面体：我的着色器能力仍然非常基础，但事实证明制作这个有趣的旋转八面体比我想象中要容易得多（从其他人那里复制了很多代码片段！）。我在做这件事时， 从一个非常有趣的叫做 符号距离函数教程：盒子和气球 的教程中学到了“符号距离函数”的重要思路。在本文中，我将介绍我用来学习编写简单着色器的步骤，并努力让你们相信着色器并不难入门！更高级着色器的示例如果你还没有看过用着色器做的真正有趣的事情，这里有几个例子：这个非常复杂的着色器就像一条河流的真实视频：https://www.shadertoy.com/view/Xl2XRW一个更抽象（更短！）有趣的着色器，它有很多发光的圆圈：https://www.shadertoy.com/view/lstSzj步骤一：我的第一个着色器我知道你可以在 shadertoy 上制作着色器，所以我去了 https://www.shadertoy.com/new。它们提供了一个默认着色器，如下图所示：代码如下：void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // 规范像素坐标 (从 0 到 1) vec2 uv = fragCoord / iResolution.xy; // 随时间改变像素颜色 vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4)); // 输出到屏幕 fragColor = vec4(col, 1.0); } 虽然还没有做什么令人兴奋的事情，但它已经教会了我着色器程序的基本结构！思路：将一对坐标（和时间）映射到一个颜色这里的思路是获得一对坐标作为输入（fragCoord），你需要输出一个 RGBA 向量作为此坐标的颜色。该函数也可以使用当前时间（iTime），图像从而可以随时间变化。这种编程模型（将一对坐标和时间映射到其中）的巧妙之处在于，它非常容易并行化。我对 GPU 了解不多，但我的理解是，这种任务（一次执行 10000 个微不足道的可并行计算）正是 GPU 擅长的事情。步骤二：使用 shadertoy-render 加快开发迭代玩了一段时间的 shadertoy 之后，我厌倦了每次保存我的着色器时都必须在 shadertoy 网站上单击“重新编译”。我找到了一个名为 shadertoy-render 命令行工具，它会在每次保存时实时查看文件并更新动画。现在我可以运行：shadertoy-render.py circle.glsl 并更快地开发迭代！步骤三：画一个圆圈接下来我想 —— 我擅长数学！我可以用一些基本的三角学来画一个会弹跳的彩虹圈！我知道圆的方程为（x^2 + y^2 = 任意正数！），所以我写了一些代码来实现它：代码如下：（你也可以 在 shadertoy 上查看）void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // 规范像素坐标 (从 0 到 1) vec2 uv = fragCoord / iResolution.xy; // 绘制一个中心位置依赖于时间的圆 vec2 shifted = uv - vec2((sin(iGlobalTime) + 1) / 2, (1 + cos(iGlobalTime)) / 2); if (dot(shifted, shifted) < 0.03) { // 改变像素颜色 vec3 col = 0.5 + 0.5 * cos(iGlobalTime + uv.xyx + vec3(0, 2, 4)); fragColor = vec4(col, 1.0); } else { // 使圆之外的其他像素都是黑色 fragColor = vec4(0,0, 0, 1.0); } } 代码将坐标向量 fragCoord 与自身点积，这与计算 x^2 + y^2 相同。我还在这个圆圈的中心玩了一点花活 – 圆心为 vec2（（sin（iGlobalTime） + 1）/ 2，（1 + cos（faster）） / 2，这意味着圆心也随着时间沿另一个圆移动。着色器是一种学习数学的有趣方式！我觉得有意思的（即使我们没有做任何超级高级的事情！）是这些着色器为我们提供了一种有趣的可视化方式学习数学 - 我用 sin 和 cos 来使某些东西沿着圆移动，如果你想更直观地了解三角函数的工作方式， 也许编写着色器会是一种有趣的方法！我喜欢的是，可以获得有关数学代码的即时视觉反馈 - 如果你把一些东西乘以 2，图像里的东西会变得更大！或更小！或更快！或更慢！或更红！但是我们如何做一些真正有趣的事情呢？这个会…