Shadertoy 被称为 “玩具” 是有原因的。这基本上是一个谜题。仅给定一个函数,将当前像素位置作为输入,编写一个生成图像的函数。
该网站设置 WebGL 以绘制单个四边形(矩形),然后让您提供一个函数,该函数将当前渲染为 fragCoord 的像素传递。然后你用它来计算一些颜色。
例如,如果你这样做了
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec4 red = vec4(1, 0, 0, 1);
vec4 green = vec4(0, 1, 0, 1);
fragColor = mix(red, green, sin(fragCoord.x / 10.0) * 0.5 + 0.5);
}
你会得到像这样的红色和绿色条纹
https://www.shadertoy.com/view/3l2cRz
Shadertoy 提供了一些其他输入。最常见的是被渲染为iResolution 的分辨率。如果您将fragCoord 除以iResolution,那么您会得到在画布上从 0 到 1 和从 0 到 1 的值,这样您就可以轻松地使您的函数分辨率独立。
这样做我们可以像这样在中心画一个椭圆
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
// uv goes from 0 to 1 across and up the canvas
vec2 uv = fragCoord / iResolution.xy;
vec4 red = vec4(1, 0, 0, 1);
vec4 green = vec4(0, 1, 0, 1);
float distanceFromCenter = distance(uv, vec2(0.5));
fragColor = mix(red, green, step(0.25, distanceFromCenter));
}
产生
第二个最常见的输入是iTime(以秒为单位),随着时间的推移,您可以在函数中使用动画参数。
因此,鉴于这些输入,如果您应用足够的数学运算,您可以制作出令人难以置信的图像,例如 this shadertoy shader 生成此图像
令人惊奇的是,仅在上述输入的情况下,有人就计算出了生成该图像所需的数学运算。
许多最令人惊叹的 shadertoy 着色器使用一种称为光线行进的技术和一些称为“有符号距离场”的数学,您可以阅读关于 here
但是,我认为重要的是要指出,虽然有很多很酷的东西可以从 shadertoy 着色器中学习,但其中许多只适用于“我如何才能制作只有一个函数的漂亮图像”的“难题”输入是像素位置,其输出是单色”。他们没有回答“我应该如何为高性能应用编写着色器”。
将上面的海豚与这款快艇游戏进行比较
https://www.youtube.com/watch?v=7v9gZK9HqqI
海豚着色玩具着色器在我的 NVidia GeForce GT 750 上全屏时以每秒约 2 帧的速度运行,而快艇游戏以 60 fps 运行。游戏运行速度快的原因是它使用了更传统的技术来绘制带有投影三角形的形状。即使是 NVidia 1060 GTX 在全屏时也只能以每秒 10 帧左右的速度运行海豚着色器。