GrafikaGyakorloOpenGL Cg

A VIK Wikiből
A lap korábbi változatát látod, amilyen (vitalap) 2012. október 21., 21:58-kor történt szerkesztése után volt. (Új oldal, tartalma: „{{GlobalTemplate|Infoalap|GrafikaGyakorloOpenGL_Cg}} ===Mintakérdések a Számítógépes grafika és képfeldolgozás tárgy vizsgájára való felkészüléshez ===…”)
(eltér) ← Régebbi változat | Aktuális változat (eltér) | Újabb változat→ (eltér)
Ugrás a navigációhoz Ugrás a kereséshez

Ez az oldal a korábbi SCH wiki-ről lett áthozva. Az eredeti változata itt érhető el.

Ha úgy érzed, hogy bármilyen formázási vagy tartalmi probléma van vele, akkor kérlek javíts rajta egy rövid szerkesztéssel.

Ha nem tudod, hogyan indulj el, olvasd el a migrálási útmutatót


Mintakérdések a Számítógépes grafika és képfeldolgozás tárgy vizsgájára való felkészüléshez

OpenGL, Cg nyelv

75. Egy Catmull-Clark subdivision görbe négy kontrolja: (0,0), (1,0), (1,1), (2,1). Írjon C++/OpenGL függvényt, amely a görbét 1 felosztás után felrajzolja! (Segítség: a Catmull-Clark súlyértékei: 0.5, 0.25, 0.5). Az ablak megnyitásával és a transzformációk beállításával nem kell foglalkozni.

  • A Catmull-Clark módszer görbék és felületek simítására való: kiindulunk egy töröttvonalból, és új csúcsokat veszünk fel, a meglévőket pedig módosítjuk, hogy az eredmény hasonló legyen az eredetihez, csak simább. A módszer felületekre is általánosítható. A konkrét lépések: kiindulunk a [math] r_0,\; r_1,\; ...,\; r_n [/math] pontokból; minden él felezőpontjára felveszünk egy új pontot ([math] h_i=0.5r_i+0.5r_{i+1} [/math]), majd az eredeti pontokat (a végpontok kivételével) áthelyezzük: [math] r_i^\prime=0.5r_i+0.25h_{i-1}+0.25h_i [/math].
  • Itt a konkrét pontok, amik a felosztás után kijönnek: (0, 0), (0.5, 0), (1.125, 0.125), (1, 0.5), (1.125, 0.875), (1.5, 1), (2, 1). Egy olyan program, ami képes tetszőleges szintű felosztást megcsinálni, és azt kirajzolni:
void draw(Array<Vector> points, unsigned int level) {
  Array<Vector> temp;
  for ( ; level>0; level--) {
	 for (int i=0; i<points.size()-1; i++) {
		temp[2*i+1]=points[i]*0.5+points[i+1]*0.5;
	 }
	 temp[0]=points[0];
	 temp[points.size()*2-2]=points[points.size()-1];
	 for (int i=1; i<points.size()-1; i++) {
		temp[2*i]=points[i]*0.5+temp[2*i-1]*0.25+temp[2*i+1]*0.25;
	 }
	 points=temp;
  }
  glBegin(GL_LINE_STRIP);
  for (int i=0; i<points.size(); i++) {
	 glVertex3f(points[i].x, points[i].y, points[i].z);
  }
  glEnd();
}

Javítás: A pontok pontosan ezek: (0, 0), (0.5, 0), (*0.875*, 0.125), (1, 0.5), (1.125, 0.875), (1.5, 1), (2, 1). Ha felrajzolod koordináta-rendszerben látszik is, hogy így lesz közelítve a vonal. -- Brad - 2011.06.13.

76. A színtér két háromszögből áll, az egyik nem átlátszó, a másik átlátszósága 50%-os. Hogyan lehet megjeleníteni a színteret OpenGL-lel?

Megoldás:
  • Az OpenGL nem képes arra, hogy általánosan kezelje az átlátszóságot, vagyis hogy tetszőleges sorrendben megadott, tetszőleges átlátszósággal rendelkező dolgokat kirajzoljon. Bizonyos megkötésekkel viszont használható erre a célra a blending.
  • Blending nélkül egy primitív rajzolása úgy néz ki, hogy raszterizálás után minden pixelét beírja a framebufferbe, felülírva, ami ott volt. (Ha a mélységteszt be van kapcsolva, akkor lehet, hogy az eredeti pixelt hagyja meg.) Bekapcsolt blending mellett viszont a beérkező (source) és a már ottlévő (destination) pixelnek egy lineáris kombinációját számítja ki, és az lesz az új érték. Azt, hogy milyen tényezőkkel végzi a lineáris kombinációt, a glBlendFunc() állítja be. Használható pl. a source alpha értéke, egy mínusz a source alphája, konstans 1 vagy 0, stb.
  • A konkrét esetben célszerű a source "súlyát" a saját alphájára, míg a destination-ét egy mínusz a source alphájára állítani. Így, először kirajzolva (1-es alphával) az átlátszatlan háromszöget, az teljesen felülírja a hátteret, majd erre 0.5-ös alphával rárajzoljuk az áttetszőt, a mélységtesztet pedig bekapcsoljuk. A közös részükön, ahol az áttetsző van előrébb, fele-fele arányban lesz kombinálva a színük, ahol pedig az átlátszatlan, ott a mélységteszt miatt marad az első háromszög színe. Egy lehetséges megvalósítás:
void init() {
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void draw() {
  glBegin(GL_TRIANGLES);
  glColor4f(0, 1, 0, 1);
  glVertex3f(-1, 1, 0.9);
  glVertex3f(-1, -1, 0.9);
  glVertex3f(1, 0, 0.1);
  glColor4f(0, 0, 1, 0.5);
  glVertex3f(1, -1, 0.9);
  glVertex3f(1, 1, 0.9);
  glVertex3f(-1, 0, 0.1);
  glEnd();
}
Javítás:

Szerintem a mélység-teszt nem teljesen így van : ha be van kapcsolva, akkor az újonnan számított adatok akkor írják át a régieket, ha az újak a régebbi előtt vannak (közelebb a kamerához, kisebb mélység értékkel). Ha kikapcsolod, akkor meg mindenképpen felülírják a régit, akár előtte, akár mögötte vannak. Amire figyelni kell inkább az az, hogy a blendeléskor nem egyszerűen felülírjuk az odáig a frame-bufferben lévő értéket, hanem ahogy írtad a régi és az új érték valamilyen függvénye szerint jön ki az, amit beírunk : tehát fontos, hogy már bent legyen az eredeti érték, amit felülírunk. Összegezve : a térbeli helyességért bekapcsolnám a mélység-tesztet, de a blendelt dolgokat (λ < 1) rajzolnám a legvégén. (Érdekesség : a blendelésnél a depth-bufferbe beírt mélység érték is blendelődik, így több blendelt objektum egymás felett megint csak gondot jelent.. akit érdekel, nézzen utána.) -- k317h - 2009.06.07.

77. Mi a billboard?

  • Bizonyos objektumoknak elég bonyolult struktúrája van, ezért csak nagyon nehezen leírhatók hagyományos eszközökkel. Némelyiknek viszont megvan az a tulajdonsága, hogy minden irányból hasonlóan néz ki: pl. világító köddel körülvett lövedékek, robbanás részecskéi, fák. Az ilyenek megjelenítésére egy módszer a billboarding: az objektum helyén egy téglalapot jelenítünk meg, amit a kamera felé fordítunk, és erre feltextúrázzuk az objektum (előre kiszámított, megrajzolt) kinézetét. Általában a textúrának egy része átlátszó kell legyen (mert az objektum nem látszik minden irányból téglalap alakúnak.

78. Mit csinál a fragmens árnyaló (fragment shader) modulatív textúrázás esetén, mi a bemenete és a kimenete?

  • A fragment shader feladata egy pixel (fragmens) színének számítása, a pixel helyének, színének, textúrakoodinátáinak és esetleg egyéb paramétereinek (pl. Phong árnyalást megvalósító shader esetén az interpolált normáljának) ismeretében.
  • Modulatív textúrázásnál először kiszámolódik a pixel textúrázatlan színe a vertexszínek interpolálásával, valamint a textúrakoordináták szintén interpolációval, és ezeket kapja meg a fragment shader. A kapott színt összeszorozza (modulálja) a textúra megfelelő pixelének színével, és ez lesz a kimenete (a pixel színe a képernyőn).

79. Mit csinál (milyen programot hajt végre) az OpenGL beépített pixel (fragment) árnyalója (shader) a következő OpenGL hívások esetén:

glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( ); gluPerspective(fov, (double)width/height, front, back);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( ); gluLookAt(eyex, eyey, eyez, vrpx, vrpy, vrpz, vupx, vupy, vupz);
glBegin(GL_TRIANGLES);
glTexCoord2f(u1, v1); glVertex4f(x1, y1, z1, w1);
glTexCoord2f(u2, v2); glVertex4f(x2, y2, z2, w2);
glTexCoord2f(u3, v3); glVertex4f(x3, y3, z3, w3);
glEnd();
  • A legtöbb utasításnak nincs hatása a fragment shaderre. A második sor bekapcsolja a textúrázást a pixelek árnyalásakor, a harmadik modulatív textúrázást állít be (a textúra megfelelő pixelének színét szorozza a pixel interpolált színével). A glTexParameteri hívások azt állítják be, hogy ha kicsinyíteni (...MIN_FILTER) illetve nagyítani (...MAX_FILTER) kellene a textúrát a képernyőre rajzoláshoz, akkor mi történjen: a textúrának a legközelebbi pixelét használja (GL_NEAREST) vagy lineárisan interpolálja a 4 legközelebbit (GL_LINEAR). Ez utóbbit nem tudom, hogy a fragment shader végzi-e, szerintem inkább a textúrakoodináták generálásánál, illetve a fragment shader által hívott, textúrakoordináták alapján színt generáló függvényben történik.

78. Milyen algoritmust valósít meg az alábbi program? Alakítsa át úgy, hogy Phong árnyalással dolgozzon (vigyázat, nem a Phong BRDF-ről van szó).

Vertex shader:
struct inputs {	
	float4 position  : POSITION;
	float3 normal	 : NORMAL;
	float2 texcoord  : TEXCOORD0;
};

struct outputs {
	float4 hposition : POSITION;
	float4 color	  : COLOR0;  
	float2 texcoord  : TEXCOORD0;
};

outputs main( inputs IN, 
uniform float4x4 modelviewIT,	// modelview matrix inverz-transzponáltja
uniform float4x4 modelviewproj, // modelview és projekciós mátrix szorzata
uniform float3 lightdir,		  // fény iránya
uniform float4 I,					// fény intenzitása
uniform float4 kd ) {			  // diffúz visszaverődési tényező
	outputs OUT;
	OUT.hposition = mul(modelviewproj, IN.position);
	float3 N = normalize( mul(modelviewIT, IN.normal).xyz );
	float costheta = dot(N, normalize(lightdir)); 
	if (costheta < 0) costheta = 0;
	OUT.color = I * kd * costheta;
	return OUT;
}

Fragment shader:
float4 main( in float4 color : COLOR0 ) : COLOR { return color; }

Megoldás

  • A program diffúz visszaverődéssel jeleníti meg a felületeket, mert a megvilágítás a nézeti iránytól nem függ, a fényforrás szögének koszinuszával pedig fordítottan arányos, és Gouraud árnyalással dolgozik, ugyanis a vertexek színét a raszterizáció során az OpenGL lineárisan interpolálja. Textúrákat nem jelenít meg (a vertex shader már nem is adja át a textúrakoordinátákat), és egyetlen irányfényforrással dolgozik.
  • A Phong árnyaláshoz az kellene, hogy a csúcsoknak ne a színe, hanem a normálja legyen interpolálva. Az OpenGL ilyet alapból nem tud, viszont a vertex és a fragment shader közt nem csak színeket, hanem (akár háromdimenziós) textúrakoordinátákat is interpoláltathatunk vele. Az OpenGL-nek viszont teljesen mindegy, hogy a textúrakoordináta regiszter valójában milyen adatot tartalmaz, azt a fragment shader dönti el, hogy textúra egy pixelét keresi ki vele, vagy másra használja. Így ebben átadhatjuk a normált, és ekkor a tényleges fény- és színszámítás átkerül a fragmens árnyalóba.
Vertex shader:
struct inputs {	
	float4 position  : POSITION;
	float3 normal	 : NORMAL;
	float2 texcoord  : TEXCOORD0;
};

struct outputs {
	float4 hposition : POSITION;
	float4 color	  : COLOR0;
	float2 texcoord  : TEXCOORD0;
	float3 normal	 : TEXCOORD1;
};

outputs main(
inputs IN,
uniform float4x4 modelviewIT,	// modelview matrix inverz-transzponáltja
uniform float4x4 modelviewproj, // modelview és projekciós mátrix szorzata
) {
	outputs OUT;
	OUT.hposition = mul(modelviewproj, IN.position);
	OUT.normal = normalize( mul(modelviewIT, IN.normal).xyz );
	return OUT;
}

Fragment shader:
float4 main(
in float3 normal	: TEXCOORD1;
uniform float4 lightdir,
uniform float4 I,					// fény intenzitása
uniform float4 kd					// diffúz visszaverődési tényező
) : COLOR {
	float costheta = dot(normal, normalize(lightdir));
	if (costheta < 0) costheta = 0;
	float4 color = Idiff * kd * costheta;
	return color;
}


Javítás

Csak néhány megjegyzés a pontosság kedvéért: Idiff : fény színe, kd : anyag színe, costheta : a felület (egységnyi hosszú) normálvektora és a fényforrás fele mutató (egység)vektor által bezárt szög koszinusza diffúz szín tehát costheta-tól egyenesen arányosan függ (és persze costheta >= 0). Gouraud-árnyalás : a csúcspontokban számoljuk ki teljesen a színeket, és azokat a közbülső pixelekben interpoláljuk. Phong-árnyalás : a csúcspontokban csak a szín számításához szükséges adatokat számoljuk ki (normál vektor, fény irányába mutató vektor, nézeti irányba mutató vektor, ...) és ezeket interpoláljuk a közbülső pixelekben, majd pixelenként külön számítjuk ki a színeket.

Kis hiba a shaderben : a csatornák 0 és 1 közötti floatokat juttatnak át, egyébként vágnak. Ezért a mi -1 és 1 közé eső (egység hosszú) vektorainkat betömörítjük 0 és 1 közé a vertex shaderben, majd kitömörítjük pixel shaderben :

Vertex shader:

float3 normal = normalize( mul(modelviewIT, IN.normal).xyz );
OUT.normal = normal * 0.5 + 0.5;

Feltétlenül normalizálni kell a bejövő normalt, mert a lineáris interpoláció elrontja az egység hosszúságot:

Pixel shader:

float3 N = normalize(normal * 2 - 1);
float costheta = dot(N, normalize(lightdir));

-- k317h - 2009.06.07.


95. Miért használ float4 adatformátumot az OpenGL egy pont leírására?

  • Mert 3D homogén (projektív) koordinátákkal dolgozik.

96. Írjon OpenGL programot, amely a földgömböt rajzol fel, mégpedig úgy, hogy az egyes pontok vörös komponense a hosszúsági, a kék komponense pedig a szélességi körrel legyen arányos.

Megoldás

Ha ezt OpenGL-ből kell shaderek nélkül.. Megoldás menete : tesszellálunk egy (egység sugarú) gömböt u paraméter a szélességi, v paraméter a hosszúsági kör, színnek az u és v paramétert szorítjuk be 0 és 1 közé.

int uTess;	  // u paraméter mentén ennyinként osztjuk fel (tesszelláljuk) a gömböt
int vTess;	  // v paraméter mentén ennyinként osztjuk fel (tesszelláljuk) a gömböt
#define PI 3.1416
void drawLameSphere() {
	 int i, j;

	 glBegin(GL_QUADS);
	 for (i = 0; i < uTess - 1; i++) {
		  float _u = (float)i / (float)uTess;				// u paraméter 0 és 1 között;
		  float u = _u * 2 * PI;
		  float _u1 = (float)(i + 1) / (float)uTess;	  // u paraméter az eggyel későbbi pontban, 0 és 1 között;
		  float u1 = _u1 * 2 * PI;
		  for (j = 0; j < vTess - 1; j++) {
				float _v = (float)j / (float)vTess;		  // v paraméter 0 és 1 között;
				float v = _v * PI;
				float _v1 = (float)(j + 1) / (float)vTess; // v paraméter az eggyel későbbi pontban, 0 és 1 között;
				float v1 = _v1 * PI;
				glColor3f(_u, 0, _v);
				glVertex3f(sin(u) * cos(v), cos(u), sin(u) * sin(v));
				glColor3f(_u1, 0, _v);
				glVertex3f(sin(u1) * cos(v), cos(u1), sin(u1) * sin(v));
				glColor3f(_u1, 0, _v1);
				glVertex3f(sin(u1) * cos(v1), cos(u1), sin(u1) * sin(v1));
				glColor3f(_u, 0, _v1);
				glVertex3f(sin(u) * cos(v1), cos(u), sin(u) * sin(v1));
		  }
	 }
	 glEnd();
}

-- k317h - 2009.06.07.

97. Rajzolja fel az OpenGL megjelenítési csővezetékét. Milyen operációkat hajt végre az OpenGL az egyes pontokon? Mikor van szükség a mátrix vermekre?

Megoldás

Az eleje a könyvben bennevan. Akkor van szükség mátrix vermekre, ha több dolgot rajzolunk amik ugye máshol, más szögben vannak. Ezekre ugyanis más-más transzformáció vonatkozik. Úgy dolgozunk általánosan, hogy a kamera-trafó, ami mindenkire igaz bent van a mátrixban, és minden objektumra hozzászorozzuk a saját trafóját, kirajzoljuk, majd visszaváltunk csak a kamera-trafóra. (Objektumon belül is megtehetjük, hogy az egész objektumra vonatkozó trafókat beállítjuk, majd a külön részekre vonatkozó trafót hozzászorozzuk, kirajzoljuk a részt, és eldobjuk a részhez szükséges mátrixot.) Ezen mátrixok egymás fölött egy stack-ben helyezkednek el, ezt kezelni így lehet :

//init-ben beállítottuk már a mátrixokat
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
objektumTransform();
objektumDraw();
// ide ékelődhet be a részobjektum-rajzolás hasonló módon
glPopMatrix();

A csővezetékben amikor (az elején) érvényre juttatjuk a model-nézeti (és projekciós) mátrixo(ka)t, akkor szorzódnak össze a stackben lévő elemek. -- k317h - 2009.06.07.

98. A grafikus kártya a modell-view és projektív transzformáció, vágás, homogén osztás és képernyő-transzformáció után egy (x1, y1, z1), (x2, y2, z2), (x3, y3, z3) csúcsú háromszög xy vetületét kitölti, és az egyes pixeleket a z koordinátájukkal a z-buffernek továbbítja a takarási feladat megoldásának érdekében. Mennyivel növeli meg a hardver a z értékét két, ugyanabban a pásztában lévő (közös y koordinátájú), szomszédos (x és x+1 koordinátájú) pixel között?

  • Egy síkon mozgunk, tehát z előállítható Ax+By+C alakban. A, B, C konstansokról tudjuk, hogy kielégítik a következő egyenletrendszert: [math] Ax_1+By_1+C=z_1,\; Ax_2+By_2+C=z_2,\; Ax_3+By_3+C=z_3 [/math] Ez alapján az elsőfokú egyenletrendszer megoldására a determinánsos szabályt alkalmazva, kifejezhetjük A értékét: [math] A=(z_1(y_2-y_3)+z_2(y_3-y_1)+z_3(y_1-y_2))/(x_1(y_2-y_3)+x_2(y_3-y_1)+x_3(y_1-y_2)) [/math] Mivel x növelése és y változatlanul hagyása mellett z pont A-val nő, ezért ennyi lesz a z növekménye.

99. Írja le, hogy mi történik a csúcspont árnyaló (vertex shader) kimenete és a pixel árnyaló (fragment shader) bemenete között egy GL_TRIANGLES primitív feldolgozása során! A leírásnak olyan részletesnek kell lennie, hogy egy koordinátageometriában jártas programozó implementálni tudja az egyes lépéseket.

100. Adott egy háromszög képernyő koordinátarendszerben a következő csúcsokkal: (0,0,0), (10, 0, 10), (8, 10, 4). Mekkora azon két pont z koordinátáinak különbsége, amelyek az (5,5) illetve a (6,5) pixelen keresztül látszanak?

101. Mit csinál a csúcspont árnyaló a következő beállítások hatására? A választ egy C++ függvénnyel adja meg, amelyben feltételezheti, hogy már létezik egy float3 háromelemű és float4 4 elemű vektor, valamint float4x4 mátrix típus a szokásos műveletekkel. Egy float4 típusú p adatot p.xyz művelettel alakíthat float3-ra.

static float kd[4]={kdr, kdg, kdb, kda}, ks[4] = {kdr, kdg, kdb, kda};
glMaterialfv( GL_FRONT, GL_DIFFUSE, kd );
glMaterialfv( GL_FRONT, GL_SPECULAR, ks );
glMaterialf( GL_FRONT, GL_SHININESS, n);

static float I[4]={Ir, Ig, Ib, Ia}, zero[4] = {0, 0, 0, 0};
glLightfv( GL_LIGHT0, GL_DIFFUSE,  I );
glLightfv( GL_LIGHT0, GL_SPECULAR, zero );
glLightfv( GL_LIGHT0, GL_AMBIENT, zero );

static float lightpos[4] = {lpx,lpy,lpz,0}; // Vigyázat a 4. koordináta zérus!!!
glLightfv( GL_LIGHT0, GL_POSITION, lightpos );
glEnable( GL_LIGHT0 );
glEnable( GL_LIGHTING );

glDisable(GL_NORMALIZE);
glEnable(GL_DEPTH_TEST);

float P[4][4], Q[4][4];
ComputeTranforms(P, Q);
glViewport(0, 0, windowWidth, windowHeight);  
glMatrixMode(GL_PROJECTION);	
glLoadIdentity();  
glMultMatrixf(P);
glMatrixMode(GL_MODELVIEW);
glMultMatrixf(Q);

glNormal3f( 0, 0, 1 );
glBegin( GL_POINTS );
glVertex3f( x1, y1, z1 );
glEnd( );

102. Síklapra vetített és árnyék térkép (depth mapped shadows) árnyék számító algoritmusok.

  • A síklapokra vetülő árnyékok számítása a legegyszerűbb: minden háromszög a fényforrás és a sík között egy háromszög alakú árnyékot fog vetni, aminek csúcsai a háromszög csúcspontjainak síkra vett vetületei lesznek.
  • Az árnyék térkép algoritmusnál először renderelünk egy képet a fényforrás szemszögéből (irányfényforrásnál ortografikus vetítéssel, pontfényforrásnál perspektivikusan). Ezt a képet nem jelenítünk meg, viszont kiolvassuk a z-buffer tartalmát. Megjelenítéskor minden csúcspontot áttranszformálunk az előző rendereléshez használ koordinátarendszerbe, és a mélységértéke alapján döntjük el, hogy árnyékban van-e.
  • Wikipédia: árnyék térkép

103. Beugrató kérdés: a glEnable(GL_SHADOW) melyik algoritmust kapcsolja be?

  • Az OpenGL nem ismer semmilyen árnyékszámító algoritmust, és nincs olyan konstans, hogy GL_SHADOW.

104. Készítsen OpenGL autót! Az autó karosszériája téglatest alakú, hosszúsága 4, szélessége 2, magassága 1 m. Az autónak négy kereke van, amelyek henger alakúak, szélességük 0.5 m, átmérőjük 1 m. A kerek tengelye az autó aljához van rögzítve, az autó elejétől illetve a végétől 1-1 méterre. Az autó az x-y síkon az x tengely irányába 1m/s sebességgel halad, t=0-ban az origóból indul. A kerekek a talajon gördülnek. Írjon egy C nyelvű Render(float t) kirajzoló függvényt, amely t időpontban felrajzolja az autót. Feltételezheti, hogy készen áll egy Kocka függvény, amely egységoldalú, origó középpontú, koordinátatengelyekkel párhuzamos élű kockát rajzol ki, valamint egy Henger függvény, amely egység sugarú és magasságú, origóban álló hengert rajzol ki (a körlap az x-y síkon van). Az ajánlott OpenGL függvények: glScalef, glRotatef, glTranslatef, glPushMatrix, glPopMatrix.

105. Készítsen OpenGL tengert! A tenger egy 100x100 m-es téglalap, amelynek közepén egy kis (pontszerű) hajó 1 méter magasságú, 1/sec frekvenciájú hullámokat kelt. A hullámok 2 m/s sebességgel haladnak a tenger széle felé. A hullámzás amplitúdója a forrástól vett távolság négyzetével csökken. A tenger képe felülnézetből a hullámok ellenére állandó. Ezt a képet az id azonosítójú OpenGL textúra tartalmazza. Írjon egy C nyelvű Render(float t) kirajzoló függvényt, amely t időpontban felrajzolja a tengert! Feltételezheti, hogy a kamera már megfelelően be van állítva. A tenger felületét 2 millió háromszögre tesszellálja fel! Az ajánlott OpenGL függvények: glBindTexture, glBegin, glEnd, glutSwapBuffers, glVertex3f, glTexCoord2f.

106. Segítsen a GLU rendszer elkészítésében, és írja meg a gluPerspective függvény egy egyszerűsített változatát. A függvénynek egy xy síkkal párhuzamos alapú csonka gúlát kell leképeznie az origó középpontú 2 egység oldalú kockába (figyelem, a z irányban is 2 egységnyi a céltartomány, lásd a lenti ábra). A csonka gúla levágott csúcsa az origóban van, az alapja az origótól bp, a teteje fp távolságra található. A csonka gúla nyílásszöge mind x, mind pedig y irányban 90 fok.

Ezen a helyen volt linkelve a Clipboard03.png nevű kép a régi wiki ezen oldaláról. (Kérlek hozd át ezt a képet ide, különben idővel el fog tűnni a régi wikivel együtt)


107. Milyen transzformációt (melyik OpenGL transzformációt és milyen értékekkel) módosít a gluPerspective(fovy, aspect, front, back) GLU függvény. Segítség: fovy= field of view, nézeti szög az y irányban; aspect=aspect ratio, a magasság és szélesség aránya, width/height; front=első vágósík távolsága a szemtől; back=hátsó vágósík távolsága a szemtől.

108. Írja le részletesen, hogy mit csinál a grafikus kártya csúcspont árnyaló (vertex shader) és pixel árnyaló (pixel shader) egysége glEnable/glDisable(GL_TEXTURE_2D), glEnable/glDisable(GL_LIGHTING), glEnable/glDisable(GL_NORMALIZE) beállítások mellett, a következő utasítások hatására:

glBegin(GL_TRIANGLES);
 for(int i = 0; i < 3; i++) {
  glColor3f(r, g, b); glNormal3f(nx, ny,  nz); glTexCoord2f(u, v); glVertex(x, y, z);
 }
 glEnd( );

109. Melyik pixelt színezi át a következő program, és milyen színűre?

glViewport(0,0,200,200);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( );
gluLookAt(0,0,0, 3,4,0, 0,0,1); 
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glColor3f(1,2,3);
glBegin(GL_POINTS); glVertex3f(0.5,0.5,0.5);
glEnd( );

Segítség: gluLookAt(eyex,eyey,eyez, lookatx,lookaty,lookatz, upx,upy,upz);

110. Az alábbi ábrán a Maya kezelői felülete látható, amely a virtuális világot három ortografikus (merőlegesen vetített) és egy perspektív nézetben mutatja meg.


Ezen a helyen volt linkelve a Clipboard04.png nevű kép a régi wiki ezen oldaláról. (Kérlek hozd át ezt a képet ide, különben idővel el fog tűnni a régi wikivel együtt)


Az ábrán egy egységoldalú kocka látható. A Maya OpenGL-t használ a megjelenítéshez. Milyen MODELVIEW és PROJECTION transzformációt állított be a Maya a jobb alsó ablakban, ha a kocka képe 100x100 pixelt fed le, 400x200 felbontású nézet közepén? A koordinátarendszer közepe az ablak közepére kerül, a y tengely felfelé mutat, a z tengely balra, az x pedig befelé.

-- G - 2008.12.26.