第一步:了解Gerstner波
上述即为Gerstner波的方程,下面我们来说一下这个方程当中各个变量的含义:
1、x:水面静止时,某个顶点的x轴坐标。
2、y:水面静止时,某个顶点的y轴坐标。
3、Qi:用于控制波浪平滑度的变量,当Qi为0的时候,波浪就是一个正弦函数的波形。当Qi为1/(wi*Ai)时,波峰的形状最尖,波底较为平滑,若Qi继续增大则波峰会变成环状,另外要注意的是,因为最后我们要将各个波形叠加,有可能会导致其值变得太大,所以我们一般用Qi = Q/(wi Ai x numWaves)。
4、Ai:单个波的振幅
5、Di:波矢量,即波的传递方向,用一个二维向量表示
6、wi:单个波的角速度
第二步:初始化水面
void initWave()
{
//1.用结构体存储每一个波纹的基本参数
waves.time = 0.0;
for (int i = 0; i<numberofwaves; i++)
{
waves[i].phi= 初相;
waves[i].height = 振幅;
waves[i].dirx = 传播方向x坐标;
waves[i].diry = 传播方向y坐标;
waves[i].w = 角速度;
}
//2.先将要构建的水面的顶点数据求出
int index= 0;
for (int i = 0; i<waterwide; i++)
{
for (int j = 0; j<waterlength; j++)
{
pt_strip[index] = -1.0f + i * 0.02f;
pt_strip[index + 1] = -1.0f + j * 0.02f;
pt_strip[index + 2] = 0.0f;
//把数据再额外存储一份,用来备用
pt_strip2[index] = -1.0f + i * 0.02f;
pt_strip2[index + 1] = -1.0f + j * 0.02f;
pt_strip2[index + 2] = 0.0f;
index += 3;
}
}
}
第三步:将初始数据带入Gerstner方程计算
int index = 0;
for (int i = 0; i<waterwide; i++)
{
for (int j = 0; j<waterlength; j++)//枚举各个顶点
{
vec2 offset = vec2(0.0f, 0.0f);
GLfloat height = 0.0f;
for (int k = 0; k < 3; k++)//枚举波形
{
vec2 K = vec2(waves[k].dirx, waves[k].diry);
GLfloat Qi = 1 / (waves[k].height * waves[k].w) * 0.3;
GLfloat p = waves[k].w * dot(K, vec2(pt_strip2[index], pt_strip2[index + 1])) + glfwGetTime() * waves[k].phi;
offset.x += Qi * waves[k].height * K.x*cos(p);
offset.y += Qi * waves[k].height * K.y*cos(p);
height += wave_para2[k][1] * sin(p);
}
pt_strip[index] = pt_strip2[index] + offset.x;
pt_strip[index + 1] = pt_strip2[index + 1] + offset.y;
pt_strip[index + 2] = -height;
index += 3;
}
}
第四部:将计算好的数据进行排序,便于绘制网格
int pt;
for (int c = 0; c<(waterwide- 1); c++)
{
for (int l = 0; l<2 * waterlength; l++)
{
if (l % 2 == 1)
{
pt = c*waterlength + l / 2;
}
else
{
pt = c*waterlength + l / 2 + waterlength;
}
index = waterlength * 2 * c + l;
for (int i = 0; i<3; i++)
{
vertex_data[index * 3 + i] = pt_strip[pt * 3 + i];
normal_data[index * 3 + i] = pt_normal[pt * 3 + i];
}
}
}
第五步:传递数据并进行绘制
while (!glfwWindowShouldClose(window))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
Do_Movement();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
values.time = currentFrame;
calcuWave2();
mat4 projection = perspective(radians(camera.Zoom), (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 100.0f);
mat4 view = camera.GetViewMatrix();
mat4 model;
model = rotate(model, radians(90.0f), vec3(1.0f, 0.0f, 0.0f));
model = scale(model, vec3(10.0f, 10.0f, 10.0f));
GLfloat time = glfwGetTime();
shader.Use();
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, value_ptr(model));
RenderWater();
glfwSwapBuffers(window);
}
以上仅仅是计算波形的顶点位置,如果没有问题的话,将会得到一下结果: