OpenGl - schwarzes Fenster



  • Hallo allerseits,
    ich habe seit einer geschlagenen Stunde ein Problem, unzwar wollte ich einen OpenGL Beispielcode ausführen, nur das Fenster bleibt einfach schwarz, obwohl eigentlich ein Fenster mit vielen Pixeln in unterschiedlichen Graustufen entstehen sollte, ich hoffe ihr könnt mir helfen, hier der Code aus der Main Datei, solltet ihr den Code aus der screen_interface.h auch noch benötigen, dann sagt es mir bitte 🙂 Außerdem wird mir keine Fehlermeldung angezeigt.

    #include <windows.h>
    #include <gl\gl.h>
    #include <gl\glu.h>
    
    #include "screen_interface.h"
    
    MSG msg;
    unsigned char key_pressed( void );
    
    int WINAPI WinMain( HINSTANCE hinst, HINSTANCE pinst, LPSTR cmdl, int cmds )
    {
      screen_interface.open_window( hinst, 640, 480 );
    
      while( 1 )
      {
        if( key_pressed() ) break; 
    
        glBegin( GL_POINTS );
    
          GLubyte c = rand() % 256;
          GLdouble sx = rand() % x_res;
          GLdouble sy = rand() % y_res;
    
          glColor3ub( c, c, c );
          glVertex2d( sx, sy );
    
        glEnd();
      }
    
      return msg.wParam;
    }
    
    unsigned char key_pressed( void )
    {
      if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
      {
        if( msg.message == WM_QUIT || msg.message == WM_KEYDOWN ) return 1;
    
        TranslateMessage( &msg );
        DispatchMessage( &msg );
      }
    
      return 0;
    }
    


  • Ich geh mal davon aus, dass du Double-Buffering verwendest. Lösung: SwapBuffers
    Ansonsten solltest du noch wissen, dass das OpenGL was du lernst veraltetes OpenGL ist. Mehr zu dem Thema kannst du hier erfahren. Momentan ist man bei OpenGL 4.3 also der Thread zu modernem OpenGL ist auch nicht mehr ganz aktuell (behandlet OpenGL 3.x). Leider kann ich dir (falls du umsteigen willst, was ich auf jeden Fall empfehle) kein gutes Tutorial zu modernem OpenGL empfehlen (ich glaub zu 4.0 und höher gibt es auch kein gutes Tutorial). Hoffe ich konnte trotzdem helfen.

    floorball



  • Okey, danke schonmal für deine Antwort, nur habe mir jetzt mal ein paar Sachen zu dem SwapBuffer durchgelsen, doch ich steige noch nicht wirklich dahinter wie ich das Dingen benutze, könntest du es mir an hand meines Quelltextes erklären ?



  • Dafür bräuchten wir den Quellcode vom Screeninterface.
    Bin grad zu faul ins Regal zu gehen und das Buch rauszukramen um nachzugucken. :p



  • Bitteschön 🙂

    #ifndef SCREEN_INTERFACE_H
    #define SCREEN_INTERFACE_H
    
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    typedef unsigned char uchar;
    typedef unsigned short ushort;
    typedef unsigned long ulong;
    
    void exit_error( char *message );
    void exit_nofile( char *user, char *filename );
    void exit_nomemory( char *user, char *array );
    void message( char *title, char *message );
    
    #define x_res screen_interface.get_xr()
    #define y_res screen_interface.get_yr()
    
    #define WIN32_LEAN_AND_MEAN
    
    LRESULT CALLBACK main_window_procedure( HWND main_window_handle, UINT message, WPARAM wparam, LPARAM lparam )
    {
      if( message == WM_CLOSE ) {  PostQuitMessage( 0 );  return 0;  }
    
      return DefWindowProc( main_window_handle, message, wparam, lparam );
    }
    
    class hardware_interface
    {
      private:
    	uchar enlarged;
    	long x_resolution, y_resolution;
    
        HWND main_window_handle;
        HDC device_context;
        HGLRC rendering_context;
    	DEVMODE old_screen_settings;
    
        void initialise_platform( void );
    
      public:
        void fullscreen( HINSTANCE hInstance, long xr, long yr );
    	void open_window( HINSTANCE hInstance, long xr, long yr );
        void close_window( void );
    
    	long get_xr( void ) {  return x_resolution;  }
        long get_yr( void ) {  return y_resolution;  }
    
        void swap_buffers( void ) {  SwapBuffers( device_context );  }
    
    	hardware_interface( void ) : enlarged( 0 ), x_resolution( 0 ), y_resolution( 0 )
        {
          main_window_handle = NULL;  device_context = NULL;  rendering_context = NULL;
          memset( &old_screen_settings, 0, sizeof( old_screen_settings ) );
        }
       ~hardware_interface( void ) {  close_window();  }
    } screen_interface;
    
    void hardware_interface::fullscreen( HINSTANCE hinst, long xr, long yr )
    {
      x_resolution = xr;  y_resolution = yr;
      enlarged = 1;
    
      if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &old_screen_settings ) != TRUE )
    	exit_error( "Fehler während der Ermittlung der aktuellen Bildschirmbetriebsart.\n" );
    
      WNDCLASS winclass;
    
      winclass.style = CS_OWNDC;
      winclass.lpfnWndProc = main_window_procedure;
      winclass.cbClsExtra = 0;
      winclass.cbWndExtra = 0;
      winclass.hInstance = hinst;
      winclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
      winclass.hCursor = LoadCursor( NULL, IDC_ARROW );
      winclass.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
      winclass.lpszMenuName = NULL;
      winclass.lpszClassName = "Main Window";
      RegisterClass( &winclass );
    
      char window_name[] = "3D-Grafik Programmierung";
    
      main_window_handle = CreateWindowEx
      (
        WS_EX_TOPMOST, "Main Window", window_name, WS_VISIBLE | WS_POPUP,
        0,0, xr, yr, NULL, NULL, hinst, NULL
      );
    
      if( main_window_handle == 0 )
        exit_error( "Fehler beim Öffnen des Programmfensters.\n" );
    
      long bit_depth = 32;
    
      DEVMODE new_screen_settings;
    
      memset( &new_screen_settings, 0, sizeof( new_screen_settings ) );
      new_screen_settings.dmSize = sizeof( new_screen_settings );
      new_screen_settings.dmPelsWidth = xr;
      new_screen_settings.dmPelsHeight = yr;
      new_screen_settings.dmBitsPerPel = bit_depth;
      new_screen_settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    
      if( ChangeDisplaySettings( &new_screen_settings, 0 ) != DISP_CHANGE_SUCCESSFUL )
    	exit_error( "Fehler beim Einstellen der gewünschten Bildschirmbetriebsart.\n" );
    
      ShowCursor( 0 );
    
      initialise_platform();
    }
    
    void hardware_interface::open_window( HINSTANCE hinst, long xr, long yr )
    {
      x_resolution = xr;  y_resolution = yr;
      long bit_depth = 32;
    
      WNDCLASS winclass;
    
      winclass.style = CS_OWNDC;
      winclass.lpfnWndProc = main_window_procedure;
      winclass.cbClsExtra = 0;
      winclass.cbWndExtra = 0;
      winclass.hInstance = hinst;
      winclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
      winclass.hCursor = LoadCursor( NULL, IDC_ARROW );
      winclass.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
      winclass.lpszMenuName = NULL;
      winclass.lpszClassName = "Main Window";
      RegisterClass( &winclass );
    
      int x_add = 2 * (GetSystemMetrics( SM_CXBORDER ) + GetSystemMetrics( SM_CXEDGE ));
      int y_add = 2 * (GetSystemMetrics( SM_CYBORDER ) + GetSystemMetrics( SM_CYEDGE )) + GetSystemMetrics( SM_CYCAPTION );
    
      char window_name[] = "Test";
    
      main_window_handle = CreateWindow
      (
        "Main Window", window_name, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
        0, 0, xr+x_add, yr+y_add, NULL, NULL, hinst, NULL
      );
    
      if( main_window_handle == 0 )
        exit_error( "Fehler beim Öffnen des Programmfensters.\n" );
    
      initialise_platform();
    }
    
    void hardware_interface::initialise_platform( void )
    {
      PIXELFORMATDESCRIPTOR pfd;
      int format;
    
      memset( &pfd, 0, sizeof( pfd ) );
      pfd.nSize = sizeof( pfd );
      pfd.nVersion = 1;
      pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;// | PFD_DOUBLEBUFFER;
      pfd.iPixelType = PFD_TYPE_RGBA;
      pfd.cColorBits = 32;
      pfd.cDepthBits = 32;
      pfd.cAlphaBits = 8;
      pfd.iLayerType = PFD_MAIN_PLANE;
    
      device_context = GetDC( main_window_handle );
      format = ChoosePixelFormat( device_context, &pfd );
      SetPixelFormat( device_context, format, &pfd );
    
      rendering_context = wglCreateContext( device_context );
      wglMakeCurrent( device_context, rendering_context );
    
      glMatrixMode( GL_PROJECTION );  glLoadIdentity();
      gluOrtho2D( 0, x_resolution, 0, y_resolution );
      glMatrixMode( GL_MODELVIEW );
    }
    
    void hardware_interface::close_window( void )
    {
      if( enlarged )
        if( ChangeDisplaySettings( &old_screen_settings, 0 ) != DISP_CHANGE_SUCCESSFUL )
    	  exit_error( "Fehler beim Einstellen der ursprünglichen Bildschirmbetriebsart.\n" );
    
      wglMakeCurrent( NULL, NULL );
      wglDeleteContext( rendering_context );
      ReleaseDC( main_window_handle, device_context );
    
      DestroyWindow( main_window_handle );
    }
    
    void exit_error( char *message )
    {
      screen_interface.close_window();
    
      ShowCursor( 1 );
      MessageBox( NULL, message, "Programmabbruch nach einem schwerwiegenden Fehler", MB_OK );
    
      exit( 1 );
    }
    
    void exit_error( char *message, char *title )
    {
      screen_interface.close_window();
    
      ShowCursor( 1 );
      MessageBox( NULL, message, title, MB_OK );
    
      exit( 1 );
    }
    
    void exit_nofile( char *user, char *filename )
    {
      char string[ 500 ];
      sprintf( string, "%s: Fehler beim Öffnen der Datei '%s'.\n", user, filename );
    
      exit_error( string );
    }
    
    void exit_nomemory( char *user, char *array )
    {
      char string[ 500 ];
      sprintf( string, "%s: Fehler während der Reservierung von Arbeitsspeicher für das Array '%s'.\n", user, array );
    
      exit_error( string );
    }
    
    void message( char *title, char *message )
    {
      MessageBox( NULL, message, title, MB_OK ); 
    }
    
    #endif
    


  • Wav3oR schrieb:

    PIXELFORMATDESCRIPTOR pfd;
      int format;
     
      memset( &pfd, 0, sizeof( pfd ) );
      pfd.nSize = sizeof( pfd );
      pfd.nVersion = 1;
      pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;// | PFD_DOUBLEBUFFER;
      pfd.iPixelType = PFD_TYPE_RGBA;
      pfd.cColorBits = 32;
      pfd.cDepthBits = 32;
      pfd.cAlphaBits = 8;
      pfd.iLayerType = PFD_MAIN_PLANE;
    

    1. Das PFD_DOUBLEBUFFER flag wieder setzen.

    Wav3oR schrieb:

    Okey, danke schonmal für deine Antwort, nur habe mir jetzt mal ein paar Sachen zu dem SwapBuffer durchgelsen, doch ich steige noch nicht wirklich dahinter wie ich das Dingen benutze

    2. Double-Buffering verstehen: http://de.wikipedia.org/wiki/Doppelpufferung
    3. Anwenden: SwapBuffers verlangt als Parameter deinen Device Context (HDC). Wie im Wikipedia-Artikel steht rendert deine Anwendung in den Back-Buffer, also irgendwas im Hintergrund. Dieser Back-Buffer "gehört" deinem Device-Context. Der Device-Context hat allerdings auch den Front-Buffer. Mit SwapBuffers bringst du nun dein im Hintergrund gerendertes Zeug in den Vordergrund.
    ==> SwapBuffers muss am Ende deine Render-Loop stehen.
    Meine Empfehelung: Implementiere in deine Hardware_interface Klasse eine weitere Methode

    void swap(){
    SwapBuffers(this->device_context);
    };
    

    und ruf diese am Ende deiner while-Schleife auf:

    int WINAPI WinMain( HINSTANCE hinst, HINSTANCE pinst, LPSTR cmdl, int cmds )
    {
      screen_interface.open_window( hinst, 640, 480 );
    
      while( 1 )
      {
        if( key_pressed() ) break; 
    
        glBegin( GL_POINTS );
    
          GLubyte c = rand() % 256;
          GLdouble sx = rand() % x_res;
          GLdouble sy = rand() % y_res;
    
          glColor3ub( c, c, c );
          glVertex2d( sx, sy );
    
        glEnd();
        screen_interface.swap(); //<-- Hier
    
      }
    
      return msg.wParam;
    }
    

    Ich muss allerdings anmerken, dass ich mir nicht sicher bin ob das auch wirklich funktioniert, denn du hattest Double-Buffering ausgeschaltet. D.h. meine Fehlerdiagnose war vermutlich falsch. 😞 😞
    Naja, ich hoffe mal es funktioniert trotzdem 🙂

    floorball



  • @floorball:
    Die Funktion gibts btw schon, heißt swap_buffers.

    Bei mir gehts übrigens auch nicht.



  • Nathan schrieb:

    @floorball:
    Die Funktion gibts btw schon, heißt swap_buffers.

    Bei mir gehts übrigens auch nicht.

    Hab ich übersehen, habs nur kurz überflogen. Aber als ich sie grad eben gesucht hab,ist mir aufgefallen, dass glViewport fehlt. Hoffentlich hab ich diesmal nichts übersehen... :p
    @Wav3oR: Nach wglMakeCurrent aufrufen ersten beiden Parameter 0 und dann die breite und anschließend höhe deines Fensters
    Hoffe diesmal stimmt alles

    floorball

    EDIT: Verdammt, hat OpenGL nicht einen Default-Viewport der gesetzt wird wenn wglCreateContext aufgerufen wird?? Dann hab lieg ich wohl wieder falsch 😡 😡



  • So, habe mir jetzt auch mal einen richtigen Account hier gemacht, bzw. meinen alten wieder zum Leben erweckt 🙂 Nur deine Lösung funktioniert leider nicht, hast du vll noch eine andere Lösung ?

    Habe jetzt nochmal einen anderen Code versucht, doch wieder mit dem selbigen Ergebnis, ich poste den Code auch nochmal, vieleicht könnt ihr ja irgentwelche Parallen zwischen den beiden Codes erkennen, dass dies zu einer Lösung führt 🙂

    #include <windows.h>
    #include <gl\gl.h>
    #include <gl\glu.h>
    
    #include "screen_interface.h"
    
    struct vertex
    {
      GLint wx, wy;
    
      vertex( void ) : wx( 0 ), wy( 0 ) { }
      vertex( GLint x, GLint y ) : wx( x ), wy( y ) { }
    };
    
    MSG msg;
    unsigned char key_pressed( void );
    
    int WINAPI WinMain( HINSTANCE hinst, HINSTANCE pinst, LPSTR cmdl, int cmds )
    {
      screen_interface.open_window( hinst, 640, 480 );
    
      vertex a( 80, 80 );
      vertex b( 560, 400 );
      vertex c( 160, 150 );
      vertex d( 480, 330 );
    
      glClearColor( 0.25f, 0.2f, 1, 0 );
      glClear( GL_COLOR_BUFFER_BIT );
    
      while( 1 )
      {
        if( key_pressed() ) break;    
    
        vertex pos;
        pos.wx = a.wx + (rand() % (b.wx - a.wx + 1));
        pos.wy = a.wy + (rand() % (b.wy - a.wy + 1));
    
        if( pos.wx >= c.wx && pos.wx <= d.wx && pos.wy >= c.wy && pos.wy <= d.wy )
          continue;
    
        glBegin( GL_POINTS );
    
          GLubyte c = rand() % 256;
    
          glColor3ub( c, c, c );
          glVertex2i( pos.wx, pos.wy );
    
        glEnd();
      }
    
      return msg.wParam;
    }
    
    unsigned char key_pressed( void )
    {
      if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
      {
        if( msg.message == WM_QUIT || msg.message == WM_KEYDOWN ) return 1;
    
        TranslateMessage( &msg );
        DispatchMessage( &msg );
      }
    
      return 0;
    }
    

    ~Naris



  • Ich tue es zwar ungern, aber #push weil ich solangsam echt verzweifelt bin 😕



  • Prüf die Rückgabewerten von:
    - GetDC: Gibt NULL zurück wenns fehlschlägt
    - ChoosePixelFormat: Gibt 0 zurück wenns fehlschlägt
    - SetPixelFormat: Gibt FALSE zurück wenns fehlschlägt
    - wglCreateContext: Gibt NULL zurück wenns fehlschlägt
    - wglMakeCurrent: Gibt FALSE zurück wenns fehlschlägt

    Dann noch mithilfe GetLastError mehr erfahren

    floorball



  • Danke erstmal für deine Antwort, nur da ich noch eher ein Anfänger in der Programmierung bin, schaffe ich es gerade nicht mir die Rückgabewerten von den externen Funktion zu liefern, bzw. ich musste das mein Projekt fehlerfrei kompiliert wird in VS10 als SubSystem Windows einstellen, nur jetzt habe ich keine Konsole mehr um mir Sachen ausgeben zu lassen, obwohl ich als Projekt eine Konsoleanwendung habe, natürlich könnte ich die Sachen in eine Datei speichern, doch gibt es noch eine elegantere Lösung die Konsole wieder zu bekommen ?

    #Naris#



  • Das wär mir neu, dass man die Konsole deaktivieren muss...
    Ich bin jetzt auch nicht der Experte von VS, aber es gibt da eine Funktion, die heißt OutputDebugString, die hilft evtl.



  • Kriegs leider auch damit nicht hin, da das Rückgabe Format nicht stimmt, heißt kann darüber nix vom Typ HDC, welcher in der Variable verwendet wird, ausgeben. Solangsam denke ich echt drüber nach, das Buch in die Tonne zu drücken, nur hat leider 50 Takken gekostet ...



  • Naris schrieb:

    Kriegs leider auch damit nicht hin, da das Rückgabe Format nicht stimmt, heißt kann darüber nix vom Typ HDC, welcher in der Variable verwendet wird, ausgeben. Solangsam denke ich echt drüber nach, das Buch in die Tonne zu drücken, nur hat leider 50 Takken gekostet ...

    Das Buch bringt einem extrem veraltetes OpenGL bei, das stimmt.
    Aber es erklärt echt gut die mathematischen Grundlagen dahinter, ist in meiner Erfahrung gut als Begleitlektüre für bspw. ein Online-Tutorial geeignet.



  • Habe mich jetzt mal im Bereich "Wissenswertes" nach einem Tutorial für OpenGL 3.0 umgeschaut, nur das einziege Tutorial ist auf English, gibt es da schon etwas in der deutschen Kategorie was gut ist, weil das meiste was ich über Google finde bricht in der Tutorial Reihe aprubt ab.



  • Naris schrieb:

    Habe mich jetzt mal im Bereich "Wissenswertes" nach einem Tutorial für OpenGL 3.0 umgeschaut, nur das einziege Tutorial ist auf English, gibt es da schon etwas in der deutschen Kategorie was gut ist, weil das meiste was ich über Google finde bricht in der Tutorial Reihe aprubt ab.

    Ein vernünftiges Tutorial:
    http://arcsynthesis.org/gltut/

    Und als Programmierer solltest du englisch können. Ist, für mich, eine Grundvoraussetzung. Deutsche Programmierbücher sind meistens grausam.
    Ausserdem versperrst du dir den Weg zu vielen guten Tutorials und Beispielen ohne Englisch Kenntnisse.

    Davon abgesehen, verwende doch einfach SFML oder SDL um ein Fenster zu erstellen. Sich mit WinAPI rumzuärgern ist nicht lustig.



  • Vor allem wenn du ein OpenGL-Tut siehst was noch glBegin und glEnd nimmt, dann schaue es dir gar nicht erst an. Seit vielen Jahren und auch auf mobilen Geräten wird nur noch mit Buffern+Shadern programmiert.



  • 👎 native GUI
    👍 SDL

    Wieso der ganze Aufwand 😕 😕 😕 ?
    Wennst Events brauchst, dass SDL_PollEvent. Einfach geht's nicht!

    SDL2 + GL + GLEW

    int main (int argc, char** argv)
    {
        SDL_Init(SDL_INIT_VIDEO);
    
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    
        const int w = 600, h = 600;
        SDL_Window *win = SDL_CreateWindow("Sandbox", 0, 0, w, h, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
        SDL_GL_CreateContext(win);
        glewInit();
    
        glViewport(0,0,w,h);
    
        do {
        // your crap here !!
        SDL_GL_SwapWindow(win); // swaaaaap ...
        } while(foo);
    
        SDL_DestroyWindow(win);
        return 0;
    }
    

    // edit swap in einer Zeile



  • SFML geht auch und würde ich ehrlich gesagt bevorzugen mittlerweile, vor allem wenn man mit C++ arbeitet.


Anmelden zum Antworten