sfml使用opengl着色器实现2d水面波浪

⌚Time: 2024-01-20 22:06:48

👨‍💻Author: Jack Ge

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;

}