OpenGL zeichnet nichts, obwohl der Code durchlaufen wird
-
Guten Abend,
vorneweg, ich bin ein Neuling auf dem OpenGL Gebiet. Mein erster Versuch vor ein paar Monaten funktionierte zwar, glich aber nach einiger Zeit einem wilde Gehacke. Deshalb habe ich mich dazu entschieden, das Ganze nochmal zu schreiben.
Dummerweise funktioniert das Ganze jetzt nicht mehr. Ich hab mich dazu entschlossen, vor allem wegen der Übersichtlichkeit, alles in Klassen zu organisieren.
Ich hab bisher eine Klasse, welche das Fenster erstellt und die Nachrichten verarbeitet:
CDevice.h:
#include <windows.h> #include "OpenGL.h" class CDevice { HWND hWnd; //Window Handle WNDCLASS wc; //Window Class HINSTANCE hInstance; //Instanz HDC hDC; //Device Context int XRes, YRes; static CALLBACK WndProc(HWND Wnd, UINT uMsg, WPARAM wParam, LPARAM lParam); COpenGL t; public: CDevice(); virtual ~CDevice(); bool CreateGLWindow(int ResX, int ResY); void SetDCPixelFormat(void); };CDevice.cpp:
CDevice::CDevice() { } CDevice::~CDevice() { } bool CDevice::CreateGLWindow(int ResX, int ResY) { XRes=ResX; YRes=ResY; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "wigfx"; //Fensterklasse registrieren: if(RegisterClass(&wc) == 0) { MessageBox(NULL,"Couldn't register the class","Runtime Error", MB_OK | MB_ICONERROR); return false; } //Fenster erstellen: this->hWnd = CreateWindow( "wigfx", "wigfx", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0,0, ResY,ResX, NULL, NULL, hInstance, NULL); if(this->hWnd == NULL) { MessageBox(NULL,"Couldn't create the window","Runtime Error", MB_OK | MB_ICONERROR); return false; } ShowWindow(hWnd,SW_SHOW); UpdateWindow(hWnd); t.Init(ResX,ResY,this->hDC); return true; } CDevice::WndProc(HWND Wnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CDevice *device; //printf(" switch(uMsg) { case WM_CREATE: SetWindowLong(Wnd,GWL_USERDATA,lParam); device=(CDevice*)lParam; device->hDC = GetDC(Wnd); device->SetDCPixelFormat(); break; case WM_DESTROY: device=(CDevice*)GetWindowLong(Wnd,GWL_USERDATA); wglMakeCurrent(device->hDC,NULL); PostQuitMessage(0); break; case WM_PAINT: device=(CDevice*)GetWindowLong(Wnd,GWL_USERDATA); printf("WMPAINT"); break; } return DefWindowProc(Wnd,uMsg,wParam,lParam); } void CDevice::SetDCPixelFormat(void) { int nPixelformat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0,0,0,0,0,0, 0,0, 0,0,0,0,0, 16, 0, 0, 0, 0, 0,0,0}; nPixelformat = ChoosePixelFormat(hDC,&pfd); SetPixelFormat(hDC,nPixelformat,&pfd); }Dazu kommt dann nur noch die COpenGL, die eigentlich im moment ein simples Dreieck auf schwarzem Hintergrund zeichnen sollte, macht sie aber nicht...
OpenGL.h
#include <windows.h> #include <gl\gl.h> #include <gl\glu.h> #include <gl\glaux.h> #pragma comment(lib,"OpenGL32.lib") #pragma comment(lib,"GLu32.lib") #pragma comment(lib,"GLaux.lib") class COpenGL { HGLRC hRC; HDC hDC; public: COpenGL(); virtual ~COpenGL(); GLvoid ResizeScene(int ResX, int ResY); GLvoid Init(int ResX, int ResY, HDC _hDC); GLvoid Draw(); };OpenGL.cpp:
COpenGL::COpenGL() { } COpenGL::~COpenGL() { } GLvoid COpenGL::Draw() { do { printf("render\n"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-6.0f); glBegin(GL_TRIANGLES); glVertex3f(0.5f,-0.5f,0.0f); glVertex3f(-0.5f,-0.5f,0.0f); glVertex3f(0.0f,0.5f,0.0f); glEnd(); SwapBuffers(hDC); }while(1); } GLvoid COpenGL::ResizeScene(int ResX, int ResY) { if(ResY==0) ResY=1; glViewport(0,0,ResX,ResY); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)ResX/(GLfloat)ResY,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } GLvoid COpenGL::Init(int ResX,int ResY,HDC _hDC) { hRC = wglCreateContext(_hDC); wglMakeCurrent(_hDC,hRC); if(_hDC==NULL) { MessageBox(NULL,"Device Context not available","Runtime Error", MB_OK | MB_ICONERROR); return; } this->hDC=_hDC; glShadeModel(GL_SMOOTH); glClearColor(0.0f,1.0f,0.0f,0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glBlendFunc(GL_SRC_ALPHA,GL_ONE); this->ResizeScene(ResX,ResY); this->Draw(); }Ich hoffe das ist nicht allzu lang geworden...
Hab bereits die Suchfunktion bemüht, aber nichts passendes gefunden, auch google ect brachten mir keine Antworten, oder ich bin einfach blind.
Jedenfalls find ich den Fehler leider auch nicht. Hoffentlich isses kein allzu peinlicher

Bei Bedarf lade ich das Projekt auch gerne irgendwo hoch.
MfG
Shelling(Ist der Stil eigentlich soweit in Ordnung? :D)
-
stell mal deinen code online damit man mal durchdebuggen kann - dann sag ich dir deinen fehler - anschließend können wir ja mal über dein klassendesign diskutieren
-
do { printf("render\n"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-6.0f); glBegin(GL_TRIANGLES); glVertex3f(0.5f,-0.5f,0.0f); glVertex3f(-0.5f,-0.5f,0.0f); glVertex3f(0.0f,0.5f,0.0f); glEnd(); SwapBuffers(hDC); }while(1);veilleicht liegt der hund schon hier begraben -> windows kann nicht mehr die Event Queue abarbeiten, in der z. B. drin steht, dass das Fenster neu gezeichnet werden soll...
-
Oh, so früh schon eine Antwort, danke.
Werde den Hinweis aber erst Morgen bearbeiten, im Moment ist es einfach schon zu spät.
Aber ich stell hier mal das Projekt als Archiv zu Verfügung:
ProjektMuss Windows denn trotzdem noch die Event Queue abarbeiten? Ist mir zwar bewußt, das ich in diesem Beispiel das Fenster nicht größer/kleiner machen kann ect. Aber es sollte doch schon wegen der Endlosschleife durchgehend neu gezeichnet werden, oder irre ich mich da?
Ich hab im Moment irgendwie die Vermutung, das ich irgendwohin zeichne, nur nicht dahin wo es hin soll...
MfG
Shelling
-
Die Windows Nachrichten solltest du auf jeden Fall abarbeiten - und dort dann nicht mit GetMessage sonder mit PeekMessage:
MSG msg; Initialize(); if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) SetActive(false); else { TranslateMessage(&msg); DispatchMessage(&msg); } } else GameLoop(); }das solltest du zunächst mal in dein "Codedesign" einfließen lassen - wenn du soweit bist und immer noch Probleme hast post dein Projekt nochmal

-
Ok, habs nochmal nach deinem Vorschlag abgeändert. D.h. die Windows Nachrichten, jedenfalls ein paar, werden jetzt abgearbeitet. Leider hat dies nichts geändert, auch wenn viele WM_PAINT Nachrichten ankommen und daraufhin der Zeichencode ausgeführt wird, passiert nichts.
Das Projekt hab ich soweit wieder hochgeladen: Projekt
GetMessage hab ich eigentlich aus dem Grund genommen, weil ich später noch in der CDevice einen Thread fürs Zeichnen zu erstellen und den Startthread wieder in die main laufen lassen wollte. Oder spricht da irgendwas gegen?
//EDIT:
Auch wenns schon spät ist, ich glaub ich hab den Fehler gefunden. hRC ist dummerweise immer NULL. Ich glaube nicht, dass das so korrekt ist...//EDIT2:
Ich glaub ich hab den Fehler. Zu dem Zeitpunkt, an dem wglMakeCurrent(); aufgerufen wird, wurde noch nicht die WM_CREATE Nachricht bearbeitet, in der ich erst den Device Context mit GetDC(); hole. Kann dann ja auch nicht funktionieren...Jedenfalls ist hRC schonmal nicht mehr NULL. Nur das bisherige Problem besteht noch immer, es wird immer noch nichts gezeichnet. Dazu kommt, das sich Fenster, welche sich vor dem Zeichenfenster befinden, nur ruckelnt bewegen lassen. Schiebt man diese zur Seite, lassen sie sich wieder flüssig bewegen....
Ich update mal das downloadbare Projekt... vll findet ja wer den Denkfehler...
MfG
Shelling
-
nix dramatisches - aber schöner wäre es wenn du den Rückgabetyp nicht einfach wegläßt:
Error 1 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\dokumente und einstellungen\julian\desktop\wigfx\wigfx\device.h 23
Error 2 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\dokumente und einstellungen\julian\desktop\wigfx\wigfx\device.cpp 77
Error 3 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\dokumente und einstellungen\julian\desktop\wigfx\wigfx\device.h 23
Error 4 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\dokumente und einstellungen\julian\desktop\wigfx\wigfx\wigfx_main.cpp 4
-
Hier deine Endlosschleife:
while(1) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { device.t.Draw(); } }Hier dein Code zum Zeichnen:
GLvoid COpenGL::Draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-6.0f); glBegin(GL_TRIANGLES); glVertex3f(0.5f,-0.5f,0.0f); glVertex3f(-0.5f,-0.5f,0.0f); glVertex3f(0.0f,0.5f,0.0f); glEnd(); }Problem: SwapBuffers fehlt in der Draw Methode
beseitige das Problem und wir können weiter reden

-
Hehe... ja... das ist mir jetzt schon fast peinlich

Daran hats gelegen, musste nur SwapBuffers(); hinzufügen, frag mich nur warum mir das noch nicht aufgefallen ist...
Aber vielen Dank für deine Hilfe, manchmal sieht man den Wald vor lauter Bäumen nicht

Übrigens, die Fehler werden bei mir nicht angezeigt, trotz höchster Warnstufe (Stufe 4 ist das höchste was ich bei Visual C++ 6 angeben kann). Werde mal gucken ob ich auf eine neuere Version umsteigen kann, ist ja schon relativ alt.
Ich hab jetzt mal angenommen, das sich die Warnungen auf die CDevice::WndProc und auf die main beziehen.
Ist der Code soweit eigentlich in Ordnung? Durfte mir in der Schule schon ein paar mal anhören das mein Code eher nach Hackerei aussieht.
Mfg
Shelling
-
Shelling schrieb:
Ist der Code soweit eigentlich in Ordnung? Durfte mir in der Schule schon ein paar mal anhören das mein Code eher nach Hackerei aussieht.
das findest du selber mit der Zeit raus - versuch einfach weiter dein "Ziel" zu erreichen und wenn du mal eine Stelle kommst wo es nicht mehr weiter geht überleg warum
