You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SFML中实现RGB色轮效果?附矩形实现代码

SFML实现RGB调色板:矩形优化与圆形效果实现

一、优化矩形RGB调色板的实现

你原来的代码每次循环创建sf::RectangleShape,频繁生成销毁对象会导致性能低下。推荐使用**顶点数组(sf::VertexArray)**一次性绘制所有色块,大幅提升渲染效率:

#include <SFML/Graphics.hpp>

const int windowSize = 450;
const int colorRange = 255;

int main()
{
    sf::RenderWindow window(sf::VideoMode(windowSize, windowSize), "Optimized Color Palette", sf::Style::Close | sf::Style::Resize);
    sf::View mainView = window.getDefaultView();

    // 创建顶点数组,类型为四边形(每个色块对应4个顶点)
    sf::VertexArray palette(sf::Quads, colorRange * colorRange * 4);
    float rectSize = static_cast<float>(windowSize) / colorRange;

    // 提前填充所有顶点数据,仅初始化一次
    for (int i = 0; i < colorRange; ++i)
    {
        for (int j = 0; j < colorRange; ++j)
        {
            float x = i * rectSize;
            float y = j * rectSize;
            sf::Color color(i, j, 127, 255);

            // 为当前色块的四个顶点赋值
            int index = (i * colorRange + j) * 4;
            palette[index] = sf::Vertex(sf::Vector2f(x, y), color);
            palette[index + 1] = sf::Vertex(sf::Vector2f(x + rectSize, y), color);
            palette[index + 2] = sf::Vertex(sf::Vector2f(x + rectSize, y + rectSize), color);
            palette[index + 3] = sf::Vertex(sf::Vector2f(x, y + rectSize), color);
        }
    }

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            else if (event.type == sf::Event::Resized)
            {
                mainView.setSize(static_cast<float>(event.size.width), static_cast<float>(event.size.height));
                mainView.setCenter(static_cast<float>(event.size.width)/2, static_cast<float>(event.size.height)/2);
                window.setView(mainView);
            }
        }

        window.clear(sf::Color::White);
        window.draw(palette); // 一次调用完成所有色块绘制
        window.display();
    }

    return 0;
}

核心优化点

  • 顶点数组仅初始化一次,避免循环内重复创建图形对象
  • 单次draw()调用完成全部渲染,减少渲染管线开销
  • 色块尺寸随窗口自动计算,适配窗口缩放

二、实现圆形RGB调色板

圆形调色板通常对应HSL色彩空间:角度对应色相(H)、半径对应饱和度(S),再将HSL转为RGB颜色。以下用顶点数组实现高效的圆形调色板:

#include <SFML/Graphics.hpp>
#include <cmath>

// HSL转RGB颜色函数
sf::Color hslToRgb(float h, float s, float l)
{
    h = fmod(h, 360.0f);
    if (h < 0) h += 360.0f;

    float c = (1.0f - fabs(2*l - 1)) * s;
    float x = c * (1.0f - fabs(fmod(h/60.0f, 2) - 1));
    float m = l - c/2;

    float r, g, b;
    if (h < 60)      { r = c; g = x; b = 0; }
    else if (h < 120){ r = x; g = c; b = 0; }
    else if (h < 180){ r = 0; g = c; b = x; }
    else if (h < 240){ r = 0; g = x; b = c; }
    else if (h < 300){ r = x; g = 0; b = c; }
    else             { r = c; g = 0; b = x; }

    return sf::Color(
        static_cast<sf::Uint8>((r + m)*255),
        static_cast<sf::Uint8>((g + m)*255),
        static_cast<sf::Uint8>((b + m)*255)
    );
}

int main()
{
    const int windowSize = 450;
    sf::RenderWindow window(sf::VideoMode(windowSize, windowSize), "Circular RGB Palette", sf::Style::Close | sf::Style::Resize);
    sf::View mainView = window.getDefaultView();

    // 圆形参数:中心坐标、半径
    sf::Vector2f center(windowSize/2.0f, windowSize/2.0f);
    float radius = windowSize/2.0f - 10; // 预留10px边距
    const int segments = 360; // 角度分段数(控制圆周精细度)
    const int radiusSteps = 255; // 半径方向分段数(控制径向精细度)

    // 创建顶点数组,每个环形分段用四边形绘制
    sf::VertexArray circularPalette(sf::Quads, segments * radiusSteps * 4);

    float angleStep = 2 * M_PI / segments;
    float radiusStep = radius / radiusSteps;

    // 提前填充所有顶点数据
    for (int r = 0; r < radiusSteps; ++r)
    {
        float innerRadius = r * radiusStep;
        float outerRadius = (r + 1) * radiusStep;

        for (int a = 0; a < segments; ++a)
        {
            float angle = a * angleStep;
            float nextAngle = (a + 1) * angleStep;

            // 计算当前环形分段的四个顶点坐标
            sf::Vector2f p1(center.x + innerRadius * cos(angle), center.y + innerRadius * sin(angle));
            sf::Vector2f p2(center.x + outerRadius * cos(angle), center.y + outerRadius * sin(angle));
            sf::Vector2f p3(center.x + outerRadius * cos(nextAngle), center.y + outerRadius * sin(nextAngle));
            sf::Vector2f p4(center.x + innerRadius * cos(nextAngle), center.y + innerRadius * sin(nextAngle));

            // 颜色映射:角度对应色相,半径对应饱和度,亮度固定为0.5
            float hue = angle * 180 / M_PI; // 弧度转0-360度色相
            float saturation = innerRadius / radius; // 0-1范围饱和度
            sf::Color color = hslToRgb(hue, saturation, 0.5f);

            // 为顶点数组赋值
            int index = (r * segments + a) * 4;
            circularPalette[index] = sf::Vertex(p1, color);
            circularPalette[index + 1] = sf::Vertex(p2, color);
            circularPalette[index + 2] = sf::Vertex(p3, color);
            circularPalette[index + 3] = sf::Vertex(p4, color);
        }
    }

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            else if (event.type == sf::Event::Resized)
            {
                mainView.setSize(static_cast<float>(event.size.width), static_cast<float>(event.size.height));
                mainView.setCenter(static_cast<float>(event.size.width)/2, static_cast<float>(event.size.height)/2);
                window.setView(mainView);
            }
        }

        window.clear(sf::Color::White);
        window.draw(circularPalette);
        window.display();
    }

    return 0;
}

实现说明

  • 通过极坐标映射HSL色彩空间,实现符合视觉习惯的圆形调色板
  • 顶点数组一次性渲染所有环形分段,性能远高于绘制大量小图形
  • 可调整segments和radiusSteps参数,平衡调色板精细度与性能

内容的提问来源于stack exchange,提问作者Thanos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:15:55