
Semua suasana hati yang baik dan suhu yang lebih rendah di luar jendela. Seperti yang dijanjikan, saya menerbitkan kelanjutan artikel tentang super-duper OpenGL modern. Siapa yang belum membaca bagian pertama -
Ultramodern OpenGL. Bagian 1Mungkin Anda beruntung dan saya bisa memasukkan semua bahan yang tersisa ke dalam artikel ini, ini tidak pasti ...
Tekstur array
Array tekstur ditambahkan kembali di OpenGL 3.0, tetapi untuk beberapa alasan beberapa orang menulis tentang mereka (informasi disembunyikan oleh Freemason). Anda semua sudah terbiasa dengan pemrograman dan tahu apa itu
array , meskipun saya lebih baik "pendekatan" dari sisi lain.
Untuk mengurangi jumlah peralihan di antara tekstur, dan sebagai hasilnya, untuk mengurangi operasi peralihan keadaan, orang menggunakan
atlas tekstur (tekstur yang menyimpan data untuk beberapa objek). Tapi orang-orang pintar dari Khronos telah mengembangkan alternatif bagi kita - Tekstur array. Sekarang kita dapat menyimpan tekstur sebagai lapisan dalam array ini, yaitu, itu adalah alternatif untuk atlas. Wiki OpenGL memiliki deskripsi yang sedikit berbeda tentang mipmaps, dll, tetapi tampaknya terlalu rumit bagi saya (
tautan ).
Keuntungan menggunakan pendekatan ini dibandingkan dengan atlas adalah bahwa setiap lapisan dianggap sebagai tekstur terpisah dalam hal pembungkus dan pemetaan.
Tetapi kembali ke domba jantan kami ... Array tekstur memiliki tiga jenis target:
- GL_TEXTURE_1D_ARRAY
- GL_TEXTURE_2D_ARRAY
- GL_TEXTURE_CUBE_MAP_ARRAY
Kode untuk membuat array tekstur:
GLsizei width = 512; GLsizei height = 512; GLsizei layers = 3; glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &texture_array); glTextureStorage3D(texture_array, 0, GL_RGBA8, width, height, layers);
Yang paling penuh perhatian memperhatikan bahwa kami sedang membuat repositori untuk tekstur 2D, tetapi untuk beberapa alasan kami menggunakan array 3D, tidak ada kesalahan atau salah ketik di sini. Kami menyimpan tekstur 2D, tetapi karena terletak di "lapisan", kami mendapatkan larik 3D (sebenarnya, data piksel disimpan, bukan tekstur. Larik 3D memiliki lapisan 2D dengan data piksel).
Di sini mudah dipahami pada contoh tekstur 1D. Setiap baris dalam array piksel 2D adalah layer 1D yang terpisah. Tekstur mipmap juga dapat dibuat secara otomatis.
Mengenai ini, semua kesulitan berakhir dan menambahkan gambar ke lapisan tertentu cukup sederhana:
glTextureSubImage3D(texarray, mipmap_level, offset.x, offset.y, layer, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
Saat menggunakan array, kita perlu sedikit mengubah shader
#version 450 core layout (location = 0) out vec4 color; layout (location = 0) in vec2 texture_0; uniform sampler2DArray texture_array; uniform uint diffuse_layer; float getCoord(uint capacity, uint layer) { return max(0, min(float(capacity - 1), floor(float(layer) + 0.5))); } void main() { color = texture(texture_array, vec3(texture_0, getCoord(3, diffuse_layer))); }
Opsi terbaik adalah menghitung layer yang diinginkan di luar shader, untuk ini kita dapat menggunakan
UBO /
SSBO (ini juga digunakan untuk mentransfer matriks, dan banyak data lainnya, tetapi entah bagaimana lain kali). Jika ada yang tidak bisa menunggu
tyk_1 dan
tyk_2 , Anda dapat membaca.
Adapun ukuran, yaitu GL_MAX_ARRAY_TEXTURE_LAYERS yang 256 di OpenGL 3.3 dan 2048 di OpenGL 4.5.
Perlu diceritakan tentang Objek Sampler (tidak terkait dengan tekstur Array, tetapi hal yang bermanfaat) - ini adalah objek yang digunakan untuk menyesuaikan keadaan unit tekstur, terlepas dari objek mana yang saat ini melekat pada unit. Ini membantu memisahkan status sampler dari objek tekstur tertentu, yang meningkatkan abstraksi.
GLuint sampler_state = 0; glGenSamplers(1, &sampler_state); glSamplerParameteri(sampler_state, GL_TEXTURE_WRAP_S, GL_REPEAT); glSamplerParameteri(sampler_state, GL_TEXTURE_WRAP_T, GL_REPEAT); glSamplerParameteri(sampler_state, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler_state, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glSamplerParameterf(sampler_state, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
Saya baru saja membuat objek sampler, mengaktifkan penyaringan linier dan 16x penyaringan anisotropik untuk unit tekstur.
GLuint texture_unit = 0; glBindSampler(texture_unit, sampler_state);
Di sini kita hanya mengikat sampler ke unit tekstur yang diinginkan, dan ketika itu berhenti menjadi bindim 0 yang diinginkan untuk unit ini.
glBindSampler(texture_unit, 0);
Ketika kami menautkan sampler, pengaturannya lebih diutamakan daripada pengaturan unit tekstur. Hasil: Tidak perlu memodifikasi basis kode yang ada untuk menambahkan objek sampler. Anda dapat membiarkan pembuatan tekstur apa adanya (dengan status sampler sendiri) dan hanya menambahkan kode untuk mengontrol dan menggunakan objek sampler.
Ketika tiba saatnya untuk menghapus objek, kita cukup memanggil fungsi ini:
glDeleteSamplers(1, &sampler_state);
Tampilan tekstur
Saya akan menerjemahkan ini sebagai "penunjuk tekstur (mungkin lebih tepat daripada tautannya, saya xs)", karena saya tidak tahu terjemahan terbaik.
Apa petunjuk dalam perspektif OpenGL?
Semuanya sangat sederhana, ini adalah penunjuk ke data tekstur yang tidak dapat diubah (yaitu, bisa berubah), seperti yang kita lihat dalam gambar di bawah ini.

Sebenarnya, ini adalah objek yang membagikan data texel dari objek tekstur tertentu, untuk analogi kita dapat menggunakan
std :: shared_ptr dari C ++ . Selama setidaknya ada satu pointer tekstur, tekstur asli tidak akan dihapus oleh pengemudi.
Wiki dijelaskan secara lebih rinci, serta layak dibaca tentang jenis tekstur dan target (mereka tidak harus cocok)
Untuk membuat pointer, kita perlu mendapatkan deskriptor tekstur dengan memanggil
glGenTexture (tidak diperlukan inisialisasi) dan kemudian
glTextureView .
glGenTextures(1, &texture_view); glTextureView(texture_view, GL_TEXTURE_2D, source_name, internal_format, min_level, level_count, 5, 1);
Pointer tekstur dapat menunjuk ke tingkat N dari mipmap, cukup berguna dan nyaman. Pointer dapat berupa array tekstur, bagian array, lapisan tertentu dalam array ini, atau dapat berupa irisan tekstur 3D sebagai tekstur 2D.
Buffer tunggal untuk indeks dan vertex
Yah, semuanya akan cepat dan mudah. Sebelumnya, spesifikasi OpenGL untuk
Vertex Buffer Object merekomendasikan agar pengembang memecah data verteks dan indeks menjadi buffer yang berbeda, tetapi sekarang ini tidak diperlukan (sejarah panjang mengapa tidak).
Yang kita butuhkan adalah menyimpan indeks di depan simpul dan memberi tahu di mana simpul dimulai (lebih tepatnya, offset), untuk ini ada perintah
glVertexArrayVertexBufferInilah cara kami akan melakukannya:
GLint alignment = GL_NONE; glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment); const GLsizei ind_len = GLsizei(ind_buffer.size() * sizeof(element_t)); const GLsizei vrt_len = GLsizei(vrt_buffer.size() * sizeof(vertex_t)); const GLuint ind_len_aligned = align(ind_len, alignment); const GLuint vrt_len_aligned = align(vrt_len, alignment); GLuint buffer = GL_NONE; glCreateBuffers(1, &buffer); glNamedBufferStorage(buffer, ind_len_aligned + vrt_len_aligned, nullptr, GL_DYNAMIC_STORAGE_BIT); glNamedBufferSubData(buffer, 0, ind_len, ind_buffer.data()); glNamedBufferSubData(buffer, ind_len_aligned, vrt_len, vrt_buffer.data()); GLuint vao = GL_NONE; glCreateVertexArrays(1, &vao); glVertexArrayVertexBuffer(vao, 0, buffer, ind_len_aligned, sizeof(vertex_t)); glVertexArrayElementBuffer(vao, buffer);
Tessellation dan komputasi warna
Saya tidak akan memberi tahu Anda tentang shading tessellation, karena ada banyak materi di Google tentang ini (dalam bahasa Rusia), berikut adalah beberapa pelajaran:
1 ,
2 ,
3 . Kami terus mempertimbangkan shader untuk perhitungan (bliiin, juga banyak materi, saya akan memberitahu Anda secara singkat).
Keuntungan dari kartu video dalam jumlah inti yang sangat besar, kartu video dirancang untuk sejumlah besar tugas kecil yang dapat dilakukan secara paralel. Shader kalkulasi, sesuai namanya, memungkinkan untuk menyelesaikan masalah yang tidak terkait dengan grafik (tidak perlu).
Gambar, saya tidak tahu harus menyebutnya apa (seperti aliran dikelompokkan).

Untuk apa kita bisa menggunakannya?
- Pemrosesan gambar
- Bloom
- Algoritma Berbasis Ubin (Shading Tertunda)
- Simulasi
- Partikel
- Air
Lebih lanjut saya tidak melihat alasan untuk menulis, ada juga banyak informasi di Google, berikut adalah contoh sederhana penggunaan:
Berikut adalah contoh penghitung komputasi kosong:
#version 430 layout(local_size_x = 1, local_size_y = 1) in; layout(rgba32f, binding = 0) uniform image2D img_output; void main() {
Berikut adalah beberapa tautan untuk melihat lebih dalam pada
1 ,
2 ,
3 ,
4 .
Pembuatan jalur
Ini adalah ekstensi baru (bukan baru) dari
NVidia , tujuan utamanya adalah rendering vektor 2D. Kita dapat menggunakannya untuk teks atau UI, dan karena grafiknya vektor, itu tidak bergantung pada resolusi, yang tidak diragukan lagi merupakan nilai tambah yang besar dan UI kita akan terlihat hebat.
Konsep dasarnya adalah stensil, kemudian penutup (penutup aslinya). Atur path stencil, lalu visualisasikan pikselnya.
Untuk manajemen, GLuint standar digunakan, dan fungsi create dan delete memiliki konvensi penamaan standar.
glGenPathsNV
Ini sedikit tentang bagaimana kita bisa mendapatkan jalan:
- SVG atau PostScript di string'e
glPathStringNV
- berbagai perintah dengan koordinat yang sesuai
glPathCommandsNV
dan untuk memperbarui data glPathSubCommands, glPathCoords, glPathSubCoords
- font
glPathGlyphsNV, glPathGlyphRangeNV
- kombinasi linier dari jalur yang ada (interpolasi satu, dua atau lebih jalur)
glCopyPathNV, glInterpolatePathsNV, glCombinePathsNV
- transformasi linear dari jalur yang ada
glTransformPathNV
Daftar perintah standar:
- pindah ke (x, y)
- jalur dekat
- line-to (x, y)
- kurva kuadratik (x1, y1, x2, y2)
- kurva kubik (x1, y1, x2, y2, x3, y3)
- kurva halus-kuadratik (x, y)
- kurva halus-kubik (x1, y1, x2, y2)
- elips-busur (rx, ry, rotasi sumbu-x, bendera busur-besar, bendera-sapu, x, y)
Inilah yang tampak seperti string path di PostScript:
"100 180 moveto 40 10 lineto 190 120 lineto 10 120 lineto 160 10 lineto closepathโ // "300 300 moveto 100 400 100 200 300 100 curveto 500 200 500 400 300 300 curveto closepathโ
Dan di sini di SVG:
"M100,180 L40,10 L190,120 L10,120 L160,10 zโ // "M300 300 C 100 400,100 200,300 100,500 200,500 400,300 300Zโ
Masih ada segala macam roti dengan jenis isian, pinggiran, tikungan:

Saya tidak akan menjelaskan semuanya di sini, karena ada banyak bahan dan itu akan membutuhkan seluruh artikel (jika menarik, saya akan menulisnya entah bagaimana).
Berikut adalah daftar rendering primitif
- Kurva kubik
- Kurva kuadratik
- Garis
- Mesin terbang font
- Arcs
- Dash & Endcap Style
Berikut ini beberapa kode, dan kemudian ada banyak teks:
Itu saja.
Tampaknya bagi saya bahwa artikel ini kurang menarik dan informatif, sulit untuk memilih hal utama dalam materi. Jika seseorang tertarik untuk mempelajari lebih detail, saya dapat membuang beberapa materi NVidia dan tautan ke spesifikasi (jika saya ingat di mana saya menyimpannya). Saya juga senang atas bantuan dalam mengedit artikel.
Seperti yang dijanjikan, saya akan menulis artikel berikut tentang mengoptimalkan dan mengurangi panggilan undian. Saya ingin meminta Anda untuk menulis di komentar tentang apa lagi yang ingin Anda baca dan apa yang Anda minati:
- Menulis game di cocos2d-x (Berlatih saja, tanpa air)
- Terjemahan Seri Artikel Vulkan
- Beberapa topik tentang OpenGL (angka empat, fungsionalitas baru)
- Algoritma grafis komputer (pencahayaan, oklusi ambien layar ruang, refleksi layar ruang)
- Opsi Anda
Terima kasih atas perhatiannya.