SFML中使用GLSL着色器来绘制水波。
效果

代码
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
const int WIDTH = 800;
const int HEIGHT = 600;
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "2D Water Surface");
window.setFramerateLimit(30);
sf::Clock clock;
// 创建一个矩形顶点数组
sf::VertexArray surface(sf::Quads, 4);
surface[0].position = sf::Vector2f(0, 0);
surface[1].position = sf::Vector2f(WIDTH, 0);
surface[2].position = sf::Vector2f(WIDTH, HEIGHT);
surface[3].position = sf::Vector2f(0, HEIGHT);
// 创建一个着色器来实现水面效果
sf::Shader shader;
if (!shader.loadFromFile("shader.txt", sf::Shader::Fragment))
{
std::cout << "Failed to load shader!" << std::endl;
return -1;
}
shader.setUniform("g_resolution", sf::Vector2f(800, 600));
// 主循环
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
// 更新水面效果的时间参数
shader.setUniform("g_time", clock.getElapsedTime().asSeconds());
// 渲染水面
window.clear();
window.draw(surface, &shader);
window.display();
}
return 0;
}
着色器代码
shader.txt
uniform vec2 g_resolution;
uniform float g_time;
void main( )
{
// 将像素坐标归一化(区间 [0.0, 1.0])
vec2 uv = gl_FragCoord / g_resolution.xy;
// 振幅(控制波浪顶端和底端的高度)
float amplitude = 0.05;
// 角速度(控制波浪的周期)
float angularVelocity = 10.0;
// 频率(控制波浪移动的速度)
float frequency = 5.0;
// 偏距(设为 0.5 使得波浪垂直居中于屏幕)
float offset = 0.3;
// 初相位(正值表现为向左移动,负值则表现为向右移动)
float initialPhase = frequency * g_time;
// 代入正弦曲线公式计算 y 值
// y = Asin(ωx ± φt) + k
float y = amplitude * sin((angularVelocity * uv.x) + initialPhase) + offset;
// 区分 y 值上下部分,设置不同颜色形成波浪
vec4 color = uv.y > y ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(0.0, 0.7, 0.9, 1.0);
// 输出到屏幕
gl_FragColor = color;
}