Einstieg in OpenGL, Anfängerprobleme



  • 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



  • Du meinst es kracht schon in Zeile 11? Also wenn vertexvbo ein GLint ist wüsste ich nicht was dort für ein Problem auftreten sollte.

    Allerdings ist dort ein Fehler in der Zeile 16. Das vertices ist bereits die Adresse, weswegen der Adress Operator zu viel ist.

    Davon auszugehen das ein struct/class genau die Größe seiner Elemente hat kann auch kritisch werden, da der Compiler padding Bytes einfügen darf. Das dürfte hier wahrscheinlich nicht der Fall sein, aber wenn man wie in dem Beispiele sizeof benutzt, ist man auf der sicheren Seite.



  • Tobiking2 schrieb:

    Allerdings ist dort ein Fehler in der Zeile 16. Das vertices ist bereits die Adresse, weswegen der Adress Operator zu viel ist.

    Habs geändert, hat aber nicht viel gebracht. Ich hab mal nen paar Screens vom Debugger gemacht:

    Vor allen GL Funktionen:
    Bild 1

    Nach glGenBuffers():
    Bild 2
    Man sieht, das bei pindices und vertices einige Werte, aber nicht alle geändert wurden.

    Nach glBindBuffer():
    Bild 3
    Danach sieht man nurnoch misst im Debugger...

    Und dann nach glBufferData():
    Bild 4
    Jetzt sieht man nurnoch Fragezeichen...

    Bei glDrawElements(), dort wo die Zugriffverletzung geschieht, siehts dann so aus:
    Bild 5

    Und jetzt habe ich keine Ahnung, wieso die Daten so verhunzt werden...



  • Ich mal eine komplett neue Klasse erstellt nur für die VBO's und das Problem ist das gleiche.
    Bei einem Testprojekt, welches ich auf das minimum reduziert habe, und nur VBO's gezeichnet werden besteht auch das gleiche Problem. Also muss der Fehler ja irgendwie im Code liegen.



  • openglnoob schrieb:

    Ich mal eine komplett neue Klasse erstellt nur für die VBO's und das Problem ist das gleiche.
    Bei einem Testprojekt, welches ich auf das minimum reduziert habe, und nur VBO's gezeichnet werden besteht auch das gleiche Problem. Also muss der Fehler ja irgendwie im Code liegen.

    Kann die Graka das überhaupt? Mal nen ARB-String abgefragt und nachgeschaut?



  • Ja hab ich gemacht, und die GraKa sollte das können. Hier mal die glewinfo.txt die glew erstellt:
    http://www.file-upload.net/download-2834265/glewinfo.txt.html

    EDIT: Hab sie beim Filehoster hochgeladen, da die Datei zu lang für Forum oder Pastebin war.



  • So ich bin etzt glaube ich einen Schritt weiter.
    Also ich hab diese beiden globalen Variablen:

    GLuint vboid;
    GLint vertices[] = {0,0,50,0,50,50,0,50};
    

    Dann hab ich das in meiner Initialisierungfunktion:

    glGenBuffers(1, &vboid);
    glBindBuffer(GL_ARRAY_BUFFER, vboid);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    

    Das klappt auch alles soweit.

    Dann steht das hier in meiner Zeichenmethode:

    glBindBuffer(GL_ARRAY_BUFFER, vboid);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_INT, 0, BUFFER_OFFSET(0));
    glDrawArrays(GL_QUADS, 0, 8);
    glDisableClientState(GL_VERTEX_ARRAY);
    

    Da ist dann bei glDrawArrays eine Zugriffsverletzung, aber Debugger sieht ganz konform aus und ohne VBO klappt auch alles.


Anmelden zum Antworten