Direct3D'ye Giriş
Direct3D'ye Giriş
DirectX le çalışırken SDK ile gelen Dx dokümanları elimizin altından
hiçbir zaman eksik etmememiz gereken en önemli kaynaklardan biri
olmalıdır. Nasıl bir buzdolabı, çamaşır makinesinin bir kullanım
kılavuzu varsa DirectX inde kullanım kılavuzu SDK ile gelen
dokümanlarıdır. Dokümanlar içinde DirectX in barındırdığı bütün
sistemler, yapılar , fonksiyonların kullanımları anlatılmaktadır. Yani
malzemeler bellidir. Ancak neyin, nerede, ne zaman kullanılacağını da
zamanla tecrübe ederek, bol bol araştırarak, okuyarak öğreneceksiniz.
Direct3D ye IDirect3D9 arabiriminden (interface) giriş yapalım. IDirect3D9 arabirimi Direct3D nin temel arabirimlerinden biridir ve bir bakıma Direct3D ye giriş noktası sayılır. Ekran kartının fiziksel bilgilerini, desteklediği özellikleri, görüntü modlarını, desteklenen format bilgilerini alma, Direct3D sürücüsünü oluşturma gibi fonksiyonları içerir.
Direct3D ye IDirect3D9 arabiriminden (interface) giriş yapalım. IDirect3D9 arabirimi Direct3D nin temel arabirimlerinden biridir ve bir bakıma Direct3D ye giriş noktası sayılır. Ekran kartının fiziksel bilgilerini, desteklediği özellikleri, görüntü modlarını, desteklenen format bilgilerini alma, Direct3D sürücüsünü oluşturma gibi fonksiyonları içerir.
IDirect3D9 arabiriminin üyeleri
IDirect3D9::CheckDepthStencilMatch: Belirtilen depth-stencil formatının belirtilen render-target formatı ile uyumlu olup olmadığını test etmekte kullanılır.
IDirect3D9::CheckDeviceFormat: Belirtilen yüzey (surface) formatının belirtilen kaynak tipinde doku formatı olarak olarak kullanılabilir mi. Yada depth-stencil buffer veya render target formatı ile kullanılabilir mi. Aslında bunu şöyle açıklayalım. Direct3D de bir çok format tipi vardır. Görüntü (display) formatı, back buffer format, stencil format, texture formatı vs. Bu formatların her biri birbiri ile uyumlu olmayabilir. Yada yukarıda kaynak tipi diye bir ibare kulandık. Kaynak tipi dediğimiz aşağıdaki yapı içerisinde yer alan tanımlardır. Bu format şu kaynak tipi için kullanılabilir mi. Bu format şu formatla uyumlu mu? gibi soruları bu fonksiyonla sorabiliriz.
IDirect3D9::CheckDeviceFormat: Belirtilen yüzey (surface) formatının belirtilen kaynak tipinde doku formatı olarak olarak kullanılabilir mi. Yada depth-stencil buffer veya render target formatı ile kullanılabilir mi. Aslında bunu şöyle açıklayalım. Direct3D de bir çok format tipi vardır. Görüntü (display) formatı, back buffer format, stencil format, texture formatı vs. Bu formatların her biri birbiri ile uyumlu olmayabilir. Yada yukarıda kaynak tipi diye bir ibare kulandık. Kaynak tipi dediğimiz aşağıdaki yapı içerisinde yer alan tanımlardır. Bu format şu kaynak tipi için kullanılabilir mi. Bu format şu formatla uyumlu mu? gibi soruları bu fonksiyonla sorabiliriz.
C/C++ kodu:
typedef enum D3DRESOURCETYPE { D3DRTYPE_SURFACE = 1, D3DRTYPE_VOLUME = 2, D3DRTYPE_TEXTURE = 3, D3DRTYPE_VOLUMETEXTURE = 4, D3DRTYPE_CubeTexture = 5, D3DRTYPE_VERTEXBUFFER = 6, D3DRTYPE_INDEXBUFFER = 7, D3DRTYPE_FORCE_DWORD = 0x7fffffff, } D3DRESOURCETYPE, *LPD3DRESOURCETYPE;
IDirect3D9::CheckDeviceFormatConversion: Bu fonksiyon belirtilen formatın diğer belirttiğimiz bir formata çevrilip çevrilemeyeceğini test etmekte kullanılır.
IDirect3D9::CheckDeviceMultiSampleType: MultiSample (çoklu örnekleme) olayı çizgi, polygonların vs çizimi sırasında oluşan tırtıklanmayı önlemeye yarar. Bu olaya antialising denilmektedir. Bu da daha kaliteli bir görüntü elde etmeye olanak sağlar. Bu fonksiyonla ekran kartımızın bu özelliği destekleyip desteklemediğini, destekliyorsa hangi seviyeye kadar desteklediğini öğrenebiliriz.
Aşağıdaki iki polygondan ilkinde antialising yok ikincisinde ise işlem sonunda meydana gelen düzelmeyi görebilirsiniz.
IDirect3D9::CheckDeviceMultiSampleType: MultiSample (çoklu örnekleme) olayı çizgi, polygonların vs çizimi sırasında oluşan tırtıklanmayı önlemeye yarar. Bu olaya antialising denilmektedir. Bu da daha kaliteli bir görüntü elde etmeye olanak sağlar. Bu fonksiyonla ekran kartımızın bu özelliği destekleyip desteklemediğini, destekliyorsa hangi seviyeye kadar desteklediğini öğrenebiliriz.
Aşağıdaki iki polygondan ilkinde antialising yok ikincisinde ise işlem sonunda meydana gelen düzelmeyi görebilirsiniz.
IDirect3D9::CheckDeviceType: Belirtilen sürücü tipinin ekran
kartı tarafından desteklenip desteklenmediğini test etmekte kullanılır.
Direct3D nin desteklediği sürücü tipleri aşağıda verilmiştir.
typedef enum D3DDEVTYPE { D3DDEVTYPE_HAL = 1, D3DDEVTYPE_NULLREF = 4, D3DDEVTYPE_REF = 2, D3DDEVTYPE_SW = 3, D3DDEVTYPE_FORCE_DWORD = 0xffffffff, } D3DDEVTYPE, *LPD3DDEVTYPE;
IDirect3D9::CreateDevice: Direct3D sürücüsünü oluşturmak için kullanılır.
IDirect3D9::EnumAdapterModes: Belirtilen görüntü formatına ait belirtilen sıradaki mod bilgisini verir.
IDirect3D9::GetAdapterCount: Bilgisayara takılı olan ekran kartı sayısını verir.
IDirect3D9::GetAdapterDisplayMode: Ekran kartının şu an kullandığı görüntü modu bilgisini verir.
IDirect3D9::GetAdapterIdentifier: Belirtilen ekran kartına ait fiziksel bilgileri verir.(Isim, üretici, driver dosyası vs.)
IDirect3D9::GetAdapterModeCount: Ekran kartının belirtilen görüntü formatına ait kaç adet görüntü modu desteklediğinin sayısını verir.
IDirect3D9::GetAdapterMonitor: Bilgisayarımıza birden fazla monitör bağlı ise Direct3D ile çalışan uygulamamızın hangi monitörde çalıştığını öğrenmemizi sağlar.
IDirect3D9::GetDeviceCaps: Ekran kartının desteklediği özellikleri almak için kullanılır.
IDirect3D9::RegisterSoftwareDevice: Kendi yazmış olduğunuz yada başka bir yerden tedarik ettiğiniz software rasterizeri (yazılım tabanlı çizdirici diyelim) Direct3D ile kullanabilmenizi sağlar.
Bu dersimizde DirectX'i kullanarak ekran kartı bilgilerini nasıl elde edeceğimizi öğreneceğiz.
IDirect3D9 arabirimi ile ilgili bu kadar bilgi yeter. Olayı pekiştirmek amacıyla IDirect3D9 arabirimine ait bazı fonksiyonları kullanarak ekran kartımıza ait bazı bilgileri nasıl elde edeceğimizi gösteren ufak bir örnek hazırladım. Örneğimizin MFC ve konsol olmak üzere iki verisyonu bulunmakta. MFC kütüphanesini kullanarak hazırladığım örneğimizde sadece konumuzla ilgili olan kodları ele alacağız.
Örneğimizin görünüşü aşağıdaki gibidir. Ugulama önce sistemde bulunan ekran kartlarını aşağıda gördüğünüz gibi bir combobox içinde listeler. Listelenen ekran kartlarından birini seçtiğimizde de "Desteklenen görüntü modları" kısmında ekran kartının desteklediği çözünürlük, ekran tazeleme ve görüntü formatı bilgilerini listeler. "Ekran kartı bilgileri" kısmında da ekran kartına ait fiziksel bilgilerin bir dökümü listelenir. Bunlar ekran kartının kullandığı sürücü dosyası, ekran kartının adı, sürücü versiyonu, ekran kartının çipsetinin üreticisi, karta ait özel id, ekran kartı üreticisi (board), ekran kartının Microsoft tarafından verilen Windows Hardware Quality Labs (WHQL) onayı var mı yok mu gibi bilgilerdir.
Örneğimizin görüntüsü aşağıdaki gibidir:
Kodlara bir göz atalım.
Aşağıda programımızın başında yapmış olduğumuz tanımlamaları görüyorsunuz.
C/C++ kodu:
#include <d3d9.h> //IDirect3D9 arabiriminin tanımlı olduğu başlık dosyası #pragma comment(lib,"d3d9.lib")//IDirect3D9 arabiriminin tanımlı olduğu kütüphane char * FCevir(D3DFORMAT d3dformat); IDirect3D9 * gD3D9; D3DADAPTER_IDENTIFIER9 kartidf;//Ekran kartı bilgilerini temsil eden yapı D3DFORMAT kFormat;//Format bilgilerini temsil eden yapı D3DDISPLAYMODE kMod;//Görüntü modlarını temsil eden yapı
MFC de ugulamaların açılması sırasında OnInitDialog() fonksiyonu çalışır. Bizde bu fonksiyonun içerisine kendi kodlarımızı yazarak açılışta yapılmasını istediğimiz işlemleri gerçekleştirebiliriz. Aşağıdaki kod parçasında sistemde bulunan ekran kartları formdaki comboboxa ekleme işlemi yapılır.
C/C++ kodu:
BOOL CDXBilgiDlg::OnInitDialog() { CDialog::OnInitDialog(); //////////////////////////////////////////////////////////////////// //Direct3D nesnesini oluştur if(NULL==(gD3D9=Direct3DCreate9(D3D_SDK_VERSION))){ AfxMessageBox("Direct3D yaratılamadı"); } else { int nKsayi; //Bilgisayarda kaç ekran kartı var nKsayi=gD3D9->GetAdapterCount(); for(int k=0;k<=nKsayi-1;k++){ //Ekran kartı bilgilerini al gD3D9->GetAdapterIdentifier(k,NULL,&kartidf); //Ekran kartlarının isimlerini comboboxa ekle cmb_Kartlar.AddString(kartidf.Description); } } . . . }
Aşağıdaki kod parçasında da comboboxta listelenen ekran kartlarından birini seçtiğimizde ekran kartı ile ilgili bilgileri elde edilmesi ve kontrollere eklenmesi işlemleri yapılır.
C/C++ kodu:
void CDXBilgiDlg::OnCbnSelchangeKartlar() { //Direct3D yaratılamadıysa diğer kodları icra etme if(NULL==gD3D9) return; //Ekran kartı bilgilerini al gD3D9->GetAdapterIdentifier(cmb_Kartlar.GetCurSel(),NULL,&kartidf); //Elran kartı bilgilerinin olduğu listeyi temizle lst_ebilgi.ResetContent(); CString ebilgi; //Liste kutusuna eklemek için formatla ebilgi.Format("Driver : %s",kartidf.Driver); lst_ebilgi.AddString(ebilgi); ebilgi.Format("Description : %s",kartidf.Description); lst_ebilgi.AddString(ebilgi); ebilgi.Format("DriverVersion : %d",kartidf.DriverVersion); lst_ebilgi.AddString(ebilgi); ebilgi.Format("DriverVersion.LowPart : %d",kartidf.DriverVersion.LowPart); lst_ebilgi.AddString(ebilgi); ebilgi.Format("DriverVersion.HighPart : %d",kartidf.DriverVersion.HighPart); lst_ebilgi.AddString(ebilgi); ebilgi.Format("VendorId : 0x%x",kartidf.VendorId); lst_ebilgi.AddString(ebilgi); ebilgi.Format("DeviceId : 0x%x",kartidf.DeviceId); lst_ebilgi.AddString(ebilgi); ebilgi.Format("SubSysId : 0x%x",kartidf.SubSysId); lst_ebilgi.AddString(ebilgi); ebilgi.Format("Revision : 0x%x",kartidf.Revision); lst_ebilgi.AddString(ebilgi); ebilgi.Format("DeviceGUID : %x-%x-%x-%x",kartidf.DeviceIdentifier.Data1, kartidf.DeviceIdentifier.Data2, kartidf.DeviceIdentifier.Data3, kartidf.DeviceIdentifier.Data4); lst_ebilgi.AddString(ebilgi); if(kartidf.WHQLLevel==0){ lst_ebilgi.AddString("WHQLLevel : WHQL onayı yok"); }else if(kartidf.WHQLLevel==1){// lst_ebilgi.AddString("WHQLLevel : WHQL onayı var"); }else{ // DWORD e paketlenmiş tarih verisini aç. int yil =(kartidf.WHQLLevel>>16)&0xFF; byte ay =(kartidf.WHQLLevel>>8)&0x0F; byte gun =(kartidf.WHQLLevel>>0)&0x0F; ebilgi.Format("WHQLLevel : WHQL onay tarihi %d-%d-%d",gun,ay,yil); } //********************************************************* //Direct3D'nin desteklediği görüntü formatları D3DFORMAT iFormats[6]= { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A2R10G10B10, D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_R5G6B5 }; lst_cozunurluk.ResetContent();//Mod listeleme kutusunu temizle CString modlar; //Tüm görüntü formatları için dön for(int m=0;m<6;m++){ //Seçili format için desteklenen mod sayısı kadar dön for(unsigned int k=0;k<gD3D9->GetAdapterModeCount(cmb_Kartlar.GetCurSel(),iFormats[m]);k++){ //Sırayla görüntü formatına ait mod bilgilerini al gD3D9->EnumAdapterModes(cmb_Kartlar.GetCurSel(),iFormats[m],k,&kMod); //Mod bilgisini liste kutusu için formatla modlar.Format("%d x %d - %dHz - %s",kMod.Width, //Genişlik kMod.Height, //Yükseklik kMod.RefreshRate, //Tazeleme hızı FCevir(iFormats[m]) //Görüntü formatı ); //Modları liste kutusuna ekle lst_cozunurluk.AddString(modlar); } } } char * FCevir(D3DFORMAT d3dformat){ switch (d3dformat) { case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8"; case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8"; case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10"; case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5"; case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5"; case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5"; } return ""; }Örneğimizin konsol versiyonu:
C/C++ kodu:
#include "stdafx.h" #include <stdlib.h> #include <d3d9.h> //IDirect3D9 arabiriminin tanımlı olduğu başlık dosyası #pragma comment(lib,"d3d9.lib")//IDirect3D9 arabiriminin tanımlı olduğu kütüphane IDirect3D9 * gD3D9; D3DADAPTER_IDENTIFIER9 kartidf;//Ekran kartı bilgilerini temsil eden yapı D3DFORMAT kFormat;//Format bilgilerini temsil eden yapı D3DDISPLAYMODE kMod;//Görüntü modlarını temsil eden yapı //fonksiyon prototipleri bool D3DInit(); void KartListesi(); void KartBilgileri(int kart_no); char * FCevir(D3DFORMAT d3dformat); int _tmain(int argc, _TCHAR* argv[]) { D3DInit(); static char secim; do{ system("cls"); KartListesi(); fflush(stdin); printf("nEkran karti secim: "); scanf("%c",&secim); if(secim!='x')KartBilgileri(atoi(&secim)); }while(secim!='x'); return 0; } bool D3DInit(){ //Direct3D nesnesini oluştur if(NULL==(gD3D9=Direct3DCreate9(D3D_SDK_VERSION))) return false; else return true; } void KartListesi(){ if(gD3D9==NULL) return; int nKsayi; //Bilgisayarda kaç ekran kartı var nKsayi=gD3D9->GetAdapterCount(); for(int k=0;k<=nKsayi-1;k++){ //Ekran kartı bilgilerini al gD3D9->GetAdapterIdentifier(k,NULL,&kartidf); //Ekran kartlarının isimlerini listele printf("%d-%s\n",k+1,kartidf.Description); } } void KartBilgileri(int kart_no){ if(NULL==gD3D9) return; kart_no--; //Ekran kartı bilgilerini al if(D3DERR_INVALIDCALL == gD3D9->GetAdapterIdentifier(kart_no,NULL,&kartidf)){ printf("nHatali parametren"); system("pause"); return; }; printf("nEkran karti bilgileri:\n",kartidf.Driver); printf("Driver : %s\n",kartidf.Driver); printf("Description : %s\n",kartidf.Description); printf("DriverVersion : %d",kartidf.DriverVersion); printf("DriverVersion.LowPart : %dn",kartidf.DriverVersion.LowPart); printf("DriverVersion.HighPart : %dn",kartidf.DriverVersion.HighPart); printf("VendorId : 0x%x\n",kartidf.VendorId); printf("DeviceId : 0x%x\n",kartidf.DeviceId); printf("SubSysId : 0x%x\n",kartidf.SubSysId); printf("Revision : 0x%x\n",kartidf.Revision); printf("DeviceGUID : %x-%x-%x-%x\n",kartidf.DeviceIdentifier.Data1, kartidf.DeviceIdentifier.Data2, kartidf.DeviceIdentifier.Data3, kartidf.DeviceIdentifier.Data4); if(kartidf.WHQLLevel==0){ printf("WHQLLevel : WHQL onayi yok\n"); }else if(kartidf.WHQLLevel==1){ printf("WHQLLevel : WHQL onayi var\n"); }else{ // DWORD e paketlenmiş tarih verisini aç. int yil =(kartidf.WHQLLevel>>16)&0xFF; byte ay =(kartidf.WHQLLevel>>8)&0x0F; byte gun =(kartidf.WHQLLevel>>0)&0x0F; printf("WHQLLevel : WHQL onay tarihi %d-%d-%d\n",gun,ay,yil); } //********************************************************* printf("nnDesteklenen goruntu modlari:\n"); //Direct3D'nin desteklediği görüntü formatları D3DFORMAT iFormats[6]= { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A2R10G10B10, D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_R5G6B5 }; for(int m=0;m<6;m++){ //Seçili format için desteklenen mod sayısı kadar dön for(unsigned int k=0;k<gD3D9->GetAdapterModeCount(kart_no,iFormats[m]);k++){ //Sırayla görüntü formatına ait mod bilgilerini al gD3D9->EnumAdapterModes(kart_no,iFormats[m],k,&kMod); //Mod bilgisini liste kutusu için formatla printf("%d x %d - %dHz - %s\n",kMod.Width, //Genişlik kMod.Height, //Yükseklik kMod.RefreshRate, //Tazeleme hızı FCevir(iFormats[m]) //Görüntü formatı ); } } system("pause"); } char * FCevir(D3DFORMAT d3dformat){ switch (d3dformat) { case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8"; case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8"; case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10"; case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5"; case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5"; case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5"; } return ""; }
Kaynak kodlar
http://www.mediafire.com/download/p899jbr9mbm8bub/Direct3D_Giris.zip
Bir sonraki dersimizde görüşünceye kadar kendinize iyi bakın.
Bilgin Terzi ( 3ddreams )
Yorumlar
Yorum Gönder