您的位置:

如何使用gl_fragcoord进行自由变换

一、gl_fragcoord的概念和作用

在对OpenGL ES进行着色器编程时,gl_fragcoord常常被用来完成一些自由变换。gl_fragcoord指的是一个四维向量,其分量分别为(x, y, z, 1),其中z代表深度值,可用于深度测试。而x和y则表示屏幕上对应像素的坐标。

在顶点着色器中,gl_Position是一个四维向量,其分量表示顶点变换后的位置,而在片段着色器中,gl_fragcoord则表示当前片元在屏幕上的位置。这个位置不是标准的笛卡尔坐标系,而是用像素坐标表示的。

因此,利用gl_fragcoord我们可以轻松实现屏幕上各种自由变换效果,例如水波纹、扭曲等等。

二、利用gl_fragcoord进行自由变换

下面我们以一个简单的例子来说明如何利用gl_fragcoord进行自由变换。

    precision mediump float;

    uniform float time;

    void main() {
        vec2 uv = gl_FragCoord.xy / vec2(640.0, 480.0);

        uv -= 0.5;
        uv *= 10.0;

        float amount = length(uv);

        vec2 offset = uv * sin(amount * 10.0 + time) / 10.0;

        gl_FragColor = texture2D(u_texture, uv + offset);
    }

在上面的片段着色器代码中,我们首先将屏幕坐标系转化为uv坐标系。然后将坐标系上的值都*10,使其放大10倍。

接着,我们根据坐标的长度算出一个amount变量,然后利用amount和时间、uv坐标系上的值来算出一个偏移量,用这个偏移量来采样纹理。这样就完成了一个简单的水波纹效果。通过改变坐标系上的值,我们就可以获得各种自由变换的效果。

三、利用gl_fragcoord实现扭曲效果

下面我们来看一个应用到实际场景中的例子,即如何利用gl_fragcoord实现扭曲效果。

    precision mediump float;

    uniform vec2 u_resolution;
    uniform float u_time;
    uniform sampler2D u_texture;

    void main() {
        vec2 p = gl_FragCoord.xy/u_resolution.xy - 0.5;
        p.x *= u_resolution.x / u_resolution.y;

        float offset = texture2D(u_texture, vec2(p.x * 0.2 + u_time/5.0, p.y * 0.85)).r;
        float fx = sin(p.y * 15.0 * offset + u_time) * 0.5;
        float fy = sin(p.x * 15.0 * offset + u_time) * 0.5;

        vec4 pixel = texture2D(u_texture, vec2(p.x + fx, p.y + fy));
        gl_FragColor = pixel;
    }

在这个例子中,我们首先将屏幕坐标系转换为uv坐标系,然后将x轴进行了拉伸,以适应不同宽高比的屏幕。接着,我们利用gl_fragcoord采样一张纹理,并利用p.x * 0.2 + u_time/5.0和p.y * 0.85这两个值来确定纹理采样的位置。

接下来,我们根据采样到的纹理值计算出一个偏移值,并将其用于sin函数计算。最后,我们将偏移值应用到uv坐标系上,并采样出像素。这样,就完成了一个简单的扭曲效果。

四、总结

gl_fragcoord是一个非常有用的变量,通过它我们可以轻松实现各种自由变换效果。以上代码均可在OpenGL ES中使用,如果想要尝试更多有趣的自由变换效果,可以利用gl_fragcoord进行实现。