Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 25. březen 2011, 11:10:32 Předmět: Skeletální animace+VBO+GLSL |
|
|
Zdravím,
řeším teď skeletální animace. Načítám model z MS3D. Zatím tak, že pro každý joint mám vlastní matici (zhruba takto):
struct joint
{
..
CMatrix4f matrix;
}
a potom přes CPU všechno propočítám a provedu interpolace a animace.
Nyní bych to chtěl předělat přes VBO a transformaci bych pak prováděl ve Vertex Shaderu. Spíš bych řekl, že myšlenkovitě vím co udělat, ale nemám až příliš zkušenosti s shadery (akorát nějaký to texturování, bump,...).
Jak to zatím řeším:
1. Vytvořím si VBO, zatím do něj cpu jen vertexy
2. vykresluji VBO(ten shader zatím co tam mám pouze vybarví na červeno:-), abych ověřil funkčnost):
X3D_ShaderManager::GetIntance()->GetShader("pokusShader")->Bind();
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, this->m_uiVBOvertices);
glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);
glDrawArrays(GL_TRIANGLES, 0, this->m_usNumVerts);
glDisableClientState(GL_VERTEX_ARRAY);
X3D_ShaderManager::GetIntance()->GetShader("pokusShader")->UnBind();
Tak a teď nevím co dál. Myslím si, že bych měl předat všechny matice jointů do vertex shaderu:
VERTEX SHADER:
uniform mat4 boneMatrix[MAX_BONE];
Ale nevím jak(zatím ty matice mám rozdělené po jedné), tak jestli je nějak složit a pak předat jako celek do pole boneMatrix, nebo v nějakém for cyklu předat je po jedné do pole v shaderu. Ale technicky nevím jak by se to po jedné předávalo a zase skládat všechny matice do jednoho pole mi příjde taky divné.
Pomocí CPU pak provádím transformaci takto:
Joint * pJoint = &m_pJoints[pVert->m_cBone];
vecVertex = pVert->m_vVert;
vecVertex = pJoint->m_matFinal * vecVertex;
Čili získávám index jointu, ke kterému je přiřazen vertex. Pokud bych vykresloval po trojúhelníkách tak bych to do shaderu nacpat uměl, ale když to pak vykresluji přes VBO(jak ukazuji výše), tak nevím jak ten index předat.
Moc děkuji za všechny rady, už si s tím lámu hlavu pár dní, takže budu vděčný za pomoc. Díky, Honzík |
|
Návrat nahoru |
|
|
Poky
Založen: 29. 06. 2009 Příspěvky: 184 Bydliště: Písek / Plzeň
|
Zaslal: 25. březen 2011, 13:42:01 Předmět: |
|
|
Já osobně bych matice převedl na quaternion (místo matice 4x4 dostaneš pouze 7 hodnot(3 pro pozici a 4 pro natočení)) a ten teprve posílal do shaderu |
|
Návrat nahoru |
|
|
]semo[
Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 25. březen 2011, 14:14:00 Předmět: Re: Skeletální animace+VBO+GLSL |
|
|
HonzikJ napsal: |
Čili získávám index jointu, ke kterému je přiřazen vertex. Pokud bych vykresloval po trojúhelníkách tak bych to do shaderu nacpat uměl, ale když to pak vykresluji přes VBO(jak ukazuji výše), tak nevím jak ten index předat. |
Jakkoliv, buť glVertexAttribPointer, ale nejjednodužší bude, když do shaderu pošleš 4 složkový vertex - [X, Y, Z, index], místo obyč. [X, Y, Z]. Tzn. do VBO nacpeš tyhle "větší" vertexy a v shaderu přistupuješ k indexu jako (gl_Vertex.w), používáš-li gl_Vertex. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 25. březen 2011, 14:17:41 Předmět: |
|
|
citace: |
Já osobně bych matice převedl na quaternion (místo matice 4x4 dostaneš pouze 7 hodnot(3 pro pozici a 4 pro natočení)) a ten teprve posílal do shaderu
|
Ano, tak jsem to zkoušel taky nicméně stále mám ten stejný technický problém jak to do shaderu posílat.
Vlastně jsem to měl tak, že jsem měl pro každý joint quaternion (čili jako ta matice) a do shaderu jsem chtěl posílat quaternion + pozici, de bych udělal matici a pronásobil to. Ale problém mám v tom, že nevím jak to tam naposílat, tzn, jak tam poslat(třeba těch 50 kvaternionů + 50 pozic), a potom při vykreslování přes VBO index jointu, ke kterému patří daný vertex.
Naposledy upravil HonzikJ dne 25. březen 2011, 14:24:27, celkově upraveno 1 krát |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 25. březen 2011, 14:22:20 Předmět: Re: Skeletální animace+VBO+GLSL |
|
|
]semo[ napsal: |
HonzikJ napsal: |
Čili získávám index jointu, ke kterému je přiřazen vertex. Pokud bych vykresloval po trojúhelníkách tak bych to do shaderu nacpat uměl, ale když to pak vykresluji přes VBO(jak ukazuji výše), tak nevím jak ten index předat. |
Jakkoliv, buť glVertexAttribPointer, ale nejjednodužší bude, když do shaderu pošleš 4 složkový vertex - [X, Y, Z, index], místo obyč. [X, Y, Z]. Tzn. do VBO nacpeš tyhle "větší" vertexy a v shaderu přistupuješ k indexu jako (gl_Vertex.w), používáš-li gl_Vertex. |
Takže já tam pošlu třeba quaternion 4 složky, pozici 3 složky X,Y,Z a k tomu přihodím ještě W jako index? To mě nenapadlo, to hned zkusím. A nevíte ještě jak tam předat ty pole kvaternionů (nebo matic) nějak hromadně? Já vím, že tam jde jako přes funkce vvkládat pole, ale problém je, že mám ty matice, popřípadě kvaterniony rozdělené vždy ke každému jointu, jak píši výše. |
|
Návrat nahoru |
|
|
Vilem Otte
Založen: 18. 09. 2007 Příspěvky: 462 Bydliště: Znojmo - Sedlesovice, Kravi Hora
|
Zaslal: 25. březen 2011, 14:28:43 Předmět: |
|
|
Mno, já naopak quaternion + vektor (není to jen quaternion) moc pro skeletální animace nedoporučuju (určitě ne do začátků), udělají v tom celkem zmatek a celý model docela zkomplikují (pak si člověk sice může dovolit dual quaternion skinning, ale je to už docela těžké na implementace a matice už jsou rychlejší). _________________ Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration. |
|
Návrat nahoru |
|
|
nou
Založen: 28. 07. 2007 Příspěvky: 1047
|
Zaslal: 25. březen 2011, 14:41:51 Předmět: |
|
|
len daj pozor a v shadery pred tranformaciou prepis ten W index na 1.0.
a ked budes mat uniform mat4 bones[MAX_BONES] tak potom ich nahras proste cez glUiformMatrix4fv("bones", MAX_BONES, false, bones); _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
|
]semo[
Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 25. březen 2011, 14:43:41 Předmět: |
|
|
Vilem Otte: souhlas. Pokud by ale Honzik chtěl přesto do shaderu posílat méně dat pro rotaci, může použít trik, který tu někdo na fóru před časem popisoval:
Když nebude mít scale, tak bázové vektory v transformační matici jsou jednotkové. Proto může poslat jen dvě složky vektoru a třetí dopočítat (ví, že délka je 1). Navíc ty tři vektory jsou na sebe kolmé, takže může poslat jen dva a třetí dopočítat cross-produktem. Takhle může mít pro rotaci jen 4 čísla, ale neni to quaternion.
Honzik: zjisti pozice prvků pole v shaderu pomocí glGetUniformLocation(program, "pole[0]");
glGetUniformLocation(program, "pole[1]");
...
viz http://www.opengl.org/wiki/GLSL_Uniform
EDIT: co píše nou, se zdá být lepší _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 25. březen 2011, 14:58:55 Předmět: |
|
|
nou napsal: |
len daj pozor a v shadery pred tranformaciou prepis ten W index na 1.0.
a ked budes mat uniform mat4 bones[MAX_BONES] tak potom ich nahras proste cez glUiformMatrix4fv("bones", MAX_BONES, false, bones); |
No já to mám takto:
VERTEX SHADER:
uniform mat4 bone[MAXBONE];
.
.
takže teď když mám v GL render, tak přidám toto:
glUiformMatrix4fv("bone", MAXBONE, false, bones) no a to bones je vlastně pole matic, ale všech ne? To znamená, že já ty matice naskládám do jednoho pole? |
|
Návrat nahoru |
|
|
nou
Založen: 28. 07. 2007 Příspěvky: 1047
|
Zaslal: 25. březen 2011, 15:32:52 Předmět: |
|
|
presne proste budes mat v C kode float bones[MAXBONE*16]; len si treba dat pozor na maximalny pocet uniform premennych. _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 25. březen 2011, 15:41:02 Předmět: |
|
|
OK tak zatím všem děkuji, zkusím se na to vrhnout a uvidím jak to půjde, popřípadě se opět ozvu. Myslím ale, že jsem získal všechny informace, které jsem potřeboval |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 26. březen 2011, 13:56:07 Předmět: |
|
|
Tak kupodivu mi to nefunguje .
Postupuji, tak jak jste mi poradili, čili do vertexu jako atribut w předávám index joint matice:
CVector4* v_Temp = new CVector4[this->m_usNumTriangles*3];
int index = 0;
for(int i=0; i<this->m_usNumMeshes; i++)
{
for(int j=0; j<this->m_pMeshes[i].m_usNumTris; j++)
{
ModelTriangle *pTri = &m_pTriangles[m_pMeshes[i].m_uspIndices[j]];
for(int v=0; v<3; v++)
{
ModelVertex * pVert = &m_pVertices[pTri->m_usVertIndices[v]];
v_Temp[index].x = pVert->m_vVert.x;
v_Temp[index].y = pVert->m_vVert.y;
v_Temp[index].z = pVert->m_vVert.z;
v_Temp[index].w = pVert->m_cBone;
index++;
}
}
}
glGenBuffersARB(1, &this->m_uiVBOvertices);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->m_uiVBOvertices);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->m_usNumTriangles * 3 * 4 * sizeof(float), v_Temp, GL_STATIC_DRAW_ARB);
delete [] v_Temp;
v_Temp = NULL;
a dále ze všech matic utvořím jedno pole, které předávám do shaderu:
int loc = glGetUniformLocation(X3D_ShaderManager::GetIntance()->GetShader("pokusShader")->GetIDprogram(), "bone");
glUniformMatrix4fv(loc, 92, false, this->m_Matrix);
v Shaderu to pak akorát pronásobím:
const int MAXBONE = 92;
uniform mat4 bone[MAXBONE];
void main(void)
{
mat4 curMatrix = bone[gl_Vertex.w];
gl_Vertex.w = 1.0;
gl_Position = gl_ModelViewProjectionMatrix * curMatrix * gl_Vertex;
}
Zatím jsou nastaveny jen jednotkové matice, čili mělo by to vykreslit pouze model, animace ještě nedělám. Na CPU to takto funguje, ale jak to pošlu přes shader dějí se na obrazovce velmi zajímavé věci.
Nevidíte tam nějakou chybu, prosím? |
|
Návrat nahoru |
|
|
nou
Založen: 28. 07. 2007 Příspěvky: 1047
|
Zaslal: 26. březen 2011, 14:43:15 Předmět: |
|
|
ked odstranis tu curMatrix z nasobenia tak sa to nejak prejavy?
zisiel by sa screenshot co to roby. su modely rozbite ako keby len zmet trojuholnikov? _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 26. březen 2011, 14:56:14 Předmět: |
|
|
Ano když odstrraním curMatrix projeví se to tak, že je to takový malý shluk trojúhelníku v malé oblasti.
Zatímco když tam nechám tu matici, tak je to o dost větší shluk trojúhelníku, který se při pohybu výrazně problikává a zdá se, že také transformuje.
ALE když renderuju přes cpu a odstraním násobení matic před vykreslením, tak se defacto jedná o tu samou věc, jakokdyž při vykreslování odstraním tu curMatrix, a ve výsledku se jedná zřejmě spíš o rozbití modelu, čili výsledek je jiný než když odstraním curMatrix ze shaderu. |
|
Návrat nahoru |
|
|
HonzikJ
Založen: 04. 02. 2010 Příspěvky: 21
|
Zaslal: 26. březen 2011, 16:27:11 Předmět: |
|
|
Objevil jsem dvě chybičky, zřejmě.
1. přepsal jsem v renderu
glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);
na
glVertexPointer(4, GL_FLOAT, 0, (char*)NULL);
páč posílám vlastně ještě do w jako index.
2. když jsem vyráběl to pole z matic, tak jsem je podsouval transponované, takže jsem změnil indexy.
No a výsledek? Opět zajímavý; renderuje mi to hlavu a kousíček (možná ramena) což teďka absolutně nechápu. |
|
Návrat nahoru |
|
|
|