Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Játro.m
Založen: 01. 02. 2010 Příspěvky: 230
|
Zaslal: 15. květen 2011, 18:04:09 Předmět: Transformace světla v pozadí glLightfv |
|
|
Nazdar, už si připadám jako dement, že zakládám další topic ... ale prostě není karma
Dejme tomu že problém je následující, když pozici světla passnu přes glLightfv, všechno je v pohodě protože opengl za mě ztransformuje pozici modelview matici, když tento postup zkombinuju v shaderu, tak sice osvětlení pro level funguje, ale pro translatovaný a rotovaný objekty je statický, tj že když hejbnu rukama v kameře o 90 tak světlo je furt stejně.
asi nejlíp to explaine video: http://www.youtube.com/watch?v=7oJutnh83oY
normale mám přenásobený gl_NormalMatrix -> view space
světlo by melo bejt po vynasobeni gl_ModelViewMatrix ve view space taky
tak dop*dele kde je problém?
díky za trpělivost ;D |
|
Návrat nahoru |
|
 |
Vilem Otte

Založen: 18. 09. 2007 Příspěvky: 462 Bydliště: Znojmo - Sedlesovice, Kravi Hora
|
Zaslal: 15. květen 2011, 18:40:45 Předmět: |
|
|
Afaik by jsi si měl dělat matice (jak modelview, tak další) sám, protože nevím od kterého OpenGL jsou označeny za deprecated.
Je víceméně jedno v jakém prostoru to budeš počítat, jen musí vše být ve stejném!
Jeden příklad:
pozn. NormalMatrix je transponovaná rotační část 3x3 z inverzní ModelviewMatice (prvně invertujeme, pak transponujeme!)
Pozice transformujeme pomocí ModelviewMatice * Vertex
Normály transformujeme pomocí NormalMatrix * Normal
Světlo transformujeme pomocí InverzníModelviewMatice * Světlo
Důležité však je dodat, všechny matice musí být poslány pro každý transformovaný objekt (tedy poslat vždy správně ztransformované matice do shaderů). Jinak bude výsledek špatný.
Zpravidla zde můžeme hodně optimalizovat, je důležité dodat, že statické modely můžeme všechny zpracovat najednou! Dynamické však nikoliv.
Teď máme vše ve stejném prostoru a můžeme počítat osvětlení. Mohli bychom samozřejmě počítat v jiném prostoru (toto je view-space), můžeme počítat ve world-space, či třeba tangent-space.
EDIT: Jop, nějak jsem pozapomněl dodat to transponovaná ... díky Eosie, všiml jsem si. _________________ Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.
Naposledy upravil Vilem Otte dne 15. květen 2011, 22:54:07, celkově upraveno 2 krát |
|
Návrat nahoru |
|
 |
igor

Založen: 28. 07. 2007 Příspěvky: 196
|
Zaslal: 15. květen 2011, 20:07:33 Předmět: |
|
|
Vilem:
Pozice transformujeme pomocí ModelviewMatice * Vertex
Světlo transformujeme pomocí InverzníModelviewMatice * Světlo
To je trochu matoucí, má smysl dělat buď jedno nebo druhé, ne (popř. oba, ale počítat osvětlení z netransformovaných pozic)? Ale možná jsem opět mimo...
OP:
Odpověď už tady máš, ale zkusím to ještě jinak - to světlo má určitě jinou modelview matici než ta zbraň, resp. stejnou view, ale jinou model (nebo model vůbec nepoužívá, pokud je zadáno pevnou pozicí ve world space). Ty to asi děláš tak, že pro každý objekt transformuješ to světlo maticí toho objektu - výpočet osvětlení pak proběhne stejně, jako by se netransformovalo nic (takže např. zbraň i světlo se v jednom snímku oba posunou o 10 metrů doprava, v dalším snímku oba o 11 metrů doprava... což na vztahy mezi nimi nemá žádný vliv).
Při fixed function to tuším funguje tak, že v místě, kde voláš glLight, se ta pozice transformuje podle aktuální matice a pak je po celou dobu počítáno s touto transformovanou pozicí, zbraň se pak transformuje jinak. Pokud chceš napodobit toto chování, nejlépe si vypočítej pozici světla ve view space (jednou za celý snímek) a tuto pak používej pro všechny objekty (samozřejmě bez žádné transformace, už je transformovaná).
EDIT:
Jenom aby to někoho nemátlo při čtení dalších odpovědí... já tady pracuju s představou, že ta zbraň "lítá po světě" spolu s hráčem (mění se model/world matice) a pak transformuje view maticí stejně jako "normální" objekty ve světě.
Naposledy upravil igor dne 15. květen 2011, 22:00:50, celkově upraveno 2 krát |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 15. květen 2011, 21:13:57 Předmět: |
|
|
NormalMatrix je invertovaná + transponovaná 3x3 modelview. Kdyby byla jen invertovaná, moc by to nefungovalo. Je to jenom kvůli scale, kde scale x!=y nebo y!=z nebo x!=z. Pokud scale nepoužíváš nebo máš scale x=y=z, můžeš použít rovnou 3x3 z modelview, je to jedno. Je ale třeba rozumět, na co NormalMatrix je a ne to bezhlavě používat. (to pak vede jenom k tomu, že to nefunguje)
No a teď pár rad.
Základem je vysrat se na ModelView matici a rozdělit si to na Model*View. Jedno je model, druhý je kamera, samozřejmě. Někdy se Model matice (nebo taky Object matice) označuje jako World proto, že to transformuje z Object do World, tj. World je cílový prostor. View matice se zase tak jmenuje proto, že transformuje z World do View.
Takže máme matice World a View, jejichž součin dává ModelView, ten ale používat nebudem, pokud to nebude potřeba.
Princip je následující:
Všechny matice a parametry světla mít jako uniform proměnné. Nepoužívat zabudované gl_ShittyVariables, to je pro děcka. Stejně to jenom omezuje. Vertexy jsou vždy v object space, samozřejmě. Světlo bude ve world-space, protože nechceme, aby se hýbalo. Kdybychom světlo zadali ve view-space, tak se nám bude hýbat s kamerou, což nechceme. Když ho zadáme v object-space, tak se bude hýbat s objektem. Takže máme tohle (označení je prostorNázev):
kód: |
uniform mat4 world, view, projection;
uniform vec3 worldLightPos;
attribute vec3 objectVertex;
attribute vec3 objectNormal;
|
Teď si můžeme vybrat, v kterém prostoru počítat osvětlení. Pak ale musíme převést všechny proměnné do cílového prostoru, jinak to nebude fungovat. Nejdřív nastavíme pozici (ledacos by šlo předpočítat, ale to teď neřešme, jde o princip):
kód: |
gl_Position = projection * (view * (world * vec4(objectVertex, 1))); |
V object-space by se osvětlení počítalo takhle:
kód: |
vec3 objectLightPos = (inverse(world) * vec4(worldLightPos, 1)).xyz;
vec3 objectLightVec = normalize(objectLightPos - objectVertex);
float outputColor = dot(objectLightVec, objectNormal); |
Ve world-space by se osvětlení počítalo takhle:
kód: |
vec3 worldVertex = (world * vec4(objectVertex, 1)).xyz;
vec3 worldNormal = mat3(world) * objectNormal;
vec3 worldLightVec = normalize(worldLightPos - worldVertex);
float outputColor = dot(worldLightVec, worldNormal);
// Pokud je ve world matici neuniformní scale, tak:
// vec3 worldNormal = transpose(inverse(mat3(world))) * objectNormal; |
No a nakonec ve view-space by se to počítalo takhle:
kód: |
vec3 viewVertex = (view * (world * vec4(objectVertex, 1))).xyz;
vec3 viewNormal = mat3(view) * (mat3(world) * objectNormal);
vec3 viewLightPos = (view * vec4(worldLightPos, 1)).xyz;
vec3 viewLightVec = normalize(viewLightPos - viewVertex);
float outputColor = dot(viewLightVec, viewNormal);
// Opět, pokud je v matici scale, musíme udělat transpose(inverse(... u normály.
|
outputColor u všech třech řešení musí dát stejnou hodnotu, proto vždycky počítáme v tom prostoru, kde těch výpočtů je nejméně. Tzn. tady bude lepší zvolit object-space a inverse(world) předpočítat na CPU, stejně tak projection*view*world pro pozici. Navíc vůbec nemusíme řešit scale (tzn. NormalMatrix nepotřebujem).
Tohle musíš mít zažité v krvi, jinak nemá smysl pokračovat. Na tomto ta 3D grafika celá stojí. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 15. květen 2011, 21:21:53 Předmět: |
|
|
U té zbraně je to snadný. Zbraň je fixovaná na kameru, takže její view matice je identita. To zohledníš při počítání gl_Position.
Při počítání světla si převedeš pozici světla do view-space:
kód: |
vec3 viewLightPos = (view * vec4(worldLightPos, 1)).xyz; |
A pak si ji převedeš do object-space té zbraně:
kód: |
vec3 objectLightPos = (inverse(world) * vec4(viewLightPos, 1)).xyz; |
A počítáš osvětlení v object-space. Easy. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
|