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 提供了一些其他输入。最常见的是渲染为 as 的分辨率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
秒为单位的,随着时间的推移,您可以在函数中使用动画参数。
所以,给定这些输入,如果你应用足够的数学,你可以制作出令人难以置信的图像,例如这个 shadertoy 着色器生成这个图像
令人惊奇的是,仅在上述输入的情况下,有人就计算出了生成该图像所需的数学运算。
许多最令人惊叹的shadertoy着色器使用一种称为光线行进的技术和一些称为“有符号距离场”的数学,您可以在此处阅读
但是,我认为重要的是要指出,虽然从 shadertoy 着色器中可以学到很多很酷的东西,但它们中的许多只适用于“我如何用一个输入为像素位置,其输出为单色”。他们没有回答“我应该如何为高性能应用程序编写着色器”。
将上面的海豚与这个快艇游戏进行比较
https://www.youtube.com/watch?v=7v9gZK9HqqI
在我的 NVidia GeForce GT 750 上全屏运行时,海豚着色器着色器以每秒约 2 帧的速度运行,而快艇游戏以 60 fps 运行。游戏运行速度快的原因是它使用了更传统的技术来绘制带有投影三角形的形状。即使是 NVidia 1060 GTX 在全屏时也只能以每秒 10 帧左右的速度运行海豚着色器。