OpenGL Vertex Arrays



  • Hallo,

    ich habe mir heute in OpenGL eine Klasse für Vertex Arrays geschrieben. Leider funktioniert diese nicht und ich weiß nicht, wo der Fehler steckt.

    Header Datei:

    #ifndef VERTEXARRAY
    #define VERTEXARRAY
    
    #define GLEW_STATIC
    #include <GL/glew.h>
    #include <vector>
    
    struct Vector2f {
        float x, y;
    
        Vector2f(const float& x = 0.0f,
                 const float& y = 0.0f)
                 : x(x), y(y) {}
    };
    
    struct Color4f {
        float r, g, b, a;
    
        Color4f(const float& r = 0.0f,
                const float& g = 0.0f,
                const float& b = 0.0f,
                const float& a = 1.0f)
                : r(r), g(g), b(b), a(a) {}
    };
    
    struct Vertex2f {
        Vector2f position;
        Color4f color;
    
        Vertex2f(const Vector2f& position,
                 const Color4f&  color)
                 : position(position), color(color) {}
    };
    
    class VertexArray {
    private:
        GLuint VertexArrayObject;
        bool created;
        std::vector<Vertex2f> vertexData;
    
    public:
        VertexArray();
        ~VertexArray();
    
        void create();
        void release();
    
        void addVertex(const Vertex2f& vertex);
    
        void render();
    };
    
    #endif
    

    Quellcode Datei:

    #include "VertexArray.hpp"
    
    ...
    
    void VertexArray::create() {
        glGenBuffers(1, &VertexArrayObject);
    	glBindBuffer(GL_ARRAY_BUFFER, VertexArrayObject);
    
    	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex2f) * vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
    	glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    
    ...
    
    void VertexArray::render() {
        if(!created) {
            created = true;
            create();
        }
    
        glEnableVertexAttribArray(GL_VERTEX_ARRAY);
        glEnableVertexAttribArray(GL_COLOR_ARRAY);
    
        glBindBuffer(GL_ARRAY_BUFFER, VertexArrayObject);
    
        glVertexPointer(2, GL_FLOAT, sizeof(Vertex2f), &vertexData[0] + 0);
        glColorPointer (4, GL_FLOAT, sizeof(Vertex2f), &vertexData[0] + 8);
    
    	glDrawArrays(GL_TRIANGLES, 0, vertexData.size());
    
        glDisableVertexAttribArray(GL_VERTEX_ARRAY);
    	glDisableVertexAttribArray(GL_COLOR_ARRAY);
    }
    

    Als ich anstelle

    glVertexPointer(2, GL_FLOAT, sizeof(Vertex2f), &vertexData[0] + 0);
    glColorPointer (4, GL_FLOAT, sizeof(Vertex2f), &vertexData[0] + 8);
    
    glVertexAttribPointer(...)
    

    verwendet habe, wurde meine Primitive gerendert, jedoch farblos.
    (Jedoch war der restliche Quellcode der Anwendung OK und das Vertex Array Objekt auch sachgemäß initialisiert:

    vb.addVertex(Vertex2f(Vector2f(-50,  -50), Color4f(1.0f, 0.0f, 0.0f, 1.0f)));
        vb.addVertex(Vertex2f(Vector2f(  0,   50), Color4f(0.0f, 1.0f, 0.0f, 1.0f)));
        vb.addVertex(Vertex2f(Vector2f( 50,  -50), Color4f(0.0f, 0.0f, 1.0f, 1.0f)));
    

    )

    Hat jemand eine Idee, wo der Fehler in der (vermutlich) render()-Methode liegt

    VG Gruenschnabel



  • glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex2f) * vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
    

    wie groß ist denn deine vertexData?
    wenn ich das richtig in Erinnerung habe, ist dein Array zu klein und du überspringst die Color-Daten



  • Ich glaube nicht, dass das Problem hier liegen wird.

    die Vertex2f Struktur hat eine Größe von 24Byte (float x, y, r, g, b, a).

    somit müsste

    24 Byte * Anzahl der Elemente

    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex2f) * vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
    

    vollkommen legitim sein.



  • Wenn Du VBOs benutzt kommt hier...

    glVertexPointer(2, GL_FLOAT, sizeof(Vertex2f), &vertexData[0]+0); 
    glColorPointer (4, GL_FLOAT, sizeof(Vertex2f), &vertexData[0]+8);
    

    ...als letzter Parameter nur der Offset innerhalb Deiner Vertex-Struktur rein.
    Von den Vertex-Daten die bei Dir im Hauptspeicher rumliegen, will OpenGL dann nichts wissen.



  • Wenn Du VBOs benutzt kommt hier...
    Code:
    glVertexPointer(2, GL_FLOAT, sizeof(Vertex2f), &vertexData[0]+0);
    glColorPointer (4, GL_FLOAT, sizeof(Vertex2f), &vertexData[0]+8);

    ...als letzter Parameter nur der Offset innerhalb Deiner Vertex-Struktur rein.
    Von den Vertex-Daten die bei Dir im Hauptspeicher rumliegen, will OpenGL dann nichts wissen.

    Das klingt nachvollziehbar aber führte leider auch nicht zum Ziel.



  • Weiterhin macht man entweder:

    glEnableClientState(GL_VERTEX_ARRAY);
        glBindBuffer(GL_ARRAY_BUFFER, VertexArrayObject);
        glVertexPointer(...);
    

    oder:

    glEnableVertexAttribArray(GL_VERTEX_ARRAY);
        glBindBuffer(GL_ARRAY_BUFFER, VertexArrayObject);
        glVertexAttribPointer(...);
    

    Mischen ist nicht gut.



  • glEnableClientState ist eher "veraltet" und glEnableVertexAttribArray wird nicht mit GL_VERTEX_ARRAY als Parameter gefüttert, sondern mit einem integer der ein von 0 zählender Index ist.

    z.B.

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    
    glBindBuffer(GL_ARRAY_BUFFER, VertexArrayObject);
    
    int stride = sizeof(GL_FLOAT) * ( 2 + 4 );
    
    glVertexAttribPointer(0, 2, GL_FLOAT, false, stride, reinterpret_cast<GLvoid*>(  0))
    glVertexAttribPointer(1, 4, GL_FLOAT, false, stride, reinterpret_cast<GLvoid*>( sizeof(GL_FLOAT) * 2 )
    
    glDrawArrays(GL_TRIANGLES, 0, vertexData.size());
    
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    

    Sinn der Attribut Arrays ist ja, dass nicht mehr "vorgeschrieben" wird was man mit den Daten im Shader macht.
    Im Shader must du dann entsprechend die richtigen Daten als Koordinaten oder Farbwert benutzen:

    layout(location = 0) in vec2 position;
    layout(location = 1) in vec4 color;
    

    Typen Definitionen die später byte genau einer API wie GL gefüttert weren sollen würde ich übrigens immer mit pragma pack umschließen:

    #pragma pack(push)
    #pragma pack(1)
    //Type Definitionen hier
    #pragma pack(pop)
    

    Da float eine 32bit type ist hat man dort dieses Problem nicht (außer es gibt compiler die auf 8 byte aufrunden?!). Aber wenn du z.B. char bzw. byte Werte verwendest, würden die meisten compiler mehr Speicher reservieren als du denkst. Und dann klapt es nicht mehr mit der Datenübertragung zu GL.



  • @Osbios Vielen Dank für deine Antwort,

    jetzt weiß ich, dass glEnableVertexAttribArray mit einem Indexparameter gefüttert wird
    und

    layout(location = 0) in vec2 position;
    layout(location = 1) in vec4 color;
    

    war der Schlüssel zum Erfolg.


Anmelden zum Antworten