OpenGL schwarzes Fenster
-
Hallo an alle,
ich habe vor geraumer Zeit angefangen C++ zu lernen und möchte jetzt mit OpenGL beginnen. Ich habe mir Tutorials herausgesucht, aber irgendwie funktioniert keines davon. Ich möchte einfach nur ein schwarzes Fenster erstellen.Ich nutze Microsoft Visual Studio und mein Betriebssystem ist Windows 10
Dies ist mein Code:
#include <Windows.h> #pragma comment(lib, "opengl32") #pragma comment(lib, "glu32") #include <gl/gl.h> #include <gl/glu.h> HGLRC hRC = NULL; // Der OpenGL Darstellungs Kontext (RC) HDC hDC = NULL; // GDI Geräte Kontext (DC) HWND hWnd = NULL; // Windows Handle HINSTANCE hInstance; // Die Instanz der Anwendung bool keys[256]; // Vektor (Array) der den Status // einzelner Tasten enthält // (gedrückt/nicht gedrückt) bool active = TRUE; // Wenn active FALSE ist, wurde das // Fenster vom Benutzer minimiert. bool fullscreen = TRUE; // Läuft das Programm im Vollbildmodus // oder nicht? LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // WndProc wird deklariert GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Initialisierung des OpenGL-Fensters { if (height == 0) { height = 1; } // height darf nicht 0 sein, damit es im späteren // Programmablauf nicht zu einer Division durch 0 kommt. glViewport(0, 0, width, height); // Hier wird der Mittelpunkt auf den die Perspektive zuläuft // zurückgesetzt. glMatrixMode(GL_PROJECTION); // Hier wird die Projektionsmatrix festgelegt glLoadIdentity(); // und angepasst gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); // Hier wird die das Verhältnis der Höhe zur Breite übergeben // und der Verzerrungswinkel von 45 Grad übergeben glMatrixMode(GL_MODELVIEW); // Hier wird die sogenannte modelview-Matrix festgelegt glLoadIdentity(); // und angepasst. } int InitGL(GLvoid) { glShadeModel(GL_SMOOTH); // Das Smooth Shading wird aktiviert, das // sehr schöne Farbübergänge auf Körpern ermöglicht. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // In diesem Falle ein schwarzer Hintergrund glClearDepth(1.0f); // depht buffer zurückgesetzt glEnable(GL_DEPTH_TEST); // Aktivierung des depht Tests (dazu später mehr.) glDepthFunc(GL_LEQUAL); // Der Typ des Depht Tests wird festgelegt glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Perspektive wird festgelegt return TRUE; // Initialisierung scheint geklappt zu haben! } int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Die vorherige Szene wird vom Bildschirm gelöscht, // damit die neuen nicht einfach über die alten // Objekte gezeichnet werden glLoadIdentity(); // modelview-Matrix wird wieder einmal zurückgesetzt return TRUE; // Alles hat geklappt } GLvoid KillGLWindow(GLvoid) { if (fullscreen) // Kontrolle auf Vollbildmodus { ChangeDisplaySettings(NULL, 0); // Zurück zum Desktop ShowCursor(TRUE); // Der abgeschaltete Mauszeiger // wird wieder angezeigt (Nicht // vergessen ;) } if (hRC) // Rendering Context (RC) vorhanden? { if (!wglMakeCurrent(NULL, NULL)) // Kann der DC und RC überhaupt // gelöscht werden? { MessageBox(NULL, "Entfernen des DC und RC fehlgeschlagen.","Fehler", MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(hRC)) // Kann der RC gelöscht werden? { MessageBox(NULL, "Entfernen des RC fehlgeschlagen.","Fehler...", MB_OK | MB_ICONINFORMATION); } hRC = NULL; // Der RC wird NULL gesetzt, also entfernt } if (hDC && !ReleaseDC(hWnd, hDC)) // Kann der Device Context (DC) freigegeben werden? { MessageBox(NULL, "Freigabe des Device Context fehlgeschlagen.","Fehler",MB_OK | MB_ICONINFORMATION); hDC = NULL; // Der DC wird entfernt } if (hWnd && !DestroyWindow(hWnd)) // Kann das Programmfenster geschlossen werden? { MessageBox(NULL, "Konnte hWnd nicht löschen.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hWnd = NULL; // Setze den hWnd auf NULL } if (!UnregisterClass("OpenGL", hInstance)) // Kann die Registrierung rückgängig gemacht werden? { MessageBox(NULL, "Konnte Klasse nicht entfernen.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hInstance = NULL; // Setze hInstance auf NULL } } BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) { GLuint PixelFormat; // Speichert das Pixelformat WNDCLASS wc; // wc wird eine Instanz der Fensterklasse DWORD dwExStyle; // weitere Informationen DWORD dwStyle; // Fensterinformationen RECT WindowRect; // Speicher für aktuelle Auflösung WindowRect.left = (long)0; // Die linke Seite des Rechtecks wirtd auf 0 gesetzt WindowRect.right = (long)width; // Hier wird die gewünschte Breite des Fensters gespeichert WindowRect.top = (long)0; // Die obere Seite wird auch auf 0 gesetzt WindowRect.bottom = (long)height; // Und hier wird die Höhe abgelegt fullscreen = fullscreenflag; // Hier wird fullscreen // auf den Wert von fullscreenflag // gesetzt, welches ja übergeben wurde hInstance = GetModuleHandle(NULL); // Die Instanz des Programmes bekommt ein // Handle zugeordnet wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Bei Veränderungen in der Höhe und/oder Breite, // soll ne gezeichnet werden wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc behandelt die auftretenden Nachrichten wc.cbClsExtra = 0; // Wird nicht benötigt wc.cbWndExtra = 0; // und das auch nicht wc.hInstance = hInstance; // Die Instanz wird festgelegt wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Lädt das Standardsymbol wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Lädt einen Cursor wc.hbrBackground = NULL; // Es soll kein bestimmter Hintergrund angezeigt werden wc.lpszMenuName = NULL; // Auch ein Menü wird nicht benötigt. wc.lpszClassName = "OpenGL"; // OpenGL wird der Name der Klasse if (!RegisterClass(&wc)) // Versuch die Klasse zu registrieren { MessageBox(NULL, "Konnte die Fensterklasse nicht registrieren.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; // FALSE zurückgeben und beenden } if (fullscreen) // Soll im Vollbildmodus gestartet werden { DEVMODE dmScreenSettings; // Instanz von DEVMODE wird erzeugt memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Diese wird geleert dmScreenSettings.dmSize = sizeof(dmScreenSettings); // dmsize soll genauso groß wie die dmScreenSettings sein dmScreenSettings.dmPelsWidth = width; // Die drei Werte (height, width und bits) // wurden der Prozedur übergeben und werden // nun in dmScreenSettings gespeichert dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; // Hier werden die drei Werte in einem Ausdruck gespeichert if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { // CDS_FULLSCREEN blendet zusätzlich die Startleiste aus if (MessageBox(NULL, "Der gewünschte Vollbildmodus wird nicht unterstützt, soll stattdessen im Fenstermodus ausgegeben werden ? ","OpenGL" , MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { fullscreen = FALSE; // Der Benutzer möchte im Fenster weitermachen, // dazu wird fullscreen auf FALSE gesetzt } else { return FALSE; // Falls der Benutzer das Programm aus gegebenen // Anlass beenden will, wird FALSE zurückgegeben. } } } if (fullscreen) // Konnte in den Vollbildmodus geschaltet werden? // (Wenn nicht, wird ja im Fenster weitergemacht!) { dwExStyle = WS_EX_APPWINDOW; // Fenstereigenschaften dwStyle = WS_POPUP; // -"- ShowCursor(FALSE); // Der Mauszeiger wird nicht angezeigt } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Das Fenster soll zusätzlich einen 3D Rahmen bekommen dwStyle = WS_OVERLAPPEDWINDOW; // Ein typisches Windowsfenster mit // Minimieren, Maximieren, etc } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Fenster wird angepasst if (!(hWnd = CreateWindowEx(dwExStyle, // Die erweiterten Eigenschaften des Fensters "OpenGL", // Der Name der Klasse title, // Der Titel des Fensters WS_CLIPSIBLINGS | // Wird von OpenGL benötigt WS_CLIPCHILDREN | // Wird auch von OpenGL benötigt dwStyle, // auch Eigenschaften des Fensters 0, 0, // Die Position des zu erstellenden Fensters WindowRect.right - WindowRect.left, // Hier werden die ermittelten Werte für die Breite eingesetzt WindowRect.bottom - WindowRect.top, // und hier für die Länge NULL, // Es soll kein übergordnetes Fendster erstellt werden NULL, // kein Menü hInstance, // Die Instanz wird übergeben NULL))) // Wird nicht benötigt { KillGLWindow(); // Grafikeinstellungen zurücksetzen MessageBox(NULL, "Fenster konnte nicht erstellt werden.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } static PIXELFORMATDESCRIPTOR pfd = // pdf ist jetzt ein PIXELFORMATDESCRIPTOR { sizeof(PIXELFORMATDESCRIPTOR), // Die größe muss natürlich stimmen 1, // Versionsnummer PFD_DRAW_TO_WINDOW | // Das Format muss in Fenster sichtbar sein können PFD_SUPPORT_OPENGL | // OpenGL muss unterstützt werden PFD_DOUBLEBUFFER, // Double Buffering muss unterstützt werden PFD_TYPE_RGBA, // Das RGBA (Rot,Grün,Blau,Alpha(Transparenz)) // muss unterstützt werden bits, // Die Farbtiefe, die schon // übergeben wurde, wird hier benötigt 0, 0, 0, 0, 0, 0, // wird nicht benötigt 0, // kein Alpha Buffer 0, // Shift Bit ignoriert 0, // kein Accumulation Buffer 0, 0, 0, 0, // nicht benötigt 16, // 16Bit Z-Buffer (Depth Buffer) 0, // kein Stencil Buffer 0, // kein Auxiliary Buffer PFD_MAIN_PLANE, // Die Hauptebene auf die später gezeichnet wird 0, // unwichtig 0, 0, 0 // keine Ebenenmasken benötigt }; if (!(hDC = GetDC(hWnd))) // Versuch, den DC zu bekommen { KillGLWindow(); // Alles rückgängig machen MessageBox(NULL, "Konnte keinen DC erstellen.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; // FALSE zurückgeben, beenden } if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // Kann Windows ein passendes finden? { // Falls keins gefunden werden kann: KillGLWindow(); // Alles zurücksetzen MessageBox(NULL, "Konnte kein passendes Pixelformat finden." , "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; // FALSE zurück und Ende. } if (!SetPixelFormat(hDC, PixelFormat, &pfd)) // Kann das Pixelformat gesetzt werden? { KillGLWindow(); // Leider nicht, Fehlerpopup und raus MessageBox(NULL, "Konnte Pixelformat nicht setzen.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; // FALSE zurück und raus } if (!(hRC = wglCreateContext(hDC))) // Versuch den RC zu bekommen { KillGLWindow(); // Alles rückgängig machen MessageBox(NULL, "Konnte keinen Rendering Context bekommen.", "Fehler", MB_OK | MB_ICONEXCLAMATION); return FALSE; } if (!wglMakeCurrent(hDC, hRC)) // Versuch den RC zu aktivieren { KillGLWindow(); // hat nicht geklappt, also alles zurück MessageBox(NULL, "Konnte den Rendering Context nmicht aktivieren.", "Fehler", MB_OK | MB_ICONEXCLAMATION); return FALSE; } ShowWindow(hWnd, SW_SHOW); // Fenster anzeigen SetForegroundWindow(hWnd); // Priorität des Programms wird erhöht SetFocus(hWnd); // Tastatureingaben werden // jetzt an das Programm geleitet ReSizeGLScene(width, height); // Die Perspektive wird aktiviert if (!InitGL()) // Initialisiere das OpenGL Fenster { KillGLWindow(); // Falls das nicht geklappt // haben sollte alles rückgängig machen MessageBox(NULL, "Initialisierung fehlgeschlagen.", "Fehler", MB_OK | MB_ICONEXCLAMATION); return FALSE; // FALSE wird zurückgegeben } return TRUE; // Alles hat geklappt!!! } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) // Sind Nachrichten in der Nachrichtenschleife? { case WM_ACTIVATE: // Ist das Programm aktiv? { if (!HIWORD(wParam)) // Ist das Programm nicht minimiert? { active = TRUE; // active wird TRUE } else { active = FALSE; // Programm ist minimiert } return 0; // Rückgabe: 0 } case WM_SYSCOMMAND: // Ist ein Systemkommando // (wie z.B. "Bildschirmschoner // soll gestartet werden") vorhanden? { switch (wParam) // wParam würde diesen Befehl enthalten { case SC_SCREENSAVE: // Versucht Windows den Bildschirmschoner zu starten case SC_MONITORPOWER: // Soll der Monitor in den Stromsparmodus gehen? return 0; // Beide Fälle werden durch die Rückgabe von 0 verhindert } break; // Das wars. } case WM_CLOSE: // Ist eine WM_CLOSE Nachricht vorhanden? { PostQuitMessage(0); // Die Nachricht zum Beenden wird "gepostet" return 0; // und zurück. } case WM_KEYDOWN: // Drückt der Benutzer eine Taste??? { keys[wParam] = TRUE; // Der Wert im Array keys[] der dem Code // der Taste entspricht, wird true gesetzt return 0; // und zurück... } case WM_KEYUP: // Wurde eine Taste losgelassen? { keys[wParam] = FALSE; // Wen ja, dann soll dieser Wert im Array keys[] // auf FALSE gesetzt werden return 0; // und zurück. } case WM_SIZE: // Die Fenstergröße wurde geändert { ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord ist die Breite, HiWord die Höhe, // ReSizeGLScene() verändert dann die // Größe des OpenGL-Fensters return 0; // und zurück } } return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; BOOL done = FALSE; if (MessageBox(NULL, "Soll im Vollbildmodus gestartet werden?", "Vollbilmodus gewünscht?", MB_YESNO | MB_ICONQUESTION) == IDNO) { fullscreen = FALSE; // Falls nein gedrückt wurde, // wird fullscreen false gesetzt } if (!CreateGLWindow("Opengl", 640, 480, 16, fullscreen)) { return 0; // Falls ein Fehler auftrat, beenden } while (!done) // Solange done nicht TRUE ist: { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Sind Nachrichten vorhanden { if (msg.message == WM_QUIT) // Liegt eine Nachricht zum beenden vpr? { done = TRUE; // Wenn dem so ist, wird done // true und das Programm beendet } else // Wenn nicht werden die anderen Nachrichten ausgewertet { TranslateMessage(&msg); // Umformen der Nachricht DispatchMessage(&msg); } } else // Falls keine Nachrichten bereit liegen { if (active) // Programm aktiv? { if (keys[VK_ESCAPE]) // Wurde ESC gedrückt? { done = TRUE; // Wenn ESC gedrückt wurde, beenden } else // ESC wurde nicht gedrückt { DrawGLScene(); // Die Szene ausgeben SwapBuffers(hDC); // Die Puffer werden getauscht } } if (keys[VK_F1]) // Wird F1 gedrückt? { keys[VK_F1] = FALSE; // Es darf nicht gewartet werden bis F1 losgelassen wird, // ansonsten könnte das Bild mehrmals hin und herschalten KillGLWindow(); // Das aktuelle Fenster wird gelöscht fullscreen = !fullscreen; // fullscreen erhält seinen entgegengesetzten Wert // (bei FALSE TRUE, und bei TRUE FALSE.) if (!CreateGLWindow("Lektion 1", 640, 480, 16, fullscreen)) { return 0; // Zurück falls ein Fehler auftrat } } } } }
Aber beim Compilieren erhalte ich folgende Fehlermeldungen:
...Pfad\c++\opengl\opengl\main.cpp(323): warning C4838: Konvertierung von "int" zu "BYTE" erfordert eine einschränkende Konvertierung ...Pfad\c++\opengl\opengl\main.cpp(471): error C2664: "BOOL CreateGLWindow(char *,int,int,int,bool)" : Konvertierung von Argument 1 von "const char [7]" in "char *" nicht möglich ...Pfad\c++\opengl\opengl\main.cpp(471): note: Bei der Konvertierung von Zeichenfolgenliteral geht der Konstantenqualifizierer verloren (siehe /Zc:strictStrings) ...Pfad\c++\opengl\opengl\main.cpp(523): error C2664: "BOOL CreateGLWindow(char *,int,int,int,bool)" : Konvertierung von Argument 1 von "const char [10]" in "char *" nicht möglich ...Pfad\c++\opengl\opengl\main.cpp(523): note: Bei der Konvertierung von Zeichenfolgenliteral geht der Konstantenqualifizierer verloren (siehe /Zc:strictStrings)
versuchte Tut's:
https://www.youtube.com/watch?v=4Fi17JKzBqg&t=401s
http://codeworx.org/opengl_tut2.phpIch hoffe ihr könnt mir helfen
Vielen Dank im vorausKrapfen
-
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
->
BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag)
Diese und ähnliche Probleme wirst du aber mit deinem Wissensstand immer wieder haben. Besser wäre es vermutlich, wenn du mit einem Buch (nicht mit irgendwelchen Videos) erst einmal Grundlagen erarbeitest und dich dann später an Fenster, OpenGL etc. herantastest.
-
Erstmal Vielen vielen Dank für deine schnelle Antwort.
Habs gleich ausprobiert und läuft prima danke
Welches Buch würdest du mir denn empfehlen?
-
@Krapfen Zum C++ lernen wird hier viel Der C++ Programmierer von Ulrich Breymann empfohlen.
-
Ich würde gerne OpenGL lernen nicht C++, ich habe schon ein C++ Buch
-
Kennst du schon http://www.opengl-tutorial.org , https://en.wikibooks.org/wiki/OpenGL_Programming oder https://learnopengl.com ?
Besonders empfohlen wird auch oft http://nehe.gamedev.net.
-
@Krapfen sagte in OpenGL schwarzes Fenster:
Ich würde gerne OpenGL lernen nicht C++
Das eine wird ohne das andere nicht funktionieren. Lies @yahendrik s Antwort.
-
@Krapfen sagte in OpenGL schwarzes Fenster:
ich habe schon ein C++ Buch