Einstieg in OpenGL, Anfängerprobleme



  • Hallo,

    anläßlich meines geplanten Einstiegs in OpenGL habe ich mich in diesem Forum angemeldet.

    Zu OpenGL habe ich mir mehrere Büher besorgt, u.a. den offiziellen Programming Guide von Shriner und zunächst mal erschlägt einen das Ganze ein bißchen.

    Ich würde gern so einsteigen, daß ich mit Hello WOrld überhaupt erstmal irgendeine kleine Konfiguration ans Laufen kriege, und mich von dort dann praktisch weitertasten.

    Das PRoblem derzeit ist das Hello WOrld.

    Mir ist nicht ganz klar,

    1.) welche Bibliotheks- und sonstige Dateien eingebunden werden sollen, also die Dateinamen dieser Dateien sind unterschiedlich bzw. nicht genau angegeben
    2.) VOn wo man die (welche???) am besten downloadet
    3.) in welchem Verzeichnis man diese am besten unterbringt und
    4.) wie man die an den COmpiler bzw. den Linker ankoppelt.

    Es gibt für MS VisualC++ eine Anleitung, mittels Assistent, wo man sich durchklicken kann, die Arbeit mit dem Assistenten bringt natürlich absolut eines nicht, den Durchblick.

    Ich würde das gern alles manuell einrichten, damit die Zusammenhänge klar sind.

    Und ich würde statt des MSVC++ am liebsten meinen DevCPP COmpiler weiterverwenden, weil mir das ganze MS Ambiente zu schwülstig und zu überladen wirkt. Bisher ist mir das aber nicht gelungen, der Compiler schluckt gewisse gl-Befehle, aber der Linker will´s nicht akzeptieren.

    Vielleicht kann mir ja jemand bei diesem Einstiegsproblem ein paar Tips geben.

    Gruß Alex2010



  • Je nachdem welches System und Compiler du verwendest sind es andere Dateien. Hängt auch davon ab was genau du brauchst(gl, glu, glut). Bei sind es mir libGL.so und libGLU.so, bei dir vermutlich irgendwas mit gl32. Die Dateien befinden sich im Verzeichnis deines Compilers, brauchst dir also nichts downloaden. Einfach mal danach suchen. Einstellen kannst du das in deiner IDE bei den Linker Settings.



  • alex2010 schrieb:

    Ich würde das gern alles manuell einrichten, damit die Zusammenhänge klar sind.

    Und ich würde statt des MSVC++ am liebsten meinen DevCPP COmpiler weiterverwenden, weil mir das ganze MS Ambiente zu schwülstig und zu überladen wirkt. Bisher ist mir das aber nicht gelungen, der Compiler schluckt gewisse gl-Befehle, aber der Linker will´s nicht akzeptieren.

    Siehe: http://www.c-plusplus.net/forum/viewtopic-var-t-is-237002.html

    Bezüglich Einrichtung siehe hier: http://nehe.gamedev.net/

    Du musst die entsprechenden Schritte dann Analog mit deiner IDE nachvollziehen.



  • Ja Dank für die beiden Antworten.

    Ich hab es jetzt ans Laufen gekriegt, war aber nicht einfach. Weil zu DevC++ im Netz viele veraltete Links stehen, die entweder tot sind oder nicht funktionieren.

    Man muß sich drum kümmern, daß gl.h glu.h glaux.h in das include-Verzeichnis kommen. Das ist der Compiler zufrieden.

    Aber nicht der Linker.

    Dem muß man in der /lib die glu32.dll anbieten und manuell einbinden.

    Nachdem das getan ist, akzeptiert er z. B. NeHe Tutorial-Code.

    An der Stelle stehe ich gerade. Versuche, den Code so zu vereinfachen, daß man gezielt Punkte zeichnen kann, bisher erfolglos.

    Es ist mir aber gelungen, EINEn Punkt zu zeichnen, immerhin. 😉

    Trotzdem, das Hello-World ist jetzt gelungen.

    Wobei es für einen C-Programmierer, der so gelernt hat:

    int main()
    {
    printf("Hello World \n");
    }

    ein absoluter Schock ist, wieviel Code man reinbeppen muß, nur um eine Windows-Applikation mit einem leeren Fenster zu erhalten.

    Das ist eigentlich nur mit c&p zu handeln. Verstehen tu ich das alles noch nicht so richtig, aber der Mensch soll ja lernfähig sein, sagt man. 😉

    Gruß Alex



  • Jetzt hab ich noch ein kleines Problemchen mit den Koordinaten.

    Normal müßte ja der Bildschirm in openGL von links unten aus im Pixelmodus bemaßt sein.

    Ist er aber nicht!

    Jedenfalls wenn man das Tutorial von NeHe zugrundelegt, die Basis-Datei, auf der alles andere aufbaut,

    http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=01

    Dann hat der irgendwo die Koordinaten so geändert, daß der Bildschirm von -1.0 bis +1.0 reicht. Um also eine Reihe Punkte zu zeichnen, muß man die Koordinaten relativ adressieren als Fließkomma in dem gen. Bereich.

    Ich hätte aber gern die echten Pixelwerte adressiert.

    An welcher Stelle werden die Koordinaten verfälscht?

    Oder liegt das an meinem SNippet hier:

    short r=55;
    	short g=100;
    	short b=250;
    
      	glBegin(GL_POINTS);
      		glColor3ub(r,g,b);
     	   for (int i=0;i<100;i++)
      	   {
      	   glVertex3d(0.01,i*0.01,0);					
             }  
    	glEnd();
    

    Vielen Dank für Hilfe! ALex2010



  • In deinem Snippet zeichnest du Punkte im Raum und keine Pixel. Dabei wird natürlich die ganz normale Projektion etc. verwendet. Zum Zeichnen von Pixeln könntest du z.B. glDrawPixels verwenden.



  • glDrawPixels ist afaik aber ziemlich langsam. Kannst auch eine orthografische Projektion nehmen. glOrtho(0, screenwidth, 0, screenheight, 0, 1), dann fängt er links unten an.



  • Hi.
    Ich finde es toll, dass Du mit OpenGL anfangen möchtest, denn viele wählen den "Standard-Weg" DirectX. Der Weg zum OpenGL-Programmierer ist steinig, aber es ist die Mühe wert. Zumindest in meinen Augen.

    Ich empfehle Dir nicht die "normalen" Header zu nehmen, sondern GLew. Das spart Dir viel Code mit dem Du Erweiterungen aus den DLL laden müsstest und kannst sehr einfach die *_ARB Funktionen nutzen, welche erweiterte Funktionalitäten zur Verfügung stellen wie Shader oder andere lustige Dinge. Oft muss zwar für Standard-Funktionen trotzdem gegen die opengl32.lib gelinkt werden, aber alle Erweiterungen sind in glew enthalten.

    Ein Fenster für OpenGL erhälst Du schneller mit GLUT, SDL oder SFML je nach gusto. Ich bevorzuge die SDL.

    Aufgrund Deines Codes möchte ich noch anmerken, dass der Weg über glBegin() und glEnd() veraltet ist. Nehe war immer eine gute Quelle und ich habe Respekt vor dem Mann aber seine Tutorials sind leider veraltet und keine gute Referenz mehr für jemand der grade anfängt, da man es "falsch" lernt. Natürlich geht es noch und das ist auch nicht abwertend gegenüber Nehe gemeint.
    Wenn Du wirklich in OpenGL einsteigen willst, möchte ich Dir folgendes Buch ans Herz legen, welches es (leider) nur auf Englisch gibt, aber es ist gut zu lesen. Zumindest für mich:
    http://www.amazon.de/OpenGL-SuperBible-Comprehensive-Tutorial-Reference/dp/0321712617/ref=sr_1_fkmr0_1?ie=UTF8&qid=1284751710&sr=8-1-fkmr0

    rya.



  • @Scorcher24
    Wenn der Weg über glBegin() und glEnd() veraltet ist, wie soll man dann etwas zeichnen? Bei meiner ganzen google Erfahrung habe ich noch nie etwas anderes gesehen 😃



  • openglnoob schrieb:

    @Scorcher24
    Wenn der Weg über glBegin() und glEnd() veraltet ist, wie soll man dann etwas zeichnen? Bei meiner ganzen google Erfahrung habe ich noch nie etwas anderes gesehen 😃

    Beispiel aus einem Projekt von mir:

    void NLPlayfield::renderObject()
    {
    	glEnableClientState(GL_VERTEX_ARRAY);
    	glEnableClientState(GL_COLOR_ARRAY);
    	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    	glVertexPointer(3, GL_FLOAT, 0, m_detail_layer.getVertices());
    	glColorPointer(4, GL_FLOAT, 0, m_detail_layer.getColor());
    	glTexCoordPointer(2, GL_FLOAT, 0, m_detail_layer.getTextureCoords());
    	glDrawArrays(GL_QUADS, 0, m_detail_layer.getNumVertices());
    
    	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    	glDisableClientState(GL_COLOR_ARRAY);
    	glDisableClientState(GL_VERTEX_ARRAY);
    }
    

    Entweder über Arrays oder über VBO's.
    http://www.songho.ca/opengl/gl_vbo.html
    rya.



  • @Scorcher24

    nope, du benutzt immer noch deprecated methoden. Der einzige konforme weg ist über Shader.



  • otze schrieb:

    @Scorcher24

    nope, du benutzt immer noch deprecated methoden. Der einzige konforme weg ist über Shader.

    Öhm, naja im 3.0 Header waren die noch drin...
    Aber seit wann sind dann VBO bitte deprecated?
    Meh, langsam blick ich selber nimmer durch 😛
    Wird Zeit dass mein neues OpenGL Buch kommt :D.

    Aber nur über Shader? Hört sich unlustig an. Ehrlich gesagt halt ichs für schwachsinnig alles nur noch über Shader zu machen.
    rya.



  • Die VBO's klingen ganz gut, und ich hab mir die jetzt mal angeschaut.
    Aber diese Zeilen versursachen immer eine Zugriffsverletzung an Position 0x00000000:

    GLuint vbo;
    glGenBuffers(1, &vbo);
    

    Da scheiterts bei mir schon bei der allerersten Funktion 😃



  • Hast Du die Funktion aus der .dll geladen mit (w/x)glGetProcAdress oder hast Du GLew verwendet? Hast Du in dem Fall glewInit() aufgerufen vor dem Call?
    In OpenGL werden "Zusatzfunktionen" aus den .dll des Treibers geladen (ATI/NVIDIA). Windows selbst stellt OpenGL nur bis V1.5 zur Verfügung.
    rya.



  • Hey danke, mit glewInit() klappt jetzt alles 🙂



  • Ich hab jetzt noch eine Frage zu VBO's:
    Hier steht, dass ab OpenGL 3.1 die VBO's aus dem core gelöscht wurden. Funktioniert dann noch sowas:

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    

    oder muss ich das schreiben:

    glGenBuffersARB(1, &vbo);
    glBindBufferARB(GL_ARRAY_BUFFER, vbo);
    

    oder funktioniert dann noch beides (nicht)?
    Und wenn ich das dann richtig verstehe, kann man ab OpenGL 3.1 nurnoch über Shader rendern? Ich hab nur mal kurz ein Tutorial über Shader überflogen, und das scheint wahnsinnig kompliziert zu sein.



  • Bei OpenGL 3.1 und 3.2 sind die deprecated Funktionen erst rausgeflogen. Daher sind sie in den 3.0 Headern natürlich noch enthalten, sollten aber entsprechend markiert sein. Da gab es irgendwie eine möglichkeit sich dafür Warnungen ausgeben zu lassen, weiß aber grad nicht mehr wie das genau ging.

    Was jetzt kommt ist wahrscheinlich nicht ganz akkurat, sollte aber das Prinzip grob beschreiben:

    VBOs gibt es auch noch, nur werden sie anders verwendet. Es wird nur nicht mehr zwischen den Verwendungszwecken der VBO unterschieden. Egal ob Vertex Daten, Farbe, Texturkoordinaten oder sonstiges, alles wird generisch dem Shader übergeben, der damit dann entsprechend umgeht.

    Als Beispiel die entsprechenden Codeausschnitte von http://sites.google.com/site/opengltutorialsbyaks/introduction-to-opengl-3-2---tutorial-01

    glGenBuffers(2, &m_vboID[0]);
    
    //Ersten Buffer auswählen, mit Vertex Daten füllen, als Attribut 0 für den Shaders setzen und dieses Attribut aktivieren
    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[0]);
    glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vert, GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
    glEnableVertexAttribArray(0);
    
    //Zweiten Buffer auswählen, mit Farb Daten füllen und als Attribut 1 für den Shader setzen und dieses Attrobut aktivieren
    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[1]);
    glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), col, GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1); 
    
    // Im Shader
    #version 150 core
    
    in vec3 in_Position; // Attribut 0
    in vec3 in_Color; // Attribut 1
    
    out vec3 ex_Color;
    
    void main(void)
    {
          gl_Position = vec4(in_Position, 1.0); // in_Position wird für die Vertex Daten verwendet
          ex_Color = in_Color; // in_Color wird für die Farbe verwendet
    }
    


  • Hmm, das mit den Shadern wird mir zu komplex. Erstmal will ich normale VBO's zum laufen bekommen.
    Mein Problem jetzt ist jetzt, dass ich jedes mal eine Zugriffsverletzung bekomme. Der Grund dafür ist, dass wenn ich glBindBuffer() aufrufe, meine Variablen Werte anscheinend "random" zusammengewürfelt werden. Wenn ich diese Vektorkoordinaten vorher habe:

    0, 30, 800, 30, 400, 60
    

    ist daraus nach glBindBuffer das hier geworden:

    21767392, 1773223936, 56667488, 56577272, 20966352, 56332096
    

    Die Pointer zeigen dann auch ins jenseits und einem std::vector wurden einfach mal so 5 Elemente mit random Werten angehängt.

    Was mach ich diesmal falsch?

    Und da habe ich noch eine zweite Frage.
    Im Internet sieht man eigentlich immer sowas:

    glVertexPointer(3, GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(0));
    

    Wenn ich die MSDN aber richtig verstanden habe, muss der dritte Paramer nicht das offset sein, und der viere Parameter ein Pointer zu dem ersten Elements der Vertex-Arrays 😕



  • Was machst du da denn jetzt genau? Weder das glGenBuffers noch das glBindBuffer hat etwas mit deinen Vertex Daten zu tun, daher verstehe ich nicht was da überschrieben werden soll.

    openglnoob schrieb:

    Und da habe ich noch eine zweite Frage.
    Im Internet sieht man eigentlich immer sowas:

    glVertexPointer(3, GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(0));
    

    Wenn ich die MSDN aber richtig verstanden habe, muss der dritte Paramer nicht das offset sein, und der viere Parameter ein Pointer zu dem ersten Elements der Vertex-Arrays 😕

    Der dritte Parameter ist stride, das ist die Länge eines Elementes, also ist das sizeof(MyVertex) richtig. Der vierte Parameter ist eigentlich der Pointer zu den Daten, allerdings kommen die Daten aus dem VBO und der Parameter fungiert deswegen als Offset. Die Information scheint in der MSDN zu fehlen. In http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml steht es allerdings drin. Kann gut sein das die MSDN bei OpenGL auf einem sehr alten Stand ist.



  • Tobiking2 schrieb:

    Was machst du da denn jetzt genau? Weder das glGenBuffers noch das glBindBuffer hat etwas mit deinen Vertex Daten zu tun, daher verstehe ich nicht was da überschrieben werden soll.

    Also mein Code sieht jetzt so aus:

    void OpenGL::init(void) {
    	vertices[0].x = 0;
    	vertices[0].y = 30;
    	vertices[1].x = 800;
    	vertices[1].y = 30;
    	vertices[2].x = 400;
    	vertices[2].y = 60;
        pindices[0] = 0;
        pindices[1] = 1;
        pindices[2] = 2;	
        glGenBuffers(1, &vertexvbo);
    	glGenBuffers(1, &indexvbo);
    	glBindBuffer(GL_ARRAY_BUFFER, vertexvbo);
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexvbo);
    	// 4 Byte * 3 Vertex * 2 Elemente
    	glBufferData(GL_ARRAY_BUFFER, 4*3*2, &vertices, GL_STATIC_DRAW);
    	// 2 Byte * 3 Vertex
    	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2*3, pindices, GL_STATIC_DRAW);
    };
    
    void OpenGL::draw(void) {
    	glEnableClientState(GL_VERTEX_ARRAY);
    	glBindBuffer(GL_ARRAY_BUFFER, vertexvbo);
    	glVertexPointer(2, GL_INT, sizeof(MyVertex), BUFFER_OFFSET(0));
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexvbo);
    	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &indexvbo);
    	glDisableClientState(GL_VERTEX_ARRAY);
    };
    

    Sobald jetzt das erste glBindBuffer aufgerufen wird, werden ALLE Daten in der Klasse, egal ob die irgendwas mit VBO etc. zu tun haben sinnlos überschrieben. Kurz gesagt ist die ganze Klasse nachher nurnoch Datenschrott.
    Mein Code habe ich hierher


Anmelden zum Antworten