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

如何为sf::TriangleStrip类型的sf::VertexArray填充纯色?

问题:使用SFML的VertexArray绘制圆形无法填充颜色

为提升绘制数千个圆形的性能,我尝试使用单个sf::VertexArray实现,并编写了如下示例代码:

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

#define WIDTH 100
#define HEIGHT 100

int main() {
    sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "RTREE",
                            sf::Style::Close);
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) window.close();
        }

        sf::CircleShape circle(50);
        circle.setPosition(100,100);
        size_t count = circle.getPointCount();
        sf::VertexArray objects(sf::TriangleStrip, count);
        for (int i = 0; i < count; i++) {
           objects.append(circle.getPoint(i));

        }
        for (int i = 0; i < objects.getVertexCount(); i++) {
            objects[i].color = sf::Color::Blue;
        }

        window.clear();
        window.draw(objects);
        window.display();
    }
}

但设置的color仅作用于线条,无法填充图形。请问是否可以为该图形填充单一颜色?


解决方案

问题原因

你当前的代码存在两个核心问题:

  • 仅提取了圆形的轮廓顶点,没有包含填充所需的中心顶点;
  • 使用了sf::TriangleStrip类型的VertexArray,这种拓扑结构只能绘制连续线条,无法形成闭合的填充面。

SFML的sf::CircleShape内部是通过**三角形扇(TriangleFan)**实现填充的:顶点数组第一个元素是圆心,后续是轮廓上的点,通过这种结构可以自动填充整个圆形区域。

修正方案

方案1:直接复用CircleShape的顶点数据(最简单高效)

CircleShape内部已经构建好了用于填充的顶点数组,直接调用getVertexArray()即可获取,无需手动构建:

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

#define WIDTH 300
#define HEIGHT 300

int main() {
    sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "RTREE", sf::Style::Close);
    
    // 提前创建圆形,避免循环内重复初始化(提升性能)
    sf::CircleShape circle(50);
    circle.setPosition(100, 100);
    circle.setFillColor(sf::Color::Blue); // 直接设置填充色

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) window.close();
        }

        // 获取CircleShape内部的填充顶点数组
        const sf::VertexArray& vertexArray = circle.getVertexArray();

        window.clear();
        window.draw(vertexArray);
        window.display();
    }
}

方案2:手动构建TriangleFan类型的VertexArray(适合自定义场景)

如果需要完全手动控制顶点数据,可以构建包含圆心的TriangleFan:

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

#define WIDTH 300
#define HEIGHT 300

int main() {
    sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "RTREE", sf::Style::Close);
    
    const float radius = 50;
    const sf::Vector2f center(100 + radius, 100 + radius); // 圆形中心(位置+半径)
    const size_t pointCount = 30; // 圆形精度,值越大越平滑

    // 创建TriangleFan类型的VertexArray,包含1个圆心+pointCount个轮廓点
    sf::VertexArray objects(sf::TriangleFan, pointCount + 1);
    
    // 设置圆心顶点
    objects[0].position = center;
    objects[0].color = sf::Color::Blue;

    // 生成轮廓顶点
    for (size_t i = 0; i < pointCount; ++i) {
        const float angle = 2 * M_PI * i / pointCount;
        const float x = center.x + radius * cos(angle);
        const float y = center.y + radius * sin(angle);
        objects[i + 1].position = sf::Vector2f(x, y);
        objects[i + 1].color = sf::Color::Blue;
    }

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) window.close();
        }

        window.clear();
        window.draw(objects);
        window.display();
    }
}

性能优化提示

  • 避免在渲染循环内重复创建sf::CircleShape或sf::VertexArray,提前初始化后循环内仅更新必要参数(如位置、颜色);
  • 绘制大量圆形时,将所有圆形的顶点数据合并到同一个sf::VertexArray中,一次性提交绘制,这是GPU批量绘制的最优方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:55:28