前面发了一些关于 Shader 编程的文章,有读者反馈太碎片化了,希望这里能整理出来一个系列,方便系统的学习一下 Shader 编程。
这不就来了,从这一篇就开启 Shader 编程系列文章的更新,当然中间也会穿插一些音视频、OpenGL 相关文章的更新。
OpenGL ES 和 Metal
本文讲的 Shader 编程主要针对移动端设备,经常要到的图形接口是 OpenGL ES 和 Metal 。
Metal 是由苹果公司所开发的 GPU 编程接口,兼顾图形与计算功能,面向底层、低开销的硬件加速,用于代替 OpenGL ES ,OpenGL ES 在 iOS 12 已经被标记为 deprecated 状态。
Metal 比 OpenGL ES 的优点:
- Metal Api 更加 人性化,相比于 OpenGL 使用句柄的操作以及 C 语言的 Api,Metal 是面向对象的;
- Metal 的多线程支持,相比于 OpenGL 的上下文与线程的绑定,Metal 是 线程安全 的;
- Metal 的性能优于 OpenGL;
- Metal 支持 Compute shaders,能让我们使用 GPU 来做一些更加复杂的 并行计算 任务,如机器学习等,而 OpenGL 几乎只能支持与图形图像相关的。
Metal 比 OpenGL ES 的缺点:
- Metal 仅支持 Apple 平台,而 OpenGL 是跨平台的;
- Metal 对旧设备与系统支持不友好,而由于 OpenGL “出生” 较早,因此对旧的支持更好;
需要注意的是, OpenGL ES 在非苹果的移动端设备图形编程中依然保有很大的占有率,这一点从面试的时候,面试官主要问 OpenGL 相关知识可以看出来。
Shader 是什么
Shader 翻译过来叫做着色器,本质上也是一种程序,这种程序主要用于处理图像信息。Shader 代码并不运行在 CPU 上,而是运行在GPU(图形处理器)上。
使用Shader程序,开发者可以充分发挥GPU的并行计算能力,提高图形渲染的效率和质量。它们也为游戏开发、计算机视觉、科学可视化等领域提供了强大的工具,让开发者能够创造出更逼真、更吸引人的图形效果。
根据运行在渲染管线的不同阶段,Shader 主要分为三类:
- Vertex Shader 顶点着色器
- Fragment Shader 片段着色器
- Geometry Shader 几何着色器
对渲染管线不熟悉的同学可以回顾文章:建议收藏:OpenGL 渲染管线 (pipeline)
其中最常用的是片段着色器,而我们后面讲的 Shader 编程主要涉及片段着色器, 片段着色器的作用就是产生颜色。
Shader 编程语言 GLSL & MSL
OpenGL Shader 的编程语言是 GLSL - OpenGL Shading Language ,是一个以C语言为基础的高阶着色语言,之前有文章详细介绍过,可以查阅:
Metal Shader 的编程语言是 MSL ,MSL 基于C 11.0 语言设计的,在 C 基础上多了一些扩展和限制,使用 Clang 和LLVM 进行编译处理,编译器对于在GPU上的代码执行效率有更好的控制。
MSL 和 GLSL 差别很小,有着相同的内置函数,所以将 GLSL 转换为 MSL 代码时改动不大,这里列出来几处差别,大致了解下。
代码语言:javascript复制//GLSL
vec4 outColor = vec4(1.0);
outColor = texture2D(texture, uv);
//MSL
float4 outColor = float4(1.0);
outColor = texture.sample(sampler, uv);
由于主流的 Shader 编程网站,如 ShaderToy, gl-transitions 都是基于 GLSL 开发 Shader ,加上 MSL 和 GLSL 语法上差别不大,后面系列文章将以 GLSL 为主来介绍 Shader 编程。
Shader 编程环境
Shader 编程比较常用的是 ShaderToy 官网或者安装 VSCode ShaderToy 插件。
ShaderToy 官网,Shader 界的 Github ,里面的代码都是开源的,特效五花八门、应有尽有: https://www.shadertoy.com/new
VSCode ShaderToy 插件:
VSCode ShaderToy 插件使用可以参考之前的文章。
Hello World
编写第一个 Shader ,https://www.shadertoy.com/new ShaderToy 网站打开就是一个 Hello World 程序。
fragColor 表示输出颜色的向量,由 r,g,b,a 四个通道组成,fragCoord 表示像素坐标,也可以理解为纹理坐标,像素坐标原点位于左下角(你可以做实验试试),iResolution 表示开辟视口的分辨率(视口大小)。
我们直接修改它,根据每个像素所在位置的不同来生成不同的颜色,用纹理坐标分别替换 g、b 通道,然后点击左下角的编译按钮,Shader 就会直接运行起来了。
后续安排
后面 OpenGL & Metal Shader 编程系列文章大致安排:
- ShaderToy 内置全局变量
- 重要的内置函数
- 基本图形
- 距离场
- 噪声函数
- 基础特效…
- 转场特效…
- 高阶特效…