Apa beberapa metode untuk membuat transparansi di OpenGL

14

Alpha blending dapat dinyalakan untuk membuat permukaan transparan, seperti:

glDisable(GL_DEPTH_TEST); //or glDepthMask(GL_FALSE)? depth tests break blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Tapi ini hanya berfungsi jika objek dirender di urutan belakang ke depan. Kalau tidak, hal-hal di latar belakang muncul di depan objek yang lebih dekat, seperti lantai pada gambar di bawah ini. Untuk menyortir partikel dan elemen GUI boleh saja, tetapi untuk jerat segitiga sepertinya terlalu banyak usaha dan lambat, seperti yang dibahas di sini: https://www.opengl.org/wiki/Transparency_Sorting .

Apa metode umum untuk mengatasi ini? Saya tahu ini cukup luas dan tidak mengejar rincian implementasi yang mendalam, hanya uraian singkat tentang beberapa pendekatan dan apa yang mungkin terlibat.

masukkan deskripsi gambar di sini

jozxyqk
sumber
Saya tidak yakin apakah ini harus sebagai jawaban atau tidak, tetapi kesalahan pada gambar Anda disebabkan oleh rendering tanpa pengujian mendalam pada semua primitif. Anda harus membuat adegan dalam 2 pass: Pertama, biasanya membuat semua geometri padat. Setelah itu, nonaktifkan penulisan kedalaman (bukan GL_DEPTH_TEST) dan render geometri transparan dalam urutan back-to-front. Ini akan memastikan bahwa geometri transparan tidak akan digambar di depan geometri padat yang ada di depannya.
yuriks
@yuriks Dalam hal ini mungkin contoh yang buruk di pihak saya, tetapi semuanya harus transparan. Saya ingin sesuatu menunjukkan betapa salahnya transparansi bila dilakukan dengan buruk. Juga contoh di mana penyortiran geometri akan sangat sulit (misalnya di sini lantai adalah satu poligon raksasa dan mencakup seluruh rentang kedalaman).
jozxyqk

Jawaban:

10

Serangkaian teknik untuk menghindari pemesanan eksplisit menggunakan nama Transparansi Independen Pesanan (disingkat OIT).

Ada banyak teknik OIT.

Secara historis salah satunya adalah Depth Peeling . Dalam pendekatan ini, pertama-tama Anda membuat fragmen / piksel paling depan, kemudian Anda menemukan yang paling dekat dengan yang ditemukan pada langkah sebelumnya dan seterusnya, dengan sebanyak "lapisan" yang Anda butuhkan. Ini disebut pengelupasan kedalaman karena pada setiap lintasan Anda "mengupas" satu lapisan kedalaman. Semua layer Anda kemudian dapat digabungkan secara normal dari belakang ke depan. Untuk mengimplementasikan algoritma ini, Anda perlu memiliki salinan buffer kedalaman.

Serangkaian teknik lain adalah teknik campuran OIT. Salah satu yang paling baru dan menarik adalah Weighted Blended OIT yang diusulkan oleh McGuire dan Bavoil . Ini pada dasarnya menerapkan jumlah tertimbang untuk semua permukaan yang menempati fragmen tertentu. Skema pembobotan yang mereka usulkan didasarkan pada kamera-ruang Z (sebagai perkiraan oklusi) dan opacity.
Idenya adalah bahwa jika Anda dapat mengurangi masalah menjadi jumlah tertimbang, Anda tidak benar-benar peduli tentang pemesanan.

Selain kertas asli, sumber yang bagus untuk detail implementasi dan masalah Weighted Blended OIT ada di blog Matt Pettineo . Seperti yang dapat Anda baca dari jabatannya, teknik ini bukan peluru perak. Masalah utama adalah bahwa skema pembobotan adalah pusat dan perlu disetel sesuai dengan adegan / konten Anda. Dari eksperimennya, sementara tekniknya tampaknya bekerja dengan baik untuk opacity yang relatif rendah dan sedang, itu gagal ketika opacity mendekati 1 dan karenanya tidak dapat digunakan dari bahan-bahan di mana sebagian besar permukaannya buram (ia membuat contoh dedaunan).

Sekali lagi, semua berujung pada bagaimana Anda menyetel bobot-kedalaman Anda dan menemukan yang cocok dengan kasus-penggunaan Anda belum tentu sepele.

Adapun apa yang dibutuhkan untuk Weighted Blended OIT, tidak lebih dari dua target render tambahan. Warna yang Anda isi dengan warna alfa yang telah ditiru sebelumnya (warna * alfa) dan alfa, keduanya diberi bobot yang sesuai. Yang lain hanya untuk bobot.

cifz
sumber
6

Salah satu pilihan adalah dengan menggunakan peeling dalam.

Pada dasarnya, seseorang memproses adegan beberapa kali (katakanlah, nkali) untuk menentukan yang terdekat, yang kedua paling dekat, sampai nke fragmen yang paling dekat dari adegan tersebut.

Pemrosesan ini dilakukan dengan terlebih dahulu menerapkan uji kedalaman biasa ke seluruh adegan (yang secara alami mengembalikan permukaan terdekat). Seseorang kemudian menggunakan hasil dari tes kedalaman untuk menyaring lapisan pertama, dengan mengabaikan segala sesuatu dengan kedalaman yang lebih rendah daripada yang dikembalikan dalam tes kedalaman.

Menerapkan tes kedalaman lagi akan mengembalikan lapisan kedua. Ulangi sesuai kebutuhan.

Setelah Anda memiliki lapisan, Anda bisa menggambar semua lapisan dalam urutan terbalik (dengan asumsi Anda melacak warna RGBA untuk setiap lapisan), pencampuran secara normal, karena lapisan berada dalam urutan depan-ke-belakang.

es1024
sumber
1
Terima kasih! Sepertinya saya perlu dua buffer dalam untuk ini. Yaitu satu untuk menyimpan dan menyaring kedalaman terakhir, dan satu untuk melakukan pengujian mendalam untuk render saat ini. Koreksi saya jika saya salah, tetapi saya berasumsi saya akan membutuhkan dua tekstur mendalam untuk FBO yang saya tukarkan di antara setiap pass yang terkelupas.
jozxyqk
1
@ jozxyqk Benar, diperlukan dua buffer kedalaman untuk prosedur ini.
es1024
1

Creme de la creme single-pass no (atau beberapa) kompromi transparansi dalam OpenGL adalah A-buffer. Dengan OpenGL modern, dimungkinkan untuk menerapkan:

http://blog.icare3d.org/2010/06/fast-and-accurate-single-pass-buffer.html

Ini menghindari beberapa lintasan pengelupasan kedalaman dan tidak memerlukan penyortiran berat.

XenonofArcticus
sumber
3
Idealnya, jawaban harus lengkap dan sangat bergantung pada tautan eksternal. Memiliki tautan bagus untuk bahan pelengkap, tetapi jawaban tidak hanya terdiri dari kata kunci. Jika Anda dapat memasukkan beberapa detail tentang apa itu buffer-A dan cara kerjanya yang akan sangat meningkatkan jawaban Anda.
Martin Ender