KARADENİZ TEKNİK ÜNİVERSİTESİ Bilgisayar Mühendisliği Bölümü Bilgisayar Grafikleri Laboratuarı PÜRÜZLÜ YÜZEY ÜRETİMİ 1. Giriş Pürüzlü yüzey üretiminde, yüzeye kaplanacak dokudan yararlanarak yüzeyin normalini veya alpha parlaklık değerine göre yüksekliğini değiştirmeye dayanan iki yöntem vardır. Bunlardan Bump Mapping yönteminde yüzeye kaplanacak dokuyu içeren resim dosyasındaki renk değişimlerinden elde edilen "Normal Map" resim dosyası kullanılır. Bu normal mapdeki (R,G,B) değerleri yüzeyin normalinin (X,Y,Z) değerleri olarak alınır. Herhangi bir yüzeyin rengi yüzey normaline bağlı olarak hesaplandığından normal map dokusu ile değişen normalle hesaplanan renk değeri de değişecektir. 2. Parallax Mapping Parallax Mapping yönteminde ise yüzeye kaplanacak dokudaki pixellerin (R,G,B,A) değerlerinden A alpha parlaklık değerlerine bağlı olarak yüzeyin yüksekliği değiştirilir. Gerek Bump Mapping gerekse de Parallax Mapping yönteminde bilinen doku kaplama zaten yapılmaktadır. Yani doku, yüzeyin üzerine renk değerleri değiştirilmeksizin map edilmektedir. Buna ek olarak Bump Mapping yöntemi normal map ile dokuya bağlı olarak yüzey normalini değiştirmekte ve bu normal, Diffuse ve Specular renk değerleri hesaplanırken kullanıldığından yüzeyin pürüzlü görünmesine sebep olmaktadır. Parallax Mapping'de bu iki dokuya ek olarak alpha parlaklık değerlerinden oluşan "Height Map" adı verilen bir doku kullanılır. Dolayısıyla Parallax Mapping, Bump Mapping yöntemini kapsamaktadır. Bu deneyde Parallax Mapping yöntemine göre pürüzlü yüzey üretimi anlatılacaktır. Programlama dili olarak Visual C++ 2008, grafik programlama API olarak da DirectX 10 kullanılacaktır. DirectX 10 hakkında detaylı bilgi "DirectX 10 ve Shader Programlama" deney föyünde vardır. Hem Bump Mapping hem de Parallax Mapping yönteminde yüzey normali veya alpha parlaklık değerine göre yüzey yüksekliği kullanılan dokuya bağlı olarak pixel mertebesinde hassaslıkla değiştirildiğinden DirectX ile birlikte ekran kartının vertex ve pixel işlemcilerini programlayabilen HLSL shading dili kullanılacaktır. Parallax Mapping yöntemini gerçeklemek üzere Şekil.1 deki gibi üç farklı dokuyu kullanarak pürüzlü gösterilecek yüzeyin son renk değerlerini hesaplayan HLSL dilinde PS isimli pixel shader programı aşağıdaki gibidir: Şekil.1: Doku, Height Map Dokusu, Normal Map Dokusu
pixel PS( fragment IN ) pixel OUT; float fparallaxlimit = -length( IN.eye.xy ) / IN.eye.z; fparallaxlimit *= fheightmapscale; float2 voffsetdir = normalize( IN.eye.xy ); float2 vmaxoffset = voffsetdir * fparallaxlimit; float3 N = normalize( IN.normal ); float3 E = normalize( IN.eye ); float3 L = normalize( IN.light ); int nnumsamples = (int)lerp( nmaxsamples, nminsamples, dot( E, N ) ); float fstepsize = 1.0 / (float)nnumsamples; float2 dx = ddx( IN.texcoord ); float2 dy = ddy( IN.texcoord ); float2 vcurroffset = float2( 0, 0 ); float2 vlastoffset = float2( 0, 0 ); float fcurrrayheight = 1; float flastsampledheight = 1; float fcurrsampledheight = 1; int ncurrsample = 0; while ( ncurrsample < nnumsamples ) fcurrsampledheight = NormalHeightMap.SampleGrad( LinearSampler, IN.texcoord + vcurroffset, dx, dy ).a; if ( fcurrsampledheight > fcurrrayheight ) float delta1 = fcurrsampledheight - fcurrrayheight; float delta2 = ( fcurrrayheight + fstepsize ) - flastsampledheight; float ratio = delta1/(delta1+delta2); vcurroffset = (ratio) * vlastoffset + (1.0-ratio) * vcurroffset; ncurrsample = nnumsamples + 1; else ncurrsample++; fcurrrayheight -= fstepsize; vlastoffset = vcurroffset; vcurroffset += fstepsize * vmaxoffset; flastsampledheight = fcurrsampledheight; float2 vfinalcoords float4 vfinalnormal float4 vfinalcolor = IN.texcoord + vcurroffset; = NormalHeightMap.SampleGrad( LinearSampler, vfinalcoords, dx, dy ); = ColorMap.SampleGrad( LinearSampler, vfinalcoords, dx, dy ); vfinalnormal = vfinalnormal * 2.0-1.0; float3 vambient = vfinalcolor.rgb * 0.5; float3 vdiffuse = vfinalcolor.rgb * max( 0, dot(l,vfinalnormal.xyz ) ) * 0.5; vfinalcolor.rgb OUT.color return OUT; = vambient + vdiffuse; = vfinalcolor; Programın ürettiği pürüzlü yüzey örnekleri Şekil.2 de verilmiştir: 2
Şekil.2: Parallax Mapping ile üretilen pürüzlü yüzeyler PS adlı pixel shader programındaki while döngüsünde, başlangıç değeri 1 olarak setlenmiş, bakış noktasından yollanan ışının yüksekliği fcurrrayheight ile bu ışının yüzeyle kesiştiği noktaya karşılık gelen ColorMap doku renginin *0..1+ arası değişen fcurrsampledheight alpha parlaklık yani yükseklik değeri ile karşılaştırılır. fcurrsampledheight < fcurrrayheight olduğu müddetçe hem fcurrrayheight değeri fstepsize kadar azaltılır hem de ışının doku üzerindeki doğrultusunu temsil eden 2 boyutlu (2D) vcurroffset vektörü kadar eklenmiş doku koordinatlarındaki.alpha yükseklik değeri aşağıdaki ifade ile fcurrsampledheight a atanarak ilerlenir. Böylece hem fcurrrayheight hem de fcurrsampledheight değişir: NormalHeightMap.SampleGrad( LinearSampler, IN.texcoord + vcurroffset, dx, dy).a fcurrsampledheight > fcurrrayheight olduğu anda dokuda başlangıçtaki koordinatlardan vcurroffset kadar ötelenmiş doku koordinatları için hem kaplanacak ColorMap dokusu hem de bundan elde edilen NormalHeightMap den SampleGrad komutu ile alınan renk değerleri sırasıyla vambient ve vdiffuse renk değerlerinin hesaplanmasında kullanılır. Bakış noktasından gelen ışının doğrultusu olan eye vektörü kullanılarak vcurroffset vektörü, normalize( IN.eye.xy ) ile yani eye vektörünün (x,y) koordinat değerleri IN.eye.xy ile alınıp normalize edilerek (boyu 1 birim yapılarak) hesaplanır. Böylece bakış noktasından yollanan 3D ışın doğrultusuna (eye) karşılık gelen 2D doku doğrultusu (vcurroffset) bulunmuş olur. eye vektörü, VS adlı vertex shader programında P - EyePosition.xyz ile hesaplanmıştır. Burada P bakış noktasının EyePosition de yüzey üzerindeki kesişim noktasının koordinatlarıdır. 3
Şekil.3: Işının yüksekliği ve vcurroffset vektörü ile doku koordinatının belirlenmesi Bakış noktasından yollanan ışının yüksekliği azaltılarak bulunan alpha yükseklik değerine (heightmap depth) karşılık gelen doku koordinatlarının ışının 3D doğrultusunun 2D doku koordinatları açısından karşılığı vcurroffset vektörü ile bulunması Şekil.3 te gösterilmiştir. 3. Deneye Hazırlık Işının yüksekliğini azaltan fstepsize adlı değişkenin değeri nmaxsamples adlı HLSL değişkenine bağlı olarak belirlenir. nmaxsamples adlı değişkenin değeri de g_nmaxsamplesvar ve g_nmaxsamples adlı DirectX değişkenleri ile setlenmektedir. Böylece klavyenin Sağ/Sol tuşlarına basılarak nmaxsamples dolayısıyla da fstepsize değişkeninin değeri arttırılıp/azaltılmakta ve örneğin nmaxsamples=4 yapıldığında Şekil.4'teki görüntü ortaya çıkmaktadır. Programda nmaxsamples adlı değişkenin setlenmesi eksik bırakılmıştır. Bu kısmı tamamlayınız. Programınız çalışmasa da deneye getiriniz. HLSL programındaki herhangi bir değişkenin DirectX programı ile nasıl değiştirileceği DirectX 10 ve Shader Programlama deney föyünde anlatılmaktadır. 4
Şekil.4: fstepsize=4 için üretilen görüntü Şekil.5: Specular renk bileşeninin hesaplanışı 4. Deneyin Yapılışı Bilindiği gibi PS fonksiyonunda pixelin son renk değeri hesaplanırken dokudan gelen renk ile ambient, normalmap ten gelen renk ile de diffuse renk bileşeni hesaplanıyordu. Üçüncü bileşen olan specular rengin hesaplanması Şekil.5'teki gibidir. Burada ışık kaynağına doğru olan L vektörünün yüzey normali N vektöründen yansıması olan R vektörü ile bakış noktasına doğru olan C vektörü arasındaki açının kosinüs değeri =dot(r,c) skaler çarpımı ile hesaplanmaktadır. Son olarak hesaplanan değerinin genelde 2 nin katı olarak 8,16,32,64 gibi bir değer kadar kuvveti alınarak specular parlaklığın yarıçapı değiştirilir. HLSL programında gerekli değişiklikleri yaparak specular renk bileşenini ekleyiniz. R vektörünün hesabı için reflect(l,n) HLSL komutu, değerinin kuvvetini almak için de pow(,64) kullanacaksınız. Program koşulduğunda Şekil.6'daki gibi bir görüntü üretilecektir. 5. Rapor Raporda, kaynak kodların olduğu klasördeki şablon dosya kullanılarak 1. Deneye Hazırlık bölümünde istenilen kodun nasıl yazıldığı, 2. Deneyin Yapılışı bölümünde istenilen kodun nasıl yazıldığı anlatılacaktır. Şekil.6: Specular renk bileşeni eklenmiş görüntü 5