Skip to main content

15.2 使用纹理

Shadertoy 中使用纹理非常简单。打开新着色器并将代码替换为以下内容:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy; // Normalized pixel coordinates (from 0 to 1)

vec4 col = texture(iChannel0, uv);

fragColor = vec4(col); // Output to screen
}

然后,单击 iChannel0 框。当弹出窗口出现时,转到 Textures 选项卡。我们将选择 Abstract 1 纹理,但让我们检查一下弹出菜单中显示的一些细节。

-

它表示此纹理的分辨率为 1024x1024 像素,这意味着此图像最好在方形或比例画布中查看。它还有 3 个通道(红色、绿色、蓝色),每个通道都是 uint8 类型,一个 8 位的无符号整数。

继续并单击Abstract 1将此纹理加载到 iChannel0 中。然后,运行着色器程序。您应该会看到纹理出现在 Shadertoy 画布中。

-

让我们分析一下着色器程序中的代码。

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy; // Normalized pixel coordinates (from 0 to 1)

vec4 col = texture(iChannel0, uv);

fragColor = vec4(col); // Output to screen
}

UV 坐标x 轴和 y 轴上介于 01 之间。请记住,点 (0, 0) 从画布的左下角开始。texture 函数使用 iChannel0UV 坐标从纹理中检索所谓的纹素 texels

纹素 texels 是纹理上特定坐标的值。对于 2D 纹理(如图像),纹素是像素值。我们假设 UV 坐标在图像上介于 0 和 1 之间,则对 2D 纹理进行采样。然后,我们可以将纹理 UV 映射到整个 Shadertoy 画布上。

-

对于 3D 纹理,您可以将纹素视为 3D 坐标处的像素值。您通常不会看到 3D 纹理如此频繁地使用,除非您正在处理噪声生成或体积光线行进。

您可能很好奇,当我们将 iChannel0 作为参数传递给 texture 函数时,它是什么类型。Shadertoy 负责为您设置采样器。采样器是一种将纹理单元绑定到着色器的方法。采样器的类型将根据您加载到四个通道 (iChannel0、iChannel1、iChannel2、iChannel3) 之一的资源类型而变化。

在本例中,我们将 2D 纹理加载到 iChannel0 中。因此,iChannel0 的类型为 sampler2D。您可以在 OpenGL Wiki 页面上查看可用的其他采样器类型。

假设您想创建一个函数,让您传入其中一个通道。您可以通过以下代码执行此作:

vec3 get2DTexture( sampler2D sam, vec2 uv ) {
return texture(sam, uv).rgb;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy; // Normalized pixel coordinates (from 0 to 1)

vec3 col = vec3(0.);

col = get2DTexture(iChannel0, uv);
col += get2DTexture(iChannel1, uv);

fragColor = vec4(col,1.0); // Output to screen
}

如果单击 iChannel1 框,选择Abstract 3纹理,然后运行代码,您应该会看到两个图像混合在一起。

-

我们创建的 get2DTexture 函数接受 sampler2D 类型作为其第一个参数。当您在通道中使用 2D 纹理时,Shadertoy 会自动为您返回 sampler2D 类型的数据。

如果要在 Shadertoy 画布中播放视频,可以按照与 2D 纹理相同的步骤进行操作。只需在 iChannel0 中选择一个视频,您应该会看到视频开始自动播放。