Bagaimana Penandatanganan Jarak Medan Ray Jarak Jauh diterapkan untuk dunia yang dinamis?

10

Saya rasa saya mengerti dasar-dasar Signed Distance Field Ray Marching. Anda memodelkan adegan Anda dengan sekelompok bidang jarak (seperti ini: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm ), lalu untuk setiap piksel yang Anda lemparkan, mulai dari awal sinar , temukan jarak ke objek terdekat pada titik itu, dan tambah titik dengan jarak terdekat, hingga Anda menabrak sesuatu. Saya berhasil membuat penyaji sederhana, dan di situlah sebagian besar deskripsi teknik berhenti.

Ini membuat saya memiliki beberapa pertanyaan tentang bagaimana SDF Ray Marching dapat digunakan dalam skenario dunia nyata:

Pertanyaan 1: Dalam permainan nyata, adegan biasanya kompleks dan dimuat pada CPU, dengan banyak objek dinamis. Saya mengerti pemusnahan oklusi dasar (seperti octrees), dan dengan rendering poligonal, saya akan membuat daftar (pada CPU) item-item dalam tampilan frustrum untuk di-render.

Jadi, bayangkan saya memiliki adegan yang sangat kompleks dengan banyak karakter dan objek dinamis bergerak di layar, dikendalikan oleh CPU. Bagaimana cara saya streaming objek yang ingin saya render ke setiap frame GPU? Setiap contoh memiliki adegan yang dikodekan dalam GLSL. Bisakah seseorang membagikan contoh level yang dialirkan ke shader secara dinamis?

Pertanyaan 2: Bagaimana benda bisa memiliki banyak warna? Fungsi jarak hanya mengembalikan jarak, tetapi bagaimana implementasi umumnya melewatkan warna kembali? (misalnya Anda menekan bola merah dan bukan kubus biru.) Jika ini adalah implementasi CPU, saya bisa memanggil fungsi global di dalam fungsi jarak ketika itu adalah hit untuk menghentikan ray marcher, dan itu juga bisa melewati objek hit. tekstur / warna. Tapi, bagaimana Anda mengembalikan warna atau tekstur item dalam GLSL?

Terima kasih.

Andrew Price
sumber

Jawaban:

2

Ini adalah jawaban yang minimal, tetapi ingin berbagi info jika Anda tidak mendapatkan jawaban yang lebih baik.

Mengenai bagaimana game nyata menggunakan ray marching, mereka biasanya tidak. Hanya dalam beberapa tahun terakhir gim-gim ini mulai melakukan raymarching buffer kedalaman untuk melakukan refleksi ruang layar, tetapi tidak ada game yang saya tahu menggunakan ray-marching seperti yang Anda gambarkan - belum?

Untuk pertanyaan lain tentang warna dan semacamnya, orang biasanya mengasosiasikan material dengan objek dan menggunakan "koordinat tekstur" pada titik di mana sinar mengenai objek untuk mengetahui sifat material pada titik itu pada objek. Bahan umum termasuk hal-hal seperti warna difus, intensitas specular, warna emisif dan indeks transparansi / refraksi.

Semoga itu setidaknya beberapa bantuan untuk Anda! Anda mungkin juga mendapatkan jawaban yang bagus dari situs pertukaran tumpukan grafis.

Alan Wolfe
sumber
2
"tidak ada game yang saya tahu menggunakan ray marching seperti yang Anda gambarkan" Game mendatang Molecule, Dreams menggunakan field jarak yang ditandatangani untuk pembuatan konten yang dibuat pengguna, tetapi jika saya mengerti benar, field tersebut dikonversi ke cloud point untuk rendering alih-alih sedang raymarched langsung. Artikel ini mungkin memiliki beberapa ide: dualshockers.com/2015/08/15/...
DMGregory
1
@ DMGregory Bagus, tapi saya pikir ini bukan Ray Marching. Jadi intinya masih berlaku, game biasanya tidak menggunakan ray marching.
concept3d
1
Memperbarui utas ini - game yang akan datang Claybook dilaporkan membuat adegannya menggunakan sinar yang ditembakkan melalui bidang jarak jauh secara langsung , daripada mengubahnya menjadi geometri konvensional terlebih dahulu. Jadi "belum?" tampaknya telah lahir selama dua tahun. :)
DMGregory
1

Saat ini saya sedang mengembangkan mesin gim yang menggunakan bidang jarak yang ditandatangani sebagai teknik render untuk menampilkan geometri prosedural yang lancar (dihasilkan dengan primitif sederhana seperti yang ada di tautan Anda untuk saat ini, mencari untuk mengimplementasikan fraktal Julia dan IFS di masa mendatang). Karena mesin saya difokuskan pada generasi prosedural dan harus mendefinisikan angka dengan cara yang membuat mereka ramah sinar, saya kira saya berada di tempat yang baik untuk menjawab pertanyaan ini: P.

Mengenai streaming, solusi sederhana adalah dengan menggunakan semacam buffer yang diketikkan dan melemparkannya ke GPU ketika Anda ingin melakukan ray-marching Anda. Setiap elemen buffer adalah tipe kompleks (mis. Struct dalam C / C ++), dan setiap tipe berisi elemen yang mendefinisikan fungsi apa yang harus Anda gunakan untuk merepresentasikannya, posisinya, rotasi, skala, dll, dan warna rata-rata. Proses kemudian disederhanakan menjadi:

  1. Cull adegan Anda menjadi subset dikelola (perhatikan bahwa culling frustum dan oklusi culling sebagian dilakukan secara otomatis oleh algoritma ray-marching)
  2. Masukkan subset ke buffer input render Anda
  3. Lewati buffer ke GPU jika belum ada di sana, lalu render adegan Anda dengan marching ray tradisional biasa. Anda akan perlu melakukan semacam pencarian per langkah untuk mengevaluasi item mana dalam buffer input yang paling dekat dengan setiap ray untuk setiap iterasi dari march-ray, dan Anda harus menerapkan transformasi ke salah satu sinar (dalam hal ini Anda harus membalik angka rotasi sebelum mencapai GPU) atau fungsi jarak itu sendiri (memindahkan asal fungsi untuk perubahan posisi, menyesuaikan misalnya panjang sisi kubik untuk perubahan skala, dll.) Pendekatan paling sederhana adalah dengan hanya memodifikasi sinar sebelum Anda meneruskannya ke fungsi jarak inti aktual.

Mengenai warna figur, ingatlah bahwa shader memungkinkan Anda untuk mendefinisikan tipe kompleks dan primitif;). Itu memungkinkan Anda untuk melemparkan semuanya ke dalam struct gaya-C, kemudian meneruskannya kembali dari fungsi jarak Anda.

Di mesin saya, setiap struct berisi jarak, warna, dan ID yang mengikatnya ke definisi gambar yang sesuai di buffer input. Setiap ID disimpulkan dari konteks sekitarnya dari fungsi jarak yang relevan (karena fungsi pemetaan saya loop melalui buffer input untuk menemukan angka terdekat dengan setiap sinar untuk setiap langkah, saya dapat dengan aman memperlakukan nilai penghitung loop ketika setiap SDF dipanggil sebagai ID gambar untuk fungsi itu), sedangkan nilai jarak didefinisikan menggunakan SDF inti sewenang-wenang (mispoint - figure.pos untuk sebuah bola), dan warna dapat didefinisikan dari warna rata-rata elemen yang sesuai dalam buffer angka (oleh karena itu mengapa berguna untuk menjaga ID gambar tetap ada) atau melalui warna prosedural yang tertimbang menuju rata-rata yang disimpan (salah satu contoh mungkin mengambil hitungan iterasi untuk beberapa titik pada Mandelbulb, memetakan "warna rata-rata" Anda dari ruang warna FP ke ruang warna bilangan bulat, lalu menggunakan warna yang dipetakan sebagai palet dengan XOR'ing terhadap jumlah iterasi).

Tekstur prosedural adalah pendekatan lain, tetapi saya tidak pernah menggunakannya sendiri. iq telah melakukan banyak penelitian di bidang itu dan memposting beberapa demonstrasi menarik di Shadertoy, sehingga bisa menjadi salah satu cara untuk mengumpulkan beberapa informasi tambahan.

Terlepas dari apakah warna Anda statis untuk setiap angka, yang dihasilkan secara prosedural, atau ajaib sampel dari tekstur prosedural, logika dasar adalah sama: angka Abstrak menjadi semacam jenis kompleks menengah (misalnya struct), menyimpan baik jarak lokal dan lokal warna dalam instance dari tipe itu, kemudian lulus tipe kompleks sebagai nilai balik dari fungsi jarak Anda. Bergantung pada implementasi Anda, warna output kemudian dapat melewati langsung ke layar, atau mengikuti titik tumbukan ke kode pencahayaan Anda.

Saya tidak tahu apakah hal di atas cukup jelas atau tidak, jadi jangan khawatir menanyakan apakah ada yang tidak masuk akal. Saya tidak bisa benar-benar memberikan sampel kode GLSL / pixel-shading karena saya bekerja dengan HLSL dan menghitung shading, tapi saya senang mencoba dan membahas apa pun yang saya tidak tulis dengan benar sejak awal :).

Paul Ferris
sumber