简而言之,shader可以认为是渲染管线里面可编程的部分。
GAMES202里面提到的实时渲染管线:

题主认为渲染管线定义的是渲染要做什么事情,以及这些事情的执行顺序;而shader定义的是如何完成其中的着色行为,我认为这是正确的。
下面简要讲一下我的理解。
渲染要做的事情,本质上就是把3D场景转化为2D图片。
那么,在计算机中,3D场景往往是通过存储顶点以及这些顶点的连接方式而达成的。
如何把这些顶点以及连接方式渲染为一张图片,就是渲染管线要做的一系列事情。
那么其中,我们要注意到的是,往往我们存储的是这些顶点的世界坐标;而渲染到屏幕上,我们需要把世界坐标转化为屏幕上的位置,即屏幕坐标,这就需要对顶点进行处理。(具体可以看九、GAMES101_变换)
我们可以自定义处理顶点的方式:
例如,多保存一些顶点相关的信息,例如切线、法线信息,以供下一步使用;
又例如,我们的目的不一定是从相机视角出发看见的图片,而是一张光源视角看见的阴影贴图,那么我们就需要把世界坐标投影到光源(具体可以看四十一、RSM的WebGL实现简析)。
这就是vertex shader,顶点着色器。确实定义的是“how”。
fragment shader,即像素着色器,定义的是如何对屏幕上的像素进行“上色”,即赋予它一个rgb颜色值。通常,我们需要上一步顶点着色器返回的信息,利用一些着色模型,最简单的例如Blinn-Phong着色模型(十一、GAMES101_Shading、纹理、Mipmap与阴影映射),总之返回一个rgb值。
但是当然也可以利用其他的着色模型来上色,甚至加以风格化,例如在原神里就需要渲染一张二次元风格的图片;
另外,有的时候我们不一定需要返回一个色值,而是想要渲染一张广义上的“图片”,这个图片的像素储存的不再是颜色,而是这个点的深度/法线/世界坐标等等信息,这也需要用像素着色器完成。