Minggu, 08 Maret 2009

Grafis 3D: EFEK KABUT

Efek kabut memainkan peran penting dalam game 3D.
Penggunaan kabut mampu membangkitkan suasana tertentu.
Selama permainan, seperti suasana dingin, suram atau misterius.
Mengapa Game Menggunakan Efek Kabut?
Kabut (fog) secara fisik, adalah fenomena yang terjadi ketika partikel air dan debu yang ada di udara cukup rapat sehingga mampu membelokkan cahaya dan menyebabkan obyek yang semakin jauh tidak tampak.
Kabut pada grafis 3D adalah merupakan bentuk lain pencampuran warna objek dan warna kabut, ditentukan menggunakan interpolasi linier. Jika anda sering bermain game 3D, anda tentu sudah sering melihat efek kabut ini digunakan dalam game-game yang beredar saat ini.
Kabut memberi nuansa tertentu pada game, digunakan untuk menambah estetika dan membangun suasana permainan seperti diinginkan designer game. Karena kabut pada dunia nyata biasanya muncul ketika suhu cukup rendah, hal ini memberi suasana yang sama pada game 3D, yakni suasana dingin. Pada game bertema horor, efek kabut menambah ketegangan karena jarak pandang pemain menjadi terbatas. Monster-monster berbahaya dapat tiba-tiba muncul dari dalam kabut.
Selain digunakan untuk membangun suasana tertentu, efek kabut juga digunakan untuk menyembunyikan keanehan yang timbul ketika poligon yang tidak nampak, karena berada di luar volume pandang (view volume), tiba-tiba muncul ketika poligon tersebut memasuki volume pandang. Keanehan ini biasa diistilahkan sebagai polygon popping.

Efek kabut digunakan untuk menyembunyikan keanehan tersebut, namun masih menggunakan volume pandang yang tidak terlalu besar, sehingga meminimalkan jumlah polygon yang harus diproses dan hasil akhirnya kinerja aplikasi yang meningkat. Ketika poligan masuk ke volume pandang,polygon tersebut yang sebelumnya tidak tampak, akan muncul tiba-tiba. Namun karena tertutup kabut, keanehan ini tidak terlihat mata. Ketika jarak polygon semakin dekat ke pengamat, polygon perlahan-lahan akan tampak, seolah-olah keluar dari dalam kabut.

Walau demikian, Anda sebaiknya berhati-hati untuk tidak terlalu berlebihan menggunakan efek kabut dalam game 3D karena dapat menurunkan keasikan bermain. Beberapa game yang menggunakan grafis yang sangat detail terpaksa menggunakan efek kabut yang cukup tebal untuk menurunkan jumlah polygon yang harus diproses tiap frame animasi agar tingkat frame ratenya masih layak dan game cukup nyaman dimainkan pada system dengan spesifikasi hardware tidak terlalu tinggi. Kabut terlalu tebal menurunkan jarak pandang sehingga meningkatkan kesulitan untuk menyelesaikan game. Penulis kadang frustasi memainkan game yang menggunakan kabut terlalu tebal, dimana musuh berbahaya sering kali muncul tiba-tiba dan kita tidak mampu berbuat apa-apa karena jaraknya sudah terlalu dekat.

Menghidupkan Fitur Kalkulasi Kabut

Untuk menghidupkan efek kabut pada Direct 3D, Anda harus mengatur render state D3DRS, FOGENABLE dengan nilai true,atau false untuk mematikannya. Contoh kode bagaimana menghidup/matikan fitur kabut dapat Anda lihat pada listing 1.

Kalkulasi kabut pada Direct 3D

Kabut pada Direct3D diimplementasikan sebagai sebuah bentuk pencampuran warna. Ketika fitur kabut dihidupkan, pada saat rendering objek, warna objek dicampur dengan warna kabut dengan memperhitungkan jarak antara objek dengan kamera dan bagaimana perubahan kabut terhadap jarak.

Jika objek dekat kamera, proporsi warna lebih banyak pada warna objek sedangkan bila jarak cukup jauh, proporsi warna kabut lebih banyak.

Direct3D menghitung nilai proporsi yang disebut sebagai factor kabut (fog factor ).

Faktor kabut (fog factor )

Faktor kabut adalah nilai skalar antara 0.0 hingga 1.0 yang menentukan proporsi pencampuran warna objek dan warna kabut. Objek di kejauhan yang tertutup oleh kabut memiliki factor 0.0. Objek yang dekat yang tidak tertutup kabut memiliki factor kabut 1.0

Direct3D menghitung warna hasil pencampuran warna objek dan warna kabut dengan menggunakan persamaan interpolasi linier seperti yang ditunjukkan pada persamaan 1.


C akhir = F fog x C objek + (1 - F fog) x C fog

C akhir = Warna hasil pencampuran

F fog = Faktor kabut

C objek = Warna objek

C fog Warna kabut


Perhitungan Fakor Kabut

Nilai kabut dihitung berdasarkan model kabut yang kita gunakan. Ada tiga model kabut yang disediakan, model kabut linier, eksponensial, dan eksponensial kuadrat.

Kabut linier

Untuk menggunakan model kabut linier di Direct3D, Anda mengaturnya melalui render state D3DRS, FOGTABLEMODE untuk pixel fog atau D3DFOG_LINIER (Listing 2). Lebih jauh tentang pixel fog dan vertex fog dapat Anda simak dibagian “Tipe Kabut”.

Pada model kabut linier, factor kabut dihitung berdasarkan persamaan linier seperti pada Persamaan 2.


Persamaan 2. Perhitungan faktor kabut pada model kabut linier.


F fog = faktor kabut

d = jarak

end = jarak yang terjauh di mana efek kabut tidak lagi naik

start = jarak di mana efek kabut mulai berpengaruh


Pada Direct3D, nilai d pada persamaan 2, dihitung otomatis untuk Anda. Anda hanya perlu menentukan nilai end dan start. Jika tidak ditentukan, jarak dihitung menggunakan nilai koordinat z pada viewspace. Kalkulasi jarak cepat karena data nilai z tersedia pada jalur transpor

masi (transformation pipeline ) Direct3D. Namun penggunaan nilai koordinat z pada view space bukan tanpa masalah. Lebih jauh mengenai hal ini dapat Anda simak di bagian “Kabut berbasis jangkauan (range –based fog )”.

Untuk mengatur jarak dimana efek kabut mulai berpengaruh (start ), Anda mengaturnya melalui render state D3DRS_FOGEND (Gambar 2), Lihat Listing 3 untuk contoh pengaturan render state ini.

Nilai yang digunakan untuk render state D3DRS_FOGSTART dan D3DRS_FOGEND adalah floating-point. Hal ini sedikit problematic mengingat parameter kedua pada metode Set-RenderState milik IDirect3D Device9 mengharapkan tipe data DWORD. Agar kita dapat melewatkan data floating-point melalui parameter bertipe DWORD, triknya dilakukan dengan mendapatkan alamat variable bertipe floating-point (menggunakan operator @ ) lalu melakukan dereferensi (menggunakan operator ^) dan terakhir melakukan typecast ke tipe DWORD.

gambar 2. Kabut pada model linier

Kabut eksponensial

Pada model kabut eksponensial, factor kabut dihitung menggunakan Persamaan 3. Untuk menggunakan model kabut ini, render state D3DRS_FOGTABLEMODE atau D3DRS_FOGVERTEXMODE harus diisi dengan nilai D3DFOG_EXP.

Model eksponensial lebih akurat mendeskripsikan laju perubahan kerapatan kabut terhadap jarak. Pada model eksponensial, awal dan akhir kabut tidak ambil bagian dalam menentukan factor kabut, hanya kerapatan kabut yang berpengaruh .





Persamaan 3. Perhitungan faktor kabut pada model kabut eksponensial.


F fog = Faktor kabut

d = jarak

density = kerapatan kabut


Jarak d dihitung otomatis oleh Direct3D. Anda hanya perlu menentukan kerapatan kabut (density ) yang nilainya berkisar 0.0-1.0, dimana nilai 0.0 berarti tidak ada kabut dan 1.0 berarti semua objek tertutup kabut. Untuk mengatur kerapatan kabut, Anda menggunakan render state D3DRS_FOGDENSITY. Kerapatan kabut dinyatakan sebagai nilai floating-point sehingga Anda perlu melakukan trik seperti saat mengubah render state D3DRS_FOGSTART diatas.



Kabut Eksponensial Kuadrat

Model kabut eksponensial kuadrat mirip dengan model eksponsial, kecuali bahwa factor kabut dihitung dari kuadrad eksponensial seperti pada Persamaan 4. Untuk menggunakan model ini Anda menggunakan D3DFOG_EXP2.


Persamaan 4. Perhitungan faktor kabut (fog factor) antara berbagai model

F fog = Faktor kabut

d = jarak

density = kerapatan kabut

Dibandingkan model eksponensial, pada model eksponensial kuadrad, kabut tampak tidak terlalu pekat pada jarak dekat dan berubah lebih pekat pada jarak agak jauh. Gambar 3 berisi perbandingan berbagai factor kabut untuk kabut linier, eksponensial dan eksponensial kuadrat.


Tipe Kabut

Anda bisa menggunakan dua jenis kabut pada Direct 3D. Kabut berbasis vertex (vertex fog ) atau kabut berbasis pixel ( pixel fog ). Vertex fog dihitung per vertex saat pencahayaan sedangkan pixel fog dihitung tiap pixel oleh device driver. Listing 2 berisi contoh bagaimana menggunakan vertex fog atau pixel fog. Nilai default render state D3DRS_VERTEXFOGMODE dan D3DRS_TABLEFOGMODE adalah D3DFOG_NONE. Jika GPU mendukung kabut berbasis vertex dan berbasis pixel, Anda dapat mengaktifkan keduanya bersama-sama, namun tentunya

gambar 3. Perbandingan faktor kabut (fog factor) antara berbagai model

tidak terlalu berguna, karena salah satu saja sudah cukup.

Kabut berbasis vertex (vertex fog)

Ketika kabut berbasis vertex digunakan, setelah warna vertex dihitung, kalkulasi warna hasil pencampuran dengan warna kabut dikerjakan untuk tiap vertex pada polygon dan hasilnya diinterpolasi untuk semua warna pada permukaan polygon ketika proses rasterisasi. Kalkulasi kabut berbasis vertex dikerjakan oleh engine pencahayaan Direct3D. Jika Anda tidak menggunakan pencahayaan Direct3D, Anda harus menghitung sendiri warna hasil campuran warna kabut dan warna objek atau menggunakan kabut berbasis pixel (pixel fog).

Kalkulasi kabut berbasis vertex relative lebih lambat, terutama bila menggunakan model kabut eksponensial. Pada GPU yang memiliki fitur transformasi dan pencahayaan, kalkulasi kabut berbasis vertex dipercepat melalui hardware. Bila tidak kalkulasi dilakukan software yang tentunya lebih lambat.

Kabut berbasis pixel (pixel fog)

Pada kabut berbasis pixel fog, perhitungan warna campuran kabut dikerjakan tiap pixel oleh rasterizer menggunakan informasi kedalaman pixel. Pixel fog biasa disebut sebagai table fog karena beberapa device driver menggunakan tabel lock-up untuk memperoleh nilai factor kabut. Tabel lock-up ini berisi nilai-nilai factor kabut yang sudah dihitung terlebih dulu untuk berbagai jarak dan model kabut (linier atau eksponensial). Ini alasan mengapa fixel fox lebih cepat disbanding vertex fog, bahkan untuk model kabut eksponensial. GPU yang mendukung Direct 3D (dengan kata lain, menyediakan hardware abstraction layer (Hal)) umumnya mendukung kabut berbasis pixel.

Mengatur Warna Kabut

Warna kabut diatur melalui render state D3DRS_FOGCOLOR. Listing 5 berisi contoh kode bagaimana mengubah warna kabut.

Untuk menghasilkan hasil rendering yang bagus, sebaiknya anda memilih warna kabut yang serupa dengan warna langit yang Anda gunakan sebagai latar belakang. Penggunaan warna kabut yang tidak tepat justru merusak efek kabut (Gambar 4).


Gambar 4. Pemilihan warna kabut yang tepat menghasilkan hasil rendering lebih realistis


Kabut Berbasis Jangkauan (Range-based Fog)

Ada sedikit keanehan bila Anda menggunakan kabut pada Direct3D. Penyebabnya adalah jarak pada perhitungan factor kabut dihitung menggunakan nilai z pada view space. Perhatikan Gambar 5. Pada posisi awal, abjek 1 dan objek 2 berada dalam kabut. Ketika arah pandang kamera diputar dengan posisi kamera tidak berubah, objek 1 masih didalam kabut sedangkan objek 2 menjadi berada diluar kabut. Karena objek 2 masih didalam volume pandang kamera, perubahan objek 2 dari dalam kabut menjadi diluar kabut tampak mata, ini tentunya tidak kita inginkan, karena pada dunia nyata, objek yang tampak samar-samar dalam kabut, tidak serta-merta menjadi tampak jelas, hanya karena kita memutar arah pandang mata.

Problem ini dapat dihindari dengan menggunakan kabut berbasis jangkauan (range-based fog). Pada kabut berbasis jangkauan, factor kabut dihitung berdasarkan jarak vertex kekamera yang sesungguhnya, bukan komponen z pada viewspace. Oleh karena itu, renge-based fog hanya tersedia bila Anda menggunakan vertex fog. Karena operasinya melibatkan perhitungan kuadrad dan akar kuadrad (ingat rumus phytagoras di SMA dulu ), kabut berbasis jangkauan cukup menguras kinerja processor. Pada kabut berbasis jangkauan dengan model kabut linier, area yang terpengaruh kabut menyerupai area yang dibatasi dua lingkaran, yakni lingkaran terluar berjari-jari D3DRS-FOGEND dan lingkaran dalam berjari-jari D3DRS_FOGSTART.

Untuk menggunakan kabut berbasis jangkauan pada Direct3D, Anda menghidupkan render state D3DRS_RANGE-FOGENABLE (Listing 6).

Hubungan Kabut dan Matriks Proyeksi

Ketika sebuah vertex di transformasi oleh Dierct3D, matriks proyeksi digunakan. Berdasarkan matriks ini, koordinat layer dan komponen w homogen dihitung, koordinat z layer adalah dari 0.0 hingga 1.0 dan W adalah jarak terskala vertex ke pengamat.

Kalkulasi jarak dilakukan dengan memeriksa apakah kolom ke-4 pada matriks proyeksi bernilai [0.0,0.1] (Persamaan 5). Bila benar, kalkulasi jarak menggunakan nilai kedalaman berbasis z (z-based depth). Pada kedalaman berbasis z, awal kabut (D3DRS_FOGSTART) dan akhir kabut (D3DRS_FOGEND) harus bernilai antara 0.0-1.0.


Persamaan 5. Matriks proyeksi untuk kedalaman berbasis z ( nilai x berisi nilai skalar sembarang).


Jika elemen matriks proyeksi baris ke-3 kolom ke-4 bernilai 1, kalkulasi jarak dilakukan dengan menggunakan kedalaman relative terhadap mata (eye-relative depth). Pada kedalaman relative terhadap mata, awal kabut dan akhir kabut adalah relative terhadap world space.

Jika elemen matriks proyeksi baris ke-3 kolom ke-4 tidak bernilai 1, Anda harus menskalanya sedemikian agar nilainya menjadi 1, ini perlu dilakukan agar efek kabut diterapkan dengan benar (Persamaan 6). Jika menggunakan Mproj, nilai w=ez, bukan w=z yang merupakan jarak actual vertex.



Persamaan 6. Penskalaan matriks proyeksi.



Gambar 6. Screenshot aplikasi demo dengan menggunakan kabut berwarna kelabu.



Jika Anda menggunakan fungsi D3DXMatriksPerspective **() pada pustaka D3DX, matriks produksi yang dihasilkan sudah sesuai dengan Mproj’ pada Persamaan 6, dengan demikian awal dan akhir kabut selalu relative terhadap koordinat world space.

Aplikasi Demo

Aplikasi demo kali ini (Gambar 6) masih merupakan pengembangan aplikasi demo pada artikel skybox di PC Media edisi 02/2009 lalu. Source code demo-demo tersebut dapat Anda temukan di CD/DVD. Ada beberapa demo yang penulis sertakan.

Demo 1 menggunakan kabut berbasis vertex dengan model linier tanpa skybox, warna dihasilkan menggunakan warna solid. Didemo ini volume pandang diperkecil dengan mendekatkan bidang jauh (far plane). Demo 2 masih menggunakan kabut linier, namun dengan panorama langit dihasilkan menggunakan skybox. Pada beberapa bagian kabut dan skybox berpadu dengan halus, namun ada beberapa bagian dimana perpaduan warna skybox dan warna kabut tidak pas. Solusi yang mudah adalah dengan mengedit tekstur skybox, yang didemo ini belum penulis lakukan. Demo lain yang disertakan adalah modifikasi kedua demo tersebut dengan mengubah jenis kabutnya menjadi berbasis pixel dan dengan model eksponensial.

Ringkasan

Di artikel ini, Anda telah belajar bagaimana efek kabut di-implementasikan di Direct3D dan bagaimana memamfaatkan efek kabut dalam aplikasi 3D untuk membangun suasana dan meningkatkan performa aplikasi.


Sumber dari : PC Media