我想制作这样的波浪扭曲效果:
但我只能创建正常的正弦波。
这是我的片段着色器:
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;
}
结果是:
那么问题是如何将波浪扭曲到特定方向?
谢谢。
<小时/>更新: 我在计算 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);
最佳答案
好吧,我尝试重新创建你的效果,所以我用它作为纹理:
我拍摄了您的图像并将其大小调整为 512x512
所以它是 2 的幂,用黑色填充边框。由于您不共享顶点着色器,因此我创建了自己的顶点着色器。 GL 正在渲染单个四边形 <-1,+1>
仅没有纹理坐标或矩阵 glVertex2f()
具有绑定(bind)到单元的单个 2D 纹理 0
。我稍微重写了您的片段以匹配输出。我还添加了 tx,ty
通过鼠标位置轻松制作制服效果 <0,1>
这是着色器的第一个顶点:
// 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
的输出视觉上或多或少与您的示例相符:
如您所见,我在正弦波中添加了一些项,因此它也出现了偏斜失真。
如果您有 v_texCoord
已在范围内 <0,1>
然后忽略
p.x=( 0.55*p.x)+0.5;
p.y=(-0.55*p.y)+0.5;
或将其重写为(以便收缩和系数保持应有的状态)
p.x=(1.1*p.x)-0.05;
p.y=(1.1*p.y)-0.05;
如果您使用不同的纹理(不是我的),那么您需要重新调整所有系数。
[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
频率越大,沿轴的波就越多。通过纯粹的反复试验,我确定它们应该是 30.0
对于 y 轴和 25.0
对于 x 轴,因此波数与您所需的输出相匹配。
float x = sin( 25.0*p.y) * 0.05;
float y = sin( 30.0*p.x) * 0.05;
在此之后,我发现波浪应该有点倾斜,因此在经过一些调整发现这个方程后,我也添加了对另一个轴的依赖:
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>
所以我得到了最终结果:
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
。这样你就可以硬编码
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;
关于opengl - 如何在shader中制作波浪扭曲效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36174431/