VBO wird nicht gezeichnet



  • Hi,

    ich versuche gerade mir ein ganz simples Dreieck per VBO zeichnen zu lassen.
    Initialisiert wird mein VBO so:

    glGenBuffers(1, &vbo); 		//vbo ist ein unsigned int
    	glBindBufferARB(GL_ARRAY_BUFFER, vbo);
    	glEnableClientState(GL_VERTEX_ARRAY);
    	glBufferDataARB(GL_ARRAY_BUFFER, 3*3*sizeof(float), NULL, GL_STATIC_DRAW);
    	void *ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    	vboPointer = (TVert*)ptr;  	//TVert enthält drei floats: x,y,z
    
    	//Dreiecksdaten schreiben
    	vboPointer->x = 0.f;
    	vboPointer->y = 0.f;
    	vboPointer->z = 0.f;
    	vboPointer++;
    	vboPointer->x = 1.f;
    	vboPointer->y = 0.f;
    	vboPointer->z = 0.f;
    	vboPointer++;
    	vboPointer->x = 0.f;
    	vboPointer->y = 1.f;
    	vboPointer->z = 0.f;
    	glUnmapBuffer(GL_ARRAY_BUFFER);
    

    Gezeichnet wird dann mittels:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glLoadIdentity();
    	glTranslatef(-0.50f,-0.60f,-5.0f);
    	glInterleavedArrays(GL_V3F, sizeof(TVert), NULL);
    	glDrawArrays( GL_TRIANGLES, 0, 1 );
    	/*glBegin(GL_TRIANGLES);
    		glVertex3f( 0.f, 0.f, 0.f);
    		glVertex3f( 1.f, 0.f, 0.f);	
    		glVertex3f( 0.f, 1.f, 0.f);	
    	glEnd();*/
    

    Wenn ich den letzten Teil auskommentiere, erhatlte ich auch ein schönes weißes Dreieck, aber vom VBO sehe ich recht wenig.

    Weis wer was ich vergessen habe/falsch mache?
    Danke im Vorraus.



  • Du vermischst hier sämtliche OpenGL Techniken.
    Mein Tipp wäre auf 3.x Core Profile zu wechseln und VBO richtig zu lernen bzw nur noch damit zu arbeiten. Der immediate Mode (OpenGL 1.x) ist veraltet und sollte auch nicht mehr verwendet werden.
    Ausserdem brauchst du für ein Vertex Array keinen VBO.

    Hier mein Code zur Verwendung von VBO:

    Initialisierung:
    http://code.google.com/p/nightlighttv/source/browse/NightLight/trunk/NightLightDLL/NLSpriteBatcher.cpp#91

    Rendering:
    http://code.google.com/p/nightlighttv/source/browse/NightLight/trunk/NightLightDLL/NLSpriteBatcher.cpp#140

    Tutorial zu 3.x:
    http://www.arcsynthesis.org/gltut/

    edit:
    Ausserdem ist dein glDrawArrays aufruf falsch. Du willst 3 Vertices rendern, nicht 1.



  • Zuerstmal vielen Dank für die Antwort.
    Mit Übergabe von drei Vertices hat es geklappt, ich dachte
    das multipliziert es automatisch mit drei (da Triangle).

    Ich habe jetzt allerdings noch ein paar Fragen dazu:
    Dass ich das glBegin/glEnd Triangle nicht tun sollte weis ich,
    das war nur zum testen ob den prinzipiell was gezeichnet wird,
    oder ich die Initialisierung verkackt habe.

    Der Rest verwirrt mich jedoch teilweise.
    In dem Sprite-link werden sowohl ein VertexArray als auch ein
    VertexBuffer gebunden, bevor Daten mit glBufferData() geschrieben werden.
    Für was genau braucht es jetzt da zusätzlich das Array?

    So wie ich das verstehe ist ja der Unterschied eigentlich nur,
    dass der Array im Hauptspeicher liegt, das VBO im Grafikspeicher.



  • Das ist ein Vertex Array Object, kein herkömmliches Array.
    Damit kannst Du OpenGL mitteilen, wie deine Daten aufgeteilt sind.

    Meine VertexDaten:

    struct{
    	// Vertices
    	float x,y,z;
    
    	// Color
    	float r,g,b,a;
    
    	// Texture Coords
    	float s,t;
    };
    

    In der Renderfunktion:

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(NLVertexData), 0);
            glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(NLVertexData), (void*)(3*sizeof(float)));
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(NLVertexData), (void*)(7*sizeof(float)));
    

    GLSL Code:

    layout (location = 0) in vec4 vertex;
    layout (location = 1) in vec4 color;
    layout (location = 2) in vec2 texture_coord;
    

    Damit teile ich OpenGL mit, dass meine Daten jeweils 3 Werte, dann 4, dann 2 Werte enthalten.
    Und so werden die dann an den Shader übergeben.
    Damit spare ich mir feste Namen zu haben für diese Attribute und muss die nicht nachdem der Shader geladen wurde suchen.
    Es gibt auch andere Methoden, aber diese war für mich bisher am effektivsten.
    http://www.opengl.org/wiki/Vertex_Array_Object

    Und ja, die Daten liegen im VRAM.



  • Ahh, ich glaube so langsam verstehe ich.
    Lass es mich nochmal in eigenen Worten wiederholen, ob das auch so richtig ist:
    VAO selber sind für die Zustände gut, ich erspare mir also einen Aufruf von
    glColor(), etc. - dafür sind die Farbwerte direkt in dem Array.
    In dem Sprite-code hast du dir dann einen Shader geschrieben, der bei
    AttributIndex Null die Vertices sucht, bei 1 die Farben und bei 2 die Texturkoordinaten.

    Soweit korrekt?

    Wenn du nun noch gleichzeitig ein zweites VBO (z.B. m_vbo2) in Render() zeichnen wolltest,
    könntest du dann die VBA-Werte von dem ersten VBO nehmen?

    Also ca so:

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    // Enable Attribute Sets
    ...
    // Define Attribute Sets
    ...
    // Draw
    glDrawArrays(GL_TRIANGLES, 0, m_num_items*6);
    
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo2);   //das da ist neu!
    glDrawArrays(GL_TRIANGLES, 0, m_num2_items*6);
    
    // Disable Attribute Sets               
    ...
    


  • @Scorcher24:

    Eigentlich würde man doch das aktivieren der VertexAttribArrays und setzen der VertexAttribPointer auch in das VAO packen. Dann bräuchtest da da nicht bei jedem Durchlauf von renderObject() machen.



  • Habs eben gemacht:
    Stimmt. :).
    Danke für den Hinweis.
    Aber aktivieren musst sie dann trotzdem jeden Frame. Trotzdem wieder 3 Calls weniger pro Frame :).


Anmelden zum Antworten