Cara kerja rendering game 3D: rasterization dan ray tracing

gambar

Bagian 1: pemrosesan simpul

Pada artikel ini, kita akan melihat lebih dekat apa yang terjadi pada dunia 3D setelah semua simpulnya diproses. Kita lagi harus menyingkirkan debu dari buku teks matematika, membiasakan diri dengan geometri piramida pemotongan dan memecahkan misteri perspektif. Kami juga akan terjun sebentar ke fisika ray tracing, pencahayaan, dan material.

Topik utama dari artikel ini adalah tahap render yang penting, di mana dunia tiga dimensi titik, segmen, dan segitiga menjadi kotak dua dimensi blok multi-warna. Sangat sering proses ini tampaknya tidak terlihat, karena konversi dari 3D ke 2D tidak terlihat, berbeda dengan proses yang dijelaskan dalam artikel sebelumnya , di mana kita dapat langsung melihat pengaruh vertex shaders dan tessellation. Jika Anda belum siap untuk ini, Anda bisa mulai dengan artikel 3D Game Rendering 101 kami .

Mempersiapkan dua pengukuran


Sebagian besar pembaca membaca situs web ini pada layar monitor atau smartphone yang benar-benar datar; tetapi bahkan jika Anda memiliki teknik modern - monitor melengkung, maka gambar yang ditampilkan juga terdiri dari kotak datar piksel multi-warna. Namun, saat Anda memainkan Call of Mario yang baru: Deathduty Battleyard, gambarnya tampak tiga dimensi. Objek bergerak di sekitar adegan, menjadi lebih besar atau lebih kecil, mendekati dan menjauh dari kamera.


Mengambil contoh Falles 4 dari Bethesda, yang dirilis pada tahun 2014, kita dapat dengan mudah melihat bagaimana puncak diproses, menciptakan rasa kedalaman dan jarak; Ini terutama terlihat dalam mode wireframe (lihat di atas).

Jika Anda mengambil game 3D apa pun selama dua dekade terakhir, hampir setiap game melakukan urutan tindakan yang sama untuk mengubah dunia simpul 3D menjadi array piksel 2D. Konversi ini sering disebut rasterisasi , tetapi ini hanya satu dari banyak langkah dalam keseluruhan proses.

Kita perlu menganalisis berbagai tahapan dan mempelajari teknik dan perhitungan yang digunakan di dalamnya. Sebagai referensi, kami akan menggunakan urutan yang digunakan dalam Direct3D. Gambar di bawah ini menunjukkan apa yang terjadi dengan setiap simpul dunia:


Pipa Konversi Direct3D

Dalam artikel pertama [ terjemahan Habré] kita melihat apa yang terjadi di ruang dunia (World space): di sini, menggunakan berbagai perhitungan matriks, simpul-simpulnya ditransformasikan dan diwarnai. Kami akan melewati langkah berikutnya, karena di ruang kamera hanya simpul yang dikonversi dan disesuaikan setelah bergerak, sehingga kamera menjadi titik referensi.

Langkah-langkah berikut ini terlalu rumit untuk dilewati, karena itu mutlak diperlukan untuk transisi dari 3D ke 2D - jika diimplementasikan dengan benar, otak kita akan melihat layar datar, tetapi “melihat” pemandangan dengan kedalaman dan skala. Jika semuanya dilakukan dengan salah, gambarnya akan sangat aneh!

Ini semua tentang perspektif


Langkah pertama dalam urutan ini adalah mengatur ruang lingkup dari sudut pandang kamera. Untuk melakukan ini, pertama-tama Anda perlu mengatur sudut pandang bidang horisontal dan vertikal - yang pertama sering berubah dalam permainan, karena orang-orang telah mengembangkan penglihatan tepi horisontal lebih baik daripada vertikal.

Kami dapat mengetahuinya dengan melihat gambar dengan bidang pandang seseorang:


Dua sudut bidang pandang (bidang pandang, fov) mendefinisikan bentuk piramida frustum - piramida 3D dengan basis persegi yang berasal dari kamera. Sudut pertama mengatur fov vertikal , horizontal kedua; kami menunjukkannya dengan simbol α dan β . Faktanya, kita melihat dunia tidak seperti itu, tetapi dari sudut pandang perhitungan, jauh lebih mudah untuk bekerja dengan piramida pemotongan daripada mencoba menghasilkan jumlah visibilitas yang realistis.


Anda juga perlu menentukan dua parameter lagi - lokasi pesawat kliping dekat (atau depan) dan jauh (belakang) (pesawat kliping) . Yang pertama memotong bagian atas piramida, tetapi pada dasarnya menentukan seberapa dekat dengan posisi kamera semuanya digambar; yang terakhir melakukan hal yang sama, tetapi menentukan seberapa jauh dari kamera primitif akan diberikan.

Ukuran dan lokasi bidang pemotongan dekat sangat penting karena menjadi apa yang disebut viewport . Sebenarnya, ini yang kita lihat di monitor, mis. diberikan bingkai, dan di sebagian besar API grafik, viewport diambil dari sudut kiri atas. Pada gambar di bawah ini, titik (a1, b2) akan menjadi asal pesawat: lebar dan tinggi pesawat diukur relatif terhadapnya.


Rasio aspek viewport penting tidak hanya untuk menampilkan dunia yang ditampilkan, tetapi juga agar sesuai dengan rasio aspek monitor. Selama bertahun-tahun, standarnya adalah 4: 3 (atau 1,3333 ... dalam desimal). Namun, saat ini mayoritas bermain dalam rasio aspek 16: 9 atau 21: 9, disebut layar lebar dan layar lebar ultra.

Koordinat setiap titik di ruang kamera harus ditransformasikan sehingga semuanya cocok pada bidang pemotongan dekat, seperti yang ditunjukkan di bawah ini:


Memotong sisi piramida dan atas

Transformasi dilakukan menggunakan matriks lain yang disebut matriks proyeksi perspektif . Dalam contoh di bawah ini, untuk melakukan transformasi, kami menggunakan sudut ruang lingkup dan posisi bidang pemotongan; namun, Anda dapat menggunakan ukuran viewport sebagai gantinya.


Vektor posisi vertex dikalikan dengan matriks ini, yang memberi kita seperangkat koordinat yang diubah.


Voila! Sekarang semua simpul ditulis sedemikian rupa sehingga dunia sumber disajikan sebagai perspektif 3D, dan primitif di dekat bidang pemotongan depan tampak lebih besar daripada yang lebih dekat ke pesawat jauh.

Meskipun ukuran viewport dan sudut pandang terkait, mereka dapat diproses secara individual. Dengan kata lain, Anda dapat mengatur piramida pemotongan sedemikian rupa untuk mendapatkan bidang pemotongan dekat yang berbeda dalam ukuran dan rasio aspek dari viewport. Untuk melakukan ini, langkah tambahan diperlukan dalam rantai operasi, di mana simpul dalam bidang pemotongan dekat harus diubah lagi untuk memperhitungkan perbedaan ini.

Namun, ini dapat menyebabkan distorsi dari perspektif yang terlihat. Menggunakan game Bethesda Skyrim 2011 sebagai contoh , kita dapat melihat bagaimana mengubah sudut horizontal wilayah visibilitas β sambil mempertahankan rasio aspek yang sama dari viewport sangat memengaruhi pemandangan:


Pada gambar pertama ini, kami mengatur β = 75 °, dan adegan terlihat sangat normal. Mari kita coba sekarang untuk mengatur β = 120 °:


Dua perbedaan segera terlihat - pertama, sekarang kita melihat lebih banyak pada sisi "bidang penglihatan" kita; kedua, objek sekarang tampak lebih jauh (terutama pepohonan). Namun, efek visual pada permukaan air sekarang terlihat salah, karena prosesnya tidak dirancang untuk area visibilitas seperti itu.

Sekarang mari kita bayangkan bahwa karakter kita memiliki mata alien, dan atur β = 180 °!


Area penglihatan seperti itu menciptakan pemandangan yang hampir seperti panorama, tetapi Anda harus membayarnya dengan sejumlah besar distorsi objek yang dibuat di tepinya. Ini lagi terjadi karena fakta bahwa para perancang game tidak melihat situasi seperti itu dan tidak menciptakan sumber daya dan efek visual game untuk sudut pandang seperti itu (nilai standarnya sekitar 70 °).

Mungkin terlihat bahwa dalam gambar di atas kamera telah bergerak, tetapi tidak demikian - satu-satunya perubahan adalah memodifikasi piramida pemotongan, yang pada gilirannya mengubah dimensi pesawat pemotongan dekat. Pada setiap gambar, rasio aspek viewport tetap sama, sehingga penskalaan matriks diterapkan pada simpul sehingga semuanya cocok ke dalamnya.

Jadi, apakah Anda tinggal atau pergi?


Setelah melakukan transformasi pada tahap proyeksi, kami beralih ke apa yang disebut ruang klip . Meskipun ini dilakukan setelah proyeksi, lebih mudah untuk menunjukkan apa yang terjadi jika kami melakukan operasi sebelumnya:


Pada gambar di atas, kita melihat bahwa dalam bebek karet, salah satu kelelawar dan bagian dari pohon, segitiga berada di dalam piramida pemotongan; Namun, kelelawar lainnya dan pohon terjauh berada di luar batas piramida pemotongan. Meskipun simpul yang membentuk objek ini telah diproses, kami tidak akan melihatnya di viewport. Ini berarti bahwa mereka terpotong .

Ketika memotong sepanjang piramida (kliping frustum), semua primitif di luar piramida pemotongan sepenuhnya dihapus, dan mereka yang berbaring di perbatasan diubah menjadi primitif baru. Pemotongan tidak sangat meningkatkan kinerja, karena semua simpul tak terlihat ini telah diproses sebelum tahap ini dalam vertex shaders, dll. Jika perlu, seluruh langkah pemotongan bahkan dapat sepenuhnya dilewati, tetapi fitur ini tidak didukung oleh semua API (misalnya, OpenGL standar tidak akan membiarkannya dilewati, tetapi ini dapat dilakukan menggunakan ekstensi API).


Perlu dicatat bahwa posisi pesawat terpotong jauh dalam permainan tidak selalu sama dengan jarak imbang , karena yang terakhir dikendalikan oleh mesin permainan itu sendiri. Mesin juga melakukan pemangkasan pada piramida (frustum culling) - menjalankan kode yang menentukan apakah objek akan ditarik dalam piramida pemotongan dan apakah itu akan mempengaruhi objek yang terlihat; jika jawabannya tidak , maka objek tidak ditransfer ke rendering. Ini tidak sama dengan kliping frustrasi karena ia juga membuang primitif di luar piramida, tetapi mereka telah melewati tahap pemrosesan vertex. Ketika pemusnahan, mereka tidak diproses sama sekali, yang menghemat banyak sumber daya.

Kami telah melakukan semua transformasi dan pemotongan, dan tampaknya simpul akhirnya siap untuk langkah selanjutnya dalam urutan rendering. Tetapi pada kenyataannya, ini tidak demikian, karena semua perhitungan dilakukan pada tahap pemrosesan verteks dan dalam operasi konversi dari ruang dunia ke ruang pemotongan harus dilakukan dalam sistem koordinat yang seragam (mis. Masing-masing titik memiliki 4 komponen, bukan 3) . Namun, viewport benar-benar dua dimensi, yaitu, API mengharapkan bahwa informasi titik hanya berisi nilai untuk x, y (meskipun nilai kedalaman z disimpan).

Untuk menghilangkan komponen keempat, divisi perspektif dilakukan, di mana setiap komponen dibagi dengan nilai w . Operasi ini membatasi x dan y ke interval nilai yang mungkin [-1.1], dan z ke interval [0.1]. Ini disebut koordinat perangkat dinormalisasi (NDC).

Jika Anda ingin mempelajari lebih lanjut tentang apa yang baru saja kami jelaskan, dan Anda menyukai matematika, maka bacalah tutorial yang sangat bagus tentang topik ini Song Ho An. Sekarang mari kita ubah simpul-simpul ini menjadi piksel!

Kami menguasai rasterisasi


Seperti dalam kasus transformasi, kita akan melihat aturan dan proses yang digunakan untuk mengubah viewport menjadi grid piksel, menggunakan Direct3D sebagai contoh. Tabel ini menyerupai lembar kerja Excel dengan baris dan kolom, di mana setiap sel berisi nilai data yang berbeda (seperti warna, nilai kedalaman, koordinat tekstur, dll.). Biasanya kisi ini disebut gambar raster , dan proses pembuatannya disebut rasterisasi . Dalam artikel 3D rendering 101, kami menyederhanakan prosedur ini:


Gambar di atas memberi kesan bahwa primitif hanya dipotong menjadi blok-blok kecil, tetapi pada kenyataannya ada lebih banyak operasi. Langkah pertama adalah menentukan apakah primitif menghadap kamera - misalnya, pada gambar di atas dengan piramida pemotongan, primitif yang membentuk bagian belakang kelinci abu-abu tidak akan terlihat. Oleh karena itu, meskipun mereka hadir di viewport, mereka tidak perlu dirender.

Kita dapat membayangkan kira-kira seperti apa dengan melihat diagram di bawah ini. Kubus mengalami berbagai transformasi untuk menempatkan model 3D di ruang 2D layar dan dari sudut pandang kamera, beberapa wajah kubus tidak terlihat. Jika kita mengasumsikan bahwa semua permukaan buram, maka beberapa primitif ini dapat diabaikan.


Dari kiri ke kanan: ruang dunia> ruang kamera> ruang proyeksi> ruang layar

Dalam Direct3D, ini dapat diimplementasikan dengan memberi tahu sistem seperti apa keadaan renderingnya , dan instruksi ini akan memberi tahu bahwa perlu untuk menghapus ( memotong ) sisi-sisi masing-masing primitif yang melihat ke depan atau ke belakang (atau tidak memotong sepenuhnya, misalnya, dalam mode wireframe ) . Tapi bagaimana dia tahu sisi mana yang melihat ke depan atau ke belakang? Ketika kami memeriksa matematika pemrosesan simpul , kami melihat bahwa segitiga (atau lebih tepatnya simpul) memiliki vektor normal yang memberitahu sistem ke arah mana ia terlihat. Berkat informasi ini, Anda dapat melakukan pemeriksaan sederhana, dan jika primitif gagal, maka dihapus dari rantai render.

Sekarang saatnya menerapkan grid pixel. Lagi-lagi ini adalah proses yang sangat kompleks, karena sistem harus memahami apakah piksel berada di dalam primitif - sepenuhnya, sebagian, atau tidak sama sekali. Untuk melakukan ini, proses pengujian cakupan dilakukan. Gambar di bawah ini menunjukkan bagaimana segitiga dirasterisasi dalam Direct3D 11:


Aturannya cukup sederhana: piksel dianggap berada di dalam segitiga jika pusat piksel melewati tanda centang, yang oleh Microsoft disebut aturan "kiri atas" . "Top" mengacu pada memeriksa garis horizontal; pusat piksel harus berada di baris ini. "Kiri" mengacu pada garis non-horisontal, dan pusat piksel harus di sebelah kiri garis tersebut. Ada aturan lain yang terkait dengan non-primitif, misalnya, segmen dan titik sederhana, dan saat menggunakan multisampling , tambahan jika kondisi muncul dalam aturan.

Jika Anda melihat dengan cermat pada dokumentasi Microsoft, Anda dapat melihat bahwa bentuk yang dibuat oleh piksel tidak sangat mirip dengan primitif asli. Ini karena pikselnya terlalu besar untuk membuat segitiga realistis - gambar bitmap tidak mengandung cukup data tentang objek asli, yang menyebabkan fenomena yang disebut aliasing .

Mari kita lihat aliasing dengan contoh UL Benchmark 3DMark03 :


Rasterisasi 720 x 480 piksel

Pada gambar pertama, gambar raster memiliki resolusi yang sangat rendah - 720 x 480 piksel. Aliasing terlihat jelas di pagar dan bayangan yang dilemparkan oleh senjata-senjata prajurit atas. Bandingkan ini dengan hasil yang diperoleh selama rasterisasi dengan peningkatan 24 kali lipat dalam jumlah piksel:


Rasterisasi 3840 x 2160 piksel

Di sini kita melihat bahwa aliasing di pagar dan bayangan telah sepenuhnya menghilang. Tampaknya Anda harus selalu menggunakan bitmap yang besar, tetapi ukuran kisi harus didukung oleh monitor tempat bingkai akan ditampilkan. Dan dengan mempertimbangkan fakta bahwa semua piksel ini perlu diproses, jelas bahwa akan ada penurunan kinerja.

Multisampling dapat membantu di sini. Begini cara kerjanya di Direct3D:


Alih-alih memeriksa apakah pusat piksel cocok dengan aturan rasterisasi, beberapa titik di dalam setiap piksel (disebut sampel subpiksel atau sub-sampel) dicentang , dan jika beberapa di antaranya memenuhi persyaratan, mereka membentuk bagian dari gambar. Kelihatannya tidak ada manfaatnya dan aliasing bahkan ditingkatkan, tetapi ketika menggunakan multisampling, informasi tentang sub-sampel mana yang dicakup oleh primitif dan hasil pemrosesan piksel disimpan dalam buffer dalam memori.

Buffer ini kemudian digunakan untuk mencampur sub-sampel dan piksel ini sehingga ujung-ujung primitif tidak terlalu sobek. Kami akan melihat aliasing dalam artikel lain secara lebih rinci, tetapi untuk saat ini informasi ini cukup bagi kami untuk memahami apa yang dapat dilakukan multisampling ketika digunakan untuk merasterisasi terlalu sedikit piksel:


Seperti yang Anda lihat, jumlah aliasing di tepi berbagai bentuk telah menurun secara signifikan. Rasterisasi resolusi yang lebih tinggi jelas lebih baik, tetapi penurunan kinerja dapat mendorong Anda untuk menggunakan multisampling.

Juga selama rasterisasi, pengujian oklusi dilakukan. Ini perlu karena viewport akan diisi dengan primitif ditumpangkan satu sama lain - misalnya, pada gambar di atas, segitiga berwawasan ke depan yang membentuk prajurit di latar depan tumpang tindih dengan segitiga yang sama dari prajurit lain. Selain memeriksa apakah primitif mencakup piksel, Anda juga dapat membandingkan kedalaman relatif, dan jika satu permukaan berada di belakang yang lain, maka itu harus dihapus dari proses rendering yang tersisa.

Namun, jika primitif dekat transparan, maka primitif jauh akan tetap terlihat, meskipun tidak akan lulus uji tumpang tindih. Itulah sebabnya hampir semua mesin 3D melakukan pemeriksaan tumpang tindih sebelum mengirim data ke GPU dan sebaliknya menciptakan sesuatu yang disebut z-buffer , yang merupakan bagian dari proses rendering. Di sini bingkai dibuat dengan cara biasa, tetapi alih-alih menyimpan warna piksel yang sudah jadi dalam memori, GPU hanya menyimpan nilai kedalaman. Kemudian mereka dapat digunakan dalam shader untuk memeriksa visibilitas dan dengan kontrol dan akurasi aspek yang berkaitan dengan objek yang tumpang tindih.


Pada gambar yang ditunjukkan di atas, semakin gelap warna pikselnya, semakin dekat subjek ke kamera.Frame diberikan sekali untuk membuat buffer-z, dan kemudian di-render lagi, tapi kali ini selama pemrosesan piksel, shader diluncurkan, memeriksa nilai-nilai di buffer-z. Jika tidak terlihat, maka warna piksel tidak ditulis ke buffer bingkai jadi.

Sejauh ini, langkah terakhir utama kami adalah interpolasi atribut vertex - dalam skema yang disederhanakan asli, primitif adalah segitiga lengkap, tetapi jangan lupa bahwa jendela tampilan diisi hanya dengan sudut-sudut gambar, dan bukan dengan angka-angka itu sendiri. Artinya, sistem harus menentukan warna, kedalaman, dan tekstur primitif apa yang harus berada di antara simpul, dan operasi ini disebut interpolasi . Seperti yang sudah Anda tebak, ini adalah perhitungan lain, dan ini tidak sesederhana itu.

Terlepas dari kenyataan bahwa layar raster disajikan dalam 2D, struktur di dalamnya mewakili perspektif 3D. Jika garis benar-benar dua dimensi, maka kita dapat menggunakan persamaan linear sederhana untuk menghitung warna dan hal lainnya , karena kita berpindah dari satu titik ke titik lainnya. Tetapi karena aspek 3D dari adegan, interpolasi harus mempertimbangkan perspektif ini; Untuk mempelajari lebih lanjut tentang proses ini, baca artikel yang bagus dari Simon Young .

Jadi, tugas selesai - sehingga dunia 3D simpul berubah menjadi kotak 2D blok warna-warni. Tapi kita belum selesai.

Depan ke belakang (dengan beberapa pengecualian)


Sebelum kita selesai mempertimbangkan rasterisasi, kita perlu berbicara tentang urutan urutan rendering. Kami tidak berbicara tentang tahap di mana, misalnya, tessellation muncul dalam urutan pemrosesan; kami maksud urutan di mana primitif diproses. Objek biasanya diproses dalam urutan di mana mereka berada di buffer indeks (blok memori memberitahu sistem bagaimana simpul dikelompokkan bersama) dan ini dapat secara signifikan mempengaruhi cara objek transparan dan efek diproses.

Alasan untuk ini adalah bahwa primitif diproses satu per satu, dan jika Anda pertama kali membuat yang di depan, maka semua orang di belakang mereka tidak akan terlihat (ini adalah tempat oklusi pemusnahan ikut bermain) dan dapat dikeluarkan dari proses (membantu menyelamatkan kinerja). Ini biasanya disebut rendering dari depan ke belakang , dan untuk proses ini, buffer indeks harus dipesan dengan cara ini.

Namun, jika beberapa primitif ini transparan di depan kamera, maka rendering dari depan ke belakang akan menyebabkan hilangnya objek yang berada di belakang transparan. Salah satu solusinya adalah membuat kembali ke depan, di mana primitif dan efek transparan dihitung terakhir.


Dari kiri ke kanan: urutan dalam adegan, render depan ke belakang, render kembali ke depan

Artinya, dalam semua game modern, rendering dilakukan kembali ke depan? Apapun masalahnya - jangan lupa bahwa rendering setiap primitif individu akan menyebabkan penurunan kinerja yang jauh lebih besar dibandingkan dengan rendering hanya apa yang kita lihat. Ada cara lain untuk memproses objek transparan, tetapi dalam kasus umum tidak ada solusi ideal yang cocok untuk sistem apa pun, dan setiap situasi perlu dipertimbangkan secara terpisah.

Faktanya, ini memungkinkan kita untuk memahami pro dan kontra utama dari rasterisasi - pada peralatan modern ini adalah proses yang cepat dan efisien, tetapi ini masih merupakan refleksi perkiraan dari apa yang kita lihat. Di dunia nyata, setiap objek dapat menyerap, memantulkan, dan terkadang membiaskan cahaya, dan semua ini memengaruhi penampilan akhir dari adegan yang ditampilkan. Membagi dunia menjadi primitif dan menjadikan sebagian dari mereka, kita menjadi cepat. tetapi hasilnya sangat kasar.

Sekarang, jika ada cara lain ...

Cara lain adalah: ray tracing!


Hampir lima puluh tahun yang lalu, seorang ilmuwan komputer bernama Arthur Eppel bekerja pada sistem untuk merender gambar pada komputer di mana satu berkas cahaya dipancarkan dari kamera dalam garis lurus hingga bertabrakan dengan objek. Setelah tabrakan, sifat material (warna, reflektifitas, dll.) Mengubah kecerahan sinar cahaya. Untuk setiap piksel dalam gambar yang diberikan, ada satu sinar yang dipancarkan, dan algoritma melakukan rangkaian perhitungan untuk menentukan warna piksel. Proses Eppel disebut pengecoran sinar .

Sekitar sepuluh tahun kemudian, ilmuwan lain bernama John Whited , , , , . , ; , , . (ray tracing) ( , , , ) .


Dari gambar di atas, Anda dapat memahami cara kerja algoritma Whited. Untuk setiap piksel dalam bingkai, satu sinar dipancarkan dari kamera dan bergerak hingga mencapai permukaan. Dalam contoh ini, permukaannya tembus cahaya, sehingga cahaya dapat dipantulkan dan dibiaskan melaluinya. Dalam kedua kasus, sinar sekunder dihasilkan yang bergerak sampai mereka bertabrakan dengan permukaan. Sinar sekunder baru juga dihasilkan untuk menjelaskan warna sumber cahaya dan bayangan yang mereka buat.

Sifat rekursif dari proses ini adalah bahwa sinar sekunder dapat dihasilkan setiap kali sinar yang dipancarkan memotong permukaan. Ini dapat dengan cepat lepas kendali, sehingga jumlah sinar sekunder yang dihasilkan selalu terbatas. Setelah menyelesaikan jalur balok, warna pada setiap titik akhir dihitung berdasarkan sifat material permukaan ini. Nilai ini kemudian ditransmisikan sepanjang sinar sebelumnya, mengubah warna untuk permukaan ini, dan seterusnya, hingga kita mencapai titik awal dari sinar primer, yaitu piksel dalam bingkai.

Sistem seperti itu bisa sangat rumit dan bahkan adegan sederhana dapat menghasilkan sejumlah besar perhitungan. Untungnya, ada trik yang menyederhanakan pekerjaan - pertama, Anda dapat menggunakan peralatan yang dirancang khusus untuk mempercepat operasi matematika ini, mirip dengan bagaimana hal itu terjadi dengan matriks matematika dalam pemrosesan simpul (lebih lanjut tentang ini nanti). Trik penting lainnya adalah upaya untuk mempercepat proses penentuan objek ke mana sinar jatuh dan tempat persilangan yang tepat - jika objek terdiri dari banyak segitiga, maka tugas ini bisa sangat sulit:


Sumber: Real-time ray tracing dengan Nvidia RTX

Alih-alih memeriksa setiap segitiga individu di setiap objek, daftar volume pengikat (BV) dihasilkan sebelum melakukan ray tracing - ini adalah parallelepipeds biasa yang menggambarkan suatu objek. Untuk berbagai struktur di dalam objek, volume pembatas yang lebih kecil dibuat secara siklikal.

Misalnya, BV pertama adalah seluruh kelinci. Pasangan berikutnya akan menggambarkan kepala, kaki, tubuh, ekor, dll. setiap volume pada gilirannya akan menjadi kumpulan volume untuk struktur kepala, badan, dll yang lebih kecil, dan tingkat volume terakhir akan berisi sejumlah kecil segitiga untuk verifikasi. Semua volume ini sering disusun dalam daftar yang diurutkan (disebut hirarki BVatau BVH); berkat ini, sistem memeriksa jumlah BV yang relatif kecil setiap kali:


Meskipun penggunaan BVH, secara tegas, tidak mempercepat penelusuran sinar itu sendiri, menghasilkan hierarki dan algoritma pencarian berikutnya yang diperlukan dalam kasus umum jauh lebih cepat daripada memeriksa persimpangan satu sinar dengan salah satu dari jutaan segitiga di dunia 3D.

Saat ini, program seperti Blender dan POV-ray menggunakan ray tracing dengan algoritma tambahan (seperti foton tracing dan radiositas) untuk menghasilkan gambar yang sangat realistis:


Pertanyaan yang jelas mungkin muncul: jika penelusuran ray sangat baik, mengapa itu tidak digunakan di mana-mana? Jawabannya ada di dua bidang: pertama, bahkan penelusuran sinar sederhana menghasilkan jutaan sinar yang perlu dihitung berulang-ulang. Sistem dimulai dengan hanya satu berkas per piksel layar, yaitu dengan resolusi 800 x 600, ia menghasilkan 480.000 sinar primer, dan kemudian masing-masing menghasilkan banyak sinar sekunder. Ini adalah pekerjaan yang sangat sulit, bahkan untuk PC desktop modern. Masalah kedua adalah bahwa penelusuran sinar sederhana tidak terlalu realistis dan untuk implementasinya yang tepat, Anda memerlukan banyak persamaan tambahan yang sangat kompleks.

Bahkan dengan peralatan modern, jumlah pekerjaan dalam game 3D tidak dapat dicapai untuk implementasi waktu nyata. Dalam rendering 3D 101kami melihat bahwa tolok ukur ray tracing memerlukan waktu puluhan detik untuk membuat satu gambar beresolusi rendah.

Bagaimana Wolfenstein 3D pertama melakukan pengecoran sinar pada tahun 1992, dan mengapa game seperti Battlefield V dan Metro Exodus , dirilis pada 2019, menawarkan kemampuan ray tracing? Apakah mereka melakukan rasterisasi atau penelusuran sinar? Sedikit demi sedikit keduanya.

Pendekatan hibrida untuk saat ini dan masa depan


Pada bulan Maret 2018, Microsoft mengumumkan rilis ekstensi API baru untuk Direct3D 12 yang disebut DXR (DirectX Raytracing). Itu adalah pipa grafis baru yang melengkapi pipa rasterisasi dan komputasi standar. Fungsionalitas tambahan disediakan oleh penambahan shader, struktur data, dan sebagainya, tetapi tidak memerlukan dukungan perangkat keras, kecuali yang sudah dibutuhkan untuk Direct3D 12.


Pada Konferensi Pengembang Game yang sama, di mana Microsoft berbicara tentang DXR , Electronic Arts berbicara tentang Proyek Pica Pica - sebuah eksperimen dengan mesin 3D menggunakan DXR. Perusahaan telah menunjukkan bahwa ray tracing dapat digunakan, tetapi tidak untuk rendering seluruh frame. Sebagian besar pekerjaan menggunakan teknik rasterisasi tradisional dan bayangan komputasi, sedangkan DXR digunakan di daerah tertentu. Artinya, jumlah sinar yang dihasilkan jauh lebih sedikit daripada seluruh adegan.


Pendekatan hibrida ini telah digunakan di masa lalu, meskipun pada tingkat lebih rendah. Misalnya, Wolfenstein 3D menggunakan pengecoran sinar untuk membuat bingkai, tetapi itu dilakukan dengan satu balok per kolom piksel, bukan piksel. Ini mungkin masih tampak mengesankan, kecuali jika Anda ingat bahwa gim ini bekerja dengan resolusi 640 x 480 [kira-kira. transl .: sebenarnya 320 x 200], yaitu, pada saat yang sama tidak lebih dari 640 sinar yang dipancarkan.

Kartu grafis awal 2018 seperti AMD Radeon RX 580 atau Nvidia GeForce 1080 Ti memenuhi persyaratan DXR, tetapi bahkan dengan kemampuan komputasi mereka, ada kekhawatiran bahwa mereka tidak akan cukup kuat untuk membuat DXR bermakna.

Situasi berubah pada Agustus 2018 ketika Nvidia merilis arsitektur GPU terbarunya , yang diberi nama kode Turing . Fitur yang paling penting dari chip ini adalah penampilan yang disebut RT Cores: blok logika terpisah untuk mempercepat perhitungan persimpangan segitiga-ray dan berlalunya hirarki volume pembatas (BVH). Kedua proses ini adalah prosedur yang memakan waktu untuk menentukan titik-titik interaksi cahaya dengan segitiga yang membentuk objek pemandangan. Mengingat bahwa RT Cores adalah unit prosesor Turing yang unik, akses ke mereka hanya dapat dilakukan melalui API eksklusif Nvidia.

Game pertama yang mendukung fitur ini adalah Battlefield V. EA Ketika kami menguji DXR di dalamnya , kami terkesan dengan peningkatan refleksi dalam air, pada rumput dan logam, serta penurunan kinerja yang sesuai:


Sejujurnya, tambalan berikutnya meningkatkan situasi, tetapi masih ada penurunan kecepatan rendering frame (dan masih ada). Pada 2019, ada beberapa game lain yang mendukung API ini dan melakukan penelusuran sinar untuk bagian-bagian tertentu dari frame. Kami menguji Metro Exodus dan Shadow of the Tomb Raider , dihadapkan pada situasi yang sama - dengan penggunaan aktif DXR secara signifikan mengurangi frame rate.

Sekitar waktu yang sama, Tolok Ukur UL mengumumkan pembuatan uji fungsi DXR untuk 3DMark :


DXR digunakan dalam kartu grafis Nvidia Titan X (Pascal) - ya, hasilnya 8 fps

Namun, sebuah studi game dengan dukungan DXR dan tes 3DMark menunjukkan bahwa ray tracing bahkan pada tahun 2019 tetap merupakan tugas yang sangat sulit untuk GPU, bahkan dengan harga lebih dari $ 1.000. Apakah ini berarti kita tidak memiliki alternatif nyata untuk rasterisasi?

Fitur progresif dalam teknologi grafik 3D konsumen seringkali sangat mahal, dan dukungan awal mereka untuk fitur API baru bisa sangat terfragmentasi atau lambat (seperti yang kami temukan ketika menguji Max Payne 3 pada versi Direct3D yang berbeda pada tahun 2012). Masalah terakhir biasanya muncul karena pengembang game mencoba untuk memasukkan sebanyak mungkin fitur modern ke dalam produk mereka, kadang-kadang tanpa pengalaman yang cukup.

Namun, vertex dan pixel shaders, tessellation, HDR rendering, dan oklusi ambient ruang layar juga pernah menjadi teknik mahal yang hanya cocok untuk GPU yang kuat, dan sekarang mereka adalah standar untuk permainan dan banyak kartu grafis yang didukung. Hal yang sama akan terjadi dengan ray tracing; seiring waktu, itu hanya akan berubah menjadi parameter detail lain, diaktifkan secara default untuk sebagian besar pemain.

Kesimpulannya


Jadi, kita telah sampai pada bagian kedua dari analisis, di mana kita telah melihat lebih dalam ke dunia grafis-3D. Kami belajar bagaimana puncak dunia dan model ditransfer dari tiga dimensi dan berubah menjadi gambar 2D datar. Kami melihat bahwa kami perlu memperhitungkan cakupannya dan menyadari dampaknya. Kami memeriksa proses mengubah verin-verin ini menjadi piksel, dan berakhir dengan melihat sekilas alternatif dari proses rasterisasi tradisional.

Seperti pada artikel sebelumnya, kami tidak mungkin dapat mengungkapkan semua topik, dan melewatkan beberapa detail - pada akhirnya, ini bukan buku teks! Tapi kami harap Anda mempelajari sesuatu yang baru dan sekarang menghargai pekerjaan programmer dan insinyur yang menggunakan komputasi dan sains untuk mengimplementasikan semua ini di game 3D favorit Anda.

Source: https://habr.com/ru/post/id480338/


All Articles