如何在着色器中制作波浪变形效果? [英] How to make a wave warp effect in shader?
问题描述
我想制作这样的波浪变形效果:
I want to make a wave warp effect like this:
但我只能创建正常的正弦波.
But I can only create the normal sine wave.
这是我的片段着色器:
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;
}
结果是:
那么问题是如何在特定方向上扭曲波浪?
So the question is how to warp the wave on a specific direction?
谢谢.
这是原始纹理:
更新:我在计算 y 时扭曲了 x 轴,但结果似乎不对.
update: I distort x axis when compute y, but the result seems not right.
float x = p.x + p.y*tan( -0.5);
float y = sin( w*x + t) * A;
return vec2(p.x, p.y+y);
推荐答案
好的,我尝试重新创建您的效果,因此我将其用作纹理:
OK I tried to recreate your effect so I used this as texture:
我把你的图片调整为512x512
,所以它是2的幂,用黑色填充边框.由于您不共享顶点着色器,因此我创建了自己的着色器.GL 渲染单个四边形 <-1,+1>
没有纹理坐标或矩阵,只有 glVertex2f()
和单个 2D 纹理绑定到单元 0
.我稍微重写了您的片段以匹配输出.我还添加了 tx,ty
制服以轻松地为鼠标位置制作动画效果 <0,1>
这里是着色器的第一个顶点:
I took your image and resize it to 512x512
so it is power of 2 fill the border with black. As you do not share Vertex shader I created my own. The GL is rendering single quad <-1,+1>
without texture coordinates or matrices only glVertex2f()
with single 2D texture binded to unit 0
. I slightly rewrite your fragment to match the output. Also I added tx,ty
uniforms to easily animate the effect with mouse position <0,1>
Here are the shaders first vertex:
// Vertex
varying vec2 v_texCoord;
void main()
{
v_texCoord=gl_Vertex.xy;
gl_Position=gl_Vertex;
}
然后是片段:
// 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));
}
这是 tx=0.3477,ty=0.7812
的输出,在视觉上或多或少与您的示例相符:
This is output for tx=0.3477,ty=0.7812
which visually more or less matches your example:
如您所见,我在正弦波中添加了一些项,因此它也得到了歪斜失真.
As you can see I added few terms into the sin waves so it got also skew distortion.
如果 v_texCoord
已经在 <0,1>
范围内,那么忽略
If you have the v_texCoord
already in range <0,1>
then ignore the
p.x=( 0.55*p.x)+0.5;
p.y=(-0.55*p.y)+0.5;
或将其重写为(因此收缩和系数保持原样)
or rewrite it to (so the shrink and coefficients stay as should)
p.x=(1.1*p.x)-0.05;
p.y=(1.1*p.y)-0.05;
如果您使用不同的纹理(不是我的),那么您需要重新调整所有系数.
If you use different texture (not mine) then you need to rescale all the coefficients.
[edit1] 系数含义
首先我从你的开始:
float x = sin( 10.0*p.y) * 0.15;
float y = sin( 10.0*p.x) * 0.15;
0.15
是波幅,看起来太大了,所以我把它降低到 0.05
.然后 10.0
是频率,数字越大,沿轴的波数越多.通过纯粹的试验和错误,我确定它们应该是 y 轴的 30.0
和 x 轴的 25.0
以便波的数量与您想要的输出相匹配.
The 0.15
is wave amplitude which seems to be too big so I lower it to 0.05
. Then 10.0
is frequency the bigger the number the more waves along axis will be. By pure trial&error I determine they should be 30.0
for y axis and 25.0
for x axis so the number of waves matches your desired output.
float x = sin( 25.0*p.y) * 0.05;
float y = sin( 30.0*p.x) * 0.05;
在此之后,我发现波浪应该有点倾斜,所以在经过一些调整发现这个方程后,我也添加了对另一个轴的依赖:
After this I spotted that the waves should be a bit skewed so I add dependency on the other axis too after some tweaking found out this equation:
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;
其中两个系数在轴之间相同(很奇怪,但工作时我期望我需要在轴之间使用不同的系数).这只是为每个轴找到正确相位的问题,所以我添加了由鼠标位置控制的相移 (tx,ty) <0.0,1.0>
所以我得到了最终结果:>
where both coefficients are the same in between axises (weird but working I was expecting I would need to have different coefficients between axises). After this is just a matter of finding the correct phase for each axis so I add phase shift controlled by mouse position (tx,ty) <0.0,1.0>
so I got the final:
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;
然后我玩鼠标(打印它的位置),直到我足够接近以匹配您想要的输出时 tx=0.3477,ty=0.7812
这样您就可以硬编码
Then I play with mouse (printing its position) until I got close enough to match your desired output which was when tx=0.3477,ty=0.7812
so you can hard-code
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;
这篇关于如何在着色器中制作波浪变形效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!