Saya mulai menonton aliran Handmade Hero , di mana Casey Muratori menciptakan mesin permainan tanpa menggunakan kerangka atau semacamnya. Kemarin saya sampai pada bagian di mana dia menunjukkan bagaimana gambar digambar ke layar. Sejauh yang saya mengerti dia hanya mengalokasikan beberapa memori sebesar ukuran layar yang ingin dia gambar. Dan kemudian dia menciptakan bitmap yang dia berikan ke memori buffer yang dia alokasikan dan menggambarnya ke layar menggunakan fungsi spesifik os.
Ini tampaknya cukup lurus ke depan. Saya menggunakan GameMaker, berubah menjadi Love2D, bekerja sedikit dengan Sprite Kit tetapi saya selalu bertanya-tanya apa yang sebenarnya terjadi di bawah lapisan yang terkadang membingungkan ini.
Mengingat itu, mengapa repot-repot menggunakan pustaka grafis (OpenGL, SFML, SDL, ...) ketika semua yang harus Anda lakukan hanyalah mengalokasikan beberapa buffer, meneruskan bitmap dan menggambarnya ke layar?
Jika Anda kemudian ingin menggambar hal-hal yang berbeda untuk layar Anda, Anda hanya menulis mereka ke bitmap Anda yang kemudian diteruskan ke buffer. Saya cukup baru dalam pemrograman, tetapi ini tampaknya cukup sederhana bagi saya. Harap perbaiki saya jika saya salah.
sumber
Jawaban:
Ini bukan hanya tentang kecepatan eksekusi, tetapi juga tentang kesederhanaan. Meskipun rendering perangkat lunak yang digunakan dalam contoh ini akan jauh lebih lambat daripada menggunakan akselerasi perangkat keras (yaitu GPU), menggambar beberapa bitmap di layar adalah tugas yang sepele sehingga Anda tidak akan melihat penurunan kinerja.
Namun, aktivitas tingkat rendah seperti rasterisasi segitiga, pengurutan dalam dan sejenisnya adalah konsep yang dipahami dengan baik bahwa GPU dapat menangani secara implisit dengan beberapa perintah. Menerapkan kembali mereka dalam mode perangkat lunak pada dasarnya menciptakan kembali roda. Ini bagus jika Anda ingin mendapatkan pemahaman tingkat rendah tentang bagaimana rendering dilakukan, saya sendiri menulis renderer perangkat lunak 3D hanya untuk menjelajahinya sedikit, tetapi untuk sebagian besar keadaan itu membuang-buang waktu ketika OpenGL dapat melakukannya lebih cepat dari kotak.
Contoh yang Anda berikan terdengar sangat mendasar, hanya menggambar satu gambar di layar, maka implementasinya mudah. Namun, begitu Anda mulai melapisi kerumitan, Anda akan merasa semakin rumit untuk mendapatkan semua yang dirender dengan benar. Hal-hal yang harus dilakukan orang-orang di masa Gempa rendering perangkat lunak 3D adalah gila, meskipun saya menghargai Anda tidak akan sejauh itu (belum).
sumber
Pendek: Karena cepat (OpenGL, DirectX).
Panjang:
Anda mungkin berpikir Anda bisa melakukan ini sendiri. Gambar piksel ke layar. Anda dapat menulis perpustakaan kecil untuk menggambar bentuk, seperti paha depan atau segitiga. Ini akan berhasil, tentu saja. Ada banyak perpustakaan di luar sana untuk melakukan hal ini. Beberapa dari mereka bahkan mengimplementasikan OpenGL-spec (sehingga mereka seperti sisi perangkat lunak untuk OpenGL) yang akan melakukan persis seperti yang dilakukan Casey Muratori. Mereka menghitung semuanya pada sisi perangkat lunak, mengatur piksel pada sisi perangkat lunak dan menuliskan hasilnya ke layar.
Namun ini lambat . CPU yang pada akhirnya akan menjalankan semua hal ini tidak dibuat untuk skenario ini. Untuk itulah GPU digunakan. Apa yang dilakukan OpenGL (kecuali tentu saja itu adalah implementasi perangkat lunak) adalah mengambil semua yang Anda suruh untuk dilakukan dan mendorong semua data, semua panggilan-draw, hampir semuanya ke kartu grafis dan memberitahu GPU untuk melakukan pekerjaan. GPU dibuat khusus untuk jenis pekerjaan ini. Mengalikan angka floating point (thats apa yang Anda lakukan banyak ketika menggambar 3D-adegan) dan mengeksekusi shader. Dan ini secara paralel. Hanya untuk membuat Anda merasakan seberapa cepat GPU, pikirkan tentang adegan sederhana dalam 3D dalam layar penuh dengan 1920x1080 piksel. Ini adalah, dikalikan, 2.073.600 piksel untuk menggambar. Untuk setiap orangpixel, GPU akan menjalankan fragmen-shader setidaknya sekali , sebagian besar kali lebih dari sekali. Sekarang, katakanlah kita menjalankan 60 frame per detik. Ini berarti, GPU menjalankan fragmen-shader 2.073.600 * 60 = 124.416.000 kali per detik . Apakah Anda pikir Anda dapat melakukan hal seperti ini pada CPU Anda? (Itu penjelasan yang cukup disederhanakan, ada banyak hal yang perlu dipertimbangkan seperti berapa banyak piksel yang Anda overdraw oleh benda yang lebih dekat, berapa banyak MSAA yang Anda gunakan dan sebagainya, namun 124.416.000 kali per detik mungkin adalah yang terendah yang bisa Anda dapatkan, dan Anda Akan dengan mudah memiliki lebih dari 60fps dengan adegan sederhana)
Itulah yang dilakukan OpenGL dan Direct3D, untuk mesin apa yang melihat @Uri Popovs menjawab.
sumber
Apa yang dia lakukan disebut rendering perangkat lunak , yang dilakukan OpenGL disebut rendering GPU
Apa perbedaan di antara mereka? Kecepatan dan memori.
Rasterisasi (mengisi segitiga di layar) membutuhkan waktu. Jika Anda melakukannya pada CPU, Anda pada dasarnya mengambil waktu itu dari logika permainan, terutama jika itu tidak dioptimalkan dengan baik.
Dan tidak masalah, seberapa kecil gambarnya, ia perlu mengalokasikan sejumlah memori untuk itu. GPU memiliki memori video untuk ini.
sumber
Sementara jawaban dari orang lain lebih benar daripada jawaban yang bisa saya berikan, saya ingin menunjukkan kesalahpahaman mendasar tentang bagaimana pengembangan perangkat lunak bekerja yang menurut saya mendasari pertanyaan Anda. Meskipun selalu mungkin untuk melakukan hal-hal "sendiri" tanpa kerangka kerja, dan seringkali ada manfaat pendidikan yang besar dari melakukannya, kenyataannya adalah bukan bagaimana perangkat lunak modern dibuat.
Seseorang menciptakan perangkat keras dan bahasa mesin yang berjalan di atasnya. Orang lain membuat bahasa dan kompiler tingkat tinggi, driver dan sistem operasi, perpustakaan grafik dan seterusnya. Kita masing-masing membangun atas karya para pendahulu kita. Itu bukan hanya "oke", itu suatu keharusan.
Anda menarik garis dari apa yang "dapat diterima" atau tidak pada titik sembarang dalam rantai alat. Anda bisa dengan mudah mengatakan "mengapa menggunakan C ++ ketika Anda bisa melakukan hal yang sama dalam perakitan?", Atau "mengapa mengandalkan driver keyboard ketika Anda bisa dengan mudah membaca voltase yang keluar dari kabelnya dan menghitungnya sendiri?" Tidak ada cukup jam dalam sehari, atau bertahun-tahun seumur hidup bagi setiap orang untuk melakukan semuanya sendiri.
Ini tidak hanya berlaku untuk pengembangan perangkat lunak, tetapi untuk kehidupan modern secara umum. Pernahkah Anda mendengar tentang pria yang membuat pemanggang roti sendiri, dari nol? http://www.thomasthwaites.com/the-toaster-project/ . Butuh waktu yang sangat lama dan banyak usaha. Untuk pemanggang roti. Cobalah membangun semua yang diperlukan untuk mengaktualisasikan gim video dari eter semuanya sendirian!
sumber
Mesin melakukan lebih banyak hal yang hanya menggambar di layar. Mereka menangani pencahayaan, bayangan, input, deteksi tabrakan. Bahkan hanya bagian rendering jauh lebih kompleks daripada hanya mendorong buffer ke layar. Untuk adegan 3d khususnya Anda perlu melakukan banyak perhitungan pada data yang jauh lebih kompleks daripada bitmap. Biarkan saya memberi Anda analogi dengan mobil: Apa yang Anda gambarkan sebagai sederhana adalah knalpot mobil. Anda cukup membuat pipa dengan ukuran yang tepat dan kemudian Anda mendorong gas dari satu ujung ke ujung lainnya. Namun ini jauh dari satu-satunya hal yang terjadi dalam mekanisme mobil.
sumber
Jawaban di atas sangat baik, tetapi tidak ada yang benar-benar melampaui alasan paling penting mengapa OpenGL dan yang lebih disukai. Alasan utama adalah untuk menggunakan perangkat keras khusus yang dirancang khusus untuk bekerja dengan hal-hal seperti rendering jutaan piksel pada layar, GPU .
Dengan perenderan perangkat lunak, menggunakan CPU, renderer akan melakukan perulangan, satu per satu, pada semua piksel pada bitmap dan mengeluarkan perintah untuk menampilkan masing-masing di layar. Jadi, jika Anda merender gambar berukuran 1000x1000, 1.000.000 loop untuk CPU Anda akan berakhir. Mereka dirancang dengan kontrol dalam pikiran; banyak kondisi jika, melompat dari satu set instruksi ke yang lain dan arah aliran kontrol yang ketat. Namun, sebuah GPU dirancang dengan pengetahuan bahwa ia akan melakukan banyak perulangan piksel serupa pada layar.GPU akan mengambil loop for dengan iterasi 1000000 dan membagi pekerjaan lebih dari jumlah inti untuk masing-masing untuk bekerja ** secara paralel, dan independen satu sama lain **. Jadi tidak seperti CPU, setiap kali GPU menemukan kondisi if-else, ia akan menangani kedua cabang kode untuk dua inti dari dirinya sendiri DAN LALU, pada akhirnya, itu akan melihat apa yang dievaluasi kondisi dan membuang hasil dari cabang yang tidak dibutuhkan (itu sebabnya banyak kondisi if-else di GPU shaders tidak disukai; mereka selalu bertanggung jawab atas pemborosan).
Jadi ya, GPU dibangun berdasarkan paralelisme . Itu membuat bekerja pada piksel untuk mereka jauh lebih cepat dibandingkan dengan CPU.
sumber
Lihat Apakah saya benar-benar perlu menggunakan API grafik?
Tentu, Anda dapat meminta buffer, mengatur beberapa bit di dalamnya dan menuliskannya ke layar. Itu pada dasarnya satu-satunya cara untuk melakukan pemrograman grafis pada PC sampai ketersediaan akselerator grafis pada pertengahan 90-an dari 3DFX. Bahkan di Windows, DirectX dikembangkan untuk memberikan akses langsung ke memori video.
Tetapi pada perangkat keras non-PC, mesin permainan khusus, selalu ada teknik untuk mempercepat grafik dengan melepas pekerjaan dari prosesor. Bahkan Atari 2600 memiliki "sprite perangkat keras", sebagian karena tidak memiliki cukup RAM untuk framebuffer.
Kemudian (pertengahan 80-an) konsol game dioptimalkan untuk game platform. Sekali lagi, tidak ada framebuffer; alih-alih, pemrogram dapat menentukan kisi-kisi ubin :
sumber
CPU modern cukup cepat untuk melakukan permainan 2d apa pun dalam perangkat lunak, jadi untuk grafis 2d, OpenGL / DirectX tidak akan menawarkan keuntungan, di samping menambahkan ketergantungan lain dan lapisan kerumitan pada proyek Anda, seperti mengatur matriks proyeksi 3d untuk menarik banyak sprite dan mengunggah data ke GPU.
OpenGL juga akan memaksa Anda untuk mengemas semua sprite Anda di dalam tekstur 512x512 (sebuah artefak dari konsol lama, seperti PSX, mengemas grafik ke dalam halaman memori video), mengharuskan Anda untuk menulis kode pengemasan sprite yang agak rumit.
Di sisi lain, jika Anda melakukan 3d, merender jutaan segitiga dengan bayangan yang kompleks, maka GPU tidak dapat dihindari. Dahulu ada versi Direct3d 2d yang lebih sederhana, yang disebut DirectDraw, yang GPU mempercepat gambar sprite, tetapi sekarang Microsoft tidak lagi mendukungnya, mungkin karena CPU cukup cepat untuk melakukan 2d tanpa akselerasi, jika Anda tidak peduli dengan penghematan energi .
sumber