Gönderen Konu: vertex streams made my life easier.  (Okunma sayısı 18687 defa)

vertex streams made my life easier.

« : 10.08.2005 11:59:10 »
Hızlı düğmeleri aç

sensei

İleti: 23

Çevrimdışı
  • *
  • Newbie
    • Profili Görüntüle
    • http://nothing.right.now
offffffff cok baydim.. azicik ugrashtigim ishi anlatiim.. bi yerlerde effect/demo/intro/fantezi/gang bang..(err.. yok yok bu degil) olarak kullanilabilir..

blend shape'i bi cogunun bildigini kabul ediyorum.. ama temel mantik:

base_mesh var...
blend_mesh[100] var...
weight[100] var.. (blend'ler ichin)

ve temel mantik...

target_mesh = base_mesh;
for (1..100)
  target_mesh += blend_mesh[ndx] * w[ndx]

(tabi blend shape datasinin ichinde aslinda base_mesh'den subtract edilmish halini tutuyoruz...temel weighted morph mantigi...)

yukardaki mantik ayni anda 100 blend shape yapar... ama.. aslinda. ayni anda 100 adet blend shape yapilmaz genelde... genel pratik uygulamasi .. cok basit bir ornek olarak...

insan yuzunu ele alalim.. base_mesh var... kelle ishte. ve target shape'lerimiz de.. kas kaldir, kas indir, agzi ach, agzi kapa, gozu kirp...etc.. diyelim 30 tane bundan var...simdi.. bizim yukardaki blend equation'da asla 30 adet mixlemeyecez.. .yani weight bazinda dushunursek..
kas kaldir ve kas indir ornegin ayni anda "1" olmaz.. yani matematiksel olarak olabilir de... olmaz yani.. noktalar garip olur..

yani ayni anda blend etmekle blend shape target arasindaki farklari umarim anlatabilmishimdir...

WHAT:
"n" (100-200... adet) blend target
15 adet ayni anda blend shape

WHERE:
in GPU

HOW:
hah olay bu zati.. simdi olayi DX cinsinden anlatacam..isteyen GL'e veya software engine apply edebilir.

base meshimiz:
mesh'imize bi vertex structure veriyoz... diyelim cok standart bishii... ve:
struct vertex_struct {
  float4 pos;
  float3 norm;
  float2 texcoord;
}

evet.. gayet siradan...

sonra blend shape'lerimize aynini yapiyoz.
struct blend_struct {
  float4 pos;
  float3 norm;
}

bu da bu kadar.. (texcoord ayni kalacak... yani color v.s gibi sheyler olsaydi onnarda ayni kalacakti...) target mesh'de degishen sheyleri gomuyoz sadece .. aslinda degishme miktarini... yani export ederken o blend shape'i...

export_mesh.pos = blend_shape.pos - base_mesh.pos
export_mesh.norm = blend_shape.norm - base_mesh.norm

yapiyoruz (her bi blend shape ichin)

peki nasil anim falan filan..
diyelim 3 adet blend shape'imiz var..
o zaman bizim vertex shader kodumuz shoole bishii olacak...

struct VS_INPUT {
  float4 pos : POSITION0; // base mesh position at stream 0
  float3 norm : NORMAL0; // base mesh normal at stream 0
  float2 texcoord : TEXCOORD0;
  float4 pos_diff1 : POSITION1; // blend shape[1] at stream 1
  float4 pos_diff2 : POSITION2; // blend shape[2] at stream 2
  float4 pos_diff3 : POSITION3; // blend shape[3] at stream 3
  float3 norm_diff1 : NORMAL1; // blend_shape[1] at steram 1
  float3 norm_diff1 : NORMAL2; // blend_shape[2] at steram 2
  float3 norm_diff1 : NORMAL3; // blend_shape[3] at steram 3
}

struct VS_OUTPUT {
   float4 pos :  POSITION0;
   float4 color : COLOR0;
   float2 texcoord : TEXCOORD0;
}

VS_OUTPUT vs_main(VS_INPUT In) {
  VS_OUTPUT Out = (VS_OUTPUT)0;
  .....
  return Out;
}


guzel..simdi biliyoz ki 4 adet stream gerekiyo bu alet ichin. her stream'e bi buffer baglayacaz. yani setup asamasinda...

SetStreamSource(0, base_mesh_vertex_buffer);
SetStreamSource(1, blend_mesh_vertex_buffer[0]);
SetStreamSource(2, blend_mesh_vertex_buffer[1]);
SetStreamSource(3, blend_mesh_vertex_buffer[2]);

gibi bishii yapiyoruz.. ve. kodumuz yukarda da dedigimiz gibi...

float w[3]; // blend shape parameters.. dishardan setlenecek...

VS_OUTPUT vs_main(VS_INPUT In) {
  VS_OUTPUT Out = (VS_OUTPUT)0;
  float4 target_pos = In.pos;
  target_pos += In.pos_diff1 * w[0];
  target_pos += In.pos_diff2 * w[1];
  target_pos += In.pos_diff3 * w[2];
  float3 target_norm = In.norm;
  target_norm += In.norm_diff1 * w[0];
  target_norm += In.norm_diff2 * w[1];
  target_norm += In.norm_diff3 * w[2];
  // ... bu noktadan itibaren target_pos ve target_norm bitti...
  Out.pos = target_pos * matrix_cart_curt.....;
  Out.color = dot(target_norm... hesap hesap hesap....)
  Out.texcoord = In.texcoord;
  return Out;
}

simdi butun weight'ler bashta sifir oldugu ichin bi bok degishmeyecek yazdigimiz kodda.. hali ile dishardan weight'leri setlemek gerek..
ve bunu keyframe'lere bakarak yapiyoruz... keyframe'leri bi shekil export ediyoruz.. (weight'lerin key'lerini) ve zamana gore...

SetParam(w[0], key_w0[time]);
SetParam(w[1], key_w1[time]);
SetParam(w[2], key_w2[time]);

gibi bishii ile setliyoruz... hali ile 3 blend target'i olan ve key'lere gore morph eden bi sistem yaptik.. simdi.. bu sistemi,
ayni anda 15 adet yapan ve toplam 200 tane blend yapan bi yapiya nasil getiririz..

problem 15'de degil..problem 200 'de .. 15'i yapabiliriz.. shu anki DX liib'i ayni anda 16 stream destekliyo (biri kendi base meshi'imiz... o yuzden 15... ama 15 ciddi anlamda yeterli bi miktar... bana sorarsan ben 4 bile yeter derim...)
200 blend target'i nasil yapar nasil anime ederiz.. o apayri bi konu..

ilk etapda.. 200 adet vertex buffer yaratiyoz.. (ya da bi shekil ortak vertex buffer bile kullanilabilir..) ve... keyframe'lere bakiyoz...
weight'i SIFIR olmayan ilk 15'ini buluyoz her bi frame ichin...
(basitche.. buyukten kucuge dooru siralamak yeterli bu ish ichin...)
simdi elimizdeki 15 stream'e.. o frame'de weight'i olan 15 shape'i setliyoruz...

SetStreamSource(1, blend_with_weight_vertex_buffer[0]);
SetStreamSource(2, blend_with_weight_vertex_buffer[1]);
SetStreamSource(3, blend_with_weight_vertex_buffer[2]);
....
SetStreamSource(15, blend_with_weight_vertex_buffer[14]);

ve arkasindan weight'leri de giriyoz...
SetParam(w[0], key_w0[time]);
SetParam(w[1], key_w1[time]);
....
SetParam(w[14], key_w14[time]);
(tabe dikkat ediyoz O BLEND SHAPE'in weight'ini girdigimize..)

yani ozetle her frame... weight'i sifirdan farkli olan "n" sayida ( < 15 shu an ichin...ama fake ile arttirabilir...) blend shape'ler bulunup...vertex bufferlari gerekli stream'lere konulup, vertex shader'dan gechirdigimizde olay oluyo....

vertex shader fazla sheetmemish olanlar ichin...
struct VS_INPUT {
  float4 pos : POSITION0; // base mesh position at stream 0
  float3 norm : NORMAL0; // base mesh normal at stream 0
  float2 texcoord : TEXCOORD0;
  float4 pos_diff1 : POSITION1; // blend shape[1] at stream 1
  float4 pos_diff2 : POSITION2; // blend shape[2] at stream 2
  float4 pos_diff3 : POSITION3; // blend shape[3] at stream 3
  float3 norm_diff1 : NORMAL1; // blend_shape[1] at steram 1
  float3 norm_diff1 : NORMAL2; // blend_shape[2] at steram 2
  float3 norm_diff1 : NORMAL3; // blend_shape[3] at steram 3
}

structure'i bi nevi MAPPING (bi nevi degil.. bariz yani...) sagliyo.. her bi degishkene soolenen stream'deki component geliyo gibi dushunun..

boole de bi olay yani... artik nvidia'nin DAWN/PIXIE ot bok demo'larina bakip dil cikarabiliriz...(not: illa dil olmasi gerekmiyo..)

bashka bir stream anisi daha anlatiim bari.. madem vertex stream'lerden bahsettik...

WHAT:
  geometry instancing in one pass!..

REQUIREMENTS:
  vertex shader 3.0 olan kart.

IS THERE AN EXAMPLE:
  tek bilinen ornek .. black & white 2 (daha cikmadi ama oyun...)

NASIL BISHII YANI BU !?:
  mesh ayni ... tek pass'de bu mesh'in binlerce kopyasini degishik yerlere ekrana basicaz. ornegin ORMAN..veya ayni mesh'den olushan bir ORDU (blend'leri bile farkli olabilir fake'lerle...)

simdi.. vertex shader 3.0'da kartlara stream'ler ichin shoole bi olay geliyo.. stream frequency.. bu shu demek..

diyelim elimizde iki stream var..
vertex_buffer1 : --> pos0, norm0, pos1, norm1, pos2, norm2.......
vertex_buffer2 : --> texcoord0, texcoord1.......

struct vertex_struct {
  float4 pos : POSITION0;
  float3 norm : NORMAL0;
  float2 texcoord : TEXCOORD1;
}

SetStreamSource(0, vertex_buffer1);
SetStreamSource(1, vertex_buffer2);

simdi burada... gpu vertex'leri process ederken tek tek senin VERTEX STRUCT'da istedigin sheyleri gidip aliyo vertex shader'dan...
once.. stream_pos = 0 bashlangichta..
yani... STREAM1'den okursa.. pos0 ve norm0 alacak...
STREAM2'den okursa da texcoord0 alacak. netekim bunnari okuyup
bizim vertex shader'a yolluyo.. sonra stream_pos = 1 oluyo..bi sonraki vertex'leri gerekli stream'lerden okuyo...

...simdi... vertex_shader3.0 ile birlikte frequency olayi geldi..
SetStreamSourceFreq(stream_num, freq)

bu komut shunu yapiyo.. stream'ler ustunde yururken birini oburunden daha hizli calishitiryo (yani frekansina gore..)
deminki ornekte bizim vertex shader ichine sirasi ile..

pos0, norm0, tex0
pos1, norm1, tex0
pos2, norm2, tex0
pos3, norm3, tex0
....
pos100, norm100, tex0    // diyelim 100 adet nokta var..
pos0, norm0, tex1
pos1, norm1, tex1
pos2, norm2, tex1
....
pos0, norm0, tex2
...
pos0, norm0, tex3
...
pos100, norm100, tex100

yani..
SetstreamSourcefreq(0, 100) dersek... 2.stream bi kere bastan sona geleene kadar 1'ci stream 100 tur atiyo kendi etrafinda... hali ile
vertex shader'a gelen vertex sayisi (100 * 100) olmush oluoy...

simdi insanlar bunu nasil kullaniyo.. yukardaki ornege bakarsak...
biz birinci stream'in frekansini kach yaparsak... o kadar kere tekrar ediyo o buffer.. yani diyelim bir agach meshimiz var.. cizecez... freq = 100 dersek.. ayni yere 100 tane agach cizmish oluruz aslinda.. 100 tane pass gibi oluyo... ishte bu noktada cok cici bi fake giriyo olaya..

ikinci stream'in vertex struct'ini shu sekilde tanimliyoruz...

struct vertex_struct {
  float4 matrix_row_0;
  float4 matrix_row_1;
  float4 matrix_row_2;
  float4 matrix_row_3; // neticede ichine ne koyduguma kim karisir.
}

evet vertex struct ichinde aslinda o agachlarin world space matrix'ini belirtiyoruz.. ve vertex shader'da...

struct VS_INPUT {
  float4 pos : POSITION0;
  float3 norm : NORMAL0;
  float2 tex : TEXCOORD0;

  float4 mat0 : POSITION1;  // ne olarak aldigimizin onemi yok.
  float4 mat1 : TEXCOORD1; // cidden yok
  float4 mat2 : COLOR1;      // bak valla yok diyorum yaaaa
  float4 mat3 : BINORMAL1;  // alla allaaaaaaaaa.....
};

VS_OUTPUT vs_main(VS_INPUT In) {
  gelen pos'u eger ki eger.. mat0-mat3 ile belirtilen
  matrix'le carparsak burada.. tek pass'de
  "n" adet agach cizmish oluruz farkli yerlere..
  cunku 1.ci stream ilerlerken ikinci artmiyo.. freq'leri ona gore
  setledik.. birinci stream full bi tur bitince (yani bi agach cizince)
  ikinci stream bir yuruyo.. (hence, next matrix).. v.s.
}


yani bilmiyom bu iki yazdigim degishik ufuklar, fikirler acarmi da.. oole paylashayim istedim. taam belki eski sheylere benzemiyo,
metaball, plasma falan da...
bu iki teknigi bi shekil birleshtirip.. ayni anda ekranda 256 hardware sound channel'dan lip sync'li konushan (blend shape) 256 adet
kafayi TEK PASS'de basabiliriz :) bu da ishin fantezi boyutu bu..

neysem cok konushtum projeme geri doniim..
umarim faydali olmushtur.. bok gibi anlatmish olabilirim (ki tahminen oole.. sorun ishte..elimden geldigince bakarim soru varsa..)

~sensei, the unholy undead mage.
<ODBC Error 2002: Invalid(-1) length at Column 1>

vertex streams made my life easier.

« Yanıtla #1 : 10.08.2005 13:44:15 »
Hızlı düğmeleri aç

skate

İleti: 5.245

A Sinner Scener
Çevrimdışı
  • Administrator
  • *****
  • Hero Member
    • Profili Görüntüle
    • http://www.akaydin.com/
Hala 3d dedin mi ray casting derim voxel derim, daha advanced birşey ise de yine software rendering derim. Hardware support sux değil derim. Yalnızca benim işim olmaz derim... Hatta dedim!!! :)

Hardware kullanacaksam da (senin aksine Sensei kardeşim) her ne kadar olaylara DirectX ile başlamış olsam da artık OpenGL derim. Sen OpenGL'den DirectX'e döndün, ben ise tam tersi. DirectX'in benim açımdan tek avantajı yalnızca OpenGL'e eş olarak bakarsak Direct3D'den daha fazlası olması, IO işlemlerimi sound/fx, music, networking v.s. konuları beni uğraştırmadan çözmesidir. OpenGL'in zevkli tarafı ise bu tür konulara low level dalmamı sağlamasıdır :)

Tüm bunların yanı sıra Vertex Shader olayını hala test etmemiş biri olarak Vertex Shader 3.0'ın bize kazandıracakları konusunda kafam bomboş :blink: 7D5 partiye gelip bana detaylı anlatırsın ümidiyle bekliyorum :)

vertex streams made my life easier.

« Yanıtla #2 : 11.08.2005 10:16:00 »
Hızlı düğmeleri aç

sensei

İleti: 23

Çevrimdışı
  • *
  • Newbie
    • Profili Görüntüle
    • http://nothing.right.now
hmm... ben raki, peynir ve kavun diyorum abi.... :)

gelmeye calishirim bakalim.. da.. release falan yok:)
<ODBC Error 2002: Invalid(-1) length at Column 1>