Bagaimana SFML begitu cepat?
Saya perlu menggambar beberapa grafik dalam c ++, piksel demi piksel di jendela. Untuk melakukan ini saya membuat jendela SFML, sprite dan tekstur. Saya menggambar grafik yang saya inginkan ke array uint8_t dan kemudian memperbarui tekstur dan sprite dengannya. Proses ini memakan waktu sekitar 2.500 kami . Menggambar dua segitiga yang memenuhi seluruh jendela hanya membutuhkan 10 kali us . Bagaimana perbedaan besar ini mungkin? Saya sudah mencoba multithreading pada gambar piksel demi piksel, tetapi perbedaan dua lipatnya tetap ada. Saya juga mencoba menggambar piksel menggunakan peta titik, tanpa peningkatan. Saya memahami bahwa SFML menggunakan beberapa akselerasi GPU di latar belakang, tetapi hanya mengulang dan menetapkan nilai ke array piksel sudah membutuhkan ratusan mikrodetik.
Adakah yang tahu cara yang lebih efektif untuk menetapkan nilai piksel di jendela?
Berikut adalah contoh kode yang saya gunakan untuk membandingkan kecepatan gambar segitiga dan piksel demi piksel:
#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,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;
}
Jawaban
Gambar grafik di perangkat modern menggunakan kartu Grafik, dan kecepatan menggambar tergantung pada berapa banyak segitiga dalam data yang Anda kirim ke memori Grafik. Itulah mengapa menggambar dua segitiga dengan cepat.
Seperti yang Anda sebutkan tentang multithreading, jika Anda menggunakan OpenGL (saya tidak ingat apa yang digunakan SFML, tetapi seharusnya sama), apa yang Anda pikir sedang Anda gambar pada dasarnya adalah mengirim perintah dan data ke kartu grafis, jadi multithreading di sini tidak terlalu berguna. , kartu grafis memiliki utasnya sendiri untuk melakukan ini.
Jika Anda ingin tahu tentang karya kartu bagaimana grafis, ini tutorial adalah yang buku yang Anda harus membaca.
PS Saat Anda mengedit pertanyaan Anda, saya kira durasi 2500us vs 10us adalah karena Anda untuk loop membuat tekstur (bahkan jika teksturnya adalah latar belakang putih bersih) (dan loop for, Anda mungkin perlu mulai menghitung setelah loop for) , dan mengirim tekstur ke kartu grafis membutuhkan waktu, sedangkan menggambar segitiga hanya mengirimkan beberapa poin. Namun, saya menyarankan untuk membaca tutorialnya, membuat tekstur piksel demi piksel berpotensi membuktikan pemahaman yang hilang tentang cara kerja GPU.