Bu  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  bişeyler var  (  sensei  için bile  hehe  :)  )  .
Tutorial populer  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 ingilizce 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 sarfetmicem. Yani gidipte texture  map  için
doku eşlemi falan  demicem ama gereken  yerlerde de terimler/kavramlar  hakkında
gerekli açıklamaları yapacam.

Birisi Fade in mi dedi ?? 

Ne  anlattığımızı  detaylıca  açıklamanın  vakti  geldi.  Farz  edelim  bi  demo
yapıyorsunuz.  Sahneler  (yada  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şca  kararması yada  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 girecez.

- Sahnenizi normalce çizdirin.
- Depth Test i kapatın.                                                        
                
- Orthografik projeksiyona geçin.                                              
        
- Alpha Blending i aktif hale getirin.                                         
         
-   Screen   Alingned   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 orthografik  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 yada 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  fame buffer  ile
blending? OpenGL  yada Direct3D  ile çalışırken  texture stage  ler arasında  da
(multi-texturing yaptığınızı  düşünün)  blending  yapabilirsiniz.  Texture  lari
oluşturan texeller blending hesaplamalarina 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
pixeller) 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 pixellerin  de hesaba  katıldığını unutmayın)  da içerdiğinden  çok
sık yapılması önerilmez. Bizim yöntemimizde viewport taki tüm  pixellerle  alpha
blending yapacağız.  Performans  bakımından  günümüz  kartları  için  pek  fazla
sorun yok esasında.
Source  ve  destination  pixeller  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  pixeller
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 pixeller  için ,  diğerinin de  destination pixeller  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  biş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 pixelin blend faktörü
D --> Destination pixelin 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 

Yukardaki 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  bişey  değil.
Matematiği ise şöyle:

Rs,Gs,Bs ,As --> Tek bir source pixel i belirtren 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 yukarda 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üyoduk
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)  yukardaki
blending eşitliğini yazarsak :
Quad Alphası = 1 (source pixellerin alphası = 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 Alphası = 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  yada siyahtan sahnenin  görünür
hale gelmesi gibi..).

    Yöntemi anlatabilmek için  OpenGL texturing fonksiyonları  hakkında bir  kaç
şey söylemem lazım. Texture mapping yaparken texture u  uygulayacağınız  yüzeyin
rengini tamamen ihmal  edebilirisiniz böylece yüzeyin  rengi sadece texture  map
den gelir. Ayrıca bir   yüzeyin rengini texture  map den 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 de tutulan renk

Cf = Cs  * Ct                  GL_MODULATE  in yapacağı işlem bu. Bu  bilgiyi
şöyle kullanacağız : 

- Tüm sahne bir texture a çizilecek. Yukardaki 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 yukardaki 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 yukarda  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
çizdirlir.  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 switcing  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ı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 yada  .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ın belli kısımları  programlanabilir haldedir  ve pipeline nın  kabaca iki  ana
hattan oluştuğunu söyleyebiliriz : Vertex hattı ve pixel hattı.

Yukarda 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
vertexlerle 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
seviyeri var  ,  mesela  backface  culling yada  homojen  divide  gibi..  bunlar
programlanamaz)  ve  rasterizer  ı  besliyecek   her   türlü   veriyi  (modifiye
ettikleri doku  koordinatları  , normaller  vs..)  verirler. Vertex   shader lar
yeni vertex ler üretemezler , var olan vertexleri 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  çizdirecez 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 yapacaz.  Bu yüzden  her frame texture  a çizdiriliyor(Render  to
Texture). Tutorial  yeterince uzadığından  nasıl  screen alingned  quad  çizilir
yada render  to  texture nasıl  yapılır  o  konulara girmicem  ,  sadece  shader
lardan bahdisecem. 

Fade In/Out için pixel  shader da lineer  interpolasyon yapacaz. İ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 bi anlayalım.
Mesela x ekseninde, x1 koordinatından x2 koordinatına gidecez :

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 shaderlara  bir  parça
kendimizi alıştıralım. 

ilk olarak  uniform değişkenler  karşımıza çıkacak.  Uniform değişkenler  shader
ın etkilediği  her pixel  yada  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  pixel  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  texturdaki  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   u  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  yada
her pixel 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çersinde tanımlanabilmesidir. t0 pixel shader ın  kullanacağı  texture
u belirtir. s0  ise pixel  shader ın  bizim texture  umuza 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 structlarından  pek bir farkı  yok. Göze çarpan  tek fark  değişken
isimleri yanındaki kolonlar ve bazı keywordler. Bu keywordlere  semantics  denir
ve  görevleri  ise  pipeline  dan  gelen  verilerle  ilgili  GPU  registerları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
registerları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
semantici i  ile belirtilir.   HLSL  de input   ve  output registerlarının  aynı
semanticlerle 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   yada   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ısıma  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
biliyim işte t 5 saniye içersinde  1 den 0 a yada 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  un göstermek  istediğimiz  sahnemiz olduğunu  bir  kere
daha hatırlatıyim. 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.   Yukardaki  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. Ayırca bazı render  state leride bu teknik  içersinde
ayarladım.  (Tüm  direct3d   state  lerine  .fx   dosyaları  içersinden   erişip
ayarlayabiliriz.). Son  satırlar  ise  yazdığımız  shaderların  shader  compiler
tarafından hangi  shader  profiline  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