Saya memiliki latar belakang teknik sipil dan melakukan analisis hidrolik dan hidrologi secara teratur. Mereka menjual derajat untuk hal semacam itu, tapi itu benar-benar bukan ilmu roket. Baru-baru ini saya memikirkannya untuk mengimplementasikan seluruh proses hidrologi dan hidraulik untuk medan pada GPU. Saya belajar compute shaders hanya baru-baru ini jadi saya saat ini terjebak menjadi lebih baik di bidang teknik daripada merancang alur kerja GPU paralel.
Anda dapat menghitung jumlah air yang dihasilkan selama acara curah hujan menggunakan rumus:
Q (CF/S) = c * I (in/hr) * A (acres)
Saya mengalami kesulitan bergerak melampaui menghitung "luas" bahkan dari area pertama.
Ikhtisar implementasi saat ini:
- Medan adalah kisi-kisi simpul reguler pada interval 1 unit
- Heightmap berisi satu nilai tinggi R32 untuk setiap simpul
- Saat ini, saya hanya mengizinkan aliran dalam 4 arah mata angin (tanpa diagonal)
- Saya menggunakan Texture2D [int] sebagai stensil untuk simpul yang telah saya analisis
Algoritma saat ini:
- Ketika alat medan telah aktif dan, sekarang, tidak ....
- Bersihkan "stensil".
- Pindai seluruh medan untuk ketinggian terendah.
- Titik tunggal itu adalah input awal ke CS_Flood.
- CS_Flood membuat pass sumbu-X.
- Setiap simpul input diproyeksikan dalam arah X- dan X + hingga 2048 kali.
- Menemukan titik terdekat dengan koordinat OOB menunjukkan tepi medan ke arah ini. CurrentPoint ditambahkan ke buffer BoundaryPoints dan loop proyeksi untuk arah itu diakhiri. Ini mudah dan berfungsi hebat setiap saat.
- Verteks yang berdekatan dengan ketinggian> = ketinggian puncak saat ini ditandai dalam stensil dan ditambahkan ke buffer NextPass.
- Verteks yang berdekatan dengan ketinggian <ketinggian puncak saat ini menunjukkan puncak punggungan dan mengakhiri loop proyeksi. Iterasi banjir di masa depan mungkin mengalir di sekitar pangkal punggungan, di sisi "belakang" dan mendeteksi punggungan yang sama untuk kedua kalinya.
- Titik puncak / punggungan yang terdeteksi lebih dari sekali tidak akan menjadi BoundaryPoint, untuk tujuan ini.
- Titik puncak / punggungan yang terdeteksi tepat sekali ditambahkan ke BoundaryPoints dan loop proyeksi ke arah itu diakhiri.
- CS_Flood membuat pass sumbu-Z dengan kode yang sama, menggunakan titik-titik yang dihasilkan oleh pass sumbu-X sebagai input.
- Saat ini, CS_Flood terus bergantian antara dua arah tanpa batas. Akhirnya, saya akan mengakhiri keseluruhan loop setiap kali CS_Flood selesai dan buffer NextPass kosong.
Idealnya, pada titik itu, BoundaryPoints akan berisi setiap titik yang terjadi pada pembagian drainase alami. Tetesan air yang mendarat di dalam batas akhirnya mengalir ke titik rendah yang sama. Tetesan air mendarat ouside batas pergi "ke tempat lain".
Kemudian:
- Tanpa menghapus stensil, pindai kembali medan untuk titik terendah, tanpa stensil,.
- Iterasi CS_Flood.
- Ulangi sampai stensil penuh (atau yang serupa).
3D sulit dipahami dengan warna-warna ini; ini menunjukkan garis kontur pada ketinggian integral:
(lubang dikelilingi oleh tanggul di dekat tepi)
Ada sekitar 10 cara unik untuk mengalirkan seluruh simpul; memberikan masing-masing warna yang unik seperti:
(tanda alat melingkar yang terlihat, "punggungan" muncul dengan baik)
Ini menunjukkan setiap titik yang dihasilkan oleh CS_Flood, batas atau lainnya, sebagai POINTLIST:
Algoritma selalu hampir berfungsi . Terkadang, ia bekerja dengan benar. Di lain waktu, algoritmanya jelas terkandung pada bentuk yang benar tetapi akan terus menghasilkan poin tanpa batas. Seperti yang terlihat di tangkapan layar ke-3, kadang-kadang menjadi bingung. Pasti ada situasi / faktor lain yang saya abaikan. Saya akan menghargai bantuan apa pun yang menemukan pengawasan atau saran saya tentang cara-cara yang lebih sederhana dan / atau lebih elegan untuk menyerang masalah tersebut.
MissingPoint! dapat dimasukkan dengan membantu algoritma untuk menambahkan setiap BoundaryPoint baru yang terdeteksi ke buffer NextPass. Selama operan berikutnya, 99% poin yang dihasilkan oleh band-aid itu akan menghabiskan sedikit waktu GPU menentukan bahwa mereka tidak dapat pergi ke mana pun dan tidak melakukan apa-apa. Selama pass pertama, mengirimkan LowestPoint bersama dengan poin NextPass lainnya juga akan menangani skenario khusus ini.
Saya tahu itu masuk akal dan, diberikan waktu yang cukup, saya akan dapat cukup membantu untuk melakukan apa yang saya inginkan. Saya ingin melakukannya dengan cara yang lebih baik, lebih cerdas, lebih cepat, jika mungkin, dan saya belum memiliki pengalaman yang cukup untuk mengetahui lebih baik.
Jawaban:
Ketika setetes "mencoba" untuk mengunjungi titik, stensil itu ditandai dengan
InterlockedExchange
menggunakan "nilai asli" untuk menentukan apakah sudah stensil (walaupun saya baru saja menimpanya).Algoritma terbaik yang saya hasilkan memberi banjir "scratch pad" dan satu aturan: "jangan mengalir turun-bukit" (ketinggian sama dengan atau lebih besar). Itu menghilangkan hampir semua tes yang rumit. Meskipun umumnya bagus untuk tidak mengalir di atas puncak / punggungan, itu mengalir sepanjang mereka karena simpul yang berdekatan "datar". Ini kadang-kadang memungkinkan tetes untuk menyelinap melewati garis punggungan.
Setiap titik "terlalu jauh" adalah, "mengalir" dan akan mengalir "ke" area drainase (berhenti pada angka 1) atau tidak (berhenti pada angka 0). "Nots" dibuang dan scratch-pad yang dikoreksi disalin ke "final". Jika final sudah di-stensil, maka scratch scratch akan dibuang. (Masa depan: tumbukan itu secara kolektif harus mewakili batas luar area drainase saat ini.)
Di 10FPS:
The "nots" ditampilkan dalam warna merah, setelah area besar disalin ke final dan menjadi hijau, maka algoritma mengulangi untuk area yang belum distilasi tersisa.
sumber