ShaderToy学习笔记 01.基础知识
ShaderToy学习笔记
先欣赏一下用ShaderToy画出来的效果
上图代码在 https://www.shadertoy.com/view/Ms2SD1
本系列是ShaderToy的入门学习笔记,主要记录学习心得及一些学习过程中遇到的问题和解决方案。
学习资源:
- https://shadertoy.peakcoder.com/
- https://inspirnathan.com/posts/47-shadertoy-tutorial-part-1
- https://www.zhihu.com/column/c_1591440349909774336
参考资料:
- https://www.shadertoy.com/
- Learn to Paint with Mathematics
- Shadertoy Unofficial
- https://blog.csdn.net/sunboylife/article/details/139815032
- ShaderToy入门手册
- ShaderToy教程
- Ray Marching for Dummies!
- Seascape
- https://raytracing.github.io/books/RayTracingInOneWeekend.html
- 《用两天学习光线追踪》1.项目介绍和ppm图片输出_用光线追踪画图-CSDN博客
- GitHub - maijiaquan/ray-tracing-with-imgui: 本项目参考自教程《Ray Tracing in One Weekend》,使用CPU多线程加速,结合ImGUI显示渲染结果。
- https://inspirnathan.com/posts/47-shadertoy-tutorial-part-1
- Desmos | Beautiful free math.
1. 基础知识
1.1. 环境搭建
shadertoy 有以下几种方式来运行:
- 浏览器 https://www.shadertoy.com/new
- vscode 中运行
此处讲解第二种方式,需要安装以下插件:
- glsl 插件
- shader toy
1.2. 第一个shader
新建一个test1.glsl文件,输入以下内容:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{// Normalized pixel coordinates (from 0 to 1)vec2 uv = fragCoord/iResolution.xy;// Time varying pixel colorvec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));// Output to screenfragColor = vec4(col,1.0);
}
点击vscode 菜单“查看” 、“命令面板”,选择“Shader Toy: Show GLSL Preview",即可运行。
1.3. 坐标系
注意: (0,0) 在左下角
1.4. 变量
1.4.1. Resolution
vec3 iResolution: 其中前两个分量分别存储了视窗的宽度和高度(以像素为单位),即x分量是窗口宽度,y分量是窗口高度
1.4.2. Time
变量名 | 类型 | 中文说明 |
---|---|---|
iTime | float | 着色器运行时间(秒),从程序启动开始计时 |
iTimeDelta | float | 帧间隔时间(秒) |
iFrame | int | 当前帧编号 |
iMouse | vec4 | 鼠标坐标/状态,xy=当前位置,zw=点击位置 |
iDate | vec4 | 系统日期(年,月,日,秒) |
iSampleRate | float | 音频采样率 |
fragCoord | vec2 | 当前像素坐标(原点在左下角) |
fragColor | vec4 | 输出颜色(RGBA格式) |
1.5. 坐标归一化
1.5.1. 坐标归一化到[0,1]
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{// Normalized pixel coordinates (from 0 to 1)vec2 uv = fragCoord/iResolution.xy;//...
}
归一化后,uv的范围是[0,1],即左下角是(0,0),右上角是(1,1)
1.5.2. 坐标归一化到[-1,1]
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 uv = (fragCoord/iResolution.xy - 0.5)*2.0;//...
}
注意:归一化后,uv的范围是[-1,1],即左下角是(-1,-1),右上角是(1,1)
但这样会有一个问题,就是当窗口的宽高比不等于1时,会出现变形。
比如 宽高比是2:1,则归一化后x轴从[-1,1],y轴从[-1,1] ,意味着 x轴2个像素对应y轴1个像素
1.5.3. 坐标归一化,短边归一化到[-1,1],长边保持宽高比
vec2 uv = (2.0*fragCoord-iResolution.xy)/min(iResolution.x,iResolution.y);
短边归一化到[-1,1],长边保持宽高比,会取最小值作为基准进行缩放
软件中通常采用这种方式来进行归一化,这样可以保证无论窗口的宽高比如何,都可以保持正确的比例。
1.6. 常用函数
1.6.1. 基础数学函数
函数 | 说明 | 示例 |
---|---|---|
abs(x) | 返回x的绝对值 | abs(-2.0) = 2.0 |
floor(x) | 返回小于等于x的最大整数 | floor(3.7) = 3.0 |
ceil(x) | 返回大于等于x的最小整数 | ceil(3.2) = 4.0 |
fract(x) | 返回x的小数部分 | fract(3.7) = 0.7 |
mod(x,y) | 返回x对y的取模 | mod(7.0, 3.0) = 1.0 |
min(x,y) | 返回x和y中的较小值 | min(2.0, 3.0) = 2.0 |
max(x,y) | 返回x和y中的较大值 | max(2.0, 3.0) = 3.0 |
clamp(x,min,max) | 将x限制在[min,max]范围内 | clamp(2.5, 1.0, 2.0) = 2.0 |
1.6.2. 三角函数
函数 | 说明 | 示例 |
---|---|---|
sin(x) | 正弦函数 | sin(3.14159/2.0) = 1.0 |
cos(x) | 余弦函数 | cos(0.0) = 1.0 |
tan(x) | 正切函数 | tan(0.0) = 0.0 |
asin(x) | 反正弦函数 | asin(1.0) = 1.5708 |
acos(x) | 反余弦函数 | acos(1.0) = 0.0 |
atan(x) | 反正切函数 | atan(1.0) = 0.7854 |
atan(y,x) | 二参数反正切函数 | atan(1.0, 1.0) = 0.7854 |
1.6.3. 插值和平滑函数
函数 | 说明 | 数学公式 | 示例 |
---|---|---|---|
mix(x,y,a) | 在x和y之间按a进行线性插值。a的范围在[0,1]之间,当a=0时返回x,当a=1时返回y | f(x,y,a) = x * (1-a) + y * a | mix(0.0, 1.0, 0.5) = 0.5 |
step(edge,x) | 阶跃函数,创建一个突变的边界。如果x < edge返回0.0,否则返回1.0 | f(edge,x) = { 0.0, x < edge { 1.0, x ≥ edge | step(0.5, 0.7) = 1.0 |
smoothstep(edge0,edge1,x) | 在edge0和edge1之间创建平滑的Hermite插值。x值小于edge0时返回0.0,大于edge1时返回1.0 | t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0) f(edge0,edge1,x) = t * t * (3 - 2 * t) | smoothstep(0.0, 1.0, 0.5) = 0.5 |
1.6.4. 向量操作函数
函数 | 说明 | 示例 |
---|---|---|
length(v) | 返回向量的长度 | length(vec2(3.0, 4.0)) = 5.0 |
distance(p0,p1) | 返回两点之间的距离 | distance(vec2(0.0), vec2(3.0, 4.0)) = 5.0 |
dot(x,y) | 返回两个向量的点积 | dot(vec2(1.0), vec2(1.0)) = 1.0 |
cross(x,y) | 返回两个向量的叉积 | cross(vec3(1,0,0), vec3(0,1,0)) = vec3(0,0,1) |
normalize(x) | 返回向量的单位向量 | normalize(vec2(3.0, 4.0)) = vec2(0.6, 0.8) |
reflect(I,N) | 返回入射向量I关于法线N的反射向量 | reflect(vec3(1.0), vec3(0.0, 1.0, 0.0)) |
refract(I,N,eta) | 返回入射向量I关于法线N的折射向量 | refract(I, N, 1.0/1.5) |
1.6.5. 矩阵操作函数
函数 | 说明 | 示例 |
---|---|---|
matrixCompMult(x,y) | 矩阵分量相乘 | matrixCompMult(mat2(2.0), mat2(3.0)) |
inverse(m) | 返回矩阵的逆 | inverse(mat3(1.0)) |
transpose(m) | 返回矩阵的转置 | transpose(mat4(1.0)) |
1.6.6. 纹理采样函数
函数 | 说明 | 示例 |
---|---|---|
texture2D(sampler,uv) | 2D纹理采样 | texture2D(iChannel0, uv) |
textureCube(sampler,xyz) | 立方体纹理采样 | textureCube(iChannel0, vec3(1.0)) |
texture2DLod(sampler,uv,lod) | 指定LOD级别的2D纹理采样 | texture2DLod(iChannel0, uv, 1.0) |
1.6.7. 常用工具函数
函数 | 说明 | 示例 |
---|---|---|
pow(x,y) | x的y次方 | pow(2.0, 3.0) = 8.0 |
exp(x) | e的x次方 | exp(1.0) = 2.7183 |
exp2(x) | 2的x次方 | exp2(3.0) = 8.0 |
log(x) | x的自然对数 | log(2.7183) = 1.0 |
log2(x) | x的以2为底的对数 | log2(8.0) = 3.0 |
sqrt(x) | x的平方根 | sqrt(9.0) = 3.0 |
inversesqrt(x) | x的平方根的倒数 | inversesqrt(16.0) = 0.25 |
1.6.8. 常用内置变量
变量 | 说明 | 示例值 |
---|---|---|
iResolution | 渲染目标的分辨率 | vec3(1920, 1080, 1.0) |
iTime | 着色器运行的时间(秒) | 10.0 |
iTimeDelta | 上一帧到当前帧的时间差 | 0.0167 |
iFrame | 当前帧号 | 100 |
iMouse | 鼠标坐标 | vec4(x, y, click_x, click_y) |
iDate | 日期 | vec4(year, month, day, time) |
iChanneln | 输入通道n (n=0,1,2,3) | sampler2D |
1.7. 参考资料
- https://blog.csdn.net/sunboylife/article/details/139815032