index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html
![]()
本文分享了GLSL(OpenGL Shading Language)的基础知识和实践,通过几个简单的例子,包括红色填充、渐变、径向渐变和发光圆环,逐步引导读者理解GLSL的绘制原理和坐标系统。文章深入浅出地讲解了gl_FragColor、gl_FragCoord、u_resolution等关键概念,并详细解释了如何利用数学计算实现各种视觉效果,最终实现了被马斯克转发的四行代码效果。文章适合GLSL新手入门,提供了清晰的代码示例和解释,帮助读者快速上手。
💻 **GLSL核心概念:** GLSL是一种用于编写着色器的语言,其核心在于每个像素的独立计算和同时渲染。与传统2D绘图的顺序绘制不同,GLSL利用数学计算和函数式编程来定义每个像素的颜色。
🟥 **gl_FragColor与颜色:** gl_FragColor是GLSL中用于设置像素颜色的内置变量。通过设置vec4类型的gl_FragColor,可以定义红、绿、蓝和透明度(RGBA),从而控制像素的最终显示颜色。
📏 **坐标系统与归一化:** GLSL使用坐标系统,其中gl_FragCoord提供了像素的绝对坐标。通过将像素坐标归一化到0.0到1.0的范围,可以方便地实现渐变等效果,例如通过pos.x控制水平渐变。
⭕ **径向渐变与发光圆环:** 通过计算像素点到中心的距离,并结合abs和除法等数学运算,可以实现径向渐变和发光圆环效果。这种方法展示了GLSL中利用数学实现复杂视觉效果的能力。
✨ **四行代码的奥秘:** 通过对角线的数学定义(x = y)和反转亮度,最终实现被马斯克转发的四行代码效果,展示了GLSL的强大表现力。
原创 苏武南飞 2025-07-09 08:31 重庆
写在开头最近在学习glsl,在网上找相关开源代码效果学习时看到了这个被「马斯克」转发,并且只用四行就完成的效果

写在开头最近在学习glsl
,在网上找相关开源代码效果学习时看到了这个被「马斯克」转发,并且只用四行就完成的效果!自我学习之后分享出来,因为本人也是一个glsl
新手,有错误的地方欢迎大家斧正! 本篇文章只会涉及到「片段着色器」,下面代码如果不特殊提醒均为「片段着色器」 效果原作者 Xor
效果欣赏!🔑入门glsl
首先我们应该了解到之前我们使用的canvas 2D
绘制和glsl
绘制的一些差异性: Canvas 2D 的绘制方式:类似传统绘画,按顺序一笔一笔画从左上角 (0,0) 开始,y 轴向下命令式编程:moveTo(), lineTo(), fill()时间顺序执行,后画的覆盖先画的GLSL 的绘制方式:每个像素点同时计算,高度并行坐标系通常以中心为 (0,0),y 轴向上函数式编程:给定坐标,返回颜色所有像素 "瞬间" 同时渲染这是学习glsl
初期相当让人不适应的一点,glsl
非常类似中国古代的活字印刷[1]技术,所有像素点同时渲染,几何形状需要依靠数学计算来排列组合!下面举得例子中都要谨记这个概念「瞬间 / 同时渲染」 void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
gl_FragColor 是 GLSL 片元着色器 (Fragment Shader) 中的一个内置输出变量,它决定了当前像素最终显示的颜色。gl_FragColor 的核心概念本质:它是每个像素的 "最终答案" - 告诉 GPU 这个像素应该显示什么颜色。vec4 的四个分量含义gl_FragColor = vec4(r, g, b, a);
r (Red):红色分量,范围 0.0-1.0g (Green):绿色分量,范围 0.0-1.0b (Blue):蓝色分量,范围 0.0-1.0a (Alpha):透明度,0.0 完全透明,1.0 完全不透明void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
因为 r=1.0 所以我们这个代码的效果是一个红色的填充。工作原理GPU 为屏幕上的每个像素都调用一次这个片元着色器每次调用时,main() 函数执行gl_FragColor 被设置为红色所有像素都得到相同的红色值最终屏幕显示为一片红色就像每个像素都调用了 main 方法得到的命令是都给我渲染成_红色_,结果就是整个画布展示为红色。更多例子void main() {
vec2 pos = gl_FragCoord.xy / u_resolution.xy;
gl_FragColor = vec4(pos.x, 0.0, 0.0, 1.0);
}
gl_FragCoord - 像素的绝对坐标gl_FragCoord
是 GLSL 的内置变量,表示当前像素在屏幕上的绝对位置(以像素为单位)。
u_resolution - 画布的总尺寸u_resolution 是一个变量,表示画布的宽高。归一化坐标的计算vec2 pos = gl_FragCoord.xy / u_resolution.xy;
这行代码将绝对像素坐标转换为归一化坐标(0.0 到 1.0):举例:画布800x600,当前像素在(400, 300)
pos.x = 400 / 800 = 0.5 (画布中央)
pos.y = 300 / 600 = 0.5 (画布中央)
渐变效果的实现gl_FragColor = vec4(pos.x, 0.0, 0.0, 1.0);
最左边:pos.x = 0.0 → 黑色 (0, 0, 0, 1)最右边:pos.x = 1.0 → 纯红 (1, 0, 0, 1)中间:pos.x = 0.5 → 半红 (0.5, 0, 0, 1)这个效果是纵向渐变,我们举一反三实现一个垂直渐变void main() {
vec2 pos = gl_FragCoord.xy / u_resolution.xy;
gl_FragColor = vec4(pos.y, 0.0, 0.0, 1.0);
}
从这两个渐变效果我们就能了解到glsl
坐标系是「从左到右」 / 「从下到上」0,1 - - - - - 1,1
| |
| |
0,0 - - - - - 1,0
径向渐变线性渐变我们已经掌握了接下来我们来挑战一下径向渐变!void main() {
vec2 pos = gl_FragCoord.xy / u_resolution.xy;
pos = pos * 2.0 - 1.0;
float dist = length(pos);
gl_FragColor = vec4(dist, dist, dist, 1.0);
}
pos = pos * 2.0 - 1.0;
在于把中心点变换到[0,0]
,vec2 pos = gl_FragCoord.xy / u_resolution.xy;
是归一化坐标也就是坐标范围此时为[0,1]
此时坐标中心点是[0.5,0.5]
, 经过 pos * 2.0 - 1.0;
之后我们的坐标范围变成了[-1,1]
,此时的坐标中心点就是[0,0]
啦。length()
是 GLSL 中的内置数学函数,用来计算向量的欧几里得长度[2], 也就是我们熟知的勾股定理,对于对于 2D 向量vec2(x, y)
来说!length(vec2(x, y)) = sqrt(x*x + y*y)
这就是我们为什么需要把作用中心点转换到[0,0]
的原因!我们的dist
的值靠近中心点就约等于 0,越靠近外层就约等于 1发光的圆环void main() {
vec2 pos = gl_FragCoord.xy / u_resolution.xy;
pos = pos * 2.0 - 1.0;
float dist = length(pos);
float ring = abs(dist - 0.5);
float brightness = 0.1 / ring;
gl_FragColor = vec4(brightness, brightness, brightness, 1.0);
}
OK Fine,现在我们提升一点难度,开始我最不喜欢的数学!首先是dist
可以产生一个径向渐变中心是黑色往外扩散白色,但是我们的目的是一个圆环,也就是中心要是 黑色->白色->黑色
,通过float ring = abs(dist - 0.5)
就可以产生一个明显的分层效果!假设:
dist = 0; ring = 0.5;
dist = 0.5; ring = 0;
dist = 1; ring = 0.5;
float brightness = 0.1 / ring;
的作用就是提亮!ring 值
brightness = 0.1 / ring
效果
0.5
0.1 / 0.5 = 0.2
暗灰色
0.2
0.1 / 0.2 = 0.5
中等亮度
0.1
0.1 / 0.1 = 1.0
比较亮
0.05
0.1 / 0.05 = 2.0
很亮!
0.01
0.1 / 0.01 = 10.0
超亮!!
0.001
0.1 / 0.001 = 100.0
极亮!!!
❝数学规律:当分母越接近 0,结果越接近无穷大! 这就是为什么圆环会发光 - 在半径 0.5 的位置,分母最小,亮度最大!❞完成 Grok 效果看完上述几个例子后,我们已经可以完成一个发亮的圆环,现在距离最终的效果只差一个对角线! 🎯 对角线的数学定义对角线是所有满足 x = y 的点在这些点上:p.x - p.y = x - x = 0数值分布左上角:p.x < p.y,所以 p.x - p.y < 0(负值)右下角:p.x > p.y,所以 p.x - p.y > 0(正值)对角线:p.x = p.y,所以 p.x - p.y = 0(零值)除法放大0.01 / (p.x - p.y)当 p.x - p.y 接近 0 时(对角线附近)除法结果趋向无穷大 → 产生极亮的线我们加上这个对角线后为了让对角线在圆环中不发光需要反转亮度,想想我们之前的数学规律当分母越接近0,结果越接近无穷大!
, 反过来如果分母越大结果自然也就越小!! 结语glsl
实在是太有意思了!同时也太难啦!!!参考资料Xor:www.shadertoy.com/user/XorThe Book of Shaders:thebookofshaders.com/AI编程资讯AI Coding专区指南:https://aicoding.juejin.cn/aicoding

点击"阅读原文"了解详情~










阅读原文
跳转微信打开