[ glorius @ 29.01.2006. 17:43 ] @
Poceo sam da radim sa GLSL. Uzeo sam primer sa neta koji kombinuje difuznu i specular boju sa bojom teksture.

Code:


//////////////// *** VERTEX SHADER PART *** ///////////////////

varying float LightIntensity;

const float specularContribution = 0.1;
const float diffuseContribution  = 1.0 - specularContribution;

void main(void)
{
    vec3 ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex);
    vec3 tnorm      = normalize(gl_NormalMatrix * gl_Normal);
    vec3 lightVec   = normalize((gl_LightSource[0].position.xyz) - ecPosition);
    vec3 reflectVec = reflect(-lightVec, tnorm);
    vec3 viewVec    = normalize(-ecPosition);

    float spec      = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
    spec            = pow(spec, 16.0);

    LightIntensity  = diffuseContribution * max(dot(lightVec, tnorm), 0.0)
                      + specularContribution * spec;

    gl_TexCoord[0]  = gl_MultiTexCoord0;
    gl_Position     = ftransform();
}



Code:


//////////////// *** FRAGMENT SHADER PART *** ///////////////////


varying float LightIntensity;
uniform sampler2D myTexture;

void main (void)
{
    vec3 lightColor = vec3 (texture2D(myTexture, gl_TexCoord[0].st)); // kada ne koristim ovu funkciju sve radi OK

    gl_FragColor    = vec4 (lightColor * LightIntensity, 1.0);
}



Problem je sto je aplikacija neverovatno spora. Primer koji koristi ovaj kod radi super ali sam napravio svoju aplikaciju i sve ide sporo ( bez koriscenja texture, znaci samo difuzna, specular i ambient color, framerate je > 1000 ).

Ukljucivao sam i slozenije primere ( Bump + Reflection ) i sve ide glatko. Problem u OpenGL kodu? Verovatno, ali koji?
[ yooyo @ 29.01.2006. 22:10 ] @
Proverio sam i sve izgleda OK. Vertex & fragment shaderi lepo rade.
Kazes da ako ukljucis texturu onda se program vuce, a bez nje lepo radi. Mozes li nam reci koji hw i drivere koristis.

Mozda nisi podesio texure filtering (min & mag), tj. nisi napravio i ukljucio mipmape. Ako se koristi GL_NEAREST filtering onda to moze dosta da uspori prog zbog veceg mem bandwidtha koji je potreban da se texeli dovuku iz memoije u shader.

Ajde posalji relevantne delove programa...
1. kreiranje i upload texture
2. ucitavanje shadera, njihovo kompajliranje i linkovaje
3. aktiviranje shadera
4. aktiviranje texture
5. postavljanje vrednosti uniform varijabli.

yooyo
[ glorius @ 30.01.2006. 13:29 ] @
Ej, yooyo, hvala ti na odgovoru ( po ko zna koji put )!
Problem je u texturi. Mora da bude dimenzija Power of 2.

Naime, dok sam imao slabiji komp ( AMD Athlon 1 Ghz, GeForce 2 MX , WIN98), napravio sam 3D game nalik Diablu koja je koristila texture koje nisu PO2 ( nego npr 300x200 ). Sve je radilo OK. ( mada u OpenGL SDK kazu da se STRIKTNO treba drzati PO2 pravila ). Ne znam samo zbog cega je sve ovo radilo.

Igra je u XP, naravno, imala iste simptome koje sam malopre naveo ( FPS << 1 ).

Sto se tice konkretnog primera koji sam naveo, kada sam podesio texturu da bude PO2, sve je sada OK.

Inace, prepravljam svoj stari Engineda radi sa Shader-ima mada planiram da stari softverski rendering koristim za slabije masine ( AUTODETECT ekstenzija i podrzavanja Shade-a itd... ).

Inace, sad sve ide glatko. Trenutno radim na osvetljenju scene. Sledeci korak je Bump Mapping, pa refleksija itd.

Jos jedno pitanje. Iz 3D Studio MAX - a izvozim Objekte i Animaciju u obliku ASE fajla. Animaciju izvozim tako sto npr. svaki 5. frame upisujem u fajl i onda pomocu interpolacije animiram morphing objekta. Do sada sam bio zadovoljan ovim. Ali, sada bih hteo da radim sa Skin-ovanim modelom ( Bones, Weights, ... ) zbog realnije fizike. Da li se isplati trositi vreme na izucavanje matematike koja je potrebna za ovaj sistem animacije ( mada sam zadovoljan i sa morphingom ). Takodje, video sam i primer Skin animacije pomocu Shadera, mada ne mogu bas da nadjem pravi source za to.

A, da, masina na kojoj radim: P4 3.0 Ghz 64-bit 2 MB Cache, 1 GB Dual Chanel DDR400, Ati Radeon XT800GT 256 MB Ram, ...



[Ovu poruku je menjao glorius dana 30.01.2006. u 14:32 GMT+1]
[ Angel_of_Dark @ 30.01.2006. 20:27 ] @
Morph nije bas naj-elegantnije resenje (pogotovo ne memorijski). Pogotovo ako vec planiras da koristis vertex shadere i ako tvoji modeli imaju veliki broj vertexa i dugacke animacije. Uz pomoc shadera, vrlo lako mozes odraditi hardversko resenje.
[ yooyo @ 31.01.2006. 02:51 ] @
Skining nije tezak.. Evo ti source za to. Pored pozicija, normala i mapping koortinata potrebni su jos vec4 vWeight i vec4 vBoneIndex.

vWeight cuva tezinske koeficijente za max 4 kosti koje imaju uticaj na vertex. Vodi racuna da suma koeficijenata jednog vertexa (x+y+z+w) MORA biti 1.0

vBoneIndex cuva 4 indexa u nizu uniform mat4 bones[30];

mat4 bones[30] cuva globalne matrice svake koske.

Pre svega, potrena je mala prekalkulacija... Obicno, mesh se zadaje u T-pozi i kroz njega je provucen bones sistem (ili bipedi u max-u).

Neka je XF[k] globalna matrica transformacije neke kosti/bip-a i neka je V[n] neki vertex koji je zakacen na tu kost. Izracunaj inverznu matricu koske InvXF[k] i neka je V' transformisani vertex koji se racuna:

V'[n] = XF[k] * InvXF[k] * V[n];

Posto je XF * InvXF = 1 onda ce se vertex preslikati u istu tacku.

E ovde u pricu ulazi animacija.. Naime.. potrebno je da imas globalnu poziciju svake kosti u svakom frejmu i da pripremis matrice za shader na sledeci nacin:

bones[k] = Anim[k] * InvXF[k];.. znaci proizvod matrice koske iz frejma i inverzne matrice iste koske u T-Pozi.

Tezinski koeficijenti se koriste za smooth skinning.
Finalno.. formula za skining izgleda ovako:

mat4 skinmatrix = sum(k=0..3; weight[k] * bones[boneindex[k]])
tj. kad se unrolluje loop to izgleda ovako:
Code:
    
mat4 skinmatrix = w.x * bones[int(b.x)];
    skinmatrix = skinmatrix + w.y * bones[int(b.y)];
    skinmatrix = skinmatrix + w.z * bones[int(b.z)];
    skinmatrix = skinmatrix + w.w * bones[int(b.w)];


V' = skinmatrix * V;
N' = mat3(skinmatrix) * N; N i N' su vec3 pa se koristi samo gornjih 3x3 iz skinmatrice.

Pazi kako baratas sa matricma jer A * B != B * A...

Code:

attribute vec4 vWeight;
attribute vec4 vBoneIndex;

uniform mat4 bones[30];
const vec4 nula = vec4(0.0, 0.0, 0.0, 0.0);

varying vec4 col;

mat4 BuildSkinMatrix()
{
    vec4 b = vBoneIndex;
    vec4 w = vWeight;    

    mat4 result = w.x * bones[int(b.x)];
    result = result + w.y * bones[int(b.y)];
    result = result + w.z * bones[int(b.z)];
    result = result + w.w * bones[int(b.w)];
            
    return result;
}

void main(void)
{
    vec4 vtx;
    vec4 nrm;

    gl_TexCoord[0] = gl_MultiTexCoord0;
    mat4 skinmatrix = BuildSkinMatrix();
    
    vtx = skinmatrix * gl_Vertex;
    nrm = skinmatrix * vec4(gl_Normal, 0.0);
    nrm = vec4(gl_NormalMatrix * nrm.xyz, 0.0);
    col = gl_Color;
    gl_Position = gl_ModelViewProjectionMatrix * vtx;
}


Fragment shader nije bitan.

Tezinske koeficijente i indexe mozes saznati iz MAXa pomocu physics API-a. Prostudiraj malo MAX plugin API.

yooyo
[ yooyo @ 31.01.2006. 02:55 ] @
I jos nesto....

http://glintercept.nutty.org/

Pocni da koristis ovaj izuzetan tool za debagovanje OpenGL poziva. Samo podmetnes tweakovani opengl32.dll u dir od aplikacije, podesis config i startujes program. Posle pogledaj log file i mozes lako da uocis gde je OGL prijavljivao greske koje nisi kontroliaso.

yooyo
[ NastyBoy @ 31.01.2006. 18:19 ] @
Off-topic:



Nutty je inache moj kolega, "komp prekoputa", a nisam imao pojma da je ovo na njegovom sajtu :)
Svet je mali :)
[ yooyo @ 01.02.2006. 10:25 ] @
Citat:
NastyBoy:
Nutty je inache moj kolega, "komp prekoputa", a nisam imao pojma da je ovo na njegovom sajtu :)
Svet je mali :)


Pozdravi ga... Napravio je zaista korisnu stvar!

yooyo
[ glorius @ 02.02.2006. 12:58 ] @
Bones su cOol stvar. Verovatno bih se snasao sa implementacijom shader-a ali koji je najbolji nacin da se izveze informacija o Bones-ima iz MAX-a ( v5.0 )?

Po meni bi bilo logicno da se napravi Bones sistem ( koji bih koristio vise puta za stvorenja koja imaju istu skeletalnu strukturu ), pomocu Physique ili Skin modifier-a povezem mesh sa Bones-ima i ... sta dalje. Kako izvesti informacije u neki ASCII format?

Jos jedno pitanje ( fuuu, al ovaj glorius smara :) ).

Kako pomocu shadera implementirati uticaj vise svetala na objekat? Koliko sam upucen u dokumentaciju, strukture ne mogu biti uniform. To malo otezava. Mogu da renderujem objekat onoliko puta koliko imam svetala ali taj kod ne bi bio u shader fajlovima vec bi se shader stalno iznova pozivao, ali to po meni nije bas najbolje resenje. CG shader ima mogucnost da pomocu for...next petlje saberem sve uticaje svetala i da dobijem konacnu boju pixela pri jednom pozivu shadera. Ovde to nije slucaj. What to do?
[ yooyo @ 02.02.2006. 15:27 ] @
Pazi... svaki 3d karakter ima razlicit bones setup (osim ako ih 3d modelar napravi da svi modeli budu priblizno iste velicine). Ukratko.. i ako modeli imaju isti broj kostiju, a imaju kosti razlicitih duzina ili druge uglove u Tpozi onda je to drugaciji skelet.
Idealno bi bilo da napravis sledecu strukturu za 3d karakter.

1. Header sa informacijama o kostima:
- globalna matrica svake koske
- pozicija, orijentacija i duzina koske u parent sistemu
- podaci o hierarhiji

2. Vertexi (niz vertex struktura:);
• pos,
• norm, (binormala i tangenta opciono)
• color,
• texcoord
• boneindices (vec4 za max 4 uticaja)
• weighting (vec4, suma == 1.0)

3. Trouglovi sakupljeni u batcheve.

Animacije cuvaj odvojeno. Mozes da smestas globalne matrice za svaki frame a mozes i da koristis quaternione (4x manje prostora, ali kompleksniji racun i zahteva dodatne informacije iz setup-a). Takodje.. nemozes da koristis istu animaciju na 2 razlicita karaktera jer ce sve da se raspada.

Sto se renderinga tice, ako unapred znas sa koliko svetala ce biti osvetljen karakter onda napravi spec shadere za to, a ako neznas.. onda opsti shader bez svetla i koristi multipass.
- uradi soft skinning (bez shadera) u memoriji za svaku vidljivu instancu karaktera
- render Z+Ambient
- postavi addtivni blending (GL_ONE, GL_ONE) i iskljuci z-write
- za svako svetlo
- opciono renderuj shadow mapu (u offscreen buffer) ili shadow volume
- renderuj difuznu komponentu u glavni buffer i spekularnu u offscreen buffer. Ovde mozes i da primenis senke iz prethodnog koraka.
- prebaci blending na modulate
- renderuj texture
- i na kraju opet prebaci na aditivni blending i prekopiraj sadrzaj specular buffera prego glavnog.
- sada izrenderuj materijale sa self-illumination atributima

U svakom pass-u prilikom renderinga, ponovo se skinuje model. Problem je ako imas kompleksan vertex shader to moze biti usko grlo, pa je bolje uraditi skinning na CPU. Koristi VBO za transfer. Model podeli na staticke (texcoord, color, boneindexi i weighting) i dinamicke podatke (pos, norm, tangent i binormal).

Koristi FBO (i GL_ARB_draw_buffers) sa zajednickim z-bufferom. Npr.. napravi ovakav FBO setup:
- buffer0 za ambient + diffuse
- buffer1 za specular
- zbuffer
Na ovaj nacin cuvas specular komponentu u posebnom bufferu da bi je na kraju zalepio preko izrendane slike.


i na kraju... ako ti treba neka karakter animacija (hodanje, trcanje, neka radnja...) javi se... imam gomilu mocap fajlova koje mozes da iskoristis.

yooyo
[ reject @ 03.02.2006. 08:47 ] @
Citat:
yooyo: Pazi... svaki 3d karakter ima razlicit bones setup (osim ako ih 3d modelar napravi da svi modeli budu priblizno iste velicine). Ukratko.. i ako modeli imaju isti broj kostiju, a imaju kosti razlicitih duzina ili druge uglove u Tpozi onda je to drugaciji skelet.

Uglavnom svi likovi istog tipa u jednoj igri dele isti kostur i iste animacije. Kod MaxPaynea
postoje samo dva kostura u celoj igri. Jedan je kostur za igraca koji ima dodate koske za
animiranje odela i jedan kostur za ostale. COD recimo ima samo jedan kostur. Fora je u
tome da se u proizvodnji igara stedi na svemu, a najvise na vremenu, tako da u 90%
slucajeva svi humanoidi dele kostur i dobar deo animacija, a ostali imaju svoje kosture,
mada je i to manje vise standardizovano i ako ne postoji neki veoma dobar razlog, nikada
se ne radi jedan kostur za samo jedan model.


[Ovu poruku je menjao reject dana 03.02.2006. u 09:48 GMT+1]
[ glorius @ 06.02.2006. 15:33 ] @
Sta je to Batch?

Trenutno unapredjujem svoj ASCII MAX Loader koji koristi Multitexturing, Bump itd.

Hteo bih da grupisem face-ove po MaterialID-u. Da li je Batch skup face-ova sa istom texturom ( tj. MaterialID - ijem ) ili gresim?

Celu scenu bih onda "pretvorio" u BSP fajl sa Precalculated Visibility - jem za svaki Cube.

Da li je ova tehnika dobra ( pored svih zivih tehnika sortiranja poligona pre renderinga, Portala, BSP - a i svega i svacega... :)
[ reject @ 06.02.2006. 16:57 ] @
http://www.mvps.org/directx/articles/vcache.htm