Shader 魔法的学习之路(1):简介与“Hello World!”


3楼猫 发布时间:2022-05-12 09:14:32 作者:mnikn Language

这系列的教程我们会从零讲解 shader 编程,如何用 shader 做一些酷炫的效果。
不过在此之前,我们先简单介绍一下 shader 是什么。

Shader 是什么?能吃吗?

我不想讲那些太学术官方的解释,一句话概括:Shader 是系统给你的一系列钩子函数,主要用在图形上,你可以在上面的钩子函数基于像素级别改变甚至创造图形。

Shader 的使用场景

可以到Shadertoy看下别人用 shader 创造的东西。
有人可能会问,这些东西为什么不直接通过绘图软件或者动画软件搞出来,而非要用 shader 实现呢?
举个例子:大家有玩过游戏吧(没玩过那就去玩),一些游戏中当鼠标移到可交互的物品,为了看起来更显眼,这些物品会有边缘的高光,当鼠标移出去又恢复原状。这系列的场景的存在,要求我们要有动态修改图形的能力。

Shader 编程的一些基础概念和术语

下面的术语和概念在之后的教程中会反复提及,这里先预习一下,看不懂也没关系,后面会再提。
概念:
  • 图形学渲染流水线:一个图形需要经过多道工艺渲染出来,每项工艺接受上一条工艺的产物进行进一步的加功,这样每道工艺互不相干形成了流水线,我们关注的 shader 就是其中的一道工艺。详细介绍:点击跳转
术语:
  • fragment shader:处理每个像素的绘制颜色、方式的 shader
  • vetex shader:处理像素要在哪里绘制的 shader
  • uv:画布所有的像素点,整体表现为一个 0 到 1 分布的矩阵
  • 零点:坐标系的 (0,0) 点,本系列教程采用 webgl,默认零点在左下角

教程的一些参考和说明

这系列教程大部分思路和实现均来自Youtube视频“Shadertoy for absolute beginners”,教程很不错,建议去看一下。
本人目前也还在根据上述的视频学习 shader,水平有限难免有错误,如果有什么说得不对的欢迎指正。

Hello World!

接下来初步尝试下 shader 编程。
由于 shader 编程在不同平台的编写形式不同,根据语法分为 glsl 和 hlsl,根据引擎分为:opengl、webgl、directx 和其他我不知道的引擎,一些游戏引擎又会针对 shader 做一些封装:Unity、UE、Godot。
这系列的教程不会详细讲不同平台的区别,虽然不同平台的函数、变量甚至语法可能都有差异,不过思路是共通的,本系列的代码均使用 webgl,而且为了方便快速体验 shader 编程,我们会在一个封装好的平台
Shadertoy 上去写代码,如果你已经有熟悉的平台,例如 Unity,可以自己根据文中代码进行实践。

先来个 Hello World?不,我直接蓝屏!

对于 shader 编程来说,画个 hello world 还挺麻烦的,所以我们直接先画个蓝屏吧!
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = vec4(0.0, 0.0, 1.0 ,1.0); }
一句核心代码就实现了蓝屏,我们逐步看下上面的代码写的是什么意思。
首先我们定义了一个叫 mainImage 的函数,由于 shadertoy 做了一些封装,其实这个和传统的 shader 编程稍微有点不同。传统的 shader 编程这个函数应该叫 fragment,也被叫为 fragment shader ,也没有接受入参和出参。这个函数可以认为是系统给我们的钩子函数,绘制每个像素时都会调用这个函数,具体的执行时机由系统决定。
然后就是一句核心代码 fragColor = vec4(0.0, 0.0, 1.0 ,1.0)fragColor 是 webgl 的内置变量,表示当前像素的颜色。
后面的 vec4(0.0, 0.0, 1.0, 1.0)vec4 可以先看作是一个存了四个值的数据结构,变体还有 vec3vec2,里面的值类型都是 float(浮点数),vec3 存的就是三个值,以此类推。
我们给 vec4 设置的值是 (0.0, 0.0, 1.0, 1.0),因为这个值是赋给 fragColor 的,那这个值就表示的是颜色值,颜色值用 rgba 表示,所以这个值的意思是红色、绿色的值都为 0,蓝色和 alpha 值为 1.0,所以最终展现了蓝色。

再来个黄屏!

那如果我想要表现的是黄色,那要怎么做呢?根据颜色混合的原理,黄色=红色+绿色,所以我们这样设置:
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = vec4(1.0, 1.0, 0.0 ,1.0); }
一个像《赛博朋克2077》跳票通知的东西就出来啦!
这篇文章的内容目前为止没讲太多东西,主要是先让大家熟悉一下,接下来就开始正式地绘制一些常规的图案了。
本次文章的作业是,让屏幕显示出呼伦贝尔大草原的颜色。

© 2022 3楼猫 下载APP 站点地图 广告合作:asmrly666@gmail.com