Kabut Piksel (Direct3D 9)
Kabut piksel mendapatkan namanya dari fakta bahwa itu dihitung berdasarkan per piksel di driver perangkat. Ini berbeda dari kabut puncak, yang dihitung oleh alur selama transformasi dan perhitungan pencahayaan. Kabut piksel terkadang disebut kabut tabel karena beberapa driver menggunakan tabel pencarian yang telah dihitung sebelumnya untuk menentukan faktor kabut, menggunakan kedalaman setiap piksel untuk diterapkan dalam memadukan komputasi. Ini dapat diterapkan menggunakan rumus kabut apa pun yang diidentifikasi oleh anggota jenis enumerasi D3DFOGMODE . Implementasi rumus ini khusus untuk driver. Jika driver tidak mendukung rumus kabut yang kompleks, itu harus menurun ke rumus yang kurang kompleks.
Eye-Relative vs. Kedalaman Berbasis Z
Untuk meringankan artefak grafis terkait kabut yang disebabkan oleh distribusi nilai z yang tidak merata dalam buffer kedalaman, sebagian besar perangkat keras menggunakan kedalaman relatif mata alih-alih nilai kedalaman berbasis z untuk kabut piksel. Kedalaman mata-relatif pada dasarnya adalah elemen w dari set koordinat homogen. Microsoft Direct3D mengambil timbal balik elemen RHW dari koordinat ruang perangkat yang diatur untuk mereproduksi true w. Jika perangkat mendukung kabut relatif mata, perangkat mengatur bendera D3DPRASTERCAPS_WFOG di anggota RasterCaps dari struktur D3DCAPS9 saat Anda memanggil metode IDirect3DDevice9::GetDeviceCaps . Dengan pengecualian rasterizer referensi, perangkat lunak selalu menggunakan z untuk menghitung efek kabut piksel.
Ketika kabut relatif mata didukung, sistem secara otomatis menggunakan kedalaman relatif mata daripada kedalaman berbasis z jika matriks proyeksi yang disediakan menghasilkan nilai z di ruang dunia yang setara dengan nilai w di ruang perangkat. Anda mengatur matriks proyeksi dengan memanggil metode IDirect3DDevice9::SetTransform , menggunakan nilai D3DTS_PROJECTION dan meneruskan struktur D3DMATRIX yang mewakili matriks yang diinginkan. Jika matriks proyeksi tidak sesuai dengan persyaratan ini, efek kabut tidak diterapkan dengan benar. Untuk detail tentang menghasilkan matriks yang sesuai, lihat Transformasi Proyeksi (Direct3D 9).
Direct3D menggunakan matriks proyeksi yang saat ini ditetapkan dalam perhitungan kedalaman berbasis w. Akibatnya, aplikasi harus menetapkan matriks proyeksi yang sesuai untuk menerima fitur berbasis w yang diinginkan, bahkan jika tidak menggunakan alur transformasi Direct3D.
Direct3D memeriksa kolom keempat dari matriks proyeksi. Jika koefisien adalah [0,0,0,1] (untuk proyeksi affine) sistem akan menggunakan nilai kedalaman berbasis z untuk kabut. Dalam hal ini, Anda juga harus menentukan jarak mulai dan akhir untuk efek kabut linier di ruang perangkat, yang berkisar dari 0,0 pada titik terdekat dengan pengguna, dan 1,0 di titik terjauh.
Menggunakan Pixel Fog
Gunakan langkah-langkah berikut untuk mengaktifkan kabut piksel di aplikasi Anda.
- Aktifkan penpaduan kabut dengan mengatur status render D3DRS_FOGENABLE ke TRUE.
- Atur warna kabut yang diinginkan dalam status render D3DRS_FOGCOLOR.
- Pilih rumus kabut yang akan digunakan dengan mengatur status render D3DRS_FOGTABLEMODE ke anggota terkait dari jenis enumerasi D3DFOGMODE .
- Atur parameter kabut seperti yang diinginkan untuk mode kabut yang dipilih dalam status render terkait. Ini termasuk jarak mulai dan akhir untuk kabut linier, dan kepadatan kabut untuk mode kabut eksponensial.
Contoh berikut menunjukkan seperti apa langkah-langkah ini dalam kode.
// For brevity, error values in this example are not checked
// after each call. A real-world application should check
// these values appropriately.
//
// For the purposes of this example, g_pDevice is a valid
// pointer to an IDirect3DDevice9 interface.
void SetupPixelFog(DWORD Color, DWORD Mode)
{
float Start = 0.5f; // For linear mode
float End = 0.8f;
float Density = 0.66f; // For exponential modes
// Enable fog blending.
g_pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
// Set the fog color.
g_pDevice->SetRenderState(D3DRS_FOGCOLOR, Color);
// Set fog parameters.
if( Mode == D3DFOG_LINEAR )
{
g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
g_pDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&Start));
g_pDevice->SetRenderState(D3DRS_FOGEND, *(DWORD *)(&End));
}
else
{
g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
g_pDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD *)(&Density));
}
Beberapa parameter kabut diperlukan sebagai nilai floating-point, meskipun metode IDirect3DDevice9::SetRenderState hanya menerima nilai DWORD dalam parameter kedua. Contoh sebelumnya menyediakan nilai floating-point ke IDirect3DDevice9::SetRenderState tanpa terjemahan data dengan mentransmisikan alamat variabel floating-point sebagai pointer DWORD, lalu mendereferensikannya.
Topik terkait