Saya telah mengalami banyak kesulitan untuk mencoba fungsi campuran OpenGL agar berfungsi seperti yang saya harapkan dengan apa yang saya harapkan (atau dari program pengeditan gambar yang masuk akal). Sebagai contoh, saya akan menggunakan dua gambar ini untuk berbaur (agak sulit dilihat pada latar belakang putih sehingga warna diberi label):
Gambar yang akan dicampur
Inilah yang saya harapkan terjadi (dan apa yang terjadi di paint.net):
Hasil yang diharapkan
Jelas fungsi campuran default opengl membuatnya terlihat seperti ini (sangat salah):
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Setelah banyak pengujian, ini adalah yang terdekat yang bisa saya dapatkan untuk membuat fungsi campuran "baik":
glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
Melihat kembali pada hasil yang diharapkan, Anda akan melihat bahwa beberapa warna sedikit lebih redup daripada seharusnya (bagian kiri tengah). Secara khusus, mereka ditakdirkan untuk setengah nilai warna mereka (karena alpha .5), dan saya tidak bisa membuat fungsi yang tidak melakukan ini (tanpa menyebabkan masalah pencampuran aneh dengan bagian transparan merah yang nyaris tidak terlihat).
Adakah yang tahu solusi untuk masalah ini? Salah satu yang saya miliki adalah menggunakan alpha yang di-pre-multiplikasi di sumber (sementara saya tidak ingin melakukan ini karena membutuhkan kerja ekstra untuk mengubah setiap warna yang saya gunakan dalam game saya untuk di-pre-multiplikasi atau hanya menulis beberapa hal di setiap shader) dan melakukannya seperti itu :
glBlendFuncSeparate (GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) (Tanpa premultiplikasi)
Jelas itu salah juga, tetapi ini sebenarnya satu-satunya hasil yang benar yang saya dapatkan sejauh ini:
glBlendFuncSeparate (GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) (input yang diultipultasikan)
Satu-satunya masalah adalah, bagaimana saya menyingkirkan premultiplikasi untuk menampilkannya di layar? Mungkin akan membutuhkan siklus render tambahan untuk setiap hal yang saya gabungkan dan itu tampaknya terlalu rumit untuk masalah ini, jadi saya masih mencari jawaban (yang menarik sehingga saya tidak dapat menemukan apa pun tentang ini, karena OpenGL sangat banyak digunakan sehingga Saya akan membayangkan orang lain mengalami masalah ini).
Sumber:
Pengujian fungsi campuran online - http://www.andersriggelsen.dk/glblendfunc.php
Gambar Lapisan Bawah - http://i.stack.imgur.com/XjLNW.png
Gambar Lapisan Atas - http: //i.stack.imgur .com / 9CN6w.png
sumber
Jawaban:
Dalam contoh pertama Anda (
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
), Anda mengatakannya untuk mencampur warna berdasarkan alpha dari gambar yang digambar di atas ("Foreground"). Jadi ketika Anda memadukan 50% antara warna latar depan(38,50,168)
dan warna latar belakang(38,50,168)
di sudut kiri bawah gambar, Anda secara mengejutkan mendapatkan warna yang persis sama(38,50,168)
. Karena perpaduan silang itulah yang Anda perintahkan kepada OpenGL untuk dilakukan.Menilai dari gambar "yang diharapkan" Anda, Anda tidak ingin melakukan perpaduan antara dua warna - Anda ingin overlay warna latar depan di atas warna latar belakang kekuatan penuh, bukan perpaduan lintas di antara keduanya.
Untuk melakukan itu, Anda ingin menggunakan glBlendFuncSeparate (karena Anda memperlakukan warna latar belakang berbeda dari alpha-nya), dan menentukan bahwa selama operasi blending, nilai alfa latar belakang harus diperlakukan sebagai 100%.
Untuk membuatnya lebih mudah dilihat, inilah nilai-nilai RGB akhir yang diproduksi:
Dan inilah nilai transparansi akhir yang dihasilkan.
(Area transparansi '100%' itu seharusnya benar-benar dilabeli sebagai 99,7% transparan, dan area '50% 'kanan bawah harus dilabeli sebagai 49,7% transparan, keduanya karena bit berwarna merah di sisi kanan gambar pertama. Juga, maaf untuk daftar nomor menggunakan "transparansi" daripada opacity; mungkin sedikit membingungkan.)
Jika ada masalah khusus, harap tunjukkan area RGB atau gambar alfa yang menghasilkan nilai yang salah.
sumber
GL_ONE
juga? Kalau tidak, persamaan alfa sepertidest_alpha = src_alpha * src_alpha + 1 * dest_alpha
(0,0,0)
. Tentu saja lebih gelap daripada saat Anda mencampurnya dengan 50%(255,255,255)
.finalAlpha = srcAlpha + destAlpha * (1 - srcAlpha)
danfinalColor = ((srcColor * srcAlpha) + (destColor * destAlpha * (1 - srcAlpha))) / finalAlpha
TheColor * Alpha
bit dalam perhitungan warna bisa dilakukan di shader oleh keluaran nilai premultiplied, tapi theres ada cara untuk membagi oleh finalAlpha untuk menyingkirkan premultiplication tersebut. (Diambil dari sini )Saya memiliki masalah yang sama persis ketika saya ingin membuat satu set objek framebuffer yang tumpang tindih seperti lapisan. Masalahnya adalah fungsi Open GL blending linier dan berfungsi ketika latar belakang tujuan buram. Tetapi persamaan pencampuran aktual untuk pencampuran dua lapisan transparan bukanlah persamaan linier dan mengandung bagian pembagian.
out_color = {src_color * src_alpha + dest_color * dest_alpha * (1-src_alpha)} / out_alpha
Saya rasa tidak mungkin melakukan ini dengan implementasi OpengGL saat ini. Jadi sebagai pekerjaan di sekitar saya harus menggunakan shader piksel untuk secara manual menghitung output setiap piksel.
sumber