Jika Anda memainkan game AAA modern, Anda mungkin telah memperhatikan kecenderungan untuk menggunakan lanskap yang tertutup salju. Misalnya, mereka berada di
Horizon Zero Dawn ,
Rise of the Tomb Raider dan
God of War . Dalam semua gim ini, salju memiliki fitur penting: Anda dapat meninggalkan jejak di atasnya!
Berkat interaksi dengan lingkungan ini, pencelupan pemain dalam permainan ditingkatkan. Itu membuat lingkungan lebih realistis, dan mari kita jujur ββ- itu hanya menarik. Mengapa menghabiskan waktu berjam-jam menciptakan mekanik yang ingin tahu jika Anda bisa membiarkan pemain jatuh ke tanah dan membuat malaikat salju?
Dalam tutorial ini Anda akan mempelajari hal-hal berikut:
- Buat jejak kaki menggunakan capture adegan untuk menutupi objek yang dekat dengan tanah
- Gunakan topeng dengan bahan medan untuk membuat salju yang dapat dideformasi
- Untuk mengoptimalkan, tampilkan jejak kaki di salju hanya di sebelah pemain
Catatan: dipahami bahwa Anda sudah terbiasa dengan dasar-dasar bekerja dengan Unreal Engine. Jika Anda baru, lihat seri tutorial Mesin Nyata kami untuk pemula .
Mulai bekerja
Unduh
materi untuk tutorial ini. Buka
zip mereka, pergi ke
SnowDeformationStarter dan buka
SnowDeformation.uproject . Dalam tutorial ini kita akan membuat jejak dengan bantuan karakter dan beberapa kotak.
Sebelum kita mulai, Anda perlu tahu bahwa metode dari tutorial ini hanya akan menyimpan jejak di area tertentu, dan tidak di seluruh dunia, karena kecepatannya tergantung pada resolusi render target.
Misalnya, jika kita ingin menyimpan jejak untuk area yang luas, maka kita harus meningkatkan resolusi. Tapi itu juga meningkatkan dampak pengambilan adegan pada kecepatan game dan ukuran memori untuk target render. Untuk optimasi, Anda perlu membatasi ruang lingkup dan resolusi.
Setelah mengatasinya, mari cari tahu apa yang diperlukan untuk mewujudkan jejak kaki di salju.
Implementasi jejak kaki di salju
Hal pertama yang Anda butuhkan untuk membuat jejak adalah
target render . Target render akan menjadi topeng dalam skala abu-abu, di mana putih menunjukkan adanya jejak, dan hitam menunjukkan tidak adanya. Kemudian kita dapat memproyeksikan target render ke tanah dan menggunakannya untuk mencampur tekstur dan menggeser simpul.
Hal kedua yang kita butuhkan adalah cara untuk menutupi hanya benda-benda yang mempengaruhi salju. Ini dapat diterapkan dengan terlebih dahulu merender objek dalam
Kedalaman Kustom . Anda kemudian dapat menggunakan
tangkapan layar dengan
bahan proses pos untuk menutupi semua objek yang dirender di Custom Depth. Kemudian Anda bisa menampilkan topeng di render target.
Catatan: pengambilan adegan pada dasarnya adalah kamera dengan kemampuan untuk menghasilkan render target.
Bagian terpenting dari mengabadikan sebuah adegan adalah lokasinya. Berikut ini adalah contoh dari target render yang diambil dari tampilan
atas . Di sini, karakter dan kotak orang ketiga disamarkan.
Sekilas, tangkapan dengan tampilan atas cocok untuk kami. Formulir terlihat cocok untuk jerat, jadi seharusnya tidak ada masalah, bukan?
Tidak juga. Masalah menangkap dari tampilan atas adalah bahwa ia tidak menangkap apa pun di bawah titik terlebar. Berikut ini sebuah contoh:
Bayangkan bahwa panah kuning sampai ke tanah. Dalam kasus kubus dan kerucut, panah akan selalu tetap berada di dalam objek. Namun, dalam kasus bola, titik muncul darinya ketika mendekati bumi. Namun menurut kamera, ujungnya selalu di dalam bola. Beginilah bentuk sphere untuk kamera:
Oleh karena itu, topeng bola akan lebih besar dari yang seharusnya, bahkan jika area kontak dengan bumi kecil.
Selain itu, masalah ini dilengkapi dengan fakta bahwa sulit bagi kita untuk menentukan apakah objek tersebut menyangkut tanah.
Untuk mengatasi kedua masalah ini, Anda dapat menggunakan tangkapan
dari bawah .
Pegangan bawah
Tangkapan dari bawah adalah sebagai berikut:
Seperti yang Anda lihat, kamera sekarang menangkap sisi bawah, yaitu, yang menyentuh tanah. Ini menghilangkan masalah "area terluas" yang muncul saat menangkap dari atas.
Untuk menentukan apakah suatu benda menyentuh tanah, Anda dapat menggunakan bahan pasca-pemrosesan untuk melakukan pemeriksaan kedalaman. Ini memeriksa apakah kedalaman objek lebih besar dari kedalaman bumi
dan apakah itu di bawah offset yang telah ditentukan. Jika kedua kondisi terpenuhi, maka kita dapat menutupi piksel ini.
Di bawah ini adalah contoh di dalam mesin dengan zona tangkap 20 unit di atas tanah. Perhatikan bahwa topeng hanya muncul ketika objek melewati titik tertentu. Perhatikan juga bahwa topeng menjadi lebih putih saat objek mendekati tanah.
Pertama, buat bahan pasca pemrosesan untuk melakukan pemeriksaan mendalam.
Membuat Bahan Uji Kedalaman
Untuk melakukan pemeriksaan kedalaman, Anda perlu menggunakan dua buffer kedalaman - satu untuk tanah, yang lainnya untuk objek yang mempengaruhi salju. Karena menangkap pemandangan hanya melihat bumi,
Pemandangan Kedalaman akan menyimpulkan kedalaman untuk bumi. Untuk mendapatkan kedalaman untuk objek, kami hanya akan membuatnya
Depth Kustom .
Catatan: untuk menghemat waktu, saya telah merender karakter dan kotak di Kedalaman Kustom. Jika Anda ingin menambahkan objek lain yang memengaruhi salju, Anda harus mengaktifkan Render CustomDepth Pass untuknya .
Pertama, Anda perlu menghitung jarak setiap piksel ke tanah. Buka
Bahan \ PP_DepthPeriksa dan buat yang berikut:
Selanjutnya, Anda perlu membuat zona tangkap. Untuk melakukan ini, tambahkan node yang disorot:
Sekarang jika pixel berada dalam
25 unit bumi, maka akan muncul di mask. Kecerahan Masking tergantung pada seberapa dekat pixel ke tanah. Klik
Terapkan dan kembali ke editor utama.
Selanjutnya Anda perlu membuat tangkapan adegan.
Buat tangkapan adegan
Pertama, kita membutuhkan target render untuk menangkap adegan. Buka folder
RenderTarget dan buat
Target Render baru yang disebut
RT_Capture .
Sekarang mari kita membuat capture adegan. Dalam tutorial ini kita akan menambahkan adegan pengambilan ke cetak biru, karena nanti kita akan memerlukan skrip untuk itu. Buka
Cetak Biru \ BP_Capture dan tambahkan
Komponen Pengambilan Gambar 2D . Beri nama
SceneCapture .
Pertama, kita perlu mengatur pergantian tangkapan sehingga terlihat di tanah. Buka panel Detail dan atur
Rotasi ke (0, 90, 90) .
Selanjutnya adalah jenis proyeksi. Karena topeng adalah representasi 2D dari adegan, kita perlu menyingkirkan distorsi perspektif. Untuk melakukan ini, tetapkan
Jenis Proyeksi \ Jenis Proyeksi ke
Orthografis .
Selanjutnya, kita perlu memberi tahu tangkapan adegan yang menjadi target rekaman untuk direkam. Untuk melakukan ini, pilih nilai
RT_Capture untuk
Scene Capture \ Target Tekstur .
Akhirnya, kita perlu menggunakan bahan pemeriksaan kedalaman. Tambahkan PP_DepthPeriksa ke
Rendering Features \ Post Process Materials . Agar post-processing berfungsi, kita juga perlu mengubah
Scene Capture \ Capture Source ke
Final Color (LDR) di RGB .
Sekarang setelah pengambilan adegan dikonfigurasikan, kita perlu menentukan ukuran area pengambilan.
Mengatur ukuran area tangkapan
Karena lebih baik menggunakan resolusi rendah untuk target render, kita perlu menggunakan ruang secara efisien. Artinya, kita harus memilih area mana yang satu piksel akan mencakup. Misalnya, jika resolusi area tangkap dan target render sama, maka kami mendapatkan rasio 1: 1. Setiap piksel akan mencakup area 1 Γ 1 (dalam satuan dunia).
Untuk trek di salju, rasio 1: 1 tidak diperlukan, karena kita kemungkinan besar tidak membutuhkan detail seperti itu. Saya sarankan menggunakan rasio yang lebih besar karena ini akan memungkinkan Anda untuk meningkatkan ukuran area pengambilan pada resolusi rendah. Tetapi jangan membuat rasio terlalu besar, jika tidak rinciannya akan mulai hilang. Dalam tutorial ini, kita akan menggunakan rasio 8: 1, yaitu, ukuran setiap piksel akan menjadi 8 Γ 8 unit dunia.
Anda dapat mengubah ukuran area pengambilan dengan mengubah properti
Scene Capture \ Ortho Width . Misalnya, jika Anda ingin menangkap area 1024 Γ 1024, maka atur nilainya menjadi 1024. Karena kami menggunakan rasio 8: 1, atur nilainya menjadi
2048 (resolusi default dari target render adalah 256 Γ 256).
Ini berarti bahwa pengambilan adegan akan menangkap area
2048 Γ 2048 . Berjarak sekitar 20 Γ 20 meter.
Bahan dasar juga membutuhkan akses untuk menangkap ukuran untuk memproyeksikan render target dengan benar. Cara termudah untuk melakukan ini adalah dengan menyimpan ukuran tangkapan di
Koleksi Parameter Material . Ini pada dasarnya adalah kumpulan variabel yang dapat diakses materi
apa pun .
Menyimpan ukuran tangkapan
Kembali ke editor utama dan buka folder
Bahan . Buat
Koleksi Parameter Bahan yang akan di
Bahan & Tekstur . Ubah nama menjadi
MPC_Capture dan buka.
Kemudian buat
Parameter Skalar baru dan
beri nama
CaptureSize . Jangan khawatir tentang pengaturan nilainya - kami akan melakukannya terus terang.
Kembali ke
BP_Capture dan tambahkan node yang disorot ke
Event BeginPlay . Setel
Koleksi ke
MPC_Capture , dan
Nama Parameter ke
CaptureSize .
Sekarang bahan apa pun bisa mendapatkan nilai
Lebar Ortho dengan membacanya dari parameter
CaptureSize . Sejauh ini dengan penangkapan adegan kami selesai. Klik
Kompilasi dan kembali ke editor utama. Langkah selanjutnya adalah memproyeksikan target render ke tanah dan menggunakannya untuk merusak lanskap.
Deformasi lanskap
Buka
M_Landscape dan buka panel Detail. Kemudian atur properti berikut:
- Untuk Dua Sisi, pilih diaktifkan . Karena menangkap pemandangan akan "melihat" dari bawah, ia hanya akan melihat muka bumi yang terbalik. Secara default, mesin tidak membuat permukaan belakang jerat. Ini berarti bahwa ia tidak akan menyimpan kedalaman bumi dalam buffer kedalaman. Untuk memperbaiki ini, kita perlu memberitahu mesin untuk membuat kedua sisi mesh.
- Untuk D3D11 Tessellation, pilih Flat Tessellation (PN Segitiga juga dapat digunakan). Tessellation akan memecah segitiga jala menjadi yang lebih kecil. Intinya, ini meningkatkan resolusi mesh dan memungkinkan kita untuk mendapatkan detail yang lebih baik saat menggeser simpul. Tanpa ini, kepadatan puncak akan terlalu rendah untuk membuat jejak yang bisa dipercaya.
Setelah tessellations diaktifkan,
Pengganda Dunia dan
Pengganda Tessellation akan menyala.
Tessellation Multipler mengontrol jumlah tessellation. Dalam tutorial ini, kita tidak akan menghubungkan node ini, yaitu, kita menggunakan nilai default (
1 ).
World Displacement mendapatkan nilai vektor yang menggambarkan ke arah mana dan seberapa banyak untuk memindahkan titik. Untuk menghitung nilai kontak ini, pertama-tama kita harus memproyeksikan target render ke tanah.
Render Target Proyek
Untuk memproyeksikan target render, Anda perlu menghitung koordinat UV-nya. Untuk melakukan ini, buat skema berikut:
Apa yang terjadi di sini:
- Pertama kita perlu mendapatkan posisi XY dari simpul saat ini. Karena kami menangkap dari bawah, koordinat X dibalik, jadi Anda perlu membaliknya kembali (jika kami ingin menangkap dari atas, kami tidak memerlukan ini).
- Bagian ini melakukan dua tugas. Pertama, ia memusatkan target render sedemikian rupa sehingga medianya berada di koordinat (0, 0) dari ruang dunia. Dia kemudian mengubah koordinat dari ruang dunia ke ruang UV.
Selanjutnya, buat node yang dipilih dan gabungkan perhitungan sebelumnya seperti yang ditunjukkan di bawah ini. Untuk
Sampel Tekstur, pilih
RT_Capture .
Ini akan memproyeksikan target render ke tanah. Namun, semua simpul di luar area tangkapan akan mengambil sampel tepi target render. Ini sebenarnya masalah karena target render seharusnya hanya digunakan untuk simpul dalam area tangkapan. Begini tampilannya dalam game:
Untuk memperbaikinya, kita perlu menutupi semua UV yang berada di luar kisaran 0 hingga 1 (mis., Area tangkapan). Untuk ini, saya membuat fungsi
MF_MaskUV0-1 . Ini mengembalikan
0 jika UV yang ditransmisikan berada di luar kisaran 0 hingga 1 dan mengembalikan
1 jika ada di dalamnya. Mengalikan hasilnya dengan target render, kami melakukan masking.
Sekarang kita telah memproyeksikan render target, kita dapat menggunakannya untuk mencampur warna dan memindahkan titik.
Menggunakan Target Render
Mari kita mulai dengan mencampur warna. Untuk melakukan ini, kita cukup menghubungkan
1-x ke
Lerp :
Catatan: jika Anda tidak mengerti mengapa saya menggunakan 1-x , saya akan menjelaskan - ini diperlukan untuk membalikkan target render, sehingga perhitungannya menjadi sedikit lebih mudah.
Sekarang kita memiliki jejak, warna bumi berubah menjadi cokelat. Jika tidak ada warna, tetap putih.
Langkah selanjutnya adalah perpindahan simpul. Untuk melakukan ini, tambahkan node yang dipilih dan hubungkan semuanya sebagai berikut:
Ini akan menyebabkan semua area salju naik
25 unit. Daerah tanpa salju memiliki offset nol, yang akan membuat jejak.
Catatan: Anda dapat mengubah DisplacementHeight untuk menambah atau mengurangi level salju. Perhatikan juga bahwa DisplacementHeight memiliki nilai yang sama dengan capture offset. Ketika mereka memiliki makna yang sama, itu memberi kita deformasi yang tepat. Tetapi ada beberapa kasus ketika Anda perlu mengubahnya secara individual, jadi saya meninggalkannya sebagai parameter terpisah.
Klik
Terapkan dan kembali ke editor utama. Buat instance
BP_Capture di level dan berikan koordinatnya
(0, 0, -2000) untuk meletakkannya di bawah tanah. Klik
Play dan berkeliaran dengan tombol
W ,
A ,
S dan
D untuk membelokkan salju.
Deformasi bekerja, tetapi tidak ada jejak yang tersisa! Ini terjadi karena penangkapan menimpa target yang diberikan setiap kali penangkapan dilakukan. Kami membutuhkan beberapa cara untuk membuat trek
permanen .
Membuat Jejak Permanen
Untuk membuat kegigihan, kita perlu render target lain (
buffer konstan ), di mana semua konten capture akan disimpan sebelum ditimpa. Kemudian kita akan menambahkan buffer konstan ke capture (setelah menimpanya). Kami mendapatkan loop di mana setiap target membuat menulis ke yang lain. Ini adalah bagaimana kami akan membuat jejak permanen.
Pertama, kita perlu membuat buffer konstan.
Membuat buffer persisten
Buka folder
RenderTarget dan buat
Target Render baru yang disebut
RT_Persistent . Dalam tutorial ini kami tidak perlu mengubah parameter tekstur, tetapi dalam proyek Anda sendiri, Anda harus memastikan bahwa kedua target yang dirender menggunakan resolusi yang sama.
Selanjutnya, kita membutuhkan materi yang akan menyalin tangkapan ke buffer permanen. Buka
Bahan \ M_DrawToPersistent dan tambahkan simpul
Contoh Tekstur . Pilih tekstur
RT_Capture untuknya dan sambungkan sebagai berikut:
Sekarang kita perlu menggunakan bahan gambar. Klik
Terapkan , lalu buka
BP_Capture . Pertama, buat instance dinamis dari materi (nanti kita perlu memberikan nilai padanya). Tambahkan node yang disorot ke
Event BeginPlay :
Clear Render Target 2D node menghapus setiap target render sebelum digunakan.
Kemudian buka fungsi
DrawToPersistent dan tambahkan node yang disorot:
Selanjutnya, kita perlu memastikan bahwa gambar ke buffer konstan dilakukan di setiap frame, karena penangkapan terjadi di setiap frame. Untuk melakukan ini, tambahkan
DrawToPersistent ke
Event Tick .
Akhirnya, kita perlu menambahkan buffer persisten kembali ke target capture render.
Rekam kembali untuk ditangkap
Klik
Kompilasi dan buka
PP_DepthCheck . Kemudian tambahkan node yang disorot. Untuk
Sampel Tekstur, tetapkan nilainya ke
RT_Persistent :
Sekarang target membuat menulis satu sama lain, kami mendapatkan jejak yang tersisa. Klik
Terapkan , lalu tutup materi. Klik
Play dan mulai meninggalkan trek!
Hasilnya tampak hebat, tetapi sirkuit yang dihasilkan hanya berfungsi untuk satu area peta. Jika Anda melampaui area tangkapan, jejak akan berhenti muncul.
Anda dapat mengatasi masalah ini dengan memindahkan area tangkap dengan pemain. Ini berarti bahwa jejak akan selalu muncul di sekitar area di mana pemain berada.
Catatan: saat pengambilan bergerak, semua informasi di luar area pengambilan dihapus. Ini berarti bahwa jika Anda kembali ke area di mana sudah ada jejak, maka mereka akan menghilang. Dalam tutorial berikutnya, saya akan menunjukkan kepada Anda cara membuat trek yang dipertahankan sebagian.
Tangkap gerakan
Anda dapat memutuskan bahwa itu cukup sederhana untuk mengikat posisi penangkapan XY ke posisi pemain XY. Tetapi jika Anda melakukannya, maka target render akan mulai kabur. Ini karena kami memindahkan target render dengan langkah yang kurang dari satu piksel. Ketika ini terjadi, posisi piksel baru berada di
antara piksel. Akibatnya, satu piksel diinterpolasi oleh beberapa piksel. Begini tampilannya:
Untuk memperbaiki masalah ini, kita perlu memindahkan tangkapan dalam langkah-langkah terpisah. Kami menghitung
ukuran piksel di dunia , dan kemudian memindahkan tangkapan ke langkah yang sama dengan ukuran itu. Maka setiap piksel tidak akan pernah berada di antara yang lain, sehingga kekaburan tidak akan muncul.
Untuk memulai, mari kita buat parameter di mana lokasi pengambilan akan disimpan. Bahan bumi akan membutuhkannya untuk melakukan perhitungan proyeksi. Buka
MPC_Capture dan tambahkan
Parameter Vektor yang disebut
CaptureLocation .
Selanjutnya, Anda perlu memperbarui materi bumi untuk menggunakan parameter baru. Tutup
MPC_Capture dan buka
M_Landscape . Ubah bagian pertama dari perhitungan proyeksi sebagai berikut:
Sekarang target render akan selalu diproyeksikan ke lokasi penangkapan. Klik
Terapkan dan tutup materi.
Selanjutnya, kita akan melakukan penangkapan dengan langkah terpisah.
Gerakan menangkap langkah diskrit
Untuk menghitung ukuran piksel di dunia, Anda dapat menggunakan persamaan berikut:
(1 / RenderTargetResolution) * CaptureSize
Untuk menghitung posisi baru, kami menggunakan persamaan yang ditunjukkan di bawah ini untuk setiap komponen posisi (dalam kasus kami, untuk koordinat X dan Y).
(floor(Position / PixelWorldSize) + 0.5) * PixelWorldSize
Sekarang gunakan dalam pengambilan cetak biru. Untuk menghemat waktu, saya membuat makro
SnapToPixelWorldSize untuk persamaan kedua. Buka
BP_Capture , lalu buka fungsi
MoveCapture . Selanjutnya, buat diagram berikut:
Ini akan menghitung lokasi baru, dan kemudian menyimpan perbedaan antara lokasi baru dan saat ini di
MoveOffset . Jika Anda menggunakan resolusi selain 256 Γ 256, maka ubah nilai yang disorot.
Selanjutnya, tambahkan node yang dipilih:
Sirkuit ini akan memindahkan tangkapan dengan offset yang dihitung. Dia kemudian akan menyimpan lokasi pengambilan baru di
MPC_Capture sehingga dapat digunakan oleh bahan dasar.
Akhirnya, kita perlu melakukan pembaruan posisi di setiap frame. Tutup fungsinya dan tambahkan ke
Event Tick sebelum
DrawToPersistent MoveCapture .
Memindahkan tangkapan hanya setengah dari solusi. Kita juga perlu memindahkan buffer konstan. Kalau tidak, capture dan buffer persisten akan tidak sinkron dan akan menghasilkan hasil yang aneh.
Pindah Buffer Permanen
Untuk menggeser buffer konstan, kita harus melewati offset perpindahan yang dihitung. Buka
M_DrawToPersistent dan tambahkan node yang disorot:
Karena ini, buffer konstan akan digeser oleh nilai offset yang ditransmisikan. Seperti pada materi bumi, kita perlu membalik koordinat X dan melakukan masking. Klik
Terapkan dan tutup materi.
Maka Anda perlu mentransfer ofset. Buka
BP_Capture , lalu buka fungsi
DrawToPersistent . Selanjutnya, tambahkan node yang disorot:
Ini adalah bagaimana kami mengonversi
MoveOffset ke ruang UV, dan kemudian meneruskannya ke bahan gambar.
Klik
Kompilasi , lalu tutup cetak biru. Klik
Play dan jalankan sesuka hati Anda! Tidak peduli seberapa jauh Anda berlari, jejak akan selalu ada di sekitar Anda.
Ke mana harus pergi selanjutnya?
Proyek yang sudah selesai dapat diunduh dari sini.
Tidak perlu menggunakan trek yang dibuat dalam tutorial ini untuk salju saja. Anda bahkan dapat menggunakannya untuk hal-hal seperti rumput yang dihancurkan (dalam tutorial berikutnya saya akan menunjukkan cara membuat versi lanjutan dari sistem).
Jika Anda ingin bekerja dengan lanskap dan rendering target, saya sarankan menonton video Chris Murphy
Building High-End Gameplay Effects dengan Blueprint . Tutorial ini akan menunjukkan cara membuat laser besar yang membakar bumi dan rumput!