OpenGL Grafiken flimmern (Vorsicht Noob)
-
Habe diesen Beitrag ind die Kathegorie "Spieleprogrammierung" gepackt, da es noch am Besten hier reinpasst.
Ich habe mich jetzt an die OpenGL-programmierung gewagt, also auch ganz neu in diesem Bereich. Habe mir ein Tutorial geschnappt und es sieht eigentlich ganz einleuchtend aus, aber mein Problem ist nun folgendes:
Ich zeichne z.B. als erste ein Dreieck und wenn ich mir das anzeigen lasse, dann flimmert dieses entsetzlich. wenn ich am Fenster ziehe, dann sehe ich die Grafik ganz normal und nicht flimmernd und wenn ich ein Screenshot vom Flimmern machen will, dann sieht das auf dem Screenshot auch so aus wie es aussehen soll.
Habe gesucht und Kumpels gefragt und bin auf die Themen Herz/VSync oder Buffer gestoßen, aber kann nicht wirklich viel damit anfangen, da das für mich Neuland ist. ich hoffe ihr könnt mir da helfen. Falls mein Code helfen sollte, kann ich ihn auch noch posten, aber ich hab den Verdacht, dass es eine typische Anfängerfrage ist...MfG Knickedi
-
benutzt du einen backbuffer? Also auf den backbuffer zeichnen, und dann front und back-buffer tauschen?
Weiterhin: Dass das Bild nicht flimmert, wenn du as fenser zeihst, is normal: Dann läuft nämlich die NAchrichtenschleife nicht weiter und es wird nichts neues gezeichnet.
-
hmm... ok
Da muss wohl tiefgreifenderes Wissen her.
Ich hab gedacht, dass ich erstmal das Grundgerüst mehr oder weniger zusammenkopiere und erstmal nach dem Motto "rumprobieren und dies und das nachschauen" rumbastle. So sollte es zumindest laut tutorial laufen. Klappte bis auf das Flimmern soweit ganz gut.
Dann muss ich wohl "wieder" mit der trockenen Theorie anfangen und etwas über Back- und Frontbuffer nachlesen.Danke dir für den Hinweis. So weiß ich wenigstens genau wo es an Wissen mangelt.
-
Wenn du GLUT benutzt:
einfach bei glutInitDisplayMode den Eintrag GLUT_DOUBLE "mitodern"
-
Ich versteh das mit dem Front- und Backbuffer nicht ganz. Dafür scheint die Funktion glDrawBuffer verantwortich zu sein und ich soll anscheinend bei jedem Zeichenvorgang erst in den Front- und beim nächsten in den Backbuffer zeichnen und immer hin und her schalten, aber ich kriegs nicht gebacken.
Kannst du das kurz erläutern oder mir einen brauchbaren Link schicken. Aus der OpenGL Doku werde ich auch nicht schlau. Und ich verstehe auch nicht warum die Beispielprogramme, als Konsolenanwendung (main anstatt WinMain) programmiert werden. Für mich ergibt das keinen Sinn und verwirrt mich noch mehr.
-
doublebuffer heisst nur dass man zwei buffer benutzt, dein einen bearbeitet man, und der andere dient als quelle fuer etwas anders. In deinem Speziellen fall ist es der Front und Backbuffer, der Frontbuffer ist der, der gerade angezeigt wird auf dem bildschirm, der backbuffer ist der, in den du reinzeichnest damit er, wenn du fertig bist, zum frontbuffer wird, der momentane frontbuffer wird dann zum backbuffer, den du erstmal loescht und dann etwas reinzeichnest.
bei opengl macht man das mit glSwapBuffers.
-
glSwapBuffers kennt er nicht...
Hat das nicht was mit GLUT zu tun?Wie gesagt: Neuland für mich.
Könnte mir jemand das einfach einbauen, damit ich eine Grundlage zum rumprobieren und lernen hab?
Ich denke mir, dass ihr da größeren Durchblick habt als ich^^
Wäre echt nett, wenn sich jemand kurz die Zeit nimmt...Dnek mal, dass das mit diesen Funktionen zusammenhängt:
int InitGL(GLvoid) { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return TRUE; } int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(-1.5f,0.0f,-6.0f); glBegin(GL_TRIANGLES); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glEnd(); return TRUE; }Falls benötigt, hier der ganze Code:
#include <windows.h> #include <gl\glu.h> #include <gl\gl.h> #include <gl\glaux.h> HGLRC hRC =NULL; HDC hDC =NULL; HWND hWnd=NULL; HINSTANCE hInstance; bool keys[256]; bool active=TRUE; bool fullscreen=TRUE; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) height=1; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int InitGL(GLvoid) { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return TRUE; } int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(-1.5f,0.0f,-6.0f); glBegin(GL_TRIANGLES); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glEnd(); return TRUE; } GLvoid KillGLWindow(GLvoid) { if (fullscreen) { ChangeDisplaySettings(NULL,0); ShowCursor(TRUE); } if (hRC) { if (!wglMakeCurrent(NULL,NULL)) MessageBox(NULL,"Entfernen des DC und RC fehlgeschlagen.","Fehler",MB_OK | MB_ICONINFORMATION); if (!wglDeleteContext(hRC)) MessageBox(NULL,"Entfernen des RC fehlgeschlagen.","Fehler...",MB_OK | MB_ICONINFORMATION); hRC=NULL; } if (hDC && !ReleaseDC(hWnd,hDC)) { MessageBox(NULL,"Freigabe des Device Context fehlgeschlagen.","Fehler",MB_OK | MB_ICONINFORMATION); hDC=NULL; } if (hWnd && !DestroyWindow(hWnd)) { MessageBox(NULL,"Konnte hWnd nicht löschen.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); hWnd=NULL; } if (!UnregisterClass("OpenGL",hInstance)) { MessageBox(NULL,"Konnte Klasse nicht entfernen.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); hInstance=NULL; } } BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) { GLuint PixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; RECT WindowRect; WindowRect.left=(long)0; WindowRect.right=(long)width; WindowRect.top=(long)0; WindowRect.bottom=(long)height; fullscreen=fullscreenflag; hInstance = GetModuleHandle(NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGL"; if (!RegisterClass(&wc)) { MessageBox(NULL,"Konnte die Fensterklasse nicht registrieren.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if (fullscreen) { DEVMODE dmScreenSettings; memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { 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; else return FALSE; } } if (fullscreen) { dwExStyle=WS_EX_APPWINDOW; dwStyle=WS_POPUP; ShowCursor(FALSE); } else { dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle=WS_OVERLAPPEDWINDOW; } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); if (!(hWnd=CreateWindowEx( dwExStyle, "OpenGL", title, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL,NULL,hInstance,NULL )) ) { KillGLWindow(); MessageBox(NULL,"Fenster konnte nicht erstellt werden.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, bits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; if (!(hDC=GetDC(hWnd))) { KillGLWindow(); MessageBox(NULL,"Konnte keinen DC erstellen.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { KillGLWindow(); MessageBox(NULL,"Konnte kein passendes Pixelformat finden.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { KillGLWindow(); MessageBox(NULL,"Konnte Pixelformat nicht setzen.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if (!(hRC=wglCreateContext(hDC))) { KillGLWindow(); MessageBox(NULL,"Konnte keinen Rendering Context bekommen.","Fehler",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if(!wglMakeCurrent(hDC,hRC)) { KillGLWindow(); MessageBox(NULL,"Konnte den Rendering Context nmicht aktivieren.","Fehler",MB_OK|MB_ICONEXCLAMATION); return FALSE; } ShowWindow(hWnd,SW_SHOW); SetForegroundWindow(hWnd); SetFocus(hWnd); ReSizeGLScene(width, height); if (!InitGL()) { KillGLWindow(); MessageBox(NULL,"Initialisierung fehlgeschlagen.","Fehler",MB_OK|MB_ICONEXCLAMATION); return FALSE; } return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_ACTIVATE: { if (!HIWORD(wParam)) active=TRUE; else active=FALSE; return 0; } case WM_SYSCOMMAND: { switch (wParam) { case SC_SCREENSAVE: case SC_MONITORPOWER: return 0; } break; } case WM_CLOSE: { PostQuitMessage(0); return 0; } case WM_KEYDOWN: { keys[wParam] = TRUE; return 0; } case WM_KEYUP: { keys[wParam] = FALSE; return 0; } case WM_SIZE: { ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); return 0; } } 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; if (!CreateGLWindow("Opengl Tutorial 2 - Farben und Formen - www.codeworx.org",640,480,16,fullscreen)) return 0; while(!done) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message==WM_QUIT) done=TRUE; else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { if (active) { if (keys[VK_ESCAPE]) done=TRUE; else { DrawGLScene(); SwapBuffers(hDC); } } if (keys[VK_F1]) { keys[VK_F1]=FALSE; KillGLWindow(); fullscreen=!fullscreen; if (!CreateGLWindow("Lektion 1",640,480,16,fullscreen)) return 0; } } } KillGLWindow(); return (msg.wParam); }
-
Soweit ich weiss, gibts auch kein glSwaBuffers(),
versuch mal SwapBuffers()
-
Der Befehl heisst glutSwapBuffers und gehört zum GLUT package!
-
Ich hab jetzt die Fuktion SwapBuffers( hDC ); ans Ende der DrawGLScene(GLvoid) Fuktion gepackt, aber es ändert nichts.
Habe jetzt einfach mal gesucht und bin darauf gestoßen:
http://www.nullterminator.net/opengl32.html
Unten ist ein Screenshot von dem, was man sehen sollte und wenn ich in den Code schaue, sollte sich dieses Dreieck nicht drehen, aber bei mir dreht es sich schnell und ist verzerrt. Wenn ich die Maus nicht bewege, ist das drehende Dreieck bei mir weiß und hat bunte Ränder und wenn ich sie bewege, dann drehen sich ein blaues, rotes und ein grünes Dreick versetzt und in der Mitte, wo sie sich überschneiden, ist es weiß. Ist das ein Treiberproblem?! Ich spiele auch OpenGL-Spiele und da klappt das ja wunderbar...
-
du hast einen parameter vergessen - dementsprechend sind alle flags falsch:
static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), // ** hier fehlt "WORD nVersion" PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, bits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 };
-
Oh mein Gott, ich danke dir.
Ich weiß zwar nicht, warum das Andere (drehendes Dreieck) nicht geht, aber jetzt habe ich endlich ein funktionierendes Grundgerüst dessen Einzelne Befehle und Funktionen ich nach und nach kennenlernen kann.Vielen, vielen Dank!