Pada demo aplikasi artikel sebelumnya, gambar terrain terlihat kotak-kotak pada jarak dekat. Kali ini kita akan bahas bagaimana memperbaiki kualitas gambar hasil render. Zamrony P. Juhara
BAGIAN 4 DARI 4 ARTIKEL
KITA AKAN membahas beberapa isu terkait detail terrain, yakni bagaimana mengurangi tampilan kotak-kotak yang terlihat ketika posisi berada dekat dengan pengama dan bagaimana menambah variasi detail pada permukaan terrain menggunakan tekstur. Sebelumnya mari kita bahas mengapa terrain terlihat kotak-kotak pada jarak dekat.
Problem Texture Mapping
Kita telah menggunakan tekstur selama artikel-artikel sebelumnya. Tekstur pada demo sebelumnya selalu dipetakan ke seluruhterrain seperti pada Gambar 1.
Jika ukuran tekstur kecil dan dipetakan ke seluruh terrain yangcukup besar, hasilnya terrain tampak kurang realistis karenatekstur terlihat kotak-kotak terutama bila dilihat dari jarak dekat (Gambar 2). Hal ini karena gambar tekstur akan ditarik (stretched) untuk memenuhi mesh terrain.
Solusi yang mudah tentunya memperbesar resolusi gambar tekstur yang dipakai. Namun, cara ini tidak selalu berhasil karena beberapa sebab. Pertama, tidak semua video card mendukung ukuran tekstur yang terlalu besar. Sebagian besar video card, hanya mengizinkan ukuran tekstur maksimal 1024x1024.
Kedua, kebutuhan memory untuk menyimpan tekstur menjadi membengkak. Tekstur tak ter-compress berukuran 1024x1024 dengan kedalaman warna 16 bit membutuhkan 1024x1024x2 byte=2097152 byte=2 MB. Memory video card saat ini mungkin cukup menampung data tekstur tersebut, namun yang perlu disimpan di memory video card tentu bukan hanya satu tekstur ini saja, Anda tentu membutuhkan memory untuk menyimpan vertex/index buffer, tekstur-tekstur lain yang jumlahnya bisa cukup banyak dan tertampung lagi di memory video card.
Lalu, bagaimana solusinya agar detail tekstur terjaga, tapi tanpa menambah resolusi tekstur?
Pada artikel “Grafi s 3D: Texture Mapping” di PC Media edisi 07/2007, kita sudah pernah mendiskusikan masalah mode pengalamatan tekstur (texture adressing mode). Texture addressing mode adalah mode yang menentukan bagaimana tekstur di-petakan ke poligon apabila koordinat teksturnya di luar nilai 0.0 hingga 1.0. Ada empat mode, yakni wrap, border color, clamp, dan mirror. Sekarang kita akan menggunakan pengetahuan tersebut untuk memecahkan problem tersebut.
Untuk menjaga detail tetap terjaga walau terrain dilihat dari jarak dekat, kita harus memetakan tekstur berderet-deret pada terrain (Gambar 3). Ini bisa kita kerjakan dengan menggunakan addressing mode wrap.
Menghitung Koordinat Tekstur
Perhatikan lagi Gambar 3. Koordinat tekstur ditandai sumbu berwarna merah. Untuk menghitung koordinat u, v agar tekstur digambar berderet-deret dari kiri ke kanan dan atas ke bawah (tile), kita hitung berapa nilai increment yang akan kita gunakan menambah koordinat vertex untuk tiap-tiap vertex. Koordinat tekstur vertex v0 adalah u=0.0, v=4.2, v3 adalah u=4.2, v=4.2, v15 adalah u=4.2, v=0.0 dan v12 di u=0.0, v=0.0. Koordinat tekstur vertex lainnya diperoleh melalui interpolasi berikut:
u=i*u_max/(jumlah vertex horizontal-1)
v=j*v_max/(jumlah vertex vertikal-1)
di mana
i=0,1,2,..,(jumlah vertex horizontal-1)
j=0,1,2,..,(jumlah vertex vertikal-1)
u_max adalah nilai koordinat u terbesar
v_max adalah nilai koordinat v terbesar
Untuk contoh pada Gambar 3, nilai u_max dan v_max adalah 4.2. Implementasi lengkap bagaimana penyusunan koordinat vertex dapat Anda temukan pada metode GenerateVertexArray() pada kelas TBruteForceTerrain. Metode ini dipanggil pada saat vertex buffer dibuat (CreateVertex()). Anda dapat temukan metode ini di fi le unit uterrain.pas pada CD/DVD.
Mengatur Mode Pengalamatan Tekstur (Texture Addresing Mode)
Langkah selanjutnya adalah mengatur mode pengalamatan tekstur menjadi D3DTADDRESS_WRAP untuk masing-masing koordinat u, v. (Listing 1). Parameter pertama pada metode SetSamplerState() adalah texture stage yang akan diubah.
Gambar 4 berisi perbandingan antara penggunaan mode pengalamatan tekstur tanpa wrap dan dengan wrap. Tampak pada Gambar 4 bagian kiri, detail pada poligon yang terdekat, terlalu rendah sehingga terlihat kotak-kotak. Pada bagian kanan, walau masih terlihat kotak-kotak, poligon yang dekat terlihat lebih detail.
Texture Filtering
Perhatikan Gambar 4. Pada jarak dekat, poligon menempati lebih banyak pixel di layar daripada di tekstur, akibatnya banyak pixel di layar dipetakan pada texel (texture element) yang sama.
Hasilnya adalah tampilan yang tampak kotak-kotak pada jarak dekat. Hal ini biasa disebut magnifi cation artifact.
Pada jarak jauh, poligon menempati lebih sedikit pixel di layar daripada di tekstur, akibatnya satu pixel harus dipetakan pada beberapa texel yang berbeda. Idealnya, warna pixel dihitung dengan mengambil rata-rata warna beberapa texel yang akan dipetakan. Namun karena perhitungan rata-rata cukup menguras kerja processor, default-nya adalah warna pixel dipilih dari warna salah satu texel yang koordinatnya diambil dari pembulatan. Pemilihan ini sering kali tidak akurat karena texel-texel yang merupakan kontributor utama integritas gambar mungkin tidak terpilih. Hasilnya adalah tampilan yang terlihat berbutir mirip pasir pada poligon di kejauhan (minifi cation artifact).
Texture filtering digunakan untuk memperbaiki kualitasgambar hasil render dengan mengurangi magnifi cation dan minification artifact.
Ada beberapa jenis filtering yang disediakan Direct3D. Pointfiltering (D3DTEXF_POINT), bilinear filtering (D3DTEXF_LINEAR), dan anisotropic filtering (D3DTEXF_ANISOTROPIC).
Point Filtering
Point filtering (kadang disebut juga nearest point sampling) dikerjakan dengan mengambil pixel pada koordinat UV yang sudah dibulatkan. Jadi bila koordinat UV adalah (10.4, 12.2) maka pixel diambil dari gambar tekstur pada koordinat (10,12).
Koordinat UV tidak langsung dibulatkan melainkan diubah darikoordinat tekstur ke koordinat gambar dengan formula:
U=u*imageWidth-0.5
V=v*imageHeight-0.5
Di mana u, v adalah koordinat tekstur.
Bilinear Filtering
Setelah koordinat UV yang sudah dibulatkan diperoleh, warna texel saat ini dan empat texel tetangga digabung untuk menghasilkan warna akhir. Bobot warna texel dihitung dengan mempertimbangkan jarak texel terhadap koordinat UV. Sebagian besar video card didesain optimal untuk penggunaan linear filtering.
Anisotropic Filtering
Kata anisotropic berarti “berbeda bentuk”. Jika filter ini dihidupkan, bentuk fi lterpada ruang koordinat tekstur dan jumlah texel yang diambil (sampling) dipengaruhi oleh orientasi poligon. Anisotropic filtering diperlukan untuk menutupi kekuranganbilinear filtering. Bilinear menggunakanfilter berbentuk kotak. Bilinear filtering bagus pada poligon-poligon yang vektornormalnya menghadap ke Anda, namununtuk poligon yang vektor normalnyamenjauhi, akan timbul efek distorsi yang disebut anisotropy.
Menambah Detail dengan Multi-texturing
Teknik berikutnya adalah menggunakan tekstur lebih dari satu untuk dipetakan dan dicampur pada suatu poligon, biasa disebut multi-texturing atau multiple texture blending. Teknik ini biasanya digunakan untuk menghasilkan efek-efek tertentu. Pada terrain rendering, teknik ini digunakan untuk menambah detil pada terrain, terutama yang dekat dengan pengamat (Gambar 6).
Multi-texturing bisa dikerjakan dengan multipass rendering atau dengan memanfaatkan multiple texture stage. Multi-texturing dengan multipass rendering dikerjakan dengan menggambar poligon yang sama lebih dari satu kali dengan tekstur yang berbeda. Teknik ini digunakan pada video card lama.
Contohnya seperti pada Listing 1.
Multipass rendering menurunkan performa keseluruhan, sebanding dengan jumlah rendering pass yang digunakan. Pada video card yang lebih baru, multi-texturing dapat dikerjakan menggunakan texture stage lebih dari satu atau dengan pixel shader yang memungkinkan multi-texturing dikerjakan dalam sekali penggambaran (single pass).
Kita akan bahas texture stage segera, sedangkan multi-texturing dengan pixel shader belum kita bahas.
Saya tidak akan menggunakan teknik multipass rendering pada demo aplikasi yang ada di CD/DVD karena sebagian besar kartu grafis mainstream saat ini umumnya mendukung multi-texturing dengan multiple texture stage.
Texture Stage
Texture stage adalah tingkat-tingkat dalam proses pencampuran tekstur (texture blending). Hasil operasi yang dikerjakan suatu stage dapat menjadi input bagi stage berikutnya (Gambar 7). Jumlah texture stage yang didukung Direct3D adalah 8, namun mungkin jumlahnya bisa lebih kecil tergantung video card.
Anda bisa mengetahuinya dari field MaxTextureBlendStages pada tipe data D3DCAPS9.
Tiap stage dapat diubah status operasi dan argumen-argu-men yang digunakan (Gambar 8). Ada beberapa operasi yang disediakan, yakni operasi untuk warna dan alpha dan operasi untuk mengatur argumen warna dan argumen alpha.
D3DTSS_COLORARGn, D3DTSS_ALPHAARGn
Operasi D3DTSS_COLORARG0, D3DTSS_COLORARG1 dan D3DTSS_COLORARG2 digunakan hanya untuk mengatur argumen-argumen input operasi warna. Sebagian besar operasi warna hanya membutuhkan ARG1 dan ARG2, namun ada beberapa yang butuh ARG0.
Operasi D3DTSS_ALPHAARG0, D3DTSS_ALPHAARG1 dan D3DTSS_ALPHAARG2 digunakan hanya untuk mengatur argumen-argumen input operasi alpha. Nilai yang valid untuk ARGn adalah konstan yang berprefiks D3DTA_ (TA singkatan dari Texture Argument) seperti pada Tabel 1.
TABEL 1. ARGUMEN TEKSTUR
|
NAMA
D3DTA_CONSTANT
D3DTA_CURRENT
D3DTA_DIFFUSE
D3DTA_TEXTURE
D3DTA_TFACTOR
D3DTA_SPECULAR |
KETERANGAN
Mengisi argumen ARGn dengan nilai konstan.
Jika digunakan pada stage bukan 0, ARGn akan diisi dengan
hasil output stage sebelumnya. Jika digunakan pada stage
0, sama dengan mengisi ARGn dengan D3DTA_DIFFUSE.
Argumen ARGn diisi dengan warna diffuse terinterpolasi.
Jika kita menggunakan pencahayaan, warna hasil kalkulasi
pencahayaan dimasukkan ke ARGn.
Warna texel disi ke ARGn.
Warna yang ada di render state D3DRS_TEXTUREFACTOR
digunakan untuk mengisi ARGn.
Warna pada pencahayaan specular diisi ke ARGn. |
Listing 2 berisi contoh bagaimana mengatur ARG1 dan ARG2 pada stage 1. ARG1 diisi dengan warna texel dan ARG2 diisi dengan warna diffuse terinterpolasi.
D3DTSS_COLOROP, D3DTSS_ALPHAOP
D3DTSS_COLOROP dan D3DTSS_ALPHAOP masing-masing digunakan untuk mengatur stage agar menggunakan operasi pencampuran warna dan alpha. Operasi yang bisa dikerjakan ditentukan oleh tipe enumerasi D3DTEXTUREOP seprti pada Tabel 2.
TABEL 2. OPERASI PADA TEKSTUR STAGE
|
OPERASI
D3DTOP_DISABLE
D3DTOP_SELECTARG1
D3DTOP_SELECTARG2
D3DTOP_MODULATE
D3DTOP_MODULATE2X
D3DTOP_MODULATE4X
D3DTOP_ADD
D3DTOP_ADDSIGNED
D3DTOP_ADDSIGNED2X
D3DTOP_SUBTRACT
D3DTOP_MULTIPLYADD
D3DTOP_LERP |
KETERANGAN
Operasi pada stage ini dimatikan.
Output stage sama dengan ARG1. Argumen lain diabaikan.
Output stage sama dengan ARG2. Argumen lain diabaikan.
Output stage = ARG1 * ARG2. Karena melipatkan perkalian
fl oating-point, outputnya lebih gelap dari inputnya. Contoh
0.6, 0.6, 0.6) * (0.5, 0.5, 0.5) = (0.3, 0.3, 0.3).
Output stage = (ARG1 * ARG2) * 2. Outputnya lebih terang.
Jika melebihi 1.0, nilainya dibatasi 1.0 (putih terang).
Output stage = (ARG1 * ARG2) * 4. Outputnya jauh lebih
erang. Jika melebihi 1.0, nilainya dibatasi 1.0.
Output stage = ARG1 + ARG2.
Output stage = ARG1 + ARG2 - 0.5. Nilainya menjadi
berkisar -0.5 hingga 0.5.
Output stage = (ARG1 + ARG2 – 0.5) * 2
Output stage = ARG1 – ARG2
Output stage = ARG1 + (ARG2 * ARG0)
Output stage = ARG1 * ARG2 + (1-ARG1) * ARG0. Interpolasi
inier. |
Listing 2 berisi contoh bagaimana melakukan multi-texturing dengan dua texture stage.
Anda perlu mengubah deklarasi tipe TTerrainVertex dengan menyertakan dua koordinat tekstur pada tiap vertex agar tiap tekstur dapat diatur koordinatnya secara independen. Deklarasi flexible vertex format (FVF) perlu diubah dari D3DFVF_TEX1 menjadi D3DFVF_TEX2 (Listing 3).
Pencampuran Tekstur Berdasarkan Ketinggian
Untuk membuat terrain semakin menarik, kita akan menghasilkan tekstur yang bervariasi hasil pencampuran beberapa tekstur berdasarkan ketinggian vertex-vertex penyusun terrain. Pada bagian terrain yang ketinggiannya rendah, terrain digambar dengan tekstur rumput (Tekstur 0), daerah yang lebih tinggi digambar dengan tekstur lumpur (Tekstur 1), Daerah tertinggi digambar dengan tekstur bebatuan (Tekstur 2) (Gambar 9).
Daerah yang ketinggiannya terletak antara daerah rumput dan daerah lumpur (0.0-0.5), diinterpolasi sehingga menghasilkan transisi halus dari daerah rerumputan ke daerah berlumpur. Pada ketinggian 0.0, opacity Tekstur 0 dan Tekstur 1 masing-masing adalah 1.0 (100%) dan 0.0 (0%). Pada ketinggian 0.5, opacity Tekstur 0 dan Tekstur 1 masing-masing adalah 0.0 (0%) dan 1.0 (100%). Cara serupa dikerjakan untuk daerah yang ketinggiannya antara 0.5-1.0.
Implementasi lengkap teknik ini dapat Anda temukan di demo 7c pada CD/DVD.
|
Listing 1
FDevice.SetSamplerState(0,
D3DSAMP_ADDRESSU,
D3DTADDRESS_WRAP);
FDevice.SetSamplerState(0,
D3DSAMP_ADDRESSV,
D3DTADDRESS_WRAP);
Listing 1
//pass 1 texture #1
FDevice.SetTextureStageState(0,
D3DTSS_COLORARG1,
D3DTA_TEXTURE );
FDevice.SetTextureStageState(0,
D3DTSS_COLOROP,
D3DTOP_SELECTARG1);
FDevice.SetRenderState(D3DRS_ALPHABLENDENABLE,
FALSE);
FDevice.SetTexture(0,FTexture1);
//lakukan penggambaran poligon
do_draw_primitives();
//pass 2 texture #2
FDevice.SetRenderState(D3DRS_ALPHABLENDENABLE,
TRUE);
FDevice.SetRenderState(D3DRS_SRCBLEND,
D3DBLEND_ONE);
FDevice.SetRenderState(D3DRS_DESTBLEND,
D3DBLEND_ONE);
FDevice.SetTexture(0,FTexture2);
//lakukan penggambaran poligon
do_draw_primitives();
Listing 2
//gunakan tekstur 0 dan kombinasi dengan warna diffuse
FDevice.SetTexture(0,FTexture);
Fdevice.SetTextureStageState(0,
D3DTSS_COLORARG1,
D3DTA_TEXTURE);
Fdevice.SetTextureStageState(0,
D3DTSS_COLORARG2,
D3DTA_DIFFUSE);
Fdevice.SetTextureStageState(0,
D3DTSS_COLOROP,
D3DTOP_MODULATE);
//gunakan hasil kombinasi tekstur 0 dan warna diffuse
//kombinasi dengan detail tekstur
FDevice.SetTexture(1,FDetailTexture);
FDevice.SetTextureStageState(1,
D3DTSS_COLORARG1,
D3DTA_CURRENT);
FDevice.SetTextureStageState(1,
D3DTSS_COLORARG2,
D3DTA_TEXTURE);
FDevice.SetTextureStageState(1,
D3DTSS_COLOROP,
D3DTOP_ADDSIGNED);
Listing 3
const D3DFVF_TERRAIN=D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF
TEX2;
type
TTerrainVertex=packed record
position:TD3DVector;
normal:TD3DVector;
u,v:single;
u2,v2:single;
end; |
LEBIH LANJUT
· Wolfgang F. Engel, “Beginning Direct3D Game Programming”, Second Edition, Premier Press, 2003.
· Gary Simmons, Adam Hoult, “Graphics Programming with DirectX 9 : Part I”, e-Institute Publishing, Inc, 2004.
· Microsoft, “DirectX 9.0 SDK Documentation”, Microsoft Corporation, 1995-2003.