2016-04-21 15 views
0

Ich versuche Suzanne (von Blender) in OpenGL 3.3 zu rendern, aber die Pufferdaten scheinen nicht korrekt zu sein. Ich bekomme diese:glBufferData und glBufferSubData Offset

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

ich auch eine Kugel mit einer einfachen Textur zu machen versucht:

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

Mein Importeur fügt die Vertexdaten in ein std :: vector als einzelne Schwimmer:

if(line.substr(0,2) == "v ") 
{ 
/** Vertex position */ 
    std::istringstream s(line.substr(2)); 
    float v[3]; 
    s >> v[0]; s >> v[1]; s >> v[2]; 

    this->vertices.push_back(v[0]); 
    this->vertices.push_back(v[1]); 
    this->vertices.push_back(v[2]); 
} 

I Setup der Array-Puffer, wie folgt:

glGenBuffers(1, &this->vbo); 
glBindBuffer(GL_ARRAY_BUFFER, this->vbo); 

glBufferData(GL_ARRAY_BUFFER, 
    sizeof(float)*(this->vertices.size()+this->textures.size()+this->normals.size()), 
    NULL, 
    GL_STATIC_DRAW); 

Und dann füge ich die aktuellen Daten mit glBufferSubData

glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*this->vertices.size(), this->vertices.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*this->vertices.size(), sizeof(float)*this->textures.size(), this->textures.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*(this->vertices.size()+this->textures.size()), sizeof(float)*this->normals.size(), this->normals.data()); 

ich auch die Indizes in der gleichen Art und Weise einsetzen (GL_ELEMENT_ARRAY_BUFFER natürlich).

ich zeigen Sie dann auf die Informationen:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size())); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size()+this->vt.size())); 

Mein Vertex-Shader in den Daten wie dies geschieht:

layout(location = 0) in vec3 position; 
layout(location = 1) in vec2 texCoord; 
layout(location = 2) in vec3 normals; 

Bin ich die Versätze vermasseln?

EDIT: Ich fand das größte Problem! Ich schrieb ein externes Lua-Programm, um die Obj-Dateien in ein Format zu konvertieren, das leichter zu importieren war, aber es endete damit, dass ich mit den Daten herumhantierte und die Indizes auf den "f #/#/# #/#/# #/#/# "so sah die Datei so aus (x-> y-> x) anstelle von (x-> y-> z)

Auch ein paar andere Fehler behoben dank der Antworten unten!

+0

Guter Fang! Ich bin froh, dass du es zum Laufen gebracht hast. – Exide

+0

Vielen Dank für Ihre Hilfe! Alles funktioniert jetzt. : D Ich erkannte, dass wenn ich ein "Drahtmodell" des Netzes zeichnete, ich GL_LINE_LOOP statt glPolygonMode (GL_FRONT_AND_BACK, GL_LINE) verwendete; Daher die zusätzlichen Flächen auf der Innenseite des Netzes. Hier ist der Beweis: P https://gyazo.com/928640e745bfe3041798954f3f32079a – sheep

Antwort

0

Ohne Ihre Shader zu sehen kann ich nicht 100% sicher sein, ob Ihre Anrufe zu glVertexAttribPointer legitim sind. Ich kann auch nicht sagen, ob Sie interleaved Vertex Daten in einem einzigen VBO wollen oder nicht. Was Sie aktuell haben, packt zuerst alle Eckenpositionen, dann alle Texturkoordinaten und schließlich alle Normalen.

Um die Daten zu verschachteln, müssten Sie zuerst alles in ein einziges Array (oder Vektor) einfügen, so dass jeder Knoten das PPPTTNNN Muster wiederholt. Wo sind die drei Position Schwimmer, TT sind die beiden Texcoord Schwimmer, und NNN sind die drei normalen Schwimmer.

Es würde wie folgt aussehen (unter Verwendung von falschen Typen, Werte und Abstand, um die Muster zu zeigen):

float[] vertices = { 
/* pX, pY, pZ, tX, tY, nX, nY, nZ */ 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 1 
    0, 0, 0, 1, 1, 0, 0, 0,  // vertex 2 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 3 
    ... 
}; 

Lassen Sie uns sagen Sie ihn alle in einem einzigen Vektor vertices genannt, dann können Sie laden es mit einem einzigen Befehl:

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW); 

Sie könnten auch jedes Attribut in einen eigenen VBO setzen. Wie Sie entscheiden, die Daten auf der GPU zu speichern, liegt letztendlich bei Ihnen.Wenn Sie die Daten absichtlich so speichern, wie Sie sie haben, lassen Sie es mich in den Kommentaren wissen und ich werde die Antwort aktualisieren.

Ok, jetzt die Shader-Bits.

Angenommen, Sie haben einen Vertex-Shader bekam die wie folgt aussieht:

in vec3 position; 
in vec2 texcoord; 
in vec3 normal; 
out vec2 uv; 

void main() { 
    gl_Position = vec4(position, 1); 
    uv = texcoord; 
} 

und ein Fragment-Shader, der wie folgt aussieht:

in vec2 uv; 
uniform sampler2D image; 
out vec4 color; 

void main() { 
    color = texture(image, uv); 
} 

Dann würden Sie die folgenden glVertexAttribPointer Anrufe wollen:

int stride = (3 + 2 + 3) * sizeof(float); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)3); 
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)5); 

Beachten Sie, wie der erste Parameter für jeden Aufruf ein anderer ist Nummer. Dies entspricht position, texcoord, normal im Vertex-Shader.

Auch Texturkoordinaten sind in der Regel nur ein Paar floats (z. B. vec2 texcoord), also änderte ich den zweiten Parameter in 2 für die Texcoord-Aufruf.

Schließlich muss der letzte Parameter bei Verwendung eines Interleaved-Arrays nur den Offset pro Vertex angeben. Somit erhalten wir 0, 3 und 5 für Positionsoffset, Texcoord Offset und Normaloffset.

Hoffentlich bringt Sie das dahin, wo Sie sein wollen.

Überprüfen Sie die docs.gl page on glVertexAttribPointer für weitere Informationen.

+0

Danke für die Antwort! Ich werde meine Frage mit den Shadern aktualisieren! Die Art und Weise, wie ich die Daten aus der obj-Datei erhalte, erleichtert es, die Daten einfach anzuhängen, anstatt sie zu verschachteln. – sheep

Verwandte Themen