在着色器中创建波浪表面

Creating a waving surface in a shader

我在顶点着色器中创建了一个波浪形表面。

顶点着色器:

#version 300 es
precision lowp float;

uniform mat4 u_mvpMatrix;
uniform sampler2D s_texture;

in vec4 a_position;
out vec2 v_textureCoordinates;

const float pi = 3.14285714286;

void main() {
    vec4 vertexCoord = a_position;
    float distance = length(vertexCoord);

    vertexCoord.y += sin(3.0 * pi * distance * 0.3 + u_lastTime) * 0.5;
    v_textureCoordinates = a_textureCoordinates;
    
    gl_Position = u_mvpMatrix * vertexCoord;
}

片段着色器:

#version 300 es
precision lowp float;

in vec2 v_textureCoordinates;
out vec4 outColor;
uniform sampler2D s_texture;

void main() {
    outColor = texture(s_texture, v_textureCoordinates);
}

结果:

但是在表面上只有一个来自中心的径向波。是否可以使用着色器创建具有多个波浪的表面?也就是让表面看起来像冒泡的水。

解决方案

谢谢@vtastek!根据他的回答,我更改了vertex shader:

#version 300 es
precision lowp float;

uniform mat4 u_mvpMatrix;
uniform sampler2D s_texture;

in vec4 a_position;
out vec2 v_textureCoordinates;

const float pi = 3.14285714286;

void main() {
    vec4 vertexCoord = a_position;
    
    vec2 origin1 = vertexCoord.xz + vec2(300.0, 300.0);
    vec2 origin2 = vertexCoord.xz + vec2(-300.0, 300.0);
    vec2 origin3 = vertexCoord.xz + vec2(300.0, -300.0);
    vec2 origin4 = vertexCoord.xz + vec2(-300.0, -300.0); 

    float distance1 = length(origin1);
    float distance2 = length(origin2);
    float distance3 = length(origin3);
    float distance4 = length(origin4);

    float wave = sin(3.3 * pi * distance1 * 0.13 + u_lastTime) * 0.125 +
    sin(3.2 * pi * distance2 * 0.12 + u_lastTime) * 0.125 +
    sin(3.1 * pi * distance3 * 0.24 + u_lastTime) * 0.125 +
    sin(3.5 * pi * distance4 * 0.32 + u_lastTime) * 0.125;
    
    vertexCoord.y += wave;

    v_textureCoordinates = a_textureCoordinates;
    
    gl_Position = u_mvpMatrix * vertexCoord;
}

结果:

在大多数示例中,它是多个单向波。不过我喜欢你的圆波想法。我只会偏移和复制。

vec2 origin1 = vertexCoord.xz + vec2(300.0, 300.0);
vec2 origin2 = vertexCoord.xz + vec2(-300.0, 300.0);
vec2 origin3 = vertexCoord.xz + vec2(300.0, -300.0);
vec2 origin4 = vertexCoord.xz + vec2(-300.0, -300.0); // random or 4 corners
    
float distance1 = length(origin1);
float distance2 = length(origin2);
float distance3 = length(origin3);
float distance4 = length(origin4);
    
float wave = sin(3.3 * PI * distance1 * 0.13 + time) * 0.125 +
             sin(3.2 * PI * distance2 * 0.12 + time) * 0.125 +
             sin(3.1 * PI * distance3 * 0.24 + time) * 0.125 +
             sin(3.5 * PI * distance4 * 0.32 + time) * 0.125;
                
vertexCoord.y += wave;

或者,您可以添加具有不同方向的单向波(与随机 vec2 相乘)。您可以查找 Gerstner 波浪以获得更逼真的波浪。核心思想是将正弦波加在一起。