.[ ČeskéHry.cz ].
Transformace světla v pozadí glLightfv

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> 3D API / 3D Enginy
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

PříspěvekZaslal: 15. květen 2011, 18:04:09    Předmět: Transformace světla v pozadí glLightfv Odpovědět s citátem

Nazdar, už si připadám jako dement, že zakládám další topic ... ale prostě není karma Mad

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Vilem Otte



Založen: 18. 09. 2007
Příspěvky: 462
Bydliště: Znojmo - Sedlesovice, Kravi Hora

PříspěvekZaslal: 15. květen 2011, 18:40:45    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovi WWW stránky
igor



Založen: 28. 07. 2007
Příspěvky: 196

PříspěvekZaslal: 15. květen 2011, 20:07:33    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Marek



Založen: 28. 07. 2007
Příspěvky: 1782
Bydliště: Velká Morava

PříspěvekZaslal: 15. květen 2011, 21:13:57    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Marek



Založen: 28. 07. 2007
Příspěvky: 1782
Bydliště: Velká Morava

PříspěvekZaslal: 15. květen 2011, 21:21:53    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> 3D API / 3D Enginy Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna