如何在着色器中制作波形扭曲效果?

thr*_*ist 7 opengl shader textures 2d glsl

我想像这样做一个波形扭曲效果:

WAVE1

但我只能创造正常的正弦波.

这是我的片段着色器:

precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_baseMap;

vec2 SineWave( vec2 p ){
    float pi = 3.14159;
    float A = 0.15;
    float w = 10.0 * pi;
    float t = 30.0*pi/180.0;
    float y = sin( w*p.x + t) * A; 
    return vec2(p.x, p.y+y);?
}
void main(){
    vec2 p = v_texCoord; 
    vec2 uv = SineWave( p ); 
    vec4 tcolor = texture2D(s_baseMap, uv); 
    gl_FragColor = tcolor; 
}
Run Code Online (Sandbox Code Playgroud)

结果是:

WAVE2

那么问题是如何在特定方向上扭曲波浪?

谢谢.

这是原点纹理: 起源纹理


更新:我在计算y时扭曲x轴,但结果似乎不正确.

float x = p.x + p.y*tan( -0.5); 
float y = sin( w*x + t) * A;
return vec2(p.x, p.y+y); 
Run Code Online (Sandbox Code Playgroud)

扭曲x轴

Spe*_*tre 8

好的我尝试重新创建你的效果所以我用它作为纹理:

质地

我拍了你的图像并调整大小,512x512所以2的力量用黑色填充边框.由于您不共享Vertex着色器,因此我创建了自己的着色器.的GL被渲染单四<-1,+1>没有纹理坐标或矩阵仅glVertex2f()与单个2D纹理绑定到单元0.我略微重写你的片段以匹配输出.我还添加了tx,ty制服,可以使用鼠标位置轻松设置效果.<0,1>以下是着色器的第一个顶点:

// Vertex
varying vec2 v_texCoord;
void main()
    {
    v_texCoord=gl_Vertex.xy;
    gl_Position=gl_Vertex;
    }
Run Code Online (Sandbox Code Playgroud)

然后片段:

// Fragment
varying vec2 v_texCoord;        // holds the Vertex position <-1,+1> !!!
uniform sampler2D s_baseMap;    // used texture unit
uniform float tx,ty;            // x,y waves phase

vec2 SineWave( vec2 p )
    {
    // convert Vertex position <-1,+1> to texture coordinate <0,1> and some shrinking so the effect dont overlap screen
    p.x=( 0.55*p.x)+0.5;
    p.y=(-0.55*p.y)+0.5;
    // wave distortion
    float x = sin( 25.0*p.y + 30.0*p.x + 6.28*tx) * 0.05;
    float y = sin( 25.0*p.y + 30.0*p.x + 6.28*ty) * 0.05;
    return vec2(p.x+x, p.y+y);
    }

void main()
    {
    gl_FragColor = texture2D(s_baseMap,SineWave(v_texCoord));
    }
Run Code Online (Sandbox Code Playgroud)

这是输出,tx=0.3477,ty=0.7812在视觉上或多或少匹配您的示例:

产量

正如你所看到的,我在sin波中添加了几个术语,因此它也会扭曲失真.

如果你v_texCoord已经在范围内,<0,1>那么忽略

    p.x=( 0.55*p.x)+0.5;
    p.y=(-0.55*p.y)+0.5;
Run Code Online (Sandbox Code Playgroud)

或重写它(所以缩小和系数保持原样)

    p.x=(1.1*p.x)-0.05;
    p.y=(1.1*p.y)-0.05;
Run Code Online (Sandbox Code Playgroud)

如果你使用不同的纹理(不是我的),那么你需要重新调整所有系数.

[edit1]系数意义

首先我从你的开始:

float x = sin( 10.0*p.y) * 0.15;
float y = sin( 10.0*p.x) * 0.15;
Run Code Online (Sandbox Code Playgroud)

0.15是波幅这似乎是太大,所以我把它降低到0.05.然后10.0频率越大,沿轴的波越多.通过纯试验和错误,我确定它们应该30.0用于y轴和25.0x轴,因此波的数量与您想要的输出相匹配.

float x = sin( 25.0*p.y) * 0.05;
float y = sin( 30.0*p.x) * 0.05;
Run Code Online (Sandbox Code Playgroud)

在此之后,我发现波浪应该有点倾斜,所以在经过一些调整发现这个等式后,我也增加了对另一个轴的依赖性:

float x = sin( 25.0*p.y + 30.0*p.x) * 0.05;
float y = sin( 25.0*p.y + 30.0*p.x) * 0.05;
Run Code Online (Sandbox Code Playgroud)

其中两个系数在轴之间是相同的(奇怪但工作我希望我需要在轴之间有不同的系数).在这之后只需找到每个轴的正确相位,所以我添加了由鼠标位置控制的相移,(tx,ty) <0.0,1.0>所以我得到了最终:

float x = sin( 25.0*p.y + 30.0*p.x + 6.28*tx) * 0.05;
float y = sin( 25.0*p.y + 30.0*p.x + 6.28*ty) * 0.05;
Run Code Online (Sandbox Code Playgroud)

然后我用鼠标(打印它的位置)玩,直到我足够接近你想要的输出,这时tx=0.3477,ty=0.7812你可以硬编码

float x = sin( 25.0*p.y + 30.0*p.x + 6.28*0.3477) * 0.05;
float y = sin( 25.0*p.y + 30.0*p.x + 6.28*0.7812) * 0.05;
Run Code Online (Sandbox Code Playgroud)