如何为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
相关产品推荐
相关产品推荐

