{
Haha, kedua pelajaran ini sudah lama diterjemahkan, tapi belum diposting. Semua orang sudah lama menunggu (Adakah yang menunggu lebih lama lagi?)
transparansi sederhana
Sebagian besar efek khusus di OpenGL terkait dengan beberapa jenis pencampuran (warna).
Pencampuran warna didefinisikan sebagai penggabungan warna piksel tertentu dengan warna piksel terkait yang tergambar di layar.
Cara kedua warna digabungkan bergantung pada nilai komponen saluran alfa warna, dan/atau fungsi pencampuran warna yang digunakan.
Alpha biasanya merupakan komponen warna ke-4 di akhir nilai warna.
Pada pelajaran sebelumnya kita menggunakan GL_RGB untuk menentukan tiga komponen warna.
GL_RGBA yang sesuai dapat menentukan nilai komponen alfa.
Selangkah lebih maju, kita bisa menggunakan glColor4f() sebagai ganti glColor3f().
Kebanyakan orang setuju bahwa komponen Alpha mewakili transparansi suatu materi.
Artinya nilai alpha 0,0 mewakili material yang benar-benar transparan.
Nilai alpha 1,0 mewakili material yang benar-benar buram.
formula pencampuran warna
Jika Anda tidak tertarik dengan matematika dan hanya ingin melihat cara mencapai transparansi, lewati bagian ini.
Jika Anda ingin pemahaman lebih dalam tentang cara kerja pencampuran (warna), bagian ini cocok untuk Anda.
『Penambahan CKER: Sebenarnya tidak sulit^-^. Rumusnya pada artikel aslinya adalah sebagai berikut, mari CKER membicarakannya lagi.
Padahal, prinsip dasar pencampuran adalah memisahkan warna setiap piksel dan warna latar belakang gambar untuk dipisahkan sesuai aturan RGB.
Menurut - Komponen warna RGB pada gambar * nilai alfa + komponen warna RGB pada latar belakang * (nilai 1 alfa)
-Setelah pencampuran dengan rumus sederhana tersebut, komponen RGB yang diperoleh melalui pencampuran akhirnya digabungkan kembali. 』
Rumusnya adalah sebagai berikut:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL menghitung hasil pencampuran warna kedua piksel tersebut sesuai rumus di atas.
Huruf kecil s dan r masing-masing mewakili piksel sumber dan piksel target. Huruf besar S dan D adalah faktor pencampuran warna yang sesuai.
Ini menentukan bagaimana Anda mencampur warna untuk piksel tersebut.
Dalam kebanyakan kasus, nilai pencampuran alfa dari setiap saluran warna adalah sama.
Dengan cara ini, kita mempunyai (As, As, As, As) untuk piksel sumber,
Piksel targetnya adalah 1, 1, 1, 1) - (As, As, As, As).
Rumus di atas menjadi sebagai berikut:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
Formula ini menghasilkan efek transparan/tembus cahaya.
Pencampuran warna di OpenGL
Langkah-langkah menerapkan pencampuran warna di OpenGL mirip dengan proses OpenGL yang kami sebutkan sebelumnya.
Kemudian atur rumusnya dan matikan cache kedalaman tulis saat menggambar objek transparan.
Karena kita ingin menggambar objek di balik bentuk semi transparan.
Ini bukan cara yang benar untuk mencampur warna, tetapi sering kali ini berfungsi dengan baik pada proyek sederhana.
Tambahan Rui Martins: Proses pencampuran warna yang benar adalah menggambar seluruh pemandangan terlebih dahulu, lalu menggambar grafik transparan.
Dan mereka digambar dalam urutan terbalik dari buffer kedalaman (objek terjauh digambar terlebih dahulu).
Pertimbangkan alpha memadukan dua poligon (1 dan 2). Urutan gambar yang berbeda akan memberikan hasil yang berbeda.
(Di sini diasumsikan poligon 1 paling dekat dengan pengamat, maka proses yang benar adalah menggambar poligon 2 terlebih dahulu, lalu menggambar poligon 1.
Seperti yang Anda lihat dalam kenyataan,
Cahaya yang datang dari belakang kedua poligon <transparan> ini selalu melewati poligon 2 terlebih dahulu.
Kemudian melewati poligon 1 dan akhirnya mencapai mata pengamat. )
Saat cache kedalaman diaktifkan, Anda harus mengurutkan grafik transparan berdasarkan kedalaman,
Dan gambarlah objek transparan ini setelah semua adegan digambar. Jika tidak, Anda akan mendapatkan hasil yang salah.
Saya tahu terkadang menyakitkan untuk melakukan hal ini, tetapi ini adalah cara yang tepat untuk melakukannya.
Kami akan menggunakan kode dari Pelajaran 7.
Mulailah dengan menambahkan dua variabel baru di awal kode. Saya menulis ulang seluruh kode untuk kejelasan.
}
Var
h_RC: HGLRC; // Rendering Konteks (tabel deskripsi bayangan).
h_DC: HDC; // Konteks Perangkat (tabel deskripsi perangkat)
h_Wnd: HWND; // pegangan jendela
h_Instance: HINST; // Contoh Program (contoh).
kunci : Array[0..255] Dari Boolean; // Array untuk rutinitas keyboard
cahaya : Boolean; // sumber cahaya hidup/mati
campuran : Boolean; // Pencampuran MATI/AKTIF?
lp : Boolean; // Apakah tombol L ditekan?
fp : Boolean; // Apakah tombol F ditekan?
bp : Boolean; // Apakah tombol B ditekan?
xrot : GLfloat; // X rotasi
yrot : GLfloat; // rotasi Y
xspeed : GLfloat; // X kecepatan putaran
yspeed : GLfloat; // kecepatan putaran Y
z : GLfloat = -5.0 f; // Jarak jauh ke dalam layar
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //Parameter cahaya sekitar (baru)
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // Parameter cahaya diffuse (baru)
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // Posisi sumber cahaya (baru)
penyaring : Gluint; // Jenis penyaring
texture : Array[0..2] Of GLuint; // Ruang penyimpanan untuk 3 tekstur
Prosedur glGenTextures(n: GLsizei; Var tekstur: GLuint);
bukagl32;
Prosedur glBindTexture(target: GLenum; tekstur: GLuint);
bukagl32;
Fungsi gluBuild2DMipmaps(target: GLenum; komponen, lebar, tinggi: GLint;
format, atype: GLenum; data: Pointer): Integer;
'gluBuild2DMipmaps';
{
Kemudian pindah ke LoadGLTextures().
Temukan apakah (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
Baris ini. Kita sekarang menggunakan tekstur kaca berwarna sebagai pengganti tekstur kotak kayu dari pelajaran sebelumnya.
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // Memuat bitmap kaca (dimodifikasi)
}
Fungsi LoadTexture: boolean; //Muat bitmap dan ubah menjadi tekstur
Var
Status : boolean; // Indikator status
TextureImage : Array[0..1] Of PTAUX_RGBImageRec; // Membuat ruang penyimpanan tekstur
Mulai
Status := salah;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // Setel penunjuk ke NULL
TextureImage[0] := LoadBMP('Dinding.bmp');
Jika TextureImage[0] <> Nihil Lalu
Mulai
Status := BENAR; // Atur Status ke BENAR
glGenTextures(1, tekstur[0]); // Membuat tekstur
// Buat peta filter terdekat
glBindTexture(GL_TEXTURE_2D, tekstur[0]);
// Menghasilkan tekstur
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Gambar Tekstur[0].ukuranX,
Gambar Tekstur[0].ukuranY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TeksturGambar[0].data);
glBindTexture(GL_TEXTURE_2D, texture[1]); //Gunakan tekstur khas yang dihasilkan dari data bitmap
// Menghasilkan tekstur
glTexImage2D(GL_TEXTURE_2D, 0, 3, Gambar Tekstur[0].ukuranX,
Gambar Tekstur[0].ukuranY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TeksturGambar[0].data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Pemfilteran linier
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Pemfilteran linier
//Buat tekstur MipMapped
glBindTexture(GL_TEXTURE_2D, tekstur[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (baru)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
Gambar Tekstur[0].ukuran, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data); //(baru) }
Akhir;
Jika ditugaskan(TextureImage[0]) Lalu // Apakah teksturnya ada
Jika ditugaskan(TextureImage[0].data) Lalu // Apakah gambar tekstur ada
TextureImage[0].data := Nihil; // Lepaskan memori yang ditempati oleh gambar tekstur
TextureImage[0] := Nihil; // Lepaskan struktur gambar
hasil := Status; // Status Pengembalian
Akhir;
{
Tambahkan dua baris berikut ke bagian kode glInit().
Baris pertama menggambar objek ini dengan kecerahan penuh dan memberikan 50% alpha blending (semi-transparan).
Saat opsi blending diaktifkan, objek ini akan menjadi 50% transparan.
Baris kedua menentukan jenis pencampuran yang digunakan.
Ditambahkan oleh Rui Martins:
Nilai saluran alfa 0,0 berarti material objek benar-benar transparan.
1.0 berarti sepenuhnya buram.
}
Prosedur glInit(); // Mulai semua pengaturan untuk OpenGL di sini
Mulai
If (Bukan LoadTexture) Then // Panggil subrutin pemuatan tekstur
exit; // Jika gagal memuat, keluar
glEnable(GL_TEXTURE_2D); // Aktifkan pemetaan tekstur
glShadeModel(GL_SMOOTH); // Aktifkan penghalusan bayangan
glClearColor(0.0, 0.0, 0.0, 0.0); // latar belakang hitam
glClearDepth(1.0); //Setel buffer kedalaman
glEnable(GL_DEPTH_TEST); // Aktifkan pengujian kedalaman
glDepthFunc(GL_LESS); // Jenis pengujian kedalaman selesai
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Penghitungan proyeksi perspektif yang sangat optimal
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]); // Mengatur cahaya sekitar
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]); // Mengatur cahaya menyebar
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Posisi sumber cahaya
glEnable(GL_LIGHT1); // Aktifkan sumber cahaya No.1
glColor4f(1.0, 1.0, 1.0, 0.5); // Kecerahan penuh, 50% pencampuran Alpha (baru)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Fungsi pencampuran tembus pandang berdasarkan nilai saluran alfa piksel sumber (baru)
Akhir;
{Temukan cuplikan kode berikut di dekat akhir Pelajaran 7.
Jika tombol[VK_LEFT] Lalu //Apakah tombol arah kiri ditekan?
yspeed := yspeed - 0.01; //Jika ya, kurangi kecepatan y
Mengikuti kode di atas, kami menambahkan kode berikut.
Garis-garis ini memantau apakah tombol B ditekan.
Jika demikian, komputer akan memeriksa apakah opsi pencampuran diaktifkan.
Kemudian atur ke keadaan sebaliknya.
}
If (keys[ord('B')] And Not bp) Then //Tombol B ditekan dan bp FALSE?
Mulai
bp := BENAR; // Jika ya, bp disetel ke BENAR
blend := Bukan blend; // Ganti opsi blending ke TRUE / FALSE
Jika (campuran) Lalu // Apakah pencampuran sedang berlangsung?
Mulai
glEnable(GL_BLEND); // Aktifkan pencampuran
glDisable(GL_DEPTH_TEST); // Matikan pengujian kedalaman
Akhir
Lain // lain
Mulai
glDisable(GL_BLEND); // Matikan pencampuran
glEnable(GL_DEPTH_TEST); // Aktifkan uji kedalaman
Akhir;
Akhir;
If (Bukan kunci[ord('B')]) Lalu // Apakah kunci B dilepaskan?
Mulai
bp := FALSE; // Jika ya, setel bp ke FALSE
Akhir;
{
Namun bagaimana Anda menentukan warna campuran saat menggunakan pemetaan tekstur?
Saat menyesuaikan mode tekstur, warna setiap piksel tekstur tekstur ditentukan oleh parameter saluran alfa.
Diperoleh dengan mengalikan warna piksel saat ini.
Misalnya warna yang digambar adalah (0,5, 0,6, 0,4),
Kita akan mengalikan warnanya untuk mendapatkan (0,5, 0,6, 0,4, 0,2)
(Jika parameter alfa tidak ditentukan, defaultnya adalah nol).
Itu saja! Mengimplementasikan Alpha blending di OpenGL memang sangat sederhana!
}
{
Catatan asli (13/11/99)
Kode pencampuran warna (NeHe) saya telah dimodifikasi untuk membuat objek yang ditampilkan terlihat lebih realistis.
Menggunakan parameter alpha untuk memadukan piksel sumber dan piksel tujuan secara bersamaan akan menyebabkan jejak buatan pada objek terlihat jelas.
Ini akan membuat bagian belakang objek tampak lebih gelap di sepanjang sisinya.
Pada dasarnya objek tersebut akan terlihat aneh.
Metode pencampuran warna yang saya gunakan mungkin bukan yang terbaik, tapi berhasil.
Dengan lampu yang diaktifkan, objek terlihat realistis.
Terima kasih kepada Tom yang telah memberikan kode aslinya. Metode pencampuran warna yang dia gunakan sudah benar.
Namun objeknya tidak terlihat semenarik yang diharapkan :)
Kode telah dimodifikasi lagi karena mengatasi masalah pada fungsi glDepthMask() pada beberapa kartu grafis.
Perintah ini tampaknya tidak terlalu efektif ketika mengaktifkan atau menonaktifkan pengujian buffer kedalaman pada beberapa kartu,
Jadi saya telah mengonversi kode untuk mengaktifkan atau menonaktifkan pengujian buffer kedalaman menjadi glEnable dan glDisable kuno.
Pencampuran alfa peta tekstur
Parameter alpha yang digunakan untuk peta tekstur dapat dibaca dari peta masalah seperti halnya warna.
Caranya adalah sebagai berikut, Anda perlu memuat material yang dibutuhkan dan mendapatkan parameter alpha-nya secara bersamaan.
Kemudian gunakan format warna GL_RGBA saat memanggil glTexImage2D().
}