IDirect3DDevice9 Arabirimi
IDirect3DDevice9 Arabirimi
IDirect3DDevice9 Direct3D'nin temel arabirimlerinden biridir. Bu
yazıda arabirimin ihtiva ettiği fonksiyonları elimden geldiği kadar
açıklamaya çalıştım.Bu yazıyı gelecek derslerimizde sık sık
kullancağımız fonksiyonların daha ayrıntılı açıklamasının bulunması
açısından bir nevi referans niteliğinde olması için hazırladım. Gerekli
gördüğüm yerlerde fonksiyonları ufak örneklerle açıklamaya çalıştım.
Zamanla bu yazıda ufak tefek düzenlemeler olabilir. Şimdilik bu hali ile
birçok kişinin işine yarayacağını düşünüyorum.
IDirect3DDevice9::BeginScene: Çizim işlemlerini başlatır. Direc3D'de bütün çizim işlemleri BeginScene ve EndScene fonksiyonları arasında icra edilmelidir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
... ... lpd3dDevice->BeginScene();//Çizim işlemlerini başlat ... lpd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);// 1 adet polygon çiz lpd3dDevice->EndScene();//Çizim işlemlerini sonlandır. ...
IDirect3DDevice9::BeginStateBlock: Çizim işlemleri
gerçekleşirken icra edilen (SetRenderState, SetSamplerState,
SetTextureStageState vb.) durum belirteçlerinin kaydının tutulması
işlemini başlatır. Kaydedilecek durum belirteçleri BeginStateBlock ve EndStateBlock
fonksiyonları arasında icra edilmelidir. Durum belirteci (States)
kavramını şu şekilde izah etmeye çalışayım. Çizim işlemleri icra
edilirken ilgili konuya ait belirteç icra edildiğinde ondan sonra gelen
tüm çizim işlemlerine doğrudan etki eden bir durum oluşur. Örneğin
SetSamplerState durum belirtecini ele alalım. Bu belirteç dokuların
adresleme ve filtreleme gibi durumlarını değiştirir. Bir kere icra
edildiğinde sonrasında yapılan bütün primitif çizimleri sırasındaki doku
atamalarında belirtilen doku adresleme ve/veya filtreler
kullanılacaktır. Bu durum başka bir belirteç icra edilene kadar etkisini
koruyacaktır. Konumuza geri dönersek. Bu icra edilen birçok durum
belirteçlerinin kaydını bu yolla tutup başka bir çizim anında sürücüye
tekrar atayabiliriz.
Fonksiyonun örnek kullanımı:
Örnek 1 :
C/C++ kodu:
IDirect3DStateBlock9* pStateBlock = NULL; lpd3dDevice->BeginStateBlock(); ... //Durum belirteçleri //SetRenderState, SetSamplerState, SetTextureStageState gibi fonksiyonlar ile sürücüye atanan belirteçler... pd3dDevice->SetRenderState ( D3DRS_ZENABLE, true ); //D3DRS_ZENABLE durum belirteci pixeller üzerinde etkilidir. pd3dDevice->SetRenderState ( D3DRS_CULLMODE, D3DCULL_CW);//D3DRS_CULLMODE durum belirteci vertexler üzerinde etkilidir. ... lpd3dDevice->EndStateBlock( &pStateBlock ); //Kayıt işlemini sonlandır ve kaydı yapılan durum belirteçlerini pStateBlock değişkenine aktarır. ... pStateBlock->Apply(); //Kaydını aldığımız durum belirteçlerini istediğimiz bir anda sürücüye atar. pStateBlock->Capture();//Daha önceden kayda aldığımız durum belirteçlerinin değerlerini günceller.
Örnek 2 :
C/C++ kodu:
IDirect3DStateBlock9* pStateBlock = NULL; lpd3dDevice->BeginStateBlock(); //modele doku atanması ile ilgili durum belirteçleri. lpDevice->SetTextureStageState( 0, D3DTSS_COLOROP,D3DTOP_SELECTARG1 ); lpDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); lpDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); lpDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); lpDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); lpDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); lpd3dDevice->EndStateBlock( &pStateBlock ); //model çiz lpDevice->SetFVF(POLYGON_VERTEX::FVF); lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX)); lpDevice->SetIndices(lpIndexBuffer); lpDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,dwNumVertex,0,dwNumPolygonIndex); .... ... .. . pStateBlock->Apply(); Kaydını tuttuğumuz durum belirteçlerini tekrar sürücü atıyoruz. //model çiz lpDevice->SetFVF(POLYGON_VERTEX::FVF); lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX)); lpDevice->SetIndices(lpIndexBuffer); lpDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,dwNumVertex,0,dwNumPolygonIndex);
IDirect3DDevice9::Clear: Çizim ekranının (yüzeyinin) belirli
bölgelerini yada tamamını, depth bufferi, stencil bufferi temizlemek
için kullanılır. Fonksiyon icra edildiğinde RenderTarget yüzey
belirtilen renkte boyanır. DepthBuffer 0-1 arasında olmak şartı ile
belirtilen yeni değerle temizlenir. StencilBuffer 0-2n-1 (n
bit derinliğini ifade etmektedir) arasında olmak şartı ile belirtilen
yeni değerle temizlenir. Bu fonksiyonun düzgün çalışabilmesi için
temizlenmek istenen unsurların var olmasına dikkat etmek gerekir.
Örneğin sürücüyü depth-stencil desteği olmadan yaratırsanız olmayan
birşeyi temizlemeye çalışacağınızdan fonksiyon düzgün çalışmayacaktır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
lpd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,100), 1.0f, 0 );
IDirect3DDevice9::ColorFill: Belirtilen yüzeyin istenilen dörtgen bir alanını belirtilen renkle doldurur/boyar.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
IDirect3DSurface9* lpSurface; RECT rc={0,0,50,50}; ... lpd3dDevice->ColorFill(lpSurface,&rc,0xff0000ff); //belirtilen yüzeyin belirtilen alanını mavi renkle boyadık.
IDirect3DDevice9::CreateAdditionalSwapChain: Yeni bir ek swap
chain (takas zinciri) oluşturmak için kullanılır. Modelleme
programlarından da hatırlayacağınız gibi aynı sahneye ait çoklu görüş
alanları oluşturmak için kullanılır. Bu görüş alanları aynı kaynakları
kullanarak sahneye çizim yapabilirler. Takas zinciri konusunu biraz
açarsak. Direct3D de çizim işlemleri gözümüzün görebileceği şekle
gelmeden önce back buffer denilen bir hafıza bölgesine çizilir. Back
buffera çizilen görüntü daha sonra front buffera aktarılır. Gözümüzün
göreceği şekle yani pencereye çizilir. Bu olaya swap chain (takas
zinciri) denilmektedir. Direct3D de bir sürücü oluşturulduğunda
otomatikman bir takas zinciri oluşur. CreateAdditionalSwapChain
fonksiyonu yeni bir görüş penceresi oluşturmak istediğimizde bu görüş
penceresi için gerçekleştireceğimiz çizim işlemlerinin gerçekleşeceği ek
bir swap chain oluşturulmasını sağlar.
Aşağıdaki örnekte 2 görüş alanı oluşturmak için izlenmesi gereken
adımlar gösterilmektedir. Örneği dikkatlice inceleyin. Yine aynı
adımları takip ederek daha fazla görüş alanı oluşturabilirsiniz.
Aşağıdaki resimde aynı kaynakları (modeller,dokular) kullanan ancak
farklı kamera görüşlerine sahip görüş alanları görülmektedir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//Tanımlamalar. HWND windowHwnd = NULL; //1 inci pencerenin id si HWND windowHwnd1 = NULL;//2 nci pencerenin id si LPDIRECT3DSWAPCHAIN9 swapChain0 = NULL; // 1 inci swap chain LPDIRECT3DSWAPCHAIN9 swapChain1 = NULL; // 2 nci swap chain //INIT //Çoklu görüş alanları için lpDevice->GetSwapChain( 0, &swapChain0 ); //Sürücü oluştururken bir swap chain zaten oluştuğu için onu alıyoruz. lpDevice->CreateAdditionalSwapChain( &d3dpp, &swapChain1 ); //Ek bir swap chain daha oluştur. //RENDER //-----1. görüş alanı için-----// LPDIRECT3DSURFACE9 pBackBuffer = NULL;//Sahnelerin çizileceği yüzey swapChain0->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );//1. sahneye ait backbufferi döndür. lpDevice->SetRenderTarget( 0, pBackBuffer );//Çizimin yapılacağı hedef yüzeyi belirt. //1. görüş alanı için projeksiyon ve görüş matrixlerini ayarla. //Modelleri çiz swapChain0->Present( NULL, NULL, windowHwnd , NULL, 0 );//1. sahneyi belirtilen pencerede çizdir. pBackBuffer->Release(); //-----2. görüş alanı için-----// swapChain1->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );//2. sahneye ait backbufferi döndür. lpDevice->SetRenderTarget( 0, pBackBuffer );//Çizimin yapılacağı hedef yüzeyi belirt. //2. görüş alanı için projeksiyon ve görüş matrixlerini ayarla. //Modelleri çiz swapChain1->Present( NULL, NULL, windowHwnd1, NULL, 0 );//2. sahneyi belirtilen pencerede çizdir. pBackBuffer->Release();
IDirect3DDevice9::CreateCubeTexture: 3 boyutlu kübik doku
kaynağı oluşturmak için kullanılır. Dokunun en,boy ve derinliği aynı
boyuttadır. 3 boyutlu dokuları bir küp gibi düşünebiliriz. Küpü
oluşturan her yüzeye ayrı ayrı dokular kaplanabilir. Kübik dokular
genelde ortamların 360 derecelik görünüşlerini tutmak amacı ile
kullanılırlar. Daha sonra bu dokular uygulama içerisinde gökyüzü
oluşturmak için (sky box), yansıtma özelliğine sahip objelerin ortamı
yansıtmasının simülasyonunda (Environment Mapping) vs.
kullanılabilirler. Sözgelimi bir arabanın kaportası, su, çaydanlık gibi
pürüzsüz yüzeylere sahip varlıkların ortamı yansıtması örnek olarak
gösterilebilir. Aşağıdaki resimlerden ilkinde küp dokunun temsili bir
resmi görünmektedir. Ikinci resimde dokuya ait yüzeylerin doku
koordinatları ile ilişkisi gösterilmektedir. Üçüncü resimde de örnek bir
küp dokusu gösterilmektedir. Yalnız aşağıdaki resim sizi yanıltmasın.
Kübik dokular fiziksel olarak dosya içerisinde aşağıdaki gibi bir
görünümde saklanmazlar. Her yüzey birbirinden bağımsızdır. Dördüncü
resimde de kübik dokuların ortamı nesneler üzerinde yansıtması amacı ile
kullanılışını görüyoruz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
IDirect3DCubeTexture9 *cubeTexture; lpd3dDevice->CreateCubeTexture( 1024, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &cubeTexture, 0 );
IDirect3DDevice9::CreateDepthStencilSurface: Depth stencil yüzeyi oluşturur. Depth buffer sahnenin derinlik bilgisini tutar. Aşağıdaki resimde görüldüğü gibi kameraya yakın modeller açık renkli, uzağa doğru gidildikçe ise modellerin koyulaştığını görüyoruz. Rasterize esnasında modellerin hangisinin önde hangisinin arkada çizileceği bu buffera bakılarak belirlenir. Ayrıca gölge, sis, ayna gibi efektlerin oluşturulmasında yine depth bufferdan yararlanılmaktadır.
Dipnot: Rasterize grafik programlamada sık kullanılan bir deyim
olduğu için yeri gelmişken onu da açıklayayım. Rasterize elimizdeki
verilerin(vertex,polygon,dokular,shaderler vs) belirli bir işlem
sürecinden geçerek karşımıza pixellerden oluşan bir görüntü olarak
gelmesi olayına denir.
IDirect3DDevice9::CreateIndexBuffer: Index buffer oluştumakta
kullanılır. Index bufferlar primitif çizerken vertex bufferdeki
vertexlerin hangi sıra ile alınıp kullanılacağını belirleyen vertex
numaralarını (indexlerini) tutan bellek bölgeleridir. Index bufferleri
kullanmak aynı vertexlerin birden çok kere kullanılmalarını önleyerek
hafıza tasarrufu ve ekran kartına çizim için gönderilecek vertex
miktarını azaltarak performans artışı sağlamaktadır.
Örneğin bir quad(kare primitif) çizmek istersek bunu aşağıdaki
resimdeki gibi iki polygonu kullanarak gerçekleştirebiliriz. Eğer quad
çizimini index bufferları kullanamadan yani indexsiz çizdirmek istersek
vertex bufferin içini polygonları oluşturan vertexlerin koordinatları
ile aşağıdaki gibi doldurmalıyız. Vertex bufferi, her polygon 3
vertexten meydana geldiğinden 2polygon*3vertex=6vertexle doldururuz.
Sadece vertex bufferler kullanıldığında primitifler çizilirken vertex
bufferlardan veri doğrusal olarak alınır. Yani vertex bufferda
belirtilen indexten başlanıp vertexler sıra ile alınıp polygon çizimi
için kullanılır. Vertex bufferdeki 0,1,2 noktaları 1. polygonu, 3,4,5
noktaları 2.polygonu, 6,7,8 3. polygonu... oluşturur ve bu böyle sıra
ile gider.
Index bufferleri kullanırsak durum aşağıda görüldüğü gibi gerçekleşir. Dikkat ederseniz vertex bufferde ortak noktaları kullanan polygonların vertexleri sadece bir kere kullanıldı. Bu yöntem örneğimizde bizim fazladan 2 vertex kullanmamızı önledi. Index bufferlar kullanıldığı zaman ekran kartı polygonları çizerken vertexleri index bufferda gösterilen sıra ile alıp kullanır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DINDEXBUFFER9 lpIndexBuffer; ... //Hafızada indexler için alan ayırma işlemi yapılıyor. lpDevice->CreateIndexBuffer(dwNumPolygonIndex*3*sizeof(int),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&lpIndexBuffer,NULL); WORD *pIndices; lpIndexBuffer->Lock(0,0,(void **)&pIndices,0); for (DWORD n=0;n<dwNumPolygonIndex;n++) { pIndices[n*3] =pPolygonIndex[n].nVertexIndex[0]; pIndices[n*3+1]=pPolygonIndex[n].nVertexIndex[1]; pIndices[n*3+2]=pPolygonIndex[n].nVertexIndex[2]; } lpIndexBuffer->Unlock();
IDirect3DDevice9::CreateOffscreenPlainSurface: Belirtilen boyutlarda bir yüzey oluşturmak için kullanılır.
C/C++ kodu:
IDirect3DSurface9* lpSurface; lpd3dDevice->CreateOffscreenPlainSurface( 512, 512, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &lpSurface, NULL);
IDirect3DDevice9::CreatePixelShader: Pixel Shader oluşturmak için kullanılır.
IDirect3DDevice9::CreateQuery: Gerçek zamanlı olarak ekran
kartı üzerinde bazı sorgulamalar yapmak için kullanılır. Vcache,
occlusion , işlenen d3d çağrıları (komutları), işlenen polygon sayısı,
işlenen verilerin yüzde olarak işlenme miktarları gibi bilgileri elde
etmek mümkündür.
Aşağıdaki örnekte bir çok alanda kullanabileceğiniz occlusion
sorgulama ile ilgili ufak bir örnek göstereceğim. Occlusion sorgusu
örnekte göreceğiniz gibi BEGIN END blokları arasında çizilen modelin kaç
pixel olarak çizildiğini sorgular. Eğer dönen değer sıfır pixel ise
model sahnede görünmüyor demektir. Occlusion sorgulamanın bu özelliğini
ne şekilde değerlendirebiliriz? Örneğin güneşten yayılan lens flare
efektinin güneşin ekrana çizilip çizilmemesi durumuna göre çizilmesini
yada çizilmemesini sağlayabiliriz. Güneş modeline bir duvarın arkasından
baktığımızda occlusion sorgulamadan bize dönecek değer 0 pixel olur.
Çünkü güneş görünmüyordur. Bu durumda lens flare efektini çizdirmeyiz.
Occlusion sorgulama eleme sistemlerinde de sıklıkla
kullanılmaktadır. Şimdi düşünün bir ormandasınız. Önünüzde binlerce ağaç
var. Siz önünüzdeki bu binlerce ağaçtan kaç tanesini görebiliyorsunuz.
Önünüzdeki ağaçlar arkalarda olan bir çok ağacı görmenizi engelliyor.
Işte bu durumda görünmeyen ağaçları çizdirmemek size inanılmaz
performans kazandıracaktır. Yalnız bu işlemin ufak bir püf noktası var.
Sahneye önce çizilecek ağaçların çok çok düşük polygonlu halleri
çizilir. Sahneye az sayıda polygon çizdirmek ekran kartını
yormaz.Occlusion sorguyu her düşük polygonlu ağaç modeli üzerinde ayrı
ayrı gerçekleştireceğiz. Eğer dönen değer 0 pixel ise ağaç sahnede
görünmüyor demektir. Bu durumda sorguyu gerçekleştirdiğimiz düşük
polygonlu ağaca ait yüksek polygonlu ağaç modelini çizdirmeyiz.
D3DQUERYTYPE_OCCLUSION yerine başka sorgular seçebilirisiniz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DQUERY9 d3dQuery; DWORD pixelsVisible; //init lpDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &d3dQuery );//Occlusion sorgusu yarat. .. //render d3dQuery->Issue( D3DISSUE_BEGIN ); //modeli çiz d3dQuery->Issue( D3DISSUE_END ); while(d3dQuery->GetData((void *) &pixelsVisible, sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE);
IDirect3DDevice9::CreateRenderTarget: Sahnenin bir yüzeye
çizilmesi için gerekli yüzey kaynağını oluşturmakta kullanılır. Daha
sonra bu yüzey sahnedeki herhangi bir primitifi kaplamakta yada
shaderlerde bazı post process efektlerin oluşturulmasında
kullanılabilir.
IDirect3DDevice9::CreateStateBlock: Yeni bir StateBlock
oluşturur ve belirtilen tipteki tüm belirteçlerin kaydı alınır.
StateBlocklar durum belirteçlerine (States) ait bilgileri tutarlar.
Fonksiyonun ilk parametresi aşağıdaki değerleri alabilir. Bu değerler
tipi belirtilen tüm durum belirteçlerinin kaydının tutulması gerektiğini
belirtir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DSBT_ALL //Tüm durum belirteçlerinin kaydını tut. D3DSBT_PIXELSTATE //Sadece pixeller üzerinde etkili olan durum belirteçlerinin kaydını tut. D3DSBT_VERTEXSTATE //Sadece vertexler üzerinde etkili olan durum belirteçlerinin kaydını tut. //Örneğin; pd3dDevice->SetRenderState ( D3DRS_ZENABLE, true ); //D3DRS_ZENABLE durum belirteci pixeller üzerinde etkilidir. pd3dDevice->SetRenderState ( D3DRS_CULLMODE, D3DCULL_CW); //D3DRS_CULLMODE durum belirteci vertexler üzerinde etkilidir. HRESULT hr; IDirect3DStateBlock9* pStateBlock = NULL; pd3dDevice->CreateStateBlock( D3DSBT_ALL , &pStateBlock);//Tüm belirteçlerin kaydını ve durumlarını al.
IDirect3DDevice9::CreateTexture: Doku kaynağı oluşturmak için kullanılır. Doku kaynakları modellerin kaplanmasında yada shaderlere parametre olarak verilebilir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DTEXTURE9 lpTexture; lpDevice->CreateTexture(512, 512, 1, D3DUSAGE_RENDERTARGET,mode.Format, D3DPOOL_DEFAULT, &lpTexture,NULL);
IDirect3DDevice9::CreateVertexBuffer: Vertex buffer oluşturmakta kullanılır. Vertex bufferlar primitiflere ait vertex dizilerini tutan bellek bölgeleridir. CreateIndexBuffer fonksiyonunun anlatımında vertex bufferlar hakkında daha ayrıntılı bilgi verilmiştir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DVERTEXBUFFER9 lpVertexBuffer; //Vertex yapısı struct POLYGON_VERTEX{ D3DXVECTOR3 vPosition;//Vertexin pozisyonu D3DXVECTOR3 vNormal;//Vertexin normali (ışıklandırma için gerekli) D3DXVECTOR2 vTex0;//Doku koordinatları (u,v) static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; //Vertexe ait özellikleri sürücüye tanıtmak için gerekli tanımlama }; ... //Vertexler için hafızada alan ayırma işlemi yapılıyor. lpd3dDevice->CreateVertexBuffer( dwNumPolygon*3*sizeof(POLYGON_VERTEX), NULL, POLYGON_VERTEX::FVF, D3DPOOL_DEFAULT, &lpVertexBuffer, NULL ); //vertex buffer dolduruluyor. HRESULT hr; hr=lpVertexBuffer->Lock(0,0,(void**)&pVertices, 0); for (DWORD n=0;n<dwNumVertex;n++) { pVertices[n].vPosition=Vertex[n].vPosition;//Polygon vertexleri pVertices[n].vNormal =Vertex[n].vNormal;//Vertex normalleri pVertices[n].vTex0 =Vertex[n].vTex0;//Doku koordinatları } lpVertexBuffer->Unlock();
IDirect3DDevice9::CreateVertexDeclaration: Shader çizimi
esnasında kullanılan primitife ait vertexlerin yapısını sürücüye
tanıtmakta kullanılan yapıları oluşturmakta kullanılır. Kısaca Flexible
Vertex Formata (FVF) benzer bir tanımlamanın vertex shaderler için
kullanılan halidir diyebiliriz. FVF primitif çizerken, Vertex
deklarasyon ise shader çizerken primitife ait vertexin yapısını sürücüye
tanıtmakta kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
IDirect3DVertexDeclaration9 *g_VertDecl= NULL; D3DVERTEXELEMENT9 vertexElement[] = { { 0, sizeof( float ) * 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, sizeof( float ) * 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, sizeof( float ) * 6, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, sizeof( float ) * 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, { 0, sizeof( float ) * 11, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, D3DDECL_END() }; lpDevice->CreateVertexDeclaration( vertexElement, &g_VertDecl );
IDirect3DDevice9::CreateVertexShader: Vertex Shader oluşturmak için kullanılır.
IDirect3DDevice9::CreateVolumeTexture: 3 boyutlu eni boyu ve derinliği birbirinden farklı dokular oluşturmak için kullanılır.
IDirect3DDevice9::DeletePatch: Id numarsı (handle) verilen patch kaynağını hafızadan siler.
IDirect3DDevice9::DrawIndexedPrimitive: Indexli primitif çizmek için kullanılır. CreateIndexBuffer fonksiyonunda index bufferlarla ilgili kısa açıklama yapılmıştır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
... lpDevice->SetFVF(POLYGON_VERTEX::FVF); lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX) ); lpDevice->SetIndices(lpIndexBuffer); lpDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,dwNumVertex,0,dwNumPolygonIndex); ...
IDirect3DDevice9::DrawIndexedPrimitiveUP: Direct3D ye ait
vertex ve index bufferları kullanmadan direk kullanıcı tanımlı dizileri
kullanarak primitif çizmekte kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
struct POLYGON_VERTEX{ D3DXVECTOR3 vPosition; D3DXVECTOR3 vNormal; D3DXVECTOR2 vTex0;//Doku koordinatları (u,v) static const DWORD FVF =(D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1); } //UP POLYGON_VERTEX *lpVertexBufferUP; WORD *lpIndexBufferUP; //init //UP vertex buffer lpVertexBufferUP=new POLYGON_VERTEX[dwNumVertex]; //vertexler için bir dizi oluştur. for (DWORD n=0;n<dwNumVertex;n++) { //Vertex dizisini daha önceden model dosyasından okuduğumuz vertex bilgileri ile doldur. lpVertexBufferUP[n].vPosition= Vertex[n].vPosition; //Vertex normalleri lpVertexBufferUP[n].vNormal= Vertex[n].vNormal; //Polygon doku koordinatları lpVertexBufferUP[n].vTex0= Vertex[n].vTex0; } //UP index buffer lpIndexBufferUP=new WORD[dwNumPolygonIndex*3];//vertex indexleri için dizi oluştur for (DWORD n=0;n<dwNumPolygonIndex;n++) {//Index dizisini daha önceden model dosyasından okuduğumuz index verisi ile doldur. lpIndexBufferUP[n*3] =pPolygonIndex[n].nVertexIndex[0]; lpIndexBufferUP[n*3+1]=pPolygonIndex[n].nVertexIndex[1]; lpIndexBufferUP[n*3+2]=pPolygonIndex[n].nVertexIndex[2]; } //Render ... //DrawIndexedPrimitiveUP fonksiyonu ile primitif çizilirken aşağıda belirtilen fonksiyonlar kullanılmaz. Çünkü bu fonksiyonlar ile yapılacak işlemler DrawIndexedPrimitiveUP fonksiyonu tarafından zaten gerçekleştiriliyor. //lpDevice->SetFVF(..); //Çağırmaya gerek yok. Çünkü DIPUP fonksiyonunda 8 inci parametre ile vertex bilgisini belirttik. //lpDevice->SetStreamSource(..);Çağırmaya gerek yok. Çünkü DIPUP fonksiyonunda 7 nci parametre ile vertex bufferi belirttik. //lpDevice->SetIndices(...);// Çağırmaya gerek yok. Çünkü DIPUP fonksiyonunda 5 inci parametre ile index bufferi belirttik. lpDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,dwNumVertex,dwNumPolygonIndex,lpIndexBufferUP,D3DFMT_INDEX16,lpVertexBufferUP,sizeof(POLYGON_VERTEX)); ...
IDirect3DDevice9::DrawPrimitive: Indexli olmayan vertex dizili primitifleri çizer. Primitif çizilirken sadece vertex buffer kullanılır. CreateIndexBuffer fonksiyonunda bu konuya deyinilmiştir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
.. lpd3dDevice->BeginScene();//Çizim işlemlerini başlat ... lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX) );//çizim sırasında kullanılacak vertex buffer belirtiliyor. lpDevice->SetFVF(POLYGON_VERTEX::FVF); //sürücüye vertex buffera ait vertexlerin yapısı bildiriliyor. lpDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );//vertex bufferin 0. indexinden başlayarak 1 adet polygon çiz lpd3dDevice->EndScene();//Çizim işlemlerini sonlandır. ...
IDirect3DDevice9::DrawPrimitiveUP: Direct3D ye ait vertex bufferı kullanmadan direk kullanıcı tanımlı dizileri kullanarak primitif çizmekte kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
struct POLYGON_VERTEX{ D3DXVECTOR3 vPosition; D3DXVECTOR3 vNormal; D3DXVECTOR2 vTex0;//Doku koordinatları (u,v) static const DWORD FVF =(D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1); } //UP POLYGON_VERTEX *lpVertexBufferUP; //init //UP vertex buffer lpVertexBufferUP=new POLYGON_VERTEX[dwNumPolygonIndex*3]; //vertexler için bir dizi oluştur. polygon sayısı * 3 //Eğer kullandığımız model dosyası içinde vertex ve index bilgileri ayrı ayrı olarak tutuluyorsa DrawPrimitiveUP fonksiyonunda primitif çizimi için sadece vertexleri kullanılacağımızdan dosyadan okuduğumuz vertexleri indexlere göre yeniden yapılandırmamız gerekiyor. Bu durumda her polygon için 3 vertex bilgisi elde etmiş olacağız. Aşağıdaki döngü bu işlemi gerçekleştiriyor. for (DWORD n=0;n<dwNumPolygonIndex;n++) { //Polygon vertexleri lpVertexBufferUP[n].vPosition= Vertex[n].vPosition; //Vertex normalleri lpVertexBufferUP[n].vNormal= Vertex[n].vNormal; //doku koordinatları lpVertexBufferUP[n].vTex0 = Vertex[n].vTex0 ; } //Render //DrawIndexedPrimitiveUP fonksiyonunda olduğu gibi yine kullanım dışı kalan fonksiyonlar var. //lpDevice->SetFVF(..); //Çağırmaya gerek yok. Çünkü DPU fonksiyonunda 4 üncü parametre ile vertex bilgisini belirttik. //lpDevice->SetStreamSource(..);Çağırmaya gerek yok. Çünkü DPU fonksiyonunda 3 üncü parametre ile vertex bufferi belirttik. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST,dwNumPolygonIndex, lpVertexBufferUP,sizeof(POLYGON_VERTEX));
IDirect3DDevice9::DrawRectPatch: Sürücüye atanmış olan vertex bufferi kullanarak dörtgen patch çizmeye yarar.
IDirect3DDevice9::DrawTriPatch: Sürücüye atanmış olan vertex bufferi kullanarak üçgen patch çizmeye yarar.
IDirect3DDevice9::EndScene: BeginScene ile başlatılan çizim blokunu sonlandırır. BeginScene fonksiyonunda fonksiyonla ilgili örnek bulunmaktadır.
IDirect3DDevice9::EndStateBlock: BeginStateBlock fonksiyonu ile başlatılan durum belirteçlerinin kayıt işlemini sonlandırır ve elde edilen bilgileri döndürür. BeginStateBlock fonksiyonunda fonksiyon ile ilgili örnek bulunmaktadır.
IDirect3DDevice9::EvictManagedResources: POOL_MANAGED parametresi ile oluşturulan kaynakları (doku, vertex buffer, index buffer) ekran kartı hafızasından sistem hafızasına gönderir. Not: POOL_MANAGED parametresi ile oluşturulan kaynaklar sistem hafızasına yüklenirler gerekli olduğu durumlarda ekran kartı hafızasına yüklenirler.
IDirect3DDevice9::GetAvailableTextureMem: Kullanılabilir doku hafızası miktarını döndürür.
IDirect3DDevice9::GetBackBuffer: Sürücüye ait back bufferı (arka tamponu) döndürür. Olayı biraz açarsak. Direct3D çizim işlemlerini gerçekleştirirken oluşan görüntüyü gözümüzün önüne getirmeden önce BackBuffer(Arka tampon) denilen bir bellek bölgesinde oluşturur. CreateAdditionalSwapChain fonksiyonunda konu ile ilgili daha fazla açıklama ve fonksiyonun örnek kullanımını bulabilirsiniz. Aşağıdaki örnekte GetBackBuffer fonksiyonunun bir başka kullanım alanını daha göstermek istedim. Fonksiyon back bufferı diske kaydediyor. Kısacası sahnenin ekran görüntüsünü çekiyor.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
void ScreenShot(char* file_name,int Width, int Height){ IDirect3DSurface9* backbuff; //belirtilen boyutta bir yüzey kaynağı oluştur g_pd3dDevice->CreateOffscreenPlainSurface(Width, Height, D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &backbuff,NULL); //Back bufferi yüzey kaynağına aktar HRESULT hr =g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backbuff); if(hr != D3D_OK){ MessageBox(NULL,"Ekran görüntüsü alınamadı","Hata",NULL); backbuff->Release(); return; } //Yüzey kaynağını diske belirtilen formatta kaydet. D3DXSaveSurfaceToFile(file_name, D3DXIFF_JPG , backbuff, NULL, NULL); backbuff->Release(); }
IDirect3DDevice9::GetClipPlane: Index numarası verilen kullanıcı tanımlı kırpma zeminine ait bilgileri almak için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DXPLANE plane; lpDevice->GetClipPlane(0,plane);
IDirect3DDevice9::GetClipStatus: Primitif çizimi sırasında
kırpılma durumu ile ilgili bilgileri almak için kullanılır. Kırpma
durumu ile ilgili bilgilere sadece sürücü "software vertex processing"
(yazılım tabanlı vertex işleme) parametresi ile oluşturuldu ise
erişilebilir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DCLIPSTATUS9 clipstatus; lpDevice->GetClipStatus(&clipstatus);
IDirect3DDevice9::GetCreationParameters: Sürücünün
oluşturulurken hangi özelliklerde oluşturulduğu ile ilgili bazı
bilgilerin alınması için kullanılır. Bu bilgileri
D3DDEVICE_CREATION_PARAMETERS yapısı üzerinde açıklayalım.
C/C++ kodu:
typedef struct _D3DDEVICE_CREATION_PARAMETERS { UINT AdapterOrdinal; //Sürücünün oluşturulduğu ekran kartının id sini belirtir. D3DDEVTYPE DeviceType; //Sürücü tipini belirtir. HAL(donanım tabanlı rasterizer),REF(yazılım tabanlı rasterizer),SW(kullanıcı tanımlı rasterizer) HWND hFocusWindow; //Sürücünün çizim yaptığı pencerenin id sini döndürür. DWORD BehaviorFlags; //Sürücünün genel işleyişini belirleyen parametreleri döndürür. Ayrıntılı bilgi için SDK dokümanlarını inceleyiniz. } D3DDEVICE_CREATION_PARAMETERS;
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DDEVICE_CREATION_PARAMETERS lpCrParameters; lpDevice->GetCreationParameters(&lpCrParameters);
IDirect3DDevice9::GetCurrentTexturePalette: Sürücüde o an aktif olan renk paletinin indexini döndürür.
IDirect3DDevice9::GetDepthStencilSurface: Sürücünün derinlik yüzeyini (Depth Buffer) almak için kullanılır.
IDirect3DDevice9::GetDeviceCaps: Ekran kartının desteklediği özellikleri, kabiliyetlerini öğrenmek için kullanılır. Bilgileri D3DCAPS9 yapısı olarak döndürür.
IDirect3DDevice9::GetDirect3D: Direct3D arabirimini döndürür.
IDirect3DDevice9::GetDisplayMode: Sürücünün ekran çözünürlüğü (320x240,800x600...), renk çözünürlüğü (16bit,32bit...), ekran tazeleme frekansı, görüntü formatı gibi özellikleri almak için kullanılır.
IDirect3DDevice9::GetFrontBufferData: Belirtilen takas zincirine (swap chain) ait ön tamponun (front buffer) bir kopyasını alır ve sistem hafızasında belirtilen yüzeye aktarır. Performans yönünden oldukça yavaştır.
IDirect3DDevice9::GetFVF: Sürücüde o an aktif olan FVF yapısını döndürür.
IDirect3DDevice9::GetGammaRamp: Sürücüye atanmış gamma dizisini döndürür.
IDirect3DDevice9::GetIndices: Sürücüye atanmış olan index bufferi geri döndürür.
IDirect3DDevice9::GetLight: Index numarası verilen ışığın özelliklerini döndürür.
IDirect3DDevice9::GetLightEnable: Index numarası verilen ışığın aktif yada pasif olup olmadığını döndürür.
IDirect3DDevice9::GetMaterial: Sürücüye atanmış olan aktif materialin özelliklerini döndürür.
IDirect3DDevice9::GetNPatchMode: Çizilmekte olan patchin segment sayısını döndürür.
IDirect3DDevice9::GetNumberOfSwapChains: Aynı sürücü üzerinde yaratılmış sahnelerin (swap chain) sayısını döndürür. Modelleme programlarından da hatırlayacağınız çoklu görüş alanlarının sayısını döndürür.
IDirect3DDevice9::GetPaletteEntries: Index numarası verilen renk paletlerini geri döndürür.
IDirect3DDevice9::GetPixelShader: O an aktif olan pixel shaderi döndürür.
IDirect3DDevice9::GetPixelShaderConstantB: Pixel shaderda belirtilen bool tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetPixelShaderConstantF: Pixel shaderda belirtilen float tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetPixelShaderConstantI: Pixel shaderda belirtilen integer tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetRasterStatus: Index numarası verilen takas zincirinin (swap chain) rasterize durumu ile ilgili bilgi verir.
IDirect3DDevice9::GetRenderState: Belirtilen durum belirtecinin değerini döndürür.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
DWORD dwDeger; lpDevice->GetRenderState(D3DRS_FILLMODE,&dwDeger); if(dwDeger==D3DFILL_SOLID)//Polygonlar katı model (içi pixellerle doldurulmuş ) olarak mı çiziliyor. lpDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); //Polygonları telkafes (polygonların sadece kenar çizgilerini çiz, içini doldurma) şeklinde çiz.
IDirect3DDevice9::GetRenderTarget: Index numarası verilen render-target ( üzerine çizim yapılabilme özelliği olan / üzerine çizim yapılmakta olan) tipli yüzeyi döndürür.
IDirect3DDevice9::GetRenderTargetData: Ekran kartı hafızasındaki render-target (üzerine çizim yapılabilme özelliği olan / üzerine çizim yapılmakta olan ) tipli yüzeyi sistem hafızasında konumlu başka bir yüzeye kopyalar. Bu işlem için her iki yüzeyinde aynı boyutta ve formatlarda olması gerekmektedir.
IDirect3DDevice9::GetSamplerState: Sürücüye atanmış olan dokunun adresleme ve filtreleme ile ilgili özelliklerine ait değerleri almak için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
DWORD dwMin; lpDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, &dwMin );
IDirect3DDevice9::GetScissorRect: Sürücüye atanmış olan kırpma alanını döndürür. SetScissorRect fonksiyonunda açıklama yapılmıştır.
IDirect3DDevice9::GetSoftwareVertexProcessing: Vertexlerin yazılımsal olarak mı yoksa donanımsal olarak mı işlendiğini döndürür.
IDirect3DDevice9::GetStreamSource: Sürücüye atanmış olan vertex bufferi döndürür.
IDirect3DDevice9::GetStreamSourceFreq: O an sürücüye atanmış örnekleme tekniği ile çizilmekte olan primitiflerden kaç tane çizildiğinin sayısını döndürür.
IDirect3DDevice9::GetSwapChain: Id numarası verilen takas zincirini (swap chain) döndürür.
IDirect3DDevice9::GetTexture: Sürücüye atanmış olan belirtilen katmandaki dokuyu geri döndürür.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DBASETEXTURE9 lpTexture; lpDevice->GetTexture(0,&lpTexture); //Sıfırıncı katmandaki sürücüye en son atanmış dokuyu döndürür. //lpDevice->SetTexture(0,lpTexture);//Sıfırıncı katmana belirtilen dokuyu atar
IDirect3DDevice9::GetTextureStageState: Sürücüye atanmış olan x katmanındaki dokunun özelliklerini döndürür.
IDirect3DDevice9::GetTransform: Sürücüye atanmış olan belirtilen tipteki matrixleri almak için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DXMATRIX matWorld, matView, matProjection, matWVP; lpDevice->GetTransform(D3DTS_WORLD,&matWorld); lpDevice->GetTransform(D3DTS_VIEW,&matView); lpDevice->GetTransform(D3DTS_PROJECTION,&matProjection); //matWVP = matWorld * matView * matProjection;
IDirect3DDevice9::GetVertexDeclaration: Sürücüye atanmış olan vertex deklesaryonunu geri döndürür.
IDirect3DDevice9::GetVertexShader: Sürücüye atanmış olan vertex shaderi geri döndürür.
IDirect3DDevice9::GetVertexShaderConstantB: Vertex shaderda belirtilen bool tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetVertexShaderConstantF: Vertex shaderda belirtilen float tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetVertexShaderConstantI: Vertex shaderda belirtilen integer tipli değişkenin değerini almak için kullanılır.
IDirect3DDevice9::GetViewport: O anki Direct3D sürücüsüne ait görüş alanı bilgisini elde etmekte kullanılır. Bilgiler belirtilen D3DVIEWPORT9 tipindeki yapımıza aktarılır.
IDirect3DDevice9::LightEnable: Index numarası verilen ışığı aktif yada pasif (açar/kapatır) yapar.
IDirect3DDevice9::MultiplyTransform: Model, görüş yada projeksiyon matrixlerini belirtilen matrixle çarpmak için kullanılır.
IDirect3DDevice9:: Present: Sürücüyü bir sonraki çizim işlemi için hazırlar.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//sahneyi temizle lpDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(100,100,100), 1.0f, 0 ); //Çizim işlemine başla lpDevice->BeginScene(); //Çizim işlemleri //Çizim işlemini sonlandır lpDevice->BeginScene(); //Şimdiye kadar icra edilen çizim işlemlerinin sonucunu ekrana göster ve sürücüyü bir sonraki çizim işlemi için hazırla lpDevice->Present( NULL, NULL, NULL, NULL );
IDirect3DDevice9::ProcessVertices: Belirtilen vertex bufferdeki vertexleri belirli bir işlem sürecinden geçirerek elde edilen yeni vertexleri belirtilen vertex buffera atar. Vertexler aşağıdaki işlem sürecinden geçer.
-Vertexler önce "world + view + projection" matrixleri tarafından dönüşüme uğrar.
-Görüş alanı özelliklerine göre (viewport) vertexlerin ekran koordinatları hesaplanır.
-Eğer kırpma açıksa kırpma kodu oluşturularak hedef vertex buffer
ile ilişkilendirilerek saklanır. Eğer vertexlerden biri görüş alanı
içerisindeyse (view frustum) vertexlerin ekran koordinatları
hesaplanarak belirtilen vertex buffera aktarılır değilse vertexlerin
projeksiyon sistemindeki konumları vertex buffera aktarılır.
IDirect3DDevice9::Reset: Çalışma zamanı sürücünün yeninden yapılandırılması istenildiğinde kullanılır. Örneğin uygulama çalışırken uygulamanın tam ekran-pencere moduna geçişini, çözünürlük değiştirme, sürücünün arızaya geçtiği durumlarda onarılması konularında bu fonksiyondan yararlanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//Sürücümüzü tam ekran modunda çalışacak şekilde oluşturduk. HRESULT InitD3D( HWND hWnd ) { if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth=640; d3dpp.BackBufferHeight=480; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat =D3DFMT_X8R8G8B8; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; ... void Render() { HRESULT hr; hr = g_pd3dDevice->TestCooperativeLevel(); if( hr==D3DERR_DEVICELOST ){//sürücü arıza durumunda mı? Sleep(100);//Her kontrolden sonra biraz bekle return;//Çizim rutinlerine geçmeden başa dön } else if( hr==D3DERR_DEVICENOTRESET ){//sürücü resetlenmeye hazır mı? ReleaseResources();//kaynakları serbest bırak g_pd3dDevice->Reset(&d3dpp);//sürücüyü resetle InitResources();//kaynakları yeniden yükle return;//Çizim rutinlerine geçmeden başa dön } g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); ...
IDirect3DDevice9::SetClipPlane: Kullanıcı tanımlı kırpma zeminleri oluşturmak için kullanılır. Zeminin arkasında kalan objeler kırpma işlemine tabi tutulur ve ekrana çizilmezler. Aynı anda birden çok kırpmaz zemini kullanmak mümkündür. Objelerin kesitlerini göstermek, ayna gibi efektlerin yapımında kullanılmaktadır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DXPLANE plane; D3DXPlaneFromPointNormal(&plane,&D3DXVECTOR3(100,0,0),&D3DXVECTOR3(1,0,0)); //(100,0,0) pozisyonunda yönü +X'e (1,0,0) bakan bir kırpma zemini(plane) oluşturduk. lpDevice->SetClipPlane(0,plane); lpDevice->SetRenderState(D3DRS_CLIPPLANEENABLE ,D3DCLIPPLANE0);
Aşağıdaki resimde örneğimizin etkileri görülmektedir. Objelerin tanımladığımız kırpma zemininin arkasında kalan kısımları çizilmemektedir.
IDirect3DDevice9::SetClipStatus: Sürücünün kırpma durumunu ayarlamakta kullanılır.
IDirect3DDevice9::SetCurrentTexturePalette: Sürücüye atanmış olan dokunun kullanacağı renk paletini belirtmek için kullanılır.
IDirect3DDevice9::SetCursorPosition: Fare imlecinin pozisyonunu değiştirmek için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
lpDevice->SetCursorPosition(100,100,D3DCURSOR_IMMEDIATE_UPDATE );
IDirect3DDevice9::SetCursorProperties: Direct3D tarafından desteklenen fare imlecinin özelliklerini belirtmek için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
IDirect3DSurface9* lpSurface; lpDevice->SetCursorProperties(1,1,lpSurface); //ilk iki parametre doku üzerinde konum belirtmek için kullanılır. Bu konum imlecimizin uç noktası olacak. Üçüncü parametrede de imleç olarak kullanılacak dokuyu belirtiyoruz.
IDirect3DDevice9::SetDepthStencilSurface: Sürücüye belirtilen yüzeyin derinlik yüzeyi olarak kullanılacağını söyler.
IDirect3DDevice9::SetDialogBoxMode: Uygulamanız tam ekran modunda çalışırken de dialog kutularının görüntülenmesine izin verir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
lpDevice->SetDialogBoxMode(true);//false
IDirect3DDevice9::SetFVF: O an çizdirilecek olan primitifin vertex yapısını sürücüye belirtmek için kullanılır. Kullanacağımız vertex yapısına göre FVF tanımlaması için kullanılacak öğeler de değişecektir. Aşağıda örnek bir tanımlama gösterilmektedir. Ayrıntılı açıklama ve diğer örnek tanımlamalar için SDK dokümanlarını inceleyiniz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//vertex yapımız struct POLYGON_VERTEX{ D3DXVECTOR3 vPosition; //D3DFVF_XYZ D3DXVECTOR3 vNormal; //D3DFVF_NORMAL float tu,tv; //D3DFVF_TEX1 static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; //vertex yapımızın özellikleri. };
Aşağıdaki satır ile çizdireceğimiz primitifdeki vertexlerin hangi özelliklere sahip olacaklarını tanımlıyoruz. Aşağıdaki tanımlamayı yukarıdaki gibi vertex yapımızın içinde de statik olarak tanımlayabiliriz. Yukarıdaki tanımlama bana daha pratik geldiğinden ben öyle kullanmayı tercih ediyorum. FVF değişken statik olarak tanımlandığı için sadece yapı içerinden erişilebilir. Dizi tanımlamalarında bellekte fazladan yer kaplamaz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//render lpDevice->SetFVF(POLYGON_VERTEX::FVF); //sürücüye vertex buffera ait vertexlerin yapısı bildiriliyor. lpDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); ...
IDirect3DDevice9::SetGammaRamp: Sürücünün parlaklık, karşıtlık ayarını değiştirmek için kullanılır. Genellikle pencere modunda iken bu fonksiyonun etkisi yoktur. Sdk dokümanlarında konu ile ilgili ayrıntılı açıklamayı bulabilirsiniz. Aşağıda D3DGAMMARAMP yapısının içeriğini görüyoruz. Görüldüğü gibi RGB yani kırmızı, yeşil ve mavi renkler 256 lık diziler şeklinde tanımlanmıştır. Bu dizilerin içeriğine göre ışığın parlaklık, karşıtlık etkileri değişecektir. Aşağıdaki örnekte her rengin dizisi aynı değerler ile ve doğrusal olarak doldurulmaktadır. Aşağıdaki grafiklerden ilkinde fonksiyonumuza 0.1f değerini verdiğimizde oluşan sayı dizisinin oluşturduğu rampayı görüyoruz. Yani ışığın en az olduğu ortamın en karanlık göründüğü an. Ikinci grafikte ise fonksiyonumuza 2.2f değerini verdiğimizde ortam ışığı gereğinden fazla aydınlıktır. Yani fonksiyonumuza 0.1 ile 2.2f arasında değerler verdiğimizde ortam parlaklığı karanlıktan aydınlığı doğru gidecektir. Değişik fonksiyonlar kullanarak değişik ışık etkileri elde etmek mümkündür. Bu size kalmış.
C/C++ kodu:
typedef struct D3DGAMMARAMP { WORD red[256]; WORD green[256]; WORD blue[256]; } D3DGAMMARAMP, *LPD3DGAMMARAMP;
Fonksiyonun örnek kullanımı:
C/C++ kodu:
void SetGamma(float Gamma){ D3DGAMMARAMP gamma; signed nValue; fGamma+=Gamma; for (int w=0;w<=255;w++) { nValue = (int)(w * fGamma * 255); if(nValue > 65535) nValue = 65535; gamma.red[w]=nValue; gamma.blue[w]=nValue; gamma.green[w]=nValue; } lpDevice->SetGammaRamp(0,D3DSGR_CALIBRATE ,γ); if (fGamma<0.1){fGamma=0.1f;} if (fGamma>2.2){fGamma=2.2f;} }
IDirect3DDevice9::SetIndices: Eğer indexli primitif çizilecekse, o anki aktif vertex bufferden vertexlerin ne sıra ile alınacağını gösteren indexlerin tutulduğu index bufferi sürücüye tanıtmak için kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
LPDIRECT3DINDEXBUFFER9 lpIndexBuffer; .. . //Render lpDevice->SetIndices(lpIndexBuffer); lpDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,dwNumVertex,0,dwNumPolygonIndex);
IDirect3DDevice9::SetLight: Belirtilen ışık kaynağını sürücüye atar. Direc3D sürücüsü tarafından oluşturulan ışık kaynakları primitiflerin vertex normallerinden yararlanarak ışık etkisini simüle ederler (Per-vertex lightining). Bu sistemde ışık vertexler baz alınarak hesaplandığından polygon üzerindeki pixellere etki edecek ışık interpolasyon (başlangıç ve bitiş değerlerine göre ara değerlerin hesaplanması) edilerek hesaplanır. Yüksek polygonlu objelerde iyi sonuçlar elde edilmesine karşın çok düşük polygonlu objelerde yada sahnelerde kötü sonuçlar elde edilmektedir. Konuyu daha iyi anlamanız açısından aşağıdaki resmi inceleyiniz.
Aşağıdaki örnekte primitife spot ışık kaynağı doğrultulmuştur.
Yüksek ve düşük polygonlu modellerde ışığın nasıl simüle edildiği
görülmektedir. Görüldüğü gibi düşük polygonlu modellerde sonuç pekte iç
açıcı olmamaktadır.
Peki bu durumda ne yapılmalı? Kaliteyi arttırmak için primitiflerin polygon sayısını mı arttıracağız? Tabiki hayır. Bildiğiniz üzere ekran kartlarının en büyük düşmanlarından biri yüksek polygon sayısıdır. Çünkü her ekran kartının kabiliyetleri ve hızı doğrultusunda işleyeceği belirli bir polygon sayısı bulunmaktadır. Ekrana ekran kartı kabiliyetlerini aşan sayıda polygon basarsak ekran kartı bu sayıdaki polygonu işlemekte zorlanacağından oyunumuz teklemeye başlayacaktır. Günümüzdeki ekran kartlarının eskiye oranla kabiliyetlerinin ve hızlarının çok çok artmasına ramen yine de belirli bir sınırları vardır. Gelişen teknolojiyle birlikte ekran kartları daha fazla polygon basabilmekte buna paralel olarakta oyundaki detaylar ve kalite artmaktadır. Ancak polygon sayısı herzaman bir handikap olarak kalmaktadır. Konumumuza dönersek per vertex ışıklandırma sistemindeki bu olumsuz durumu aşmanın iki yolu bulunmaktadır. Ilki eski oyunlarda ve günümüz oyunlarının da bir çoğunda kullanılan light-mapping yöntemidir. Light mapping yönteminde düşük polygonlu ve üzeri bir doku ile kaplı olan primitifin üzeri bir başka doku ile maskelenmektedir. Bu yöntemde çok iyi sonuç alınmasına karşın lightmap verisi (dokusu) önceden hesaplandığı için ışıklandırma statiktir ve oyun boyunca değişmez. Per-vertex ışıklandırma ise dinamik olarak hesaplandığından ışık kaynağı yer değiştirdiğinde ışığın polygonlar üzerindeki etkisi de dinamik olarak değişir. Aşağıdaki resimde lightmapping tekniğinin polygon üzerine uygulanışı gösterilmektedir. Light mapping temelde ekran kartlarının multitexturing (çoklu doku katmanı) yeteneği yardımı ile alt ve üst katman dokuların blend (karıştırılması) edilmesi ile gerçekleştirilir.
Per-vertex ışıklandırma sistemindeki bu olumsuz durumu aşmanın ikinci yolu ise ışıklandırma sistemini shaderler yardımı ile simüle etmektir. Bu sistemde ışıklandırma hesabı polygon üzerindeki her bir pixel için ayrı ayrı hesaplandığından (per-pixel lightining) çok gerçekçi ve dinamik ışık etkileri elde edilmektedir. Per-vertex ve lightmap ışıklandırma sistemleri artık yavaş yavaş yerini per-pixel ışıklandırmaya bırakmaktadırlar. Ayrıca per-pixel ışık sisteminde per-vertex ışık sistemindeki maksimum 8 dinamik ışık kullabilme gibi bir kısıtlama bulunmamaktadır.
Direct3D 3 tip ışık kaynağı desteklemektedir.
Directional Light (Doğrusal ışık kaynağı): Bu ışık kaynağı da spot ışık gibi davranır. Ancak ışık etkisini uzaklığa bağlı olarak yitirmez.
Point Light (Noktasal ışık kaynağı): Noktasal ışık kaynakları ampul gibi davranırlar. Her yöne ışık saçarlar. Işık etkisini uzaklığa göre yitirir.
Spot Light (Spot ışık kaynağı): Spot ışık kaynakları iç içe
iki koniden oluşur ve belirtilen yöne doğru ışık saçarlar. Işık etkisini
hem bakılan doğrultu boyunca hem de içteki koniden dıştaki koni
doğrultusunda uzaklığa göre yitirir.
Ambient Light: Bu ışık kaynaklarına alternatif olarak birde
ambient ışık sistemi bulunmaktadır. Bu ışık tipi nesnelerin kendinden
yansıyan ışığı ifade etmektedir. SetLight fonksiyonundan ayrı olarak
SetRenderState fonksiyonu ile sürücüye atanmaktadır. Ambient ışık
sahnedeki bütün nesnelerin vertexlerine aynı oranda etki eder. Sahnedeki
genel ışıklandırmanın yoğunluğunu ayarlamakta kullanılmaktadır. Bu
işlemde vertex normallerinin, etraftaki ışıkların pozisyonlarının yada
etki edecekleri mesafeler göz önünde bulundurulmaz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DLIGHT9 d3dLight; ZeroMemory( &d3dLight, sizeof(D3DLIGHT9) ); d3dLight.Type = D3DLIGHT_POINT; //D3DLIGHT_SPOT; //D3DLIGHT_DIRECTIONAL; //ışığın material üzerinde etki edeceği bölgelerin renkleri belirtiliyor. d3dLight.Diffuse.r = 1.0f; d3dLight.Diffuse.g = 1.0f; d3dLight.Diffuse.b = 1.0f; d3dLight.Ambient.r = 1.0f; d3dLight.Ambient.g = 1.0f; d3dLight.Ambient.b = 1.0f; d3dLight.Specular.r = 1.0f; d3dLight.Specular.g = 1.0f; d3dLight.Specular.b = 1.0f; d3dLight.Position =D3DXVECTOR3(0.0f,1000.0f,0.0f); //ışığın pozisyonu //bu parametre spot ve directional ışıklar için ışığın doğrultusunu belirtmek amacıyla kullanılır. //d3dLight.Direction=D3DXVECTOR3(0.0f,-1.0f,0.0f); //Işığın uzaklığa göre etkisinin azalması ile ilgili parametreler. Directional ışık kaynaklarında kullanılmazlar. d3dLight.Attenuation0 = 0.0f; d3dLight.Attenuation1 = 1.0f; d3dLight.Attenuation2 = 0.0f; //d3dLight.Theta=D3DXToRadian(10.0f); //d3dLight.Phi=D3DXToRadian(20.0f); d3dLight.Range = 10000.0f;//Işığın etki edeceği uzaklık miktarı. Directional ışık kaynaklarında kullanılmaz. g_pd3dDevice->SetLight(0, &d3dLight);//Oluşturduğumuz bu yapıyı 0 indexli ışık olarak ata. D3DLIGHT9 yapısının parametrelerini değiştirerek değişik tipte,pozisyonlarda,renklerde vs. değişik özelliklerde ışık kaynaklarını değişik index numaraları vererek sürücüye atayabiliriz. Istediğiniz kadar ışık kaynağı oluşturabilirsiniz ancak directx aynı anda en fazla 8 dinamik ışığı destekler. g_pd3dDevice->LightEnable( 0, TRUE );//Oluşturduğumuz 0 indexli ışık kaynağını aktive et/aç. En fazla 8 ışık. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );//Işıklandırmayı aç. Sahnedeki tüm ışıklar parametreye göre aktif yada pasif olurlar. //Ambient ışığın kullanımı m_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00ff0000);
IDirect3DDevice9::SetMaterial: Sürücü için kullanılacak materyal özelliklerini ayarlamakta kullanılır. Işıklandırmaya doğrudan etkisi bulunmaktadır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Diffuse.r = mtrl.Ambient.r =mtrl.Specular.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g =mtrl.Specular.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b =mtrl.Specular.b = 1.0f; mtrl.Diffuse.a = mtrl.Ambient.a =mtrl.Specular.a = 1.0f; mtrl.Power = 100; lpDevice->SetMaterial( &mtrl );
IDirect3DDevice9::SetNPatchMode: Çizilmekte olan patchin segment sayısını birbaşka deyişle çözünürlüğünü ayarlamakta kullanılır. Parametre olarak 0 (sıfır) verildiğinde primitif 0 numaralı şekildeki gibi çizilir.
IDirect3DDevice9::SetPaletteEntries: Renk paleti oluşturmak için kullanılır. Oluşturulan her renk paleti bir indexe atanır.
Aşağıdaki resimde farklı renk paletlerinin dokular üzerinde meydana getirdiği etkileri görebilirsiniz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
PALETTEENTRY plt[256]; for (int k=0;k<256;k++) { plt[k].peRed=k; plt[k].peGreen=k; plt[k].peBlue=k; plt[k].peFlags=0x99; } g_pd3dDevice->SetPaletteEntries(1,plt);//1 numaralı indexe paletimizi atıyoruz.
IDirect3DDevice9::SetPixelShader: Sürücüye belirtilen pixel shaderi atar.
IDirect3DDevice9::SetPixelShaderConstantB: Pixel shaderde belirtilen BOOL tipli değişkenin değerini atar.
IDirect3DDevice9::SetPixelShaderConstantF: Pixel shaderde belirtilen float tipli değişkenin değerini atar.
IDirect3DDevice9::SetPixelShaderConstantI: Pixel shaderde belirtilen integer tipli değişkenin değerini atar.
IDirect3DDevice9::SetRenderState: Sürücüye belirtilen durum belirtecini atar. Direct3D çok sayıda durum belirteci destekler. Bunlardan bir tanesi aşağıdaki örnekte gösterilmektedir. Geri kalanları sdk dokümanlarından inceleyebilirsiniz. Zamanla diğer durum belirteçlerini de yeri geldikçe örneklerimizde kullanacağız.
Fonksiyonun örnek kullanımı:
//Aşağıdaki durum belirteci ile sürücüye polygon çizimi sırasında
polygon arka yüzeylerinin elenmemesini söyledik. Normalde ilk ayar
olarak polygonların saat yününün tersi tarafında kalan yüzeyleri elenir.
Daha doğrusu rasterize işlemine tabi tutulmayarak çizilmezler. Bu da
performans artışı sağlar. Istisnaği durumlar haricinde herzaman
polygonların arka yüzeyleri elenir. Bu istisnaği durumlar; cam çizimi,
çim çizimi, ağaçların yapraklarının çizimi gibi durumlardır.
C/C++ kodu:
lpDevice->SetRenderState(D3DRS_CULLMODE, //Durum belirtecinin tipi D3DCULL_NONE); //Durum belirtecine ait ayar
IDirect3DDevice9::SetRenderTarget: Sürücüye çizimin yapılacağı hedef yüzeyin belirtilmesinde kullanılır. CreateAdditionalSwapChain fonksiyonunun açıklamasında fonksiyonun kullanımı görebilirsiniz.
IDirect3DDevice9::SetSamplerState: Sürücüye atanmış olan dokunun adresleme ve filtreleme ile ilgili özelliklerini değiştirmekte kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//Sıfırıncı katmana ait dokuya hangi filtrelerin uygulanması gerektiğini belirttik. Örneğin linear filtresi dokuların çözünürlüklerinin düşük olduğu durumlarda dokuya yumuşak bir görünüm katar. lpDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); lpDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); lpDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
IDirect3DDevice9::SetScissorRect: Ekran bazında kırpma işlemi yapmak için kullanılır. Belirtilen dörtgen alan dışında kalan kısımlar kırpılır. Bu işlemde sadece kırpma işlemini açan ve kapatan bloklar arasında yapılan çizimlerde kırpma uygulanır. Bu bloklar dışında kalan çizim işlemlerinde kırpma uygulanmaz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
RECT rc={100,100,800,600}; lpDevice->SetScissorRect(&rc); lpDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); //Sadece buradaki çizim işlemlerinde kırpma uygulanır //Çizim işlemleri lpDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); //Buradaki çizim işlemlerine kırpma uygulanmaz. //Çizim işlemleri
IDirect3DDevice9::SetSoftwareVertexProcessing: Sürücüye vertexleri yazılımsal yada donanımsal olarak işleneceğini belirtmek için kullanılır. Donanımsal vertex işleme yazılımsal vertex işlemeye oranla çok daha hızlıdır. Günümüzde yeni ekran kartlarının tümü donanımsal vertex işlemeyi desteklemektedir. Bu fonksiyon sadece sürücü D3DCREATE_MIXED_VERTEXPROCESSING parametresi ile oluşturdu ise çalışır. Yani çalışma zamanı sürücüye vertexleri yazılımsal yada donanımsal olarak işle diyebiliriz. Ancak sürücü önceden D3DCREATE_SOFTWARE_VERTEXPROCESSING yada D3DCREATE_HARDWARE_VERTEXPROCESSING parametrelerinden biri ile oluşturuldu ise çalışma zamanı bu ayar değiştirilemez.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
lpDevice->SetSoftwareVertexProcessing(TRUE);//FALSE
IDirect3DDevice9::SetStreamSource: Sürücüye primitif çizimi sırasında kullanılacak olan vertex bufferin belirtilmesinde kullanılır. Primitif çizimi ile ilgili fonksiyonların örneklerinde fonksiyonun nerelerde kullanıldığını görebilirisiniz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX) );//çizim sırasında kullanılacak vertex buffer belirtiliyor.
IDirect3DDevice9::SetStreamSourceFreq: Örnekleme (instancing) tekniği ile çizilecek primitifden kaç adet çizileceğini sürücüye belirtmek için kullanılır. Örnekleme tekniğini aynı primitifi birden çok kere çizmek istediğimizde kullanabiliriz. Bu teknik aynı primitifi değişik boyutlarda, renklerde ve konumlarda çizebilmemize olanak sağlar. Bu teknik primitif çizimi sırasında kullanılan veri miktarını düşürdüğünden performans artışı sağlar. Partikül sistemlerinde, aynı objenin birden çok çizilmesi gerektiği yerlerde (örneğin bir tapınaktaki sütünların çiziminde) kullanılabilir.
IDirect3DDevice9::SetTexture: Primitif çizimi esnasında belirtilen doku kaynağının sürücüye atanmasında kullanılır. Durumu biraz daha açarsak. Mesela sahneye bir model çizeceğiz. Önce SetTexture komutu ile sürücüye modeli kaplarken şu dokuyu kullan deriz sonra modeli çizeriz. Çizeceğimiz model birden çok doku da kullanabilir. Mesela bir ev modeli. Evin çatısı, duvarları, zemini, kapısı, penceresi vs. değişik dokular kullanır. Bu tür durumlarda da yine aynı mantıkla önce SetTexture komutu ile polygonların kullanacağı doku kaynağı sürücüye bildirilir sonra sahneye belirtilen dokuyu kullanan polygon grubu çizilir. Durumu aşağıdaki gibi örneklersek daha da anlaşılır olacaktır.
Ev modeli 1.adım Çatı dokusunu kullan Çatıya ait polygonları çiz 2.adım Duvar doksunu kullan Duvarlara ait polygonları çiz 3.adım Kapı dokusunu kullan Kapılara ait polygonları çiz 4.adım...
Fonksiyonun örnek kullanımı:
C/C++ kodu:
... lpDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); lpDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); lpDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); lpDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); lpDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); lpDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); //Triangle list for(int k=0;k<dwNumMaterialIndex;k++){ if((mMaterialIndex[k].nID-1)<dwNumMaterialIndex && lpTexture[mMaterialIndex[k].nID-1]!=NULL){ lpDevice->SetTexture( 0, lpTexture[mMaterialIndex[k].nID-1]);//belirtilen dokuyu kullan } lpDevice->SetStreamSource( 0, lpVertexBuffer, 0, sizeof(POLYGON_VERTEX) ); lpDevice->SetFVF(POLYGON_VERTEX::FVF); lpDevice->DrawPrimitive( D3DPT_TRIANGLELIST, mMaterialIndex[k].Offset, mMaterialIndex[k].nNumPoly ); } ...
IDirect3DDevice9::SetTextureStageState: Sürücüye atanmış olan x katmanındaki dokunun özelliklerini değiştirmek için kullanılır. Kullanabileceğimiz doku katmanı sayısı ekran kartının donanım özelliklerine göre değişiklik gösterebilir. Birden çok doku katmanı ile primitifler üzerinde çoklu doku kullanımını (multi texturing) gerçekleştirebiliriz. Bu fonksiyon katmanların özelliklerini değiştirebilmenin yanında katmanların birbirleri ile bir takım operasyonların gerçekleştirilebilmesine de imkan vermektedir. Operasyon işlemleri iki argüman üzerinde gerçekleştirilir. Iki argüman belirtilen operasyon doğrultusunda işlenir ve bir sonuç meydana gelir. Bu sonuç başka bir katmanın operasyonlarında argüman olarak kullanılabilir. Katmanlar üzerinde gerçekleştirilebilecek birçok operasyon türü bulunmaktadır. Bunlar renk, saydamlık, doku koordinatları, bump (kabartı) operasyonlarıdır. Bu operasyonlar birbirlerinden bağımsız ve ayrı ayrı olarak gerçekleşir. Aşağıdaki resimde çoklu doku kullanımının tasviri bir görüntüsü ve katmanlar arasındaki operasyonların işleyişi gösterilmektedir.
Örnek 1:
Aşağıdaki örneğimizde operasyon tek katman üzerinde geçerli olacak.
Kullanacağımız argümanlar aşağıdaki resimde gösterilmiştir. Birinci
argümanda kullanacağımız dokuda beyaz renkli olan yerler aslında
şeffaftır.
C/C++ kodu:
//Direct3D de indexler hep sıfırdan başlar. 0 indexli katman bizim birinci ve en alttaki katmanımız. //Sıfır indexli katmana yani birinci katmana bir doku atıyoruz. g_pd3dDevice->SetTexture( 0, g_pTexture ); g_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0x99ffffff); //Dışarıdan belirtilen bir alpha değeri. D3DTOP_BLENDFACTORALPHA operasyonu tarafından kullanılmakta. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, //Renk operasyonu yapacağız D3DTOP_MODULATE ); //Iki argüman arasında gerçekleştirilecek operasyon türünü seçiyoruz. Modulate operasyonu iki argüman arasında çarpma işlemini gerçekleşitir. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //Birinci argüman olarak dokunun kendisini (dokuya ait renkler) kullanacağımızı belirttik. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); //Ikinci argüman olarak vertexlerin diffuse rengini kullanacağımızı belirttik. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); //Saydamlık operasyonu yapılmayacak
Aşağıdaki resimde örneğimizin modulate operasyonu sonucu meydana gelen görüntüyü ve diğer operasyonların sonuçlarını görebilirsiniz. Bazı operasyonlar işlem sırasında resmin alpha (saydamlık) bilgisini kullanmaktadır. Bazıları ise SetRenderState ile atanan bilgilere bağlı olarak hesap yaparlar. Vertexlere atanan diffuse reklerinin farklı olması durumlarında da farklı sonuçlar ortaya çıkabilir. Onun için SDK dökümanlarından operasyonların gereklerini hangi parametrelere bağlı olarak işlem gerçekleştirdiklerini inceleyiniz. Bu örneğimizde gereksinimlerinin farklı olmasından dolayı bump (kabartı) operasyonlarına yer verilmemiştir.
Örnek 2:
Bir önceki örneğimiz sadece tek katman üzerinde geçerliydi. Şimdiki
örneğimizde bu operasyonları katmanlar arasında gerçekleştireceğiz.
Örneğimizde ilk katman üzerinde herhangi bir operasyon
gerçekleştirmeyeceğiz. Ikinci katmanda gerçekleştireceğimiz operasyon da
"Argüman 2" olarak ilk katmanda meydana gelen sonucu kullanacağız. Ilk
katmanda herhangi bir operasyon gerçekleştirmediğimiz için atadığımız
doku herhangi bir değişime uğramadan diskten okunduğu hali ile
kullanılacaktır.
C/C++ kodu:
g_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0x99ffffff); g_pd3dDevice->SetTexture(0,g_Texture); g_pd3dDevice->SetTexture(1,g_Texture2); //Birinci katmana ait işlemler. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); //Birinci katmanda herhangi bir operasyon gerçekleştirmek istemiyoruz. Bunun için parametre olarak argüman 1 i verdik. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );//Birinci argüman olarak dokunun kendisini (dokuya ait renkler) kullanacağımızı belirttik. g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );//Saydamlık operasyonu yapılmayacak //Ikinci katmana ait işlemler. g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE);//Iki argüman arasında gerçekleştirilecek operasyon türünü seçiyoruz. Modulate operasyonu iki argüman arasında çarpma işlemini gerçekleşitir. g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );//Birinci argüman olarak dokunun kendisini (dokuya ait renkler) kullanacağımızı belirttik. g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );//Ikinci argüman olarak ilk katmandan meydana gelen sonucu kullanacağımızı belirttik. g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );//Saydamlık operasyonu yapılmayacak
Aşağıdaki resimde örneğimizin modulate operasyonu sonucu meydana gelen görüntüyü ve diğer operasyonların sonuçlarını görebilirsiniz. Önceki örneğimizde operasyonlar hakkında belirttiğim dikkat edilecek unsurlar bu örneğimiz için de geçerlidir.
IDirect3DDevice9::SetTransform: Dönüşüm matrislerinin sürücüye atanmasında kullanılır. Atanma işleminden sonra çizilen primitifler üzerine dönüşüm uygulanır. Matrixleri ilerleyen zamanlarda daha detaylı olarak ele alacağız. Grafik programlamada matrixler çok büyük öneme sahiptir. Bu yüzden matrixlerin bu konulardaki rolünün çok iyi kavranılması gerekmektedir.
Fonksiyonun örnek kullanımı:
Örnek 1:
C/C++ kodu:
//Aşağıdaki örnekte Direct3D de kullanılan kamera sistemi için gerekli dönüşüm matrixlerinin kullanımı gösterilmektedir. Bu örnekte belirtilen özelliklere sahip bir kamera görüşü elde ediyoruz. D3DXMATRIX matProj, //Projeksiyon matrixi matView; //Görüş matrixi //Sol el görüş matrixi oluşturuluyor. Kameranın konumu, bakış noktası ve kameranın yukarı vektörü belirtiliyor. D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(225,30,-400),&D3DXVECTOR3(225,30,0),&D3DXVECTOR3(0,1,0)); //Elde edilen matrix sürücüye aktarılıyor. g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView); //Sol el perspektif matrixi oluşturuluyor. Kameranın görüş açısı , görüş alanının en/boy oranı, görüş alanının yakındaki zemini ve uzaktaki zemininin değerleri belirtiliyor. D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4,1.33f,1.0f, 10000.0f); //Elde edilen matrix sürücüye aktarılıyor. g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
Örnek 2:
C/C++ kodu:
//Bir primitifi istediğimiz bir konuma taşıyalım (primitifi istediğimiz bir konumda çizdirelim). D3DXMATRIX matTrans;//Bir matrix tanımladık. D3DXMatrixTranslation(&matTrans,0.0f,50.0f,0.0f); //Modelin çizileceği konumu belirtiyoruz. Temelde bu fonksiyon matrixin translate ile ilgili satırlarını belirtilen değerler ile dolduruluyor. g_pd3dDevice->SetTransform( D3DTS_WORLD,&matTrans); //Matrixi dünya koordinat sisteminde sürücüye atıyoruz. g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );//Primitifi çiz
Örnek 3:
C/C++ kodu:
//Bir primitifi istediğimiz bir eksende döndürelim. D3DXMATRIX matRot;//Bir matrix tanımladık. D3DXMatrixRotationY(&matRot,D3DXToRadian(45));//Primitifi Y ekseninde 45 derece döndürdük. g_pd3dDevice->SetTransform( D3DTS_WORLD,&matRot); //Matrixi dünya koordinat sisteminde sürücüye atıyoruz. g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );//Primitifi çiz
Bunlar gibi daha birçok örnek yazılabilir ancak geri kalan örneklere matrixleri daha detaylı incelerken değineceğiz.
IDirect3DDevice9::SetVertexDeclaration: CreateVertexDeclaration fonksiyonu ile oluşturduğumuz vertex deklarasyon yapısını shaderin çizdirilme esnasında sürücüye atanmasında kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
... //Efekti çizdir lpDevice->SetVertexDeclaration(g_VertDecl); UINT numPasses = 0; Effect->Begin( &numPasses, 0 ); for( UINT i = 0; i < numPasses; i++ ){ Effect->BeginPass( i ); lpDevice->SetTransform( D3DTS_WORLD, &matDM ); //mesh->Render(); Effect->EndPass(); } Effect->End(); ...
IDirect3DDevice9::SetVertexShader: Sürücüye belirtilen vertex shaderi atar.
IDirect3DDevice9::SetVertexShaderConstantB: Vertex shaderde belirtilen BOOL tipli değişkenin değerini atar.
IDirect3DDevice9::SetVertexShaderConstantF: Vertex shaderde belirtilen float tipli değişkenin değerini atar.
IDirect3DDevice9::SetVertexShaderConstantI: Vertex shaderde belirtilen integer tipli değişkenin değerini atar.
IDirect3DDevice9::SetViewport: Direct3D sürücüsüne ait görüş alanı özelliklerini değiştirmekte kullanılır. Görüş alanına ait özellikler aşağıdaki D3DVIEWPORT9 yapısında saklanmaktadır. X,Y görüş alanının sol üst noktasının koordinatlarını, Width ve Height görüş alanının en ve boyunun uzunluğunu, MinZ ve MaxZ de derinlik bilgisinin minimum ve maksimum değer aralığını belirtir. MinZ genelde 0.0 MaxZ ise genelde 1.0 olarak kullanılır. Örneğin MinZ ve MaxZ değerlerinin ikisini de 0.0 yaparsak objelerimiz sahnenin en önünde çizdirilecektir. Her iki değeri de 1.0 yaparsak objelerimiz sahnenin en arkasında çizdirilecektir.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DVIEWPORT9 vPort; vPort.X = 100; vPort.Y = 100; vPort.Width = 320; vPort.Height = 240; vPort.MinZ = 0.0f; vPort.MaxZ = 1.0f; lpDevice->SetViewport(&vPort);
Örneğimiz aşağıdaki sonucu verecektir.
IDirect3DDevice9::ShowCursor: Fare imlecini gösterir yada gizler. Fonksiyonun örnek kullanımı:
C/C++ kodu:
SetCursor( NULL ); //windowsa ait olan imleci gizle m_pd3dDevice->ShowCursor( TRUE ); //SetCursorProperties fonksiyonu ile özelliklerini verdiğimiz imleci görüntüler. FALSE parametresi verilirse gizler.
IDirect3DDevice9::StretchRect: Bir yüzeyin belirtilen dörtgen bir alanını başka bir yüzeyin belirtilen dörtgen bir alanına sığdırarak kopyalar. Bu işlemde kaynak yüzey üzerinde filtre de uygulanabilir. Fonksiyonu kullanırken dikkat edilecek hususları sdk dokümanlarından inceleyiniz.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\birdhouse.jpg",518, 324,0, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,D3DX_DEFAULT,D3DX_DEFAULT, NULL, NULL, NULL, &txTmp); D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\bird.jpg",215, 243, 0,NULL, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT ,D3DX_DEFAULT,D3DX_DEFAULT, NULL,NULL , NULL, &txTmp2); LPDIRECT3DSURFACE9 lpDSSrc; LPDIRECT3DSURFACE9 lpDSDest; RECT rcSrc ={1,1,215,243};//kaynak bölge RECT rcDest={400,50,500,300};//hedef bölge txTmp2->GetSurfaceLevel(0, &lpDSSrc); //1. dokunun yüzeyini aldık txTmp->GetSurfaceLevel(0, &lpDSDest);//2. dokunun yüzeyini aldık g_pd3dDevice->StretchRect(lpDSSrc,&rcSrc,lpDSDest,&rcDest,D3DTEXF_LINEAR); //Sığdırarak kopyalama işlemine linear filtresini de uyguladık.
Örneğimiz aşağıdaki sonucu verecektir.
IDirect3DDevice9::TestCooperativeLevel: Direct3D sürücüsünün durumu hakkında bilgiler döndürür. D3DERR_DEVICELOST olumsuz bir durum karşısında sürücünün arızaya geçtiğini belirtir. Böyle bir durumla karşılaşıldığında sürücüyü kurtarmak için Render işlemini durdurup belirli aralıklarla TestCooperativeLevel fonksiyonu çağırmak gerekir. Taa ki sürücü durumu bize D3DERR_DEVICENOTRESET dönene kadar. Bu aşamadan sonra sürücüyü IDirect3DDevice9::Reset fonksiyonu ile resetlemek gerekir. Reset fonksiyonu temelde sürücüye ağit özellikleri çalışma zamanı değiştirmeye yarar. Reset fonksiyonu ile çalışma zamanı uygulamamızın çözünürlüğünü değiştirmek için kullanabiliriz. Yada uygulamamızı tamekran-pencere modu, pencere modu-tamekran modlarına geçirmek içinde reset fonksiyonunu kullanabiliriz. Ancak reset işleminin doğru çalışabilmesi için şunu göz önünde tutmak gerekir. Eğer kaynaklar (dokular, vertex bufer,index bufferlar) daha önceden ekran kartı hafızasına yüklendi ise kaynakları serbest bırakıp sürücüyü resetleyip serbest bırakılan kaynakları tekrar yüklemek gerekir. Ancak daha önceden kaynaklar sistem hafızasına yüklendi ise kaynakları serbest bırakıp tekrar yüklemeye gerek kalmadan sürücüyü direk resetleyebilirsiniz. Sürücünün arızaya geçmesi durumunu şöyle açıklayayım. Mesela uygulamamız tam ekran modunda çalışıyorken Alt-tab tuş kombinasyonunu kullandığımızda bu işlem sürücünün arızaya geçmesine neden olacaktır. Bu durumda ekrana hiçbir şey çizilmeyecektir. Sürücüyü daha önce de belirttiğim gibi kurtardığımızda uygulamamız kaldığı yerden çalışmaya devam edecektir. Yani uygulamayı kapatıp tekrar çalıştırmadan en son kaldığımız ana geri dönebiliriz. D3DERR_DRIVERINTERNALERROR ekran kartı sürücülerinden kaynaklanan bir hata ile karşılaşıldığını belirtir. Sürücü kurtarılamaz.
IDirect3DDevice9::UpdateSurface: Bir yüzeyin belirtilen dörtgen bir bölgesini başka bir yüzeyin belirtilen noktasına kopyalamakta kullanılır. Fonksiyonu kullanırken dikkat edilecek bazı hususlar.
-Kaynak ve hedef yüzeylerin formatı aynı olmalıdır.
-Kaynak yüzey sistem hafızasında hedef yüzeyin ise ekran kartı
hafızasında olması gerekmektedir. D3DPOOL_SYSTEMMEM parametresi
kaynakların sistem hafızasında tutulmasını sağlar. D3DPOOL_DEFAULT
parametresi kaynakları hız bakımından yen iyi hafızaya yerleştirir. Bu
hafıza bölgesi de genellikle ekran kartı hafızasıdır.
-Yüzey formatları derinlik formatlarından biri olmamalıdır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\elma.jpg",NULL, NULL, 0,0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM,D3DX_DEFAULT,D3DX_DEFAULT, NULL, NULL, NULL, &txTmp); D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\greenbox.jpg",NULL, NULL, 0,0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT ,D3DX_DEFAULT,D3DX_DEFAULT, NULL, NULL, NULL, &txTmp2); LPDIRECT3DSURFACE9 lpDSSrc; LPDIRECT3DSURFACE9 lpDSDest; RECT rcSrc[]={0,0,128,125, 0,0,128,125}; //2 adet dörtgen tanımladık POINT ptPoint[]= { 0, 0, 150,150}; //2 adet nokta tanımladık txTmp->GetSurfaceLevel(0, &lpDSSrc); //1. dokunun yüzeyini aldık txTmp2->GetSurfaceLevel(0, &lpDSDest);//2. dokunun yüzeyini aldık g_pd3dDevice->UpdateSurface(lpDSSrc,&rcSrc[0],lpDSDest,&ptPoint[0]); g_pd3dDevice->UpdateSurface(lpDSSrc,&rcSrc[1],lpDSDest,&ptPoint[1]);
Örneğimiz aşağıdaki sonucu verecektir.
IDirect3DDevice9::UpdateTexture: Sistem hafızasında bulunan bir doku kaynağını ekran kartı hafızasında bulunan başka bir doku kaynağına kopyalamak için kullanılır.Fonksiyonu kullanırken dikkat edilecek bazı hususlar.
-Kaynak ve hedef doku kaynaklarının formatı aynı olmalıdır.
-Kaynak doku sistem hafızasında hedef doku ise ekran kartı
hafızasında olması gerekmektedir. D3DPOOL_SYSTEMMEM parametresi
kaynakların sistem hafızasında tutulmasını sağlar. D3DPOOL_DEFAULT
parametresi kaynakları hız bakımından yen iyi hafızaya yerleştirir. Bu
hafıza bölgesi de genellikle ekran kartı hafızasıdır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
//Ekran hafızasında belirtilen boyutlarda ve formatta bir doku kaynağı oluştur. g_pd3dDevice->CreateTexture(600,400,0,NULL, D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,&txTmp,NULL); //Diskteki bir dokuyu sistem hafızasına yükle. D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\greenbox.jpg",600, 400, 0,NULL, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM ,D3DX_DEFAULT,D3DX_DEFAULT, NULL,NULL , NULL, &txTmp2); //Sistem hafızasındaki doku kaynağını ekran kartı hafızasındaki doku kaynağına kopyala. g_pd3dDevice->UpdateTexture(txTmp2,txTmp);
IDirect3DDevice9::ValidateDevice: Sürücünün texture-blending (doku harmanlama) operasyonlarını kaç çizim işleminde (pass) yapabileceğini sorgulamakta kullanılır.
Fonksiyonun örnek kullanımı:
C/C++ kodu:
g_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0x99ffffff); g_pd3dDevice->SetTexture(0,g_Texture); g_pd3dDevice->SetTexture(1,g_Texture2); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE); g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); DWORD dwNumPass;HRESULT hr; //Eğer dwNumPass değeri 1 ise tek çizim işleminde işlem gerçekleşir. Daha büyük bir değer ise değer miktarı kadarki çizim işleminde işlem gerçekleşir. //Bazı ekran kartları kullandığımız opreasyonları desteklemiyor da olabilir. Bu sefer fonksiyon olumsuz bir değer döndürür. hr=g_pd3dDevice->ValidateDevice(&dwNumPass);
Bilgin Terzi (3ddreams)
Yorumlar
Yorum Gönder