Fények
1. Folytassuk ezt a félkész projektetet!
2. A program három melőleges négyzetet razjol ki megvilágítás nélkül.
Bővítsük a progamot, hogy legyen benne megvilágítás!
3. Vegyük ki a megvilágítás kikapcsolását az onResetDevice-ból!
_device->SetRenderState(D3DRS_LIGHTING, FALSE);
4. Adjunk hozzá egy új metódust az osztályunkhoz setLights néven!
void Lights::setLights() { //** Biztonsag kedveert _device->SetRenderState( D3DRS_LIGHTING, TRUE); //** Legyen csillanas? //_device->SetRenderState( D3DRS_SPECULARENABLE, TRUE); //** Ambient feny: ahol nem eri direkt feny az objektumokat ott is hat _device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(20, 20, 20)); //--- //** Irany fenyforras: parhuzamos sugarakban eri a fenye a szinteret D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); //** Tipusa light.Type = D3DLIGHT_DIRECTIONAL; //** Szine light.Diffuse = D3DXCOLOR(1, 0, 0, 1); light.Specular = D3DXCOLOR(1, 0, 0, 1); light.Range = 1000.0f; //** Iranya D3DXVECTOR3 vecDir = D3DXVECTOR3(-1, -2, 3); D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); //** Adjuk at a device-nak es engedelyezzuk a feny forrast _device->SetLight( 0, &light ); _device->LightEnable( 0, FALSE ); //--- //** Pont fenyforras D3DLIGHT9 light2; ZeroMemory( &light2, sizeof(D3DLIGHT9) ); light2.Type = D3DLIGHT_POINT; light2.Diffuse = D3DXCOLOR(0, 1, 0, 1); light2.Specular = D3DXCOLOR(0, 1, 0, 1); //** Nem iranya van, hanem pozicioja light2.Position = D3DXVECTOR3(-0.25f,0.5f,-0.25f); light2.Attenuation0 = 0.1f; light2.Attenuation1 = 3.0f; light2.Range = 2.0f; _device->SetLight( 1, &light2 ); _device->LightEnable( 1, FALSE ); //--- //** Spot lampa D3DLIGHT9 light3; ZeroMemory( &light3, sizeof(D3DLIGHT9) ); light3.Type = D3DLIGHT_SPOT; light3.Diffuse = D3DXCOLOR(0, 0, 1, 1); light3.Specular = D3DXCOLOR(0, 0, 1, 1); //** iranya es pozicioja is van light3.Position = D3DXVECTOR3(-0.5f,0.5f,-0.5f); D3DXVECTOR3 vecDir2 = D3DXVECTOR3(0.75f, -1, 0.75f); D3DXVec3Normalize( (D3DXVECTOR3*)&light3.Direction, &vecDir2 ); //** egyeb parameterek light3.Range = 200.0f; light3.Theta = 0.5f; light3.Phi = 1.0f; light3.Falloff = 1.0f; light3.Attenuation0 = 0.1f; _device->SetLight( 2, &light3 ); _device->LightEnable( 2, FALSE ); //--------------------------------------------------------------- //** Adjunk meg anyagot D3DMATERIAL9 material; ZeroMemory( &material, sizeof(D3DMATERIAL9) ); material.Diffuse = D3DXCOLOR(1, 1, 1, 1); material.Ambient = D3DXCOLOR(1, 1, 1, 1); material.Specular = D3DXCOLOR(1, 1, 1, 1); material.Power = 50; _device->SetMaterial( &material ); }
Az IDirect3DDevice9::SetRenderState -ben a D3DRS_LIGHTING beállítással engedélyezzük a megvilágítást.
A D3DRS_SPECULARENABLE a felületekek csillanását kapcsolja be vagy éppen ki.
A D3DRS_AMBIENT a mindenhol érvényesülő alapfény színét állítja.
Egy fényforrás létrehozásának lépései:
1. Egy D3DLIGHT9 adatszerkezetet kitöltése.
1a. Ezt először érdemes teljesen nullázni, pl. a ZeroMemory függvénnyel.
1b. A D3DLIGHT9 legfontosabb tagja a Type, ami a fényforrás típusát határozza meg. Ez alapján a fényforrás lehet írány fényforrás (D3DLIGHT_DIRECTIONAL), pont fényforrás (D3DLIGHT_POINT) vagy spot lámpaszerű fényforrás (D3DLIGHT_SPOT). Minden fényforrásnak három különböző szine van. Ezek a csillanási (Specular), szórt (Diffuse) és az ambiens szín (Ambient).
Az tulajdonságok részletes leírása megtalálható a DirectX SDK-ban, a megvilágítás pontos matematikai modelljével együtt.
2. A kitöltött adatszerkezetet át kell adni a device-nak a IDirect3DDevice9::SetLight metódus segítségével. Ennek első paramétere a fényforrás sorszáma, második pedig a kitöltött adatszerkezetre mutató pointer.
Bár sok fényforrás megadható, egyszerre csak kevéslehet aktív. A konrét szám a használt videókártyától függ, de még "jobb" kártyákon se több, mint nyolc.
3. Egy fényforrás aktiválható (vagy deaktiválható) az IDirect3DDevice9::LightEnable metódussal.
Egy felület színét a felületet érő fény és a felület anyaga együttesen adja. A felület anyagát (gyak. színét) a D3DMATERIAL9 szerkezetben lehet megadni, és a device-nak a IDirect3DDevice9::SetMaterial hívással lehet átadni.
4. Ezt a setLights-ot hívjuk meg az onResetDevice-ban!
5. A setLights-ban létrehozott fények mind ki vannak kapcsolva. Írjuk meg, hogy a 1,2,3-as gombokkal külön-külön ki-be lehessen kapcsolni őket!
6. Adjuk hozzá az osztályhoz, és inicalizáljuk:
bool lights[3];
Konstruktorban:
lights[0] = lights[1] = lights[2] = false;
7. Bővítsük a billenytyűzet kezelőt:
void Lights::keyboardProc( UINT nChar, bool bKeyDown, bool bAltDown ) { static bool pressed = false; if (bKeyDown && !pressed) { int lidx = nChar-'1'; switch (nChar) { case '1': case '2': case '3': lights[lidx] = !lights[lidx]; _device->LightEnable( lidx, lights[lidx] ); break; case 'W': wireframe = !wireframe; if (wireframe) _device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); else _device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); break; } } pressed = bKeyDown; }