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.

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;
}