Saya memutuskan untuk menulis sedikit tentang aspek pemrograman dan bagaimana komponen saling berbicara. Mungkin itu akan menjelaskan beberapa area tertentu.
Presentasi
Apa yang diperlukan bahkan untuk memiliki satu gambar itu, yang Anda poskan di pertanyaan Anda, digambar di layar?
Ada banyak cara untuk menggambar segitiga di layar. Untuk mempermudah, mari kita asumsikan tidak ada buffer vertex yang digunakan. (A buffer vertex adalah area memori di mana Anda menyimpan koordinat.) Mari kita asumsikan program hanya memberi tahu pipa pemrosesan grafis tentang setiap vertex tunggal (sebuah vertex hanya koordinat dalam ruang) dalam satu baris.
Tapi , sebelum kita bisa menggambar apa pun, pertama-tama kita harus menjalankan beberapa perancah. Kita akan lihat alasannya nanti:
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Red
glColor3f(1.0f,0.0f,0.0f);
// Top Of Triangle (Front)
glVertex3f( 0.0f, 1.0f, 0.0f);
// Green
glColor3f(0.0f,1.0f,0.0f);
// Left Of Triangle (Front)
glVertex3f(-1.0f,-1.0f, 1.0f);
// Blue
glColor3f(0.0f,0.0f,1.0f);
// Right Of Triangle (Front)
glVertex3f( 1.0f,-1.0f, 1.0f);
// Done Drawing
glEnd();
Jadi apa yang dilakukannya?
Saat Anda menulis sebuah program yang ingin menggunakan kartu grafis, biasanya Anda akan memilih semacam antarmuka untuk driver. Beberapa antarmuka yang terkenal untuk driver adalah:
Untuk contoh ini kita akan tetap menggunakan OpenGL. Sekarang, antarmuka Anda ke driver adalah apa yang memberi Anda semua alat yang Anda butuhkan untuk membuat program Anda berbicara dengan kartu grafis (atau driver, yang kemudian berbicara ke kartu).
Antarmuka ini terikat untuk memberi Anda alat tertentu . Alat-alat ini berbentuk API yang dapat Anda hubungi dari program Anda.
API itulah yang kami lihat digunakan dalam contoh di atas. Mari kita lihat lebih dekat.
Perancah
Sebelum Anda benar-benar dapat melakukan gambar yang sebenarnya, Anda harus melakukan pengaturan . Anda harus menentukan viewport Anda (area yang benar-benar akan ditampilkan), perspektif Anda ( kamera ke dunia Anda), apa anti-aliasing yang akan Anda gunakan (untuk menghaluskan tepi segitiga Anda) ...
Tapi kita tidak akan melihat itu. Kami hanya akan mengintip hal-hal yang harus Anda lakukan setiap frame . Suka:
Menghapus layar
Pipa grafis tidak akan menghapus layar untuk Anda setiap frame. Anda harus mengatakannya. Mengapa? Ini sebabnya:
Jika Anda tidak menghapus layar, Anda hanya akan menggambar setiap frame. Itu sebabnya kami memanggil glClear
dengan GL_COLOR_BUFFER_BIT
set. Bit lainnya ( GL_DEPTH_BUFFER_BIT
) memberitahu OpenGL untuk menghapus buffer kedalaman . Buffer ini digunakan untuk menentukan piksel mana yang berada di depan (atau di belakang) piksel lainnya.
Transformasi
Sumber gambar
Transformasi adalah bagian di mana kita mengambil semua koordinat input (simpul segitiga kami) dan menerapkan matriks ModelView kami. Ini adalah matriks yang menjelaskan bagaimana model kami (simpul) diputar, diskalakan, dan diterjemahkan (dipindahkan).
Selanjutnya, kami menerapkan matriks Proyeksi kami. Ini memindahkan semua koordinat sehingga mereka menghadap kamera kami dengan benar.
Sekarang kita mengubah sekali lagi, dengan matriks Viewport kami. Kami melakukan ini untuk menskalakan model kami dengan ukuran monitor kami. Sekarang kita memiliki seperangkat simpul yang siap untuk dirender!
Kami akan kembali ke transformasi sedikit kemudian.
Gambar
Untuk menggambar sebuah segitiga, kita hanya bisa mengatakan OpenGL untuk memulai baru daftar segitiga dengan memanggil glBegin
dengan GL_TRIANGLES
konstan.
Ada juga formulir lain yang bisa Anda gambar. Seperti strip segitiga atau kipas segitiga . Ini terutama adalah optimasi, karena mereka membutuhkan lebih sedikit komunikasi antara CPU dan GPU untuk menggambar jumlah segitiga yang sama.
Setelah itu, kami dapat menyediakan daftar set 3 simpul yang harus membentuk setiap segitiga. Setiap segitiga menggunakan 3 koordinat (karena kita berada dalam ruang 3D). Selain itu, saya juga memberikan warna untuk setiap titik, dengan menelepon glColor3f
sebelum memanggil glVertex3f
.
Bayangan antara 3 simpul (3 sudut segitiga) dihitung oleh OpenGL secara otomatis . Ini akan menginterpolasi warna di seluruh wajah poligon.
Interaksi
Sekarang, ketika Anda mengklik jendela. Aplikasi hanya perlu menangkap pesan jendela yang menandakan klik. Kemudian Anda dapat menjalankan tindakan apa pun di program yang Anda inginkan.
Ini menjadi jauh lebih sulit setelah Anda ingin mulai berinteraksi dengan adegan 3D Anda.
Pertama-tama Anda harus mengetahui dengan jelas piksel mana yang diklik pengguna. Kemudian, dengan mempertimbangkan perspektif Anda, Anda dapat menghitung arah sinar, dari titik klik mouse ke adegan Anda. Anda kemudian dapat menghitung jika ada objek di adegan Anda bersinggungan dengan sinar itu . Sekarang Anda tahu jika pengguna mengklik suatu objek.
Jadi, bagaimana Anda membuatnya berputar?
Transformasi
Saya mengetahui dua jenis transformasi yang umumnya diterapkan:
- Transformasi berbasis matriks
- Transformasi berbasis tulang
Perbedaannya adalah bahwa tulang memengaruhi simpul tunggal . Matriks selalu mempengaruhi semua simpul yang ditarik dengan cara yang sama. Mari kita lihat sebuah contoh.
Contoh
Sebelumnya, kami memuat matriks identitas kami sebelum menggambar segitiga kami. Matriks identitas adalah matriks yang sama sekali tidak menyediakan transformasi sama sekali. Jadi, apa pun yang saya gambar, hanya dipengaruhi oleh perspektif saya. Jadi, segitiga tidak akan diputar sama sekali.
Jika saya ingin memutarnya sekarang, saya bisa melakukan matematika sendiri (pada CPU) dan cukup menelepon glVertex3f
dengan koordinat lain (yang diputar). Atau saya bisa membiarkan GPU melakukan semua pekerjaan, dengan menelepon glRotatef
sebelum menggambar:
// Rotate The Triangle On The Y axis
glRotatef(amount,0.0f,1.0f,0.0f);
amount
tentu saja hanyalah nilai tetap. Jika Anda ingin menghidupkan , Anda harus melacak amount
dan meningkatkannya setiap frame.
Jadi, tunggu, apa yang terjadi pada semua pembicaraan matriks sebelumnya?
Dalam contoh sederhana ini, kita tidak perlu peduli dengan matriks. Kami cukup menelepon glRotatef
dan mengurus semua itu untuk kami.
glRotate
menghasilkan rotasi angle
derajat di sekitar vektor xyz. Matriks saat ini (lihat glMatrixMode ) dikalikan dengan matriks rotasi dengan produk yang menggantikan matriks saat ini, seolah-olah glMultMatrix dipanggil dengan matriks berikut sebagai argumennya:
x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1 1
Terima kasih untuk itu!
Kesimpulan
Yang menjadi jelas adalah, ada banyak pembicaraan dengan OpenGL. Tapi itu tidak memberi tahu kita apa-apa. Di mana komunikasinya?
Satu-satunya hal yang dikatakan OpenGL dalam contoh ini adalah ketika selesai . Setiap operasi akan memakan waktu tertentu. Beberapa operasi memakan waktu sangat lama, yang lain sangat cepat.
Mengirim simpul ke GPU akan sangat cepat, saya bahkan tidak tahu bagaimana mengekspresikannya. Mengirim ribuan simpul dari CPU ke GPU, setiap frame tunggal, kemungkinan besar, tidak ada masalah sama sekali.
Membersihkan layar bisa memakan waktu milidetik atau lebih buruk (perlu diingat, Anda biasanya hanya memiliki waktu sekitar 16 milidetik untuk menggambar setiap frame), tergantung pada seberapa besar viewport Anda. Untuk menghapusnya, OpenGL harus menggambar setiap piksel dalam warna yang ingin Anda hapus, yang bisa jutaan piksel.
Selain itu, kami hanya dapat menanyakan OpenGL tentang kemampuan adaptor grafis kami (resolusi maks, anti-aliasing maks, kedalaman warna maks, ...).
Tetapi kita juga dapat mengisi tekstur dengan piksel yang masing-masing memiliki warna tertentu. Setiap piksel memiliki nilai dan teksturnya adalah "file" raksasa yang diisi dengan data. Kita dapat memuatnya ke kartu grafis (dengan membuat buffer tekstur), kemudian memuat shader , memberi tahu shader itu untuk menggunakan tekstur kita sebagai input dan menjalankan beberapa perhitungan yang sangat berat pada "file" kita.
Kami kemudian dapat "membuat" hasil perhitungan kami (dalam bentuk warna baru) ke dalam tekstur baru.
Itulah cara Anda membuat GPU berfungsi untuk Anda dengan cara lain. Saya menganggap CUDA melakukan hal yang mirip dengan aspek itu, tetapi saya tidak pernah memiliki kesempatan untuk bekerja dengannya.
Kami benar-benar hanya sedikit menyentuh keseluruhan subjek. Pemrograman grafis 3D adalah binatang buas.
Sumber Gambar