-
AutorBeiträge
-
10. Oktober 2006 um 13:48 #1149azraelTeilnehmer
Aus den selben Gründen, aus welchen ich auch das C++ Tutorial schreibe, schreib ich nun ein DirectX – Tutorial. Hierzu sei gesagt, dass die Voraussetzung für dieses Tutorial die Kenntnis der Programmiersprache C++ und der WinAPI, ist. Zu beiden Themen schreibe ich auch Tutorials.
Aber nun erstmal: Was ist DirectX?
Es ist eine Sammlung von APIs (Application Programming Interfaces), die vor allem für das Programmieren von Spielen geeignet ist. Verwendet wird DirectX auf Windows-PCs und der Xbox. Das „direct“ sagt aus, dass die APIs direkt auf die Hardware zugreifen können, das heißt, dass die damit erstellten Programme/Spiele sehr schnell sind.
Wichtigste Bestandteile von DirectX:
Direct3D: Die API für das Programmieren von Grafiken, sowohl 3D als auch 2D, früher gab es noch DirectDraw, in den neusten Versionen nicht mehr
DirectSound: Die API für Soundprogrammierung. Hat mehr Effekte als ein Heavy Mettaler für seine E-gitarre
DirectInput: Die API für Eingabeprogrammierung, d.h: Maus, Tastatur, Joystick, Gamepad, Lenkrad usw… Wird z.B für force-feedback benötigt.
DirectPlay: API für Netzwerkprogrammierung, verursacht extremen Overhead, deswegen verwenden Spieleentwickler meistens WinSock dafür.
Nun zum Tutorial ( Wieder aus meinem Forum kopiert ) :
Nach ein wenig Überlegung, hab ich mich entschieden, parallel zum C++ Tutorial ein DirectX Tutorial zu schreiben. Da ich das ja nicht nur dazu mache, um Informationen an andere weiterzugeben, sondern auch, um mein eigenes Wissen zu festigen, finde ich das besser, wenn ich beide Tutorials gleichzeitig schreibe.
Die Voraussetzung für dieses Tutorial ist Kenntnis der Programmiersprache C++ sowie die Grundlagen der WinAPI (zu welcher ich logischerweise erst später ein Tutorial schreiben werde >.<). Als Compiler verwende ich hierbei das Microsoft Visual C++ 2005 Express Edition, welches hier kostenlos runtergeladen werden kann. Um mit DirectX jedoch arbeiten zu können, muss man einige Änderungen vor dem Start vornehmen. 1) Benötigte SDKs
Als erstes braucht man das Plattform SDK von Microsoft, die aktuellste Version gibt es immer hier.Achtung:
Wenn man kein Windows Prof. 64 Bit Edition installiert hat, dann lädt man die PSDK-x86.exe Datei runter, egal, welchen Prozessor man hat. Hat man die 64 Bit Version, dann lädt man für eine 64 Bit CPU von AMD die Datei PSDK-amd64.exe und für eine Intel CPU die Datei PSDK-ia64.exe runter.Die SDK solltet ihr nun installieren, habt ihr das geschafft, geht’s mit der nächsten schon weiter – der DirectX SDK (Dowloadlink <- August 2006). Installieren. Das war’s mit der Installation… Jetzt kommt die Konfiguration – und zwar von Microsoft Visual C++ 2005 Express Edition. 2) Konfiguration
1 Schritt: Die Pfadangaben ergänzen
Klickt euch in das Installationsverzeichnis von MS VC++ 2005 EE und von dort aus in das Unterverzeichnis VCvcpackages dort öffnet ihr die Datei „VCProjectEngine.Dll.Express.Config“ mit dem Editor. Dort sollte ungefähr sowas stehen:Code:xml version="1.0" encoding="utf-8"?>
Nun müsst ihr sechs Zeilen hinzuschreiben, so dass die Datei danach so aussieht:
Code:xml version="1.0" encoding="utf-8"?>
Wobei ihr nun aufpassen müsst, wohin ihr das Platform SDK und die DirectX SDK installiert habt, die Eingabe C:ProgrammeMicrosoft Platform SDK und C:ProgrammeMicrosoft DirectX SDK (August 2006) kann bei euch anders sein – es ist aber immer das Installationsverzeichniss vom PSDK.
2 Schritt:
Zusätzliche Abhängigkeiten vom Linker
Danach geht’s ins Verzeichnis VCVCProjectDefaults (vom Installationspfad des VC++). Dort findet ihr die Datei corewin_express.vsprops, diese öffnet ihr auch und ergänzt die Zeile AddtionalDependencies – danach sollte sie so aussehenAddtionalDependencies = „kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib” />
3 Schritt WIn32 Projekte ermöglichen:
Und die letzte Datei für die allgemeine Einstellung – AppSettings.htm im Unterordner VCVCWizardsAppWizGenericApplicationhtml1031 (mit editor öffnen)Dort macht ihr in den Zeilen 441 bis 444 die Schrägstriche vor den Zeilen Weg, sollte dann so aussehen:
Code:WIN_APP.disbled = true;
WIN_APP_LABEL.disabled = true;
DLL_APP.disabled = true;
DLL_APP_LABEL.disabled = true;4 Schritt Abhängigkeiten eines Projektes
Die allgemeine Konfiguration ist vorbei, jetzt zur Projektkonfiguration: das müsst ihr immer machen, wenn ihr ein DirectX-Projekt erstellt.Nach der Erstellung des Projektes geht ihr in der symbolleiste auf Projekt -> {Projektname}-Eigenschaften-> Konfigurationseigenschaften ->Linker->Eingabe bei zusätzliche Abhängigkeiten drückt ihr auf die drei Punkte und fügt folgende libs hinzu:
d3dxof.lib
dxguid.lib
d3dx9d.lib
d3d9.lib
winmm.lib
comctl32.lib
dsound.lib
dinput8.lib
shlwapi.libJedes von den libs muss in eine neue Zeile geschrieben werden. So – endlich fertig mit der Konfiguration – ich muss ehrlich zugeben ich hab teilweise aus dem Buch „Inside Microsofts DirectX 9 Spieleprogrammierung“ die Sachen abgeschrieben,. Naja die rechte liegen beim Autor oder so – ich kenn mich mit Copyright nicht so wirklich aus^^
Jetzt geht’s aber an den Quellcode.3) Der Code
Was soll das Programm überhaupt machen? Es wird ein Fenster erzeugt, in welchem ein Direct3D Device erstellt wird, mit welchen das Fenster gesäubert wird. Klingt einfach? Im Vergleich zu HDR Rendering, Displacement mapping usw. ist es einfach, aber im Vergleich zum klassische „Hello World“, wenn man eine Programmiersprache…. Egal – ihr werdet’s selber sehen.Fügt dem leeren Win32-Projekt eine neue C++ Datei hinzu und los geht’s:
Code:#include//die DirectX-Header Datei Was das jetzt ist, sollte euch klar sein, oder ihr seid hier mächtig falsch – lernt C++ zuerst
Die windows.h (für WinAPI) brauchen wir nicht extra einzufügen – die ist in der d3d9.h includet
Übrigens: lest die Kommentare, die Information ist zum größten Teil in denen enthalten.Code:LPDIRECT3D9 g_pD3D = NULL; // Das Direct3D Device
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Das Rendering-DeviceLP im Namenvorsatz heißt long pointer (to), da er auf eine Struktur zeigt, handelt es sich hierbei um einen Handle (Vielen Dank an Skabus, dass er mir das endlich erklärt hat >.<) Mehr zu Handles im kommenden WinAPI-Tutorial.
Der Präfix g_p heißt global pointer.Code:HRESULT InitD3D( HWND hWnd )
{
// Ein D3D Objekt erstellen, dass für die Erstellung des D3DDevice
// benötigt wird
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;Die Funktion erstellt ein Direct3D Device für das Fenster, das via Handle übergeben wird.
Hier sollte ich was dazu sagen: HRESULT ist der Rückgabecode einer Schnittstelle. Er ist immer 0, wenn die Funktion erfolgreich war. Sollte sie fehlschlagen, wird der Fehlercode zurückgegeben, dass ist dann immer das, was man so gerne am Bildschirm sieht: „blablabla unter der Adresse 0xFF5100AB blabla bla fehler code 0xF0A05F32 blablabla“. Jetzt fällt einem aber auf -> das ist doch eine if-anweisung, da wird doch nichts erstellt!
Doch wird es^^. Man erinnere sich an den typischen Programmierfehler: = anstatt ==, wenn man etwas vergleichen will. Hier wird das ausgenutzt – g_pD3D wird gleichzeitig etwas zugewiesen und mit Null verglichen. Praktisch – ist es dann = NULL, dann gibt die ganze Funktion E_FAIL zurück (wen das interessiert: E_FAIL ist 0x80004005)Code:// Hier wird mit der Struktur D3DPRESENT_PARAMETERS d3dpp deklariert
// und teilweise definiert
// Wir stellen Windowed auf TRUE, da wir das ganze ja in einem
// Fenster sehen wollen
// SwapEffect wird auf discard gestellt, soll angeblich die beste
// Methode sein, den Backbuffer mit dem Frontbuffer zu vertauschen
// (der Swap – Befehl vertauscht die beiden, wer mehr erfahren will,
// geht auf de.wikipedia.org/wiki/Backbuffering)
// das BackBufferFormat stellt man auf D3DFMT_UNKNOWN, was bedeutet,
// dass das Format vom Display automatisch verwendet wird
// Zero Memory füllt einen Speicherbereich mit Nullen, der erste
// Parameter ist die anfangsadresse für den Speicherblock und der
// zweite die Länge des zu füllenden SpeicherbereichD3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;// Wir erzeugen ein D3DDevice – dafür ist die Funktion CreateDevice
// zuständig – der erste Parameter ist der Video Adapter, also die
// Grafikkarte, die genutzt wird, die meisten PCs haben ja nur eine,
// bzw. SLI wird ja auch als einzelner Adapter genutzt – also
// schreiben wir D3DADAPTER_DEFAULT hin, um den Standartadapter zu
// nutzen, der zweite Parameter ist der Device Typ – mit
// D3DDEVTYPE_HAL sagen wir dem Programm, lieber Hardware als
// Software zu benutzen. Der dritte Parameter ist der Handle zum
// Fenster. Danach kommen die Verhaltensflags (mit einem | getrennt
// mehrere angaben möglich). D3DCREATE_SOFTWARE_VERTEXPROCESSING
// läuft auf allen Karten, ist hardware vertexprocessing unterstützt,
// dann ist die ersetzung des software durch hardware eine
// leistungsbeschleunigung. Eins von denen (oder …_MIXED_…) muss
// aber vorkommen, D3D…_NOWINDOWCHANGES zeigt an, dass Direct3D das
// Fokus-Fenster nicht verändern darf, der nächte Parameter ist die
// adresse zu einer D3DPRESENT_PARAMETERS – Struktur und der letzte
// ist die Adresse von einem pointer zu dem Zurückzugebenden
// IDirect3DDevice9.
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_NOWINDOWCHANGES,
&d3dpp,
&g_pd3dDevice ) ) )
{
return E_FAIL; // ist gleich 0x80004005 ^^
}// Originalkommentar: Device state would normally be set here. Punkt
return S_OK;
}Jetzt ist der Initialisierungsfunktion fertig . Jetzt brauchen wir noch die umgekehrte Funktion: die die alles wieder freigibt.
Code:VOID Cleanup()
{
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release(); //lässt wörtlich das Device losif( g_pD3D != NULL)
g_pD3D->Release(); //dasselbe hier
}Warum ist das destruktive immer einfacher?^^
Nun brauchen wir noch die Renderfunktion (Das, was das bild ans fenster malt)Code:VOID Render()
{
if( NULL == g_pd3dDevice )
return;// Die Funktion löscht den BackBuffer und füllt ihn mit i-ner Farbe
// Die Funktion arbeitet mit Rechtecken (D3DRECT – Strukturen) – der
// erste Parameter ist die anzahl der Rechtecke im Array, das im
// zweiten Parameter übergeben wird, im dritten Parameter wird
// gesagt, dass das Renderziel gesäubert werden soll, der nächste
// gibt die Farbe im ARGB Format an (die Werte in der Klammer: zuerst
// rot, dann Grün, dann Blau), der nächte Wert ist die Tiefe des
// Tiefenbuffers (von 0 bis 1, float) und danach worauf der stencil
// Buffer gesetzt wird. Ich empehle übrigens, in der Directx SDK
// Dokumentation alle funktionen nachzublättern, da könnt ihr einige
// Informationen finden
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(40,100,150), 1.0f, 0 );// Beginn der Szene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Hier wird alles gerendert, was gerendert werden soll// die Szene beenden
g_pd3dDevice->EndScene();
}// den Inhalt des Backbuffers auf den Bildschirm zaubern
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}// Den Messagehandler werde ich hier nicht erklären, erstens weil das
// Tutorial eh riesig ist und zweitens weil ich das im WinAPI tut machen
// werde
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup(); // Devices releasen
PostQuitMessage( 0 );
return 0;case WM_PAINT:
Render(); // Sachen rendern
ValidateRect( hWnd, NULL ); // Zeigt einen Rechteckigen
// Bereich im Fenster (1 Param)
// indem ein RECT (2 Param) von
// der sich aktualisierenden
// Fläche entfernt wird, bei NULL
// wird alles angezeigt
return 0;
}return DefWindowProc( hWnd, msg, wParam, lParam );
}// WinMAIN (main funktion der WinAPI)
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
// Fensterklasse registrieren (wird im WinAPI – tut näher erklärt)
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, „D3D Tutorial“, NULL };RegisterClassEx( &wc );
// Fenster der Anwendung erstellen (näheres im WinAPI – tut)
HWND hWnd = CreateWindow( „D3D Tutorial“, „D3D Tutorial 01: CreateDevice“,
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
NULL, NULL, wc.hInstance, NULL );// Direct3D initialisieren – der Folgende code soll nur ausgeführt
// werden, wenns klappt
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Das Fenster zeigen
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );// Messageschleife (näheres im WinAPI-tut)
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
// Die Fensterklasse unregistrieren
UnregisterClass( wc.lpszClassName, wc.hInstance );
return 0;
}Und für dieses bisschen nichts habe ich so lange gebraucht >.<. Jetzt schreib ich den nächsten Teil des C++ Tuts. Kritik bitte in den dazugehörigen Kritik-Thread
Achso: Tutorial © by Azrael, il Meraz
Hab ne tolle Seite gefunden: auf http://www.directx9.de/ hat man immer die Links zu der aktuellstens DirectX SDK
10. Oktober 2006 um 18:02 #3143me1357TeilnehmerHmm .. void schreibt man in C++ eigentlich üblicherweise klein, und nicht gross (VOID) so wie du das gemacht hast.
Ob und bei welchen Compilern das zu einem Fehler führen könnte, weiss ich zwar nicht, aber auf jeden Fall sieht der Code dadurch reichlich merkwürdig aus.
Selbiges auch zu int.10. Oktober 2006 um 19:15 #3144azraelTeilnehmerDas sind keine üblichen C++ – Datentypen, sondern Windows – Datentypen, wenn du eine Übersicht haben willst – http://windowssdk.msdn.microsoft.com/en-us/library/ms736992.aspx das würde bei vielen Compilern zu fehlern führen, wenn man die d3d9.h nicht einbindet
10. Oktober 2006 um 20:04 #3145me1357TeilnehmerWindows-Datentypen .. ich seh schon, da war Microsoft ja echt kreativ.
Der dazugehörige Code:
Code:#define VOID void:floet:
Manchmal frag man sich echt, was die Programmierer da den ganzen Tag lang machen.Gibt es einen ernstzunehmenden Grund dafür VOID statt void zu benutzen?
10. Oktober 2006 um 20:12 #3146azraelTeilnehmernein.
öhm – das ist so ne Sache – auf so fragen würden dir Microsoftler wohl die selbe Antwort liefern, wie google, wenn du nach „the answer to life, the universe and everything“ (ohne anführungsstriche) suchst. naja, das war wohl OT und ich muss mal den zweiten Teil des C++ Tuts schreiben :wtf:
10. Oktober 2006 um 20:28 #3147whitenexxTeilnehmerHabe gelesen, dass nur Windows Vista DirectX10 haben/unterstützen wird. Deswegen werden Gamer nicht an Vista vorbeikommen. Wenn das stimmt, heißt das, dass man seine entwickelten Spiele/Games nur unter Microsoft Produkten spielen/ausführen kann?
Oder gibt es eine Möglichkeit die Games auch für andere Systeme wie z.B. Linux zu kompilieren?10. Oktober 2006 um 20:40 #3148azraelTeilnehmerwenn man plattformunabhängige APIs nutzt, wie z.B: Allegro oder OpenGL, dann lässt sich das Problem vermeiden. DirectX ist aber die Schnellste, (Obwohl – OpenGL ist glaub ich gleich schnell), außerdem werden sich die meisten nicht die Mühe machen, eine andere API zu lernen – DirectX ist schon wahnsinnig groß und komplex.
btw: Unter Linux gabs doch immer Emulatoren für DirectX – wenn die Hardware stark genug ist, dann lässt sich jedes Spiel problemlos Spielen
10. Oktober 2006 um 21:05 #3149whitenexxTeilnehmerEs gibt für fast alles Emulatoren und Virtuallisierungssoftware.
Aber das ist nicht das wahre. Naja aber es gibt ja dann noch OpenGL…das freut mich.
Die Games die man mit C++ und DirectX entwickelt, laufen die auch auf der XboX? Oder muss man da wieder andere Sachen beachten? Ausser jetzt die EingabeHarware.
MfG10. Oktober 2006 um 21:12 #3150azraelTeilnehmerZitat aus Wikipedia:
Quote:DirectX [dajÌr[ktÈ[ks] ist eine Sammlung von Application Programming Interfaces (APIs) für Multimediaprogramme (besonders Spiele) auf der Windows-Plattform und findet auch auf der Spielekonsole Xbox Verwendung.Ja das geht, aber der Umgang mit DirectInput ist etwas anders als bei PC. Ansonsten: PC Spiele lassen sich wunderbar auf die XBox portieren. Naja – manchmal klappt das nicht so mit der Leistung^^ aber XBox360 ist ja schneller
11. Oktober 2006 um 7:44 #3151whitenexxTeilnehmerSchön schön :piece: Und hast du schon welche Spiele entwickelt oder rausgebracht/veröffentlicht?
11. Oktober 2006 um 20:29 #3152azraelTeilnehmerdas was ich entwickelt habe, würde die Welt in Schrecken versetzen, wenn ich es veröffentlichen würde…
öhm – ein vertikal Shooter im welchem man nicht sterben konnte (nicht mal mit DirectX geproggt >.<) und ein ziemlich langes Textadventure. Beide Spiele sind nicht mehr existent, weil sie mir peinlich waren :wtf: mein nächstes projekt ( nach dem lernen von DirectX ) wird wohl was RPG - mäßiges sein. Aber ich glaube mal ich werde das dann auf meinem Forum präsentieren...
-
AutorBeiträge
- Du musst angemeldet sein, um auf dieses Thema antworten zu können.