FADE IN/OUT
Retro bilgisayarBu yazıda basit geçiş (transition) efektlerinden biri olan "fade"den bahsedeceğim. Efekt birden fazla yöntemle yapılabilir. Detaya girmeden yazıda anlatılacak yöntemlere bir bakalım:
1) Frame Buffer ile Blending. (OpenGL ve fixed pipe ile) 2) Render to Texture (OpenGL ve fixed pipe ile) 3) Pixel Shader (Direct3D ve programlanabilir pipe ile)
Görüldüğü gibi herkes için bir şeyler var (sensei için bile hehe :) ). Tutorial popüler grafik API'ları ile tecrübesi olan (ileri seviye bilgi gerekmiyor) coder'lar düşünülerek hazırlandı. Yeri gelmişken söylemek istediğim bir şey var. Yazıda çok miktarda İngilizce kelime (çoğu teknik terim) olabilir. Grafik programlama terminolojisini bilenler için sorun olmaz sanırım ama Türkçeleştirme için ekstra efor sarf etmeyeceğim. Yani gidip de texture map için doku eşlemi falan demeyeceğim ama gereken yerlerde de terimler/kavramlar hakkında gerekli açıklamaları yapacağım.
Birisi Fade in mi dedi??
Ne anlattığımızı detaylıca açıklamanın vakti geldi. Farz edelim bir demo yapıyorsunuz. Sahneler (ya da part'lar mı diyelim..) arası geçişlerin de yumuşak olmasını istiyorsunuz.. Yani ani, kütük gibi geçişler olmayacak. Mesela ekranın yavaşça kararması ya da kararmış bir ekrandan sahnenin yavaş yavaş görünür hale gelmesi gibi şeylerden bahsediyorum. Sanırım yapmak istediğimiz şey anlaşılıyor. Şimdi gerekli tanımları yapalım:
Fade in: Gösterilmek istenen sahnenin yavaş yavaş görünür hale gelmesi. Genellikle siyah ekrandan başlanır ve sahne zamanla görünür hale gelir. Siyah renk zorunluluk değil tabii ki. İstediğiniz renkten başlayabilirsiniz.
Fade out: Sahnenin yavaş yavaş gözden kaybolması durumu. Genellikle siyah renge doğru gidip ekranı karartırız. Siyah dışındaki renklere de gitmek mümkün.
Tamam şimdi bu iki efekti nasıl yapabiliriz ona bakalım.
1) Frame Buffer ile Blending Yöntemi
Bu yöntem için yapılması gerekenleri kısaca bir sıralayalım, sonra detaylarına gireceğiz.
- Sahnenizi normalce çizdirin. - Depth Test'i kapatın.
- Orthographic projeksiyona geçin.
- Alpha Blending'i aktif hale getirin.
- Screen Aligned Quad (Tüm ekranı kaplayan dörtgen) çizdirin. - Alpha Blending'i kapatın.
- Tüm çizdirim işlemlerini bitirin.
Bu yöntem full-screen alpha blending kullanıyor. Önce sahneniz neyse onu çizdiriyorsunuz, ondan sonra orthographic projeksiyon moduna geçip tam ekran bir dörtgen çizdiriyorsunuz. Dörtgeni çizdirirken, dörtgeni oluşturan vertex'lerdeki alpha değerlerini zamanla 0'dan 1'e ya da 1'den 0'a doğru çekiyoruz.
Frame Buffer ile Blending ve Doğru Blending Faktörlerini Seçmek
Yöntemin ismine frame buffer ile blending dedim. Peki nedir frame buffer ile blending?
OpenGL ya da Direct3D ile çalışırken texture stage'ler arasında da (multi-texturing yaptığınızı düşünün) blending yapabilirsiniz. Texture'ları oluşturan texel'ler blending hesaplamalarına girerler ve oluşan texel değerleri diğer pipeline seviyelerine (esasında eğer varsa per fragment operations'a, yoksa frame buffer'a) yollanır. Frame buffer ile blending'de ise blending hesaplamaları frame buffer'da yazılı olan pixel değerleri (destination, dst) ile pipeline'dan gelen (rasterizasyon ve texture mapping sonucu oluşan pixel'ler) yeni pixel değerleri (source, src) arasında olur. Bu hesaplamalar OpenGL pipeline'ının en sonunda "per fragment operations" denen kısımda olur ve alpha blending olarak bilinir. Alpha blending işlemi frame buffer okumaları (destination pixel'lerin de hesaba katıldığını unutmayın) da içerdiğinden çok sık yapılması önerilmez. Bizim yöntemimizde viewport'taki tüm pixel'lerle alpha blending yapacağız. Performans bakımından günümüz kartları için pek fazla sorun yok esasında. Source ve destination pixel'ler anlaşıldıysa blending faktörlerinin nasıl seçildiğine bakalım:
OpenGL'de Alpha Blending yaparken önce Blending state'ini glEnable(GL_BLEND); ile aktif hale getiririz. Sonra glBlendFunc(srcfactor,dstfactor); ile de source ve destination pikseller için blending faktörlerini ayarlarız.
Not: glBlendFunc'a argüman olarak srcfactor ve dstfactor yazdım. Bunu sadece ilk argümanın source pikseller için, diğerinin de destination pikseller için olduğunu belirtmek için yaptım. Bu argümanlar GL_ONE, GL_SRC_COLOR vs. gibi OpenGL'de tanımlı sabitler olacak. Bu sabitlerin tam listesi için OpenGL referanslarına bakın.
İşin matematiğine geçmeden önce belirtmem gereken bir şey var. Burada bahsedeceğim blending yöntemi additive blending diye bilinen yöntemdir. OpenGL spesifikasyonu sadece bir blending yöntemi tanımlar. O da additive blending'dir. Additive blending dışındaki yöntemler: subtractive (reverse subtractive) ve min-max blending yöntemleridir. Direct3D'de de bu yöntemler tanımlıdır. Mesela aşağıdaki kod parçası kullanılacak blend operasyonunu subtractive olarak seçer.
device->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_SUBTRACT);
Direct3D için SDK'da D3DBLENDOP Enumerated Type isimli kısma bakarak daha fazla bilgi edinebilirsiniz. OpenGL'e geri dönersek, OpenGL'de additive blending dışındaki yöntemler extension mekanizmasıyla programcıların kullanımına sunulmuştur. Genel blending yöntemlerini şöyle özetleyelim:
Kullanacağım notasyon şöyle olacak:
Cf --> Blending operasyonları sonucu oluşan renk (final color value) Cs --> Source pixel'in rengi Cd --> destination pixel'in rengi S --> Source pixel'in blend faktörü D --> Destination pixel'in blend faktörü
Additive Blending:
Cf = Cs * S + Cd * D olur ve if ( Cf > 1.0 ) Cf = 1.0 else if(Cf <= 1.0) Cf = Cf
Yukarıdaki if - else bloğuyla işlemin saturated olduğunu anlatmak istedim. Yani oluşan renk değerleri 1.0'ın üzerine çıkamaz.
Subtractive Blending:
Cf = Cs * S - Cd * D olur ve if ( Cf < 0.0 ) Cf = 0.0 else if (Cf >= 0.0) Cf = Cf
OpenGL için GL_EXT_blend_subtract extension'ına bakın.
Reverse Subtractive Blending:
Cf = Cd * D - Cs * S olur ve if ( Cf < 0.0 ) Cf = 0.0 else if (Cf >= 0.0) Cf = Cf ve yine GL_EXT_blend_subtract extension'ına bakın.
MinMax Blending:
minimum için:
Cf = min ( Cs , Cd ) olur.
Sonuç source ve destination piksellerin minimumudur.. Tabii bu işlemin renk bileşenleri (RGBA) bazında yapıldığını unutmayın.
maksimum için:
Cf = max(Cs, Cd) olur.
GL_EXT_blend_minmax extension'ına bakın.
Bu hatırlatmadan sonra esas konumuza geri dönelim. Additive Blending işlemi matematiksel olarak ağırlıklı toplamadan (weighted sum) başka bir şey değil. Matematiği ise şöyle:
Rs, Gs, Bs, As --> Tek bir source pixel'i belirten 4'lü olsun. Rd, Gd, Bd, Ad --> Tek bir destination pixel'i belirten 4'lü olsun.
Sr, Sg, Sb, Sa ---> Tek bir source pixel'in blend faktörlerini belirtsin (ağırlık parametreleri) Dr, Dg, Db, Da ---> Tek bir destination pixel'in blend faktörlerini belirtsin (ağırlık parametreleri)
Blending sonucu oluşan renk: color = (Rs * Sr + Rd * Dr) , (Gs * Sg + Gd * Dg) , (Bs * Sb + Bd * Db) , (As * Sa + Ad * Da)
Final RGBA değeri yukarıda görülüyor. Şimdi bu bilgi işimize nasıl yarayacak?
Not: Alpha değerinin 1 olması opaklık durumudur. Alpha değerinin 0 olması transparanlık durumudur.
Fade in durumunu ele alalım. Sahnemiz siyah ekrandan görünür hale gelsin. Şimdi böyle bir senaryoda ekrana çizdireceğimiz quad'ın renginin siyah olması, alpha değerinin de 1'den 0'a gitmesi gerekir (nedeni aşağıda detaylı olarak anlatılacak..). Çünkü böyle bir durumda:
Sahne --------> Destination Quad --------> Source olur ve blending faktörleri de GL_SRC_ALPHA ile GL_ONE_MINUS_SRC_ALPHA seçilir. Yani Sr, Sg, Sb, Sa 1'den 0'a gider (Quad'ın alpha'sını 1'den 0'a götürüyorduk unutmayın..) , Dr, Dg, Db, Da 0'dan 1'e gider çünkü bunlara 1 - Quad Alpha değeri atanır.
Sınır koşulları için (Quad alpha değerinin 1 ve 0 olduğu durumlar) yukarıdaki blending eşitliğini yazarsak: Quad Alpha'sı = 1 (source pixel'lerin alpha'sı = 1) için, Sr = Sg = Sb = Sa = 1'dir ve Dr = Dg = Db = Da = 0'dır.
color = (Rs) , (Gs), (Bs) , (As) olur. Quad'ı görürüz.
Quad Alpha'sı = 0 için Sr = Sg = Sb = Sa = 0'dır ve Dr = Dg = Db = Da = 1'dir.
color = (Rd) , (Gd) , (Bd) , (Ad) olur ve sahneyi görürüz.
Benzer şekilde Fade out içinse Quad'ın alpha değerinin zamanla 0'dan 1'e gitmesi gerekir.
2) Render To Texture Yöntemi:
Bu yöntemin bir kısıtlaması var. Sadece siyah renk için fade in/out yapabiliyoruz (yani tüm ekranın siyaha gitmesi ya da siyahtan sahnenin görünür hale gelmesi gibi..).
Yöntemi anlatabilmek için OpenGL texturing fonksiyonları hakkında birkaç şey söylemem lazım. Texture mapping yaparken texture'ı uygulayacağınız yüzeyin rengini tamamen ihmal edebilirsiniz böylece yüzeyin rengi sadece texture map'ten gelir. Ayrıca bir yüzeyin rengini texture map'ten gelen renklerle modüle (çarpma) edebilirsiniz. Standart OpenGL size 4 tane dokulama fonksiyonu sunar. Bunlar GL_DECAL, GL_REPLACE, GL_MODULATE ve GL_BLEND. Bu fonksiyonlar glTexEnv{if}(......) komutu ile aktif hale getirilirler. Bu yöntemde GL_MODULATE'i kullanacağız.
Cf ---> sonuç renk değeri Cs ---> yüzeyin rengi Ct ---> texture map'te tutulan renk
Cf = Cs * Ct GL_MODULATE'in yapacağı işlem bu. Bu bilgiyi şöyle kullanacağız:
- Tüm sahne bir texture'a çizilecek. Yukarıdaki eşitlikteki Ct değeri bu. - Bir önceki adımda sahnenin çizildiği texture, bir screen aligned quad'a uygulanacak. Screen aligned quad Cs verisini tutuyor. - Mapping yapılırken glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE); komutu kullanılacak ve yüzeyin rengi :
Fade in için : 0'dan 1'e Fade out için : 1'den 0'a zamanla çekilecek.
Daha açık yazarsak şöyle bir işlem uygulanıyor :
(Rt,Gt,Bt) ---> Texture'un rengi. (Çizdirdiğiniz sahne) (Rs,Gs,Bs) ---> Texture'u uyguladığınız full-screen Quad'ın rengi.
Color = (Rt * Rs) , (Gt * Gs) , (Bt * Bs)
Sınır değerler için yukarıdaki eşitliği incelersek : (Rs , Gs, Bs) ---> (0.0,0.0,0.0) için : Color = (0.0) , (0.0) , (0.0) (siyah ekran)
(Rs,Gs,Bs) ---> (1.0,1.0,1.0) için : Color = (Rt) , (Gt) , (Bt) (sahne)
olur.
Quad'ın rengini mesela fade in için şu şekilde: glColor3f(t,t,t); (t değişkeni zamanla 0'dan 1'e götürülerek) ayarlanabilir.
Peki render to texture adımını nasıl yapabiliriz ? Opengl bize 3 farklı seçenek sunuyor. 1) glCopyTexImage yöntemi : Sahne backbuffer'a çizdirilir , backbuffer'a çizdirilen sahne glCopyTexImage ile bir texture'a kopyalanır. Backbuffer tekrar temizlenir (glClear (GL_COLOR_BUFFER_BIT); ) . Sonra yukarıda anlatılan yöntemler uygulanarak elde edilen texture screen aligned quad'a uygulanır. (En yavaş yöntem budur.)
2) PBuffer (Pixel Buffer) yöntemi kullanılabilir. Bu yöntemde pencerenin kullandığının dışında farklı bir render context yaratılır ve sahne buraya çizdirilir. Sonra wglARBRenderTexture extension'ı kullanılarak bu render context'in içeriği texture olarak kullanılabilir. Pbuffer'ları kurmanın karmaşıklığı yüzünden ve de render context switching hakkındaki trickleri bilmiyorsanız ( her frame'de render context switching var : pbuffer --> window --> pbuffer... GeForce 3 , Radeon 8500 altı kartlarda sürünürsünüz) PBuffer ile render to texture'dan uzak durun. Pbuffer'lar başlı başına bir tutorial konusu olabilir. Bu yüzden burda kesiyorum.
3) EXT_framebuffer_object extension'ını kullanabilirsiniz. Gerek kullanım kolaylığı ve hız açısından en uygun yöntem bu bence. Fakat detaya girmiyorum. Bu da kendi içinde bir tutorial olabilir.
3) Pixel Shader Yöntemi :
Huh , şimdiden bayağı uzun bir tutorial oldu. Bu kısmı okuyacak arkadaşların direct3d ile tecrübesi olduğunu varsayıyorum. Yani en azından burada api detaylarına girmicem. Mesela texture nasıl yüklenir ya da .fx dosyaları nasıl hazırlanır gibi.. çünkü bunlar başka bir tutorial konusu olabilir. Shader'lar ile fazla haşır neşir olmamış scener'lar için bu shader konusuna çok kısa bir giriş yapalım. Demolar (ve bilgisayar oyunları) gerçek zamanlı bilgisayar grafikleri ile ilgili olduğundan , bizim shader diyince anlamamız gereken şey şu olmalı : 3D işhattını (pipeline) modifiye eden programlar. Bu programlar GPU üzerinde (vertex ve pixel processor'ler) çalışır. Günümüz GPU teknolojisinde pipeline'ın belli kısımları programlanabilir haldedir ve pipeline'ın kabaca iki ana hattan oluştuğunu söyleyebiliriz : Vertex hattı ve pixel hattı.
Yukarıda yazılanlara göre bazı tanımlar yapabiliriz:
Vertex Shader : Pipeline'a giren her vertex üzerinde çalışan programlardır. Vertex shader ile GPU'nun vertex processor denen donanım kısmı programlanır. Vertex shader'lar girdi olarak (dolayısıyla vertex processor) herhangi bir geometrik dönüşüme uğramamış vertex'ler (object space'de tanımlı) , bu vertex'lerle ilişkilendirilmiş renk , doku koordinatı , normal vektörleri vs.. gibi verileri alırlar. Çıktı olarak ise clip space'de vertex koordinatları (rasterizer'a gitmeden önce, vertex shader'dan sonra arada başka pipeline seviyeleri var , mesela backface culling ya da homojen divide gibi.. bunlar programlanamaz) ve rasterizer'ı besleyecek her türlü veriyi (modifiye ettikleri doku koordinatları , normaller vs..) verirler. Vertex shader'lar yeni vertex'ler üretemezler , var olan vertex'leri modifiye ederler.
Pixel Shader : Rasterizasyon sonucu oluşan her pixel üzerinde çalışan programlardır. Pixel shader ile pixel processor programlanır. Input olarak rasterizer'dan gelen verileri alırlar ve çıktı olarak da color ve depth buffer'a hesapladıkları piksel değerlerini yazabilirler. Piksel shader'dan sonra son pipeline seviyesi olan per fragment operations (yeni gelen piksel değerleri ile frame buffer'da yazılı olan piksel değerleri ile ilgili her türlü işlemin yapıldığı kısım.. depth test , alpha test , alpha blending fog vs..) gelir.
Esas konumuza geri dönersek. Fade In/out işlemi bir post processing işlemi. Yine sahnemizi bir texture'a çizdireceğiz ve bu texture'u alıp bir quad üzerine map edeceğiz. Pixel shader piksel değerlerine doğrudan erişemediği için texture lookup yapacağız. Bu yüzden her frame texture'a çizdiriliyor(Render to Texture). Tutorial yeterince uzadığından nasıl screen aligned quad çizilir ya da render to texture nasıl yapılır o konulara girmicem , sadece shader'lardan bahsedeceğim.
Fade In/Out için pixel shader'da lineer interpolasyon yapacağız. İlk anlattığım yönteme (Frame Buffer ile blending) dikkatle bakarsanız lineer interpolasyon formunda olduğunu görürsünüz. Bildiğimiz iki değer arasındaki değerleri bulmak için interpolasyon kullanırız. Şimdi lineer interpolasyonu bir anlayalım. Mesela x ekseninde, x1 koordinatından x2 koordinatına gideceğiz :
LERP = x1 + (x2 - x1) * t dediğimiz zaman x1 ve x2'nin arasındaki her değeri t'yi kullanarak bulabiliriz. t'nin izin verilen değer aralığı [0,1]'dir. t = 0 için x1 , t = 1 için x2'deyiz. Interpolasyon bilgisayar grafiklerinde, özellikle animasyonda çok kullanılan matematiksel bir araçtır. Lineer'in dışında çeşitli spline eğrileri kullanan interpolatörler de vardır.
Bizde pixel shader'da texture ile fade rengi arasında lerp işlemi uygulayacağız.
Not: Lineer interpolasyon lerp olarak da bilinir.
Daha önceden yazdığım .fx dosyasına bakalım ve en azından shader'lara bir parça kendimizi alıştıralım.
İlk olarak uniform değişkenler karşımıza çıkacak. Uniform değişkenler shader'ın etkilediği her piksel ya da vertex için aynı kalan değişkenlerdir. Mesela burada mWorldViewProjection, transformasyon matrisidir. (object space ----> clip space'e) Shader'ın etkilediği geometrideki her vertex için aynıdır. t ise lineer interpolasyonda kullanılan parametredir ve her piksel için aynıdır. width ve height vertex shader'da doku koordinatları için offset değerleri hesaplanmasında kullanılır. Çünkü Direct3D sampling kurallarına göre ekrandaki pikseller ile texture'daki texellerin 1:1 eşleşmesi için doku koordinatları (u,v) yerine: u+ = offset_u, ve v+ = offset_v olmalıdır.
offset_u = (1.0/2.0) * (1.0/width) // width : screen width offset_v = (1.0/2.0) * (1.0/height) // height : screen height
Esasında HLSL'de uniform keyword'ü uniform değişkenleri belirtmekte kullanılır. Fakat global değişkenlerde (shader kodları gövdelerinde olmayan değişkenler) buna gerek yok, global değişkenler uniformdur. Genelde uniform değişkenler uygulamadan shader'a gönderilen değişkenlerdir. Her vertex ya da her piksel için ayrıca hesaplanmazlar.
float4x4 mWorldViewProj; float t; float width, height;
.fx dosyalarının bir güzelliği de texture address ve filtreleme modlarının bu dosyalar içerisinde tanımlanabilmesidir. t0 pixel shader'ın kullanacağı texture'ı belirtir. s0 ise pixel shader'ın bizim texture'ımıza erişirken (look up için) kullandığı sampler'dır.
texture t0; sampler2D s0 = sampler_state { Texture = (t0); AddressU = CLAMP; AddressV = CLAMP; MagFilter = LINEAR; MinFilter = LINEAR; MipFilter = NONE; };
Bu kısımda ise piksel ve vertex shader'ların kullandığı veri yapılarını görüyoruz. C struct'larından pek bir farkı yok. Göze çarpan tek fark değişken isimleri yanındaki kolonlar ve bazı keyword'ler. Bu keyword'lere semantics denir ve görevleri ise pipeline'dan gelen verilerle ilgili GPU register'larını birbirlerine eşlemektir. VS_IN struct'ına bakarsak pos değişkeni homojen koordinatlarda (x,y,z,w) bir noktayı temsil eder ve vertex processor'un input register'larına (position register'ı, v0) alınacağı POSITION0 semantic'i ile belirtilir. VS_OUT'a da baktığınızda pos değişkeni, vertex shader'da transform edilmiş bir noktayı temsil eder ve vertex processor'un output register'ına (output position register'ı, oPos) alınacağı yine POSITION0 semantic'i ile belirtilir. HLSL'de input ve output register'larının aynı semantic'lerle belirtildiğini görebilirsiniz.
struct VS_IN { float4 pos : POSITION0; float2 uv0 : TEXCOORD0; };
struct VS_OUT { float4 pos : POSITION0; float2 uv0 : TEXCOORD0; };
Aşağıda VS isimli vertex shader'ımıza bakalım. mul intrinsic (shader compiler'ına gömülü fonksiyonlardır) fonksiyondur. Matris çarpımlarında kullanılır. Shader'larda işlemler vektörel yapıldığından (x,y,z,w ya da r,g,b,a) komponentleri açıkça yazmanıza gerek yok. In.pos vertex buffer'dan gelen koordinat bilgilerini taşır ve her bir vertex'in koordinatları WorldViewProj matrisi ile çarpılır, clip space'deki konumları bulunur. Bu vertex shader'da gelen doku koordinatları üzerinde de modifikasyon yapıyoruz. Daha önce bahsettiğim nedenden dolayı offset değerlerini ekliyoruz.
VS_OUT VS(VS_IN In) { VS_OUT Out; Out.pos = mul(In.pos, mWorldViewProj);
//offset Out.uv0.x = In.uv0.x + 0.5 * (1.0/width); Out.uv0.y = In.uv0.y + 0.5 * (1.0/height);
return Out; }
Şimdi esas aksiyonun olduğu kısma geldik. PS fade in/out efektini gerçekleştiren piksel shader'ımız. Bu shader'da yapılan iş şu:
Color = Texture + (FadeColor - Texture) * t t uygulamadan ayarlanıyor (Herhalde bir timer class'ınız falan vardır ha? Ne bileyim işte t 5 saniye içerisinde 1'den 0'a ya da belki 0'dan 1'e gitsin tarzı şeyler programlamanız gerekecek de). t uniform değişken. 0'dan 1'e götürürsek fade out, 1'den 0'a götürürsek fade in efekti gerçekleşir. Shader'da tex2D intrinsic fonksiyonu ile texture'a erişip look up yapıyoruz. Görüldüğü gibi argüman olarak bir sampler ve texture koordinatlarını alıyor. Bu eriştiğimiz texture'ın göstermek istediğimiz sahnemiz olduğunu bir kere daha hatırlatayım. Fade color için ben bu shader'da beyaz rengini (istediğiniz rengi seçmekte serbestsiniz) seçtim ve float4(1.0,1.0,1.0,1.0) ile ayarladım. Bu vektörel bir veri tipi ve RGBA rengi temsil ediyor. C++ tipi bir constructor ile initialize ettim. Yukarıdaki interpolasyon eşitliğini lerp intrinsic fonksiyonu hesaplıyor. Son olarak piksel shader hesapladığı renk verisini ilgili register'a (COLOR0) yolluyor.
float4 PS(VS_OUT In):COLOR0 { float4 color = lerp(tex2D(s0,In.uv0), float4(1.0,1.0,1.0,1.0), t); return color; }
Aşağıdaki kısım ise hazırladığımız efektle ilgili bilgiler içeriyor. Uygulamadan bu efekte
FadeinOut ismi ile erişebiliriz. Tekniğin ismi FadeinOut ve tek pass'den oluşuyor. Ayrıca bazı render state'leri de bu teknik içerisinde ayarladım. (Tüm Direct3D state'lerine .fx dosyaları içerisinden erişip ayarlayabiliriz.). Son satırlar ise yazdığımız shader'ların shader compiler tarafından hangi shader profile'ına göre derleneceğini belirtiyor. Burada VS vertex shader 1.1'e göre, PS de piksel shader 1.1'e göre derleniyorlar.
technique FadeinOut { pass p0 { Lighting = FALSE; CullMode = NONE; VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_1_1 PS(); } }
Huh, bu tutorial burada biter, scg de yatağa gider.
Not: tutorial ile ilgili her türlü sorun için (eksik, yanlış, anlaşılmayan yerler vs..) beni rahatsız etmeyin, forumları kullanın puhaaaaaa...
Sinan "scg" Çanga