问题描述
我需要用c ++在窗口上逐像素绘制一些图形。为了做到这一点,我创建了一个SFML窗口,精灵和纹理。我将所需的图形绘制到uint8_t数组,然后使用其更新纹理和精灵。此过程大约需要 2500美元。绘制两个三角形填充整个窗口仅需 10 us 。这种巨大的差异怎么可能?我已经尝试了逐像素绘制多线程,但是仍然存在两个数量级的差异。我也尝试使用点图绘制像素,但没有任何改进。我知道SFML在后台使用了一些GPU加速功能,但是简单地循环并将这些值分配给像素数组已经花费了数百微秒。
有人知道一种更有效的方法来分配窗口中的像素值吗?
这是我用来比较三角形和逐像素绘制速度的代码示例:
#include <SFML/Graphics.hpp>
#include <chrono>
using namespace std::chrono;
#include <iostream>
#include<cmath>
uint8_t* pixels;
int main(int,char const**)
{
const unsigned int width=1200;
const unsigned int height=1200;
sf::RenderWindow window(sf::VideoMode(width,height),"MA: Rasterization Test");
pixels = new uint8_t[width*height*4];
sf::Texture pixels_texture;
pixels_texture.create(width,height);
sf::Sprite pixels_sprite(pixels_texture);
sf::Clock clock;
sf::VertexArray triangle(sf::Triangles,3);
triangle[0].position = sf::Vector2f(0,height);
triangle[1].position = sf::Vector2f(width,height);
triangle[2].position = sf::Vector2f(width/2,height-std::sqrt(std::pow(width,2)-std::pow(width/2,2)));
triangle[0].color = sf::Color::Red;
triangle[1].color = sf::Color::Blue;
triangle[2].color = sf::Color::Green;
while (window.isopen()){
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::Keypressed && event.key.code == sf::Keyboard::Escape) {
window.close();
}
}
window.clear(sf::Color(255,255,255));
// Pixel-by-pixel
int us = duration_cast< microseconds >(system_clock::Now().time_since_epoch()).count();
for(int i=0;i!=width*height*4;++i){
pixels[i]=255;
}
pixels_texture.update(pixels);
window.draw(pixels_sprite);
int duration=duration_cast< microseconds >(system_clock::Now().time_since_epoch()).count()-us;
std::cout<<"Background: "<<duration<<" us\n";
// Triangle
us = duration_cast< microseconds >(system_clock::Now().time_since_epoch()).count();
window.draw(triangle);
duration=duration_cast< microseconds >(system_clock::Now().time_since_epoch()).count()-us;
std::cout<<"Triangle: "<<duration<<" us\n";
window.display();
}
return EXIT_SUCCESS;
}
解决方法
使用图形卡在现代设备中绘制图形,绘制速度取决于发送到图形内存的数据中有多少个三角形。这就是为什么只绘制两个三角形会很快的原因。
正如您提到的多线程,如果您使用的是OpenGL(我不记得SFML的用途,但应该相同),您认为绘制的内容基本上是将命令和数据发送到图形卡,因此这里的多线程是不太有用,图形卡具有自己的线程来执行此操作。
如果您对图形卡的工作方式感到好奇,this教程是 你应该读的书。
P.S。当您编辑问题时,我认为持续时间2500us vs 10us是因为for循环创建了一个纹理(即使该纹理是纯白色背景)(而for循环,您可能需要在for循环之后开始计数),并将纹理发送到图形卡需要时间,而绘制三角形仅发送几个点。尽管如此,我还是建议阅读该教程,逐个像素地创建一个纹理,这有可能证明人们对GPU的工作原理缺乏了解。