Menghindari z-fighting dengan permukaan yang bertepatan

26

Saat merender dua permukaan co-planar yang tumpang tindih, masalah umum adalah "z-fighting", di mana penyaji tidak dapat memutuskan yang mana dari dua permukaan yang lebih dekat dengan kamera, memberikan artefak visual di bidang tumpang tindih.

Solusi standar untuk ini adalah untuk memberikan permukaan sedikit offset ketika merancang model. Apakah ada solusi yang lain?

Menandai
sumber
2
Anda dapat memeriksa buffer kedalaman logaritmik. Ada sebuah artikel di gamasutra
Soapy
1
Ketika Anda mengatakan "co-planar", apakah yang Anda maksud adalah co-planar "hampir" atau "persis" dan jika yang terakhir, apakah permukaan tersebut merupakan permukaan / segitiga yang identik? Perangkat keras rendering harus deterministik (dengan asumsi Anda tidak mengirimkan dalam urutan acak) untuk kasus terakhir dan tidak memiliki pertempuran. Jika ini merupakan kasus permukaan yang tidak identik tetapi persis co-planar, dapatkah Anda memperbarui model untuk membagi permukaan menjadi bagian yang tumpang tindih dan tidak tumpang tindih?
Simon F
@SimonF, oleh "co-planar" Maksudku "persis co-planar". Solusi Soapy hanya bekerja dalam kasus "hampir co-planar".
Markus
Bisakah Anda memberi contoh permukaan Anda? Satu-satunya hal yang dapat saya pikirkan dari atas kepala saya adalah duplikat segitiga seperti yang disebutkan @SimonF.
RichieSams
@RichieSams kasus paling umum yang dapat saya pikirkan adalah decals, di mana Anda tidak perlu duplikat segitiga.
Hari

Jawaban:

10

Jika permukaannya persis co-planer, nasib Anda tergantung pada para dewa FPU; Anda kemungkinan besar akan melawan Z. Jika segitiga identik dan Anda melakukan matematika yang sama persis untuk masing-masing, Anda akan berakhir dengan nilai Z yang sama untuk keduanya. Tetapi sekali lagi, ini hanya akan terjadi jika operasi matematika Anda identik untuk keduanya. (Karena, secara umum, operasi FPU tidak komutatif)

Salah satu solusi yang mungkin adalah tidak menggunakan buffer-Z sama sekali. Alih-alih, Anda dapat menggunakan Algoritma Painter . Memang, ini hadir dengan semua masalah algoritma pelukis juga. Tapi, itu akan menyelesaikan pertempuran Z.

Dalam contoh kasus Screen Space Decals (SSDs) Anda, solusi umum adalah dengan menggunakan offset, alias kubus tipis sederhana. Lihat presentasi Warhammer 40k tentang SSD untuk referensi. Atau posting Bart Wronski yang membahas beberapa masalah lain dengan decals, tetapi juga tautan ke beberapa presentasi lain tentang SSD

RichieSams
sumber
5
Render ulang geometri yang sama dengan transformasi yang sama tidak andal menghasilkan nilai kedalaman yang sama setiap waktu. (Yaitu itu bukan kekuatan , itu wasiat ). Karena itulah pencahayaan multi-pass berfungsi, misalnya.
Nathan Reed
@NathanReed Dikoreksi. Terima kasih atas klarifikasi
RichieSams
1
Untuk mendapatkan fungsi yang Anda butuhkan untuk menggunakan kualifikasi invarian di GLSL: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu
Perhatikan bahwa ekspresi shader identik (dan input, jelas) ketika mengevaluasi posisi simpul mungkin tidak cukup untuk mendapatkan hasil yang identik karena beberapa optimasi mungkin tergantung pada sisa shader. GLSL memiliki kata kunci "invarian" untuk menyatakan output shader yang harus dievaluasi secara identik di shader yang berbeda.
Firadeoclus
2

Inilah cara saya memecahkan ini di masa lalu:

  1. Gambarlah objek pertama (objek yang akan muncul di belakang objek lain) dengan pengujian mendalam tetapi bukan penulisan mendalam
  2. Gambarlah objek kedua dengan pengujian mendalam dan penulisan mendalam. Ini tidak akan menyebabkan z-fight karena kami tidak menulis kedalaman pada langkah 1.
  3. Gambarlah objek pertama dengan hanya menulis ke buffer kedalaman dan bukan ke buffer warna. Ini memastikan buffer kedalaman up to date untuk setiap piksel yang dicakup oleh objek 1 tetapi tidak oleh objek 2.

Catatan, objek harus digambar secara berurutan agar ini berfungsi.

standar
sumber
0

Bergantung pada renderer Anda, Anda bisa membuat permukaan lebih "fuzzy" menerapkan offset kecil dalam kedalaman multisampling menggunakan algoritma seperti noise. Ini akan menghasilkan semacam efek pencampuran untuk permukaan dalam jarak dekat. Untuk yang saya tahu pengaturan kedalaman per-sampel dalam shader fragmen cukup baru di OpenGL dan kemudian hanya sebagai ekstensi.

OpenGL memiliki PolygonOffset tetapi membutuhkan pengetahuan sebelumnya bahwa Anda akan membuat sesuatu coplanar. Meskipun tidak layak untuk permukaan dalam model tunggal, itu bisa berfungsi dengan baik misalnya ketika merender jalan yang dilapis pada sebidang tanah.

Andreas
sumber