komponenst állítjuk, ezáltal az anyag csak a terjedő fényt fogja visszaverni, tehát matt felületű lesz. A következő anyag sárga, erősen fényfolt visszaverő:
Mivel minden egyes komponens esetében a vörös és zöld értékei érvényesülnek, végeredményül egy sárga anyagot kapunk. A
Power érték kis kiterjedésű fényfoltot eredményez. A harmadik anyag ezüstös, csillogó anyagot, ezért a terjedő és fényfolt képző komponenseken van a hangsúly:
gWhiteMaterial = new Material()
{
// terjedő fényvisszaverődés beállítása
Diffuse = new Color4(1.0f, 0.3f, 0.3f, 0.3f),
// szórt fény visszaverődésének beállítása,
// ezüstös anyag, teljes mértékben visszaveri a környezet fényeit
Ambient = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
// sugárzó anyag
Emissive = new Color4(1.0f, 0.4f, 0.4f, 0.4f),
// fényfoltvisszaverődés
Specular = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
// kiterjedtebb fényfolt
Power = 15
}
A jobb hatás érdekében ezüstös anyagunk saját fénnyel is rendelkezik, amely fokozza a ragyogást, a
Power kisebb értéke pedig nagyobb fényfoltot eredményez. Természetesen a visszavert fényhez szükség van fényforrásra is. Ehhez létrehozunk egy direkcionális fényforrást, továbbá engedélyezzük a fényfolt képződést. Először is definiáljuk a fényforrás irányát, ami egy vektor lesz:
Vector3 dirVec =
new Vector3(2.0f, 2.0f, -5.0f);
Normalizáljuk az irányvektort: dirVec.Normalize();
Ezután a
Light struktúrát feltöltjük:
Light light = new Light()
{
Type = LightType.Directional,
Direction = dirVec,
Diffuse = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
Ambient = new Color4(1.0f, 0.1f, 0.1f, 0.1f),
Specular = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
};
Mivel egy direkcionális fényforrást szeretnénk létrehozni – itt az irány és a szín adott, azonban a forrás helyzete nem meghatározott –, ezért kizárólag csak a típusát, az irányát, a diffúz és a fényfolt képző adattagokat kell beállítani. Ahhoz, hogy fényfoltok képződjenek, engedélyezni kell azt a következő hívással:
device.SetRenderState(
RenderState.SpecularEnable,
true);
A fényfolt képzés elég számításigényes feladat, éppen ezért alapból nincs is engedélyezve. A fenti beállításokon kívül természetesen még be kell kapcsolni a megvilágítást valamint meg kell adni a kockák felületeinek normálvektorait is. Ehhez, most is definiálunk egy saját vertex formátumot, amely a vertex koordinátákon kívül tartalmazza a normálvektorokat is:
[StructLayout(LayoutKind.Sequential)]
struct Vertex
{
public Vector3 Position;
public Vector3 Normal;
public static readonly VertexFormat Format =
VertexFormat.Position | VertexFormat.Normal;
public Vertex(float vX, float vY, float vZ,
float nX, float nY, float nZ)
{
Position = new Vector3(vX, vY, vZ);
Normal = new Vector3(nX, nY, nZ);
}
}
A kockánkat pedig az OnResourceLoad() metódus fogja megvalósítani, amiben meghívjuk a InitMaterials() metódust és feltöltjük a vertices tömböt:
private void OnResourceLoad()
{
InitMaterials();
vertices = new Vertex[]
{
// elülső oldal
new Vertex(-1.5f, +1.5f, -1.5f, 0, 0, -1),
new Vertex(+1.5f, +1.5f, -1.5f, 0, 0, -1),
new Vertex(-1.5f, -1.5f, -1.5f, 0, 0, -1),
new Vertex(-1.5f, -1.5f, -1.5f, 0, 0, -1),
new Vertex(+1.5f, +1.5f, -1.5f, 0, 0, -1),
new Vertex(+1.5f, -1.5f, -1.5f, 0, 0, -1),
// jobb oldal
new Vertex(+1.5f, +1.5f, -1.5f, +1, 0, 0),
new Vertex(+1.5f, +1.5f, +1.5f, +1, 0, 0),
new Vertex(+1.5f, -1.5f, -1.5f, +1, 0, 0),
new Vertex(+1.5f, -1.5f, -1.5f, +1, 0, 0),
new Vertex(+1.5f, +1.5f, +1.5f, +1, 0, 0),
new Vertex(+1.5f, -1.5f, +1.5f, +1, 0, 0),
// hátsó oldal
new Vertex(+1.5f, +1.5f, +1.5f, 0, 0, +1),
new Vertex(-1.5f, +1.5f, +1.5f, 0, 0, +1),
new Vertex(+1.5f, -1.5f, +1.5f, 0, 0, +1),
new Vertex(+1.5f, -1.5f, +1.5f, 0, 0, +1),
new Vertex(-1.5f, +1.5f, +1.5f, 0, 0, +1),
new Vertex(-1.5f, -1.5f, +1.5f, 0, 0, +1),
// bal oldal
new Vertex(-1.5f, +1.5f, +1.5f, -1, 0, 0),
new Vertex(-1.5f, +1.5f, -1.5f, -1, 0, 0),
new Vertex(-1.5f, -1.5f, +1.5f, -1, 0, 0),
new Vertex(-1.5f, -1.5f, +1.5f, -1, 0, 0),
new Vertex(-1.5f, +1.5f, -1.5f, -1, 0, 0),
new Vertex(-1.5f, -1.5f, -1.5f, -1, 0, 0),
// kocka teteje
new Vertex(-1.5f, +1.5f, +1.5f, 0, +1, 0),
new Vertex(+1.5f, +1.5f, +1.5f, 0, +1, 0),
new Vertex(-1.5f, +1.5f, -1.5f, 0, +1, 0),
new Vertex(-1.5f, +1.5f, -1.5f, 0, +1, 0),
new Vertex(+1.5f, +1.5f, +1.5f, 0, +1, 0),
new Vertex(+1.5f, +1.5f, -1.5f, 0, +1, 0),
// kocka alja
new Vertex(-1.5f, -1.5f, -1.5f, 0, -1, 0),
new Vertex(+1.5f, -1.5f, -1.5f, 0, -1, 0),
new Vertex(-1.5f, -1.5f, +1.5f, 0, -1, 0),
new Vertex(-1.5f, -1.5f, +1.5f, 0, -1, 0),
new Vertex(+1.5f, -1.5f, -1.5f, 0, -1, 0),
new Vertex(+1.5f, -1.5f, +1.5f, 0, -1, 0),
};
}
Mivel a kocka ezen oldala felénk néz, normálvektora merőleges a képernyő síkjára, és kifelé – azaz a szemlélő felé – mutat, ezért koordinátái (x,y,z) formában (0,0,-1) . Ezt a logikát kell követni a többi oldal esetében is. Végezetül tekintsük meg az eredményt:
Anyagok + fények + transzformációk
A teljes forrás letölthető innen:
A tutoriál írása során nagy hasznomra volt
Nyisztor Károly:
Grafika és játékprogramozás DirectX-szel c. könyve, amit mindenkinek nyugodt lelkiismerettel ajánlok!