中EN
精修课概念页

着色器里的颜色:向量也能当颜料

Color in Shaders

更新于 2026-10-15 约 18 分钟GLSL颜色HSBmixswizzle

颜色就是一个向量

上一课用 vec2 st 表示位置,用 vec4 表示颜色。它们其实是同一种东西:GLSL 里的向量。所以同一个分量会有好几个名字,用哪个只看你想让代码读起来像什么:

下标当坐标用当颜色用当纹理坐标用
[0].x.r.s
[1].y.g.t
[2].z.b.p
[3].w.a.q

red.x 和 red.r 读到的是同一个数。这是着色语言故意的设计:让你习惯把颜色和空间坐标换着想。

swizzle:随手重排分量

分量名可以按任意顺序拼在一起,这叫 swizzle。比如 yellow.rbg 就是把黄色的三个分量按「红、蓝、绿」的顺序重新取一遍:绿和蓝对调,黄色变成了品红。

yellowr 1.0g 1.0b 0.0yellow.rbg1.00.01.0按 r、b、g 的顺序取
yellow = (1.0, 1.0, 0.0)。按 r、b、g 的顺序取出三个分量,得到 (1.0, 0.0, 1.0),也就是品红 magenta。
一种颜色,四种 swizzle
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

从左到右依次是 base、base.rbg、base.bgr、base.ggg。

mix:在两种颜色之间走

mix(a, b, t) 按比例 t 在 a 和 b 之间插值:t 为 0 时是 a,为 1 时是 b。t 的范围正好是 0 到 1,上一课练的塑形函数在这里直接就能用上。

下面用 abs(sin(u_time)) 让 t 在 0 和 1 之间来回,再过一道 smoothstep,让颜色在两头多停一会儿:

两种情绪色之间的过渡0.0s
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

底部的进度条就是当前的 t。

让三个通道各走各的

mix 的第三个参数也可以是 vec3。这样三个通道就能用不同的比例混合:红色可以早早地过去,蓝色可以拖到最后。给每个通道配一条不同的塑形曲线,普通的两色渐变就会变得有层次。

按通道混合:一段从夜色到落日的渐变
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

三条线分别是 t.r、t.g、t.b:线越高,这个通道就越接近右边的暖光。

HSB:换一种选颜色的方式

RGB 不是唯一的组织颜色的办法。HSB(色相 Hue、饱和度 Saturation、亮度 Brightness,也叫 HSV)更接近人挑颜色的习惯:先选「什么颜色」,再选「多鲜艳」「多亮」。

把横坐标当色相、纵坐标当亮度,整块画布就铺满了可见光谱。拖动滑块改饱和度:

横向是色相,纵向是亮度
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

饱和度为 0 时,整块画布只剩一条从黑到白的灰阶。

把色相绕成一圈:极坐标

HSB 原本就是按极坐标设计的:用角度表示色相,用到圆心的距离表示饱和度。要画一个色轮,先求出每个像素相对画布中心的两个量:

  • 半径:length(p),到中心的距离;
  • 角度:atan(p.y, p.x),返回 −π 到 π 之间的弧度。

角度还得换算成 0~1 才能当色相用,换算分两步:

atan(y, x)−π0π÷ 2π−0.500.5+ 0.500.51
先除以 2π,范围从 [−π, π] 变成 [−0.5, 0.5];再加 0.5,就落在 [0, 1] 里,可以当色相用了。

整个游戏就是这样:把各种范围想办法挪到 0~1 里来。再给色相加上一点随时间增长的偏移,色轮就转起来了:

会转的极坐标色轮0.0s
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

角度决定色相,半径决定饱和度:圆心是白色,越往外越鲜艳。

注意这里把表示颜色的 vec3 和表示位置的 vec2 放在一起算,完全合法。除了 length,GLSL 还有 distance、dot、cross、normalize、faceforward、reflect、refract 这些几何函数,以及 lessThan、equal、notEqual 这一族逐分量比较的函数。

在光照里:颜色是相乘出来的

前面都是「直接给颜色」。到了有光照的场景,物体的颜色是怎么来的?

现实里,我们看到的物体颜色,是它没有吸收、反射出来的那部分光。LearnOpenGL 用一个很直接的式子近似这件事:

看到的颜色=光的颜色×物体的颜色\text{看到的颜色} = \text{光的颜色} \times \text{物体的颜色}

这里的乘法是逐个通道相乘的。白光照在珊瑚色的物体上,看到的还是珊瑚色。换成绿光,物体只能反射绿色通道,就变成了暗绿色。

改改光的颜色
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

左边的色条是光本身,中间是被照亮的物体。把红、蓝都拉到 0,只留绿光试试。

后面讲 Phong 和 PBR 时,「材质的反射率 × 入射光」用的都是这同一种乘法。

在游戏里怎么用

取舍与常见的坑

小结与练习

  • 颜色和坐标在 GLSL 里是同一种向量,.rgba、.xyzw、.stpq 只是不同的名字;swizzle 能随手重排分量。
  • mix(a, b, t) 在两种颜色之间插值;t 换成 vec3,三个通道就能各走各的曲线。
  • HSB 更适合挑颜色。用 atan 和 length 换到极坐标,就能画出色轮。
  • 有光照时,看到的颜色是「光 × 物体」逐通道相乘的结果。

练习:把色轮和第一课的鼠标结合起来:让鼠标的横坐标控制整个色轮的亮度,纵坐标控制旋转速度。

  1. The Book of Shaders: color
  2. thebookofshaders.com/06
  3. Lighting — Colors
  4. learnopengl.com/Lighting/Colors

相关页面

图形学塑形函数Shaping Functions塑形函数把归一化到 [0,1] 的一维输入弯成可控制的曲线,是片元着色器里混合颜色、画边、做动画缓动的「基本功」。GLSL 的 pow/step/smoothstep/sin 等多为硬件加速;掌握一维再扩展到二维空间。图形学片元着色器与 GLSL 基础Fragment Shaders & GLSL Basics片元着色器(fragment shader)是在每个像素(片元)上并行执行的小程序:输入位置等信息,输出颜色。GLSL 是 OpenGL / OpenGL ES / WebGL 共用的着色语言;本书用全屏 billboard 上的像素着色练习,建立程序化图形的基础心智模型。图形学色度学与色彩空间Colorimetry & Color Spaces色度学研究光谱功率分布与颜色感知的关系。人眼只有三种视锥细胞,所以三个数就能精确表示任意颜色刺激;CIE XYZ 是标准的三刺激值空间,各种 RGB 色彩空间由三原色和白点定义,可用 3×3 矩阵互相转换。实时渲染用 RGB 而非光谱计算,严格说是范畴错误,但对非预测性渲染效果出奇地好。图形学显示编码与 sRGBDisplay Encoding & sRGB光照、纹理等计算假设数值是线性的,但显示缓冲和纹理使用非线性编码。简短的回答是:着色器输出 [0,1] 的颜色要取 1/2.2 次幂(gamma 校正),读入的纹理和颜色做相反的变换,多数情况下可以让 GPU 自动完成。忽略它会导致画面偏暗、色相偏移、光照叠加错误和抗锯齿边缘"绳索化"。图形学二维 SDF 形状2D SDF Shapes在片元着色器里画形,不是发三角形图元,而是对每个像素问「我在形的里面还是外面」。矩形用 step/smoothstep 做轴对齐边界;圆与更复杂形用距离场 (distance field)——到特征点的距离再阈值。这是 2D SDF 程序化造型的入门路径。图形学着色器二维矩阵变换2D Matrix Transforms in Shaders在片元里「移动形状」其实是移动坐标系:平移加向量;旋转与缩放用 mat2 乘到坐标上。绕画布中心变换时,要先把空间挪到原点、变换、再挪回。矩阵乘法顺序有关;同一套矩阵也可拿来做 YUV↔RGB 等颜色空间线性变换。图形学着色方程与经典光照模型Shading Equation & Classic Lighting ModelsGEA 把渲染方程在两条简化假设下化成的求和式称为着色方程:只有理想化的点光源和方向光,间接光只用一个环境光项粗略近似。配上 Lambert、Phong、Blinn-Phong 这类简单 BRDF,它给不出照片级真实感,但能产生可信的画面,是早期游戏的全部光照,也是理解 BRDF 用法的最好入门(GEA4 卷 II 12.4、12.5.1)。图形学基于物理的着色Physically Based Shading基于物理的着色从光与物质交互的物理出发,用 BRDF 和反射方程计算表面沿视线方向射出的辐射亮度:镜面项来自微表面理论与菲涅耳反射,漫反射项来自局部次表面散射,布料、波动光学与分层材质再作扩展。本页是 RTR4 第 9 章的总览,并收录该章第 9.13 节的材质混合与材质过滤(镜面抗锯齿)。游戏美术Base Color 与反照率制作Base Color & Albedo AuthoringBase Color(MR)/ Diffuse·Albedo(SG)承载物质固有色:电介质为漫反射反照率,金属为镜面反射色(F0)。制作要点是保持正确亮度区间、不要画进光照/阴影/AO(微遮蔽例外),并注意 sRGB 贴图与线性着色的分工。

被这些页面引用2 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原