2016-04-21 2 views
0

Je tente de rendre Suzanne (à partir de Blender) dans OpenGL 3.3, mais les données du tampon ne semblent pas correctes. Je reçois ceci:GlBufferData et glBufferSubData Offset

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

J'ai aussi essayé de rendre une sphère avec une simple texture:

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

Mon importateur insère les données de sommet dans un std :: vecteur flotteurs simples:

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]); 
} 

je configurer le tampon de matrice comme suit:

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); 

Et puis-je insérer les données réelles à l'aide 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()); 

insérer également les indices de la même manière (GL_ELEMENT_ARRAY_BUFFER bien sûr).

Je signale alors l'information:

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())); 

Mon vertex shader prend dans les données comme ceci:

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

Suis-je en plissant les compensations?

EDIT: J'ai trouvé le plus gros problème! J'ai écrit un programme Lua externe pour convertir les fichiers obj en un format plus facile à importer, mais il a fini par jouer avec les données et en dupliquant les indices sur le "f #/#/# #/#/# #/#/# "donc le fichier ressemblait à ceci (x-> y-> x) au lieu de (x-> y-> z)

Correction d'autres erreurs grâce aux réponses ci-dessous!

+0

Bonne prise! Je suis content que vous ayez réussi à le faire fonctionner. – Exide

+0

Merci beaucoup pour votre aide! Tout fonctionne maintenant. : D J'ai réalisé que lorsque je dessinais un "wireframe" du mesh, j'utilisais GL_LINE_LOOP au lieu de glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); D'où les visages supplémentaires à l'intérieur de la maille. Voici la preuve: P https://gyazo.com/928640e745bfe3041798954f3f32079a – sheep

Répondre

0

Sans voir vos shaders je ne peux pas être sûr à 100% si vos appels à glVertexAttribPointer sont légitimes. Je ne peux pas dire si vous voulez des données de vertex entrelacées dans une seule VBO ou non. Ce que vous avez actuellement emballe toutes les positions de vertex en premier, puis toutes les coordonnées de texture, et enfin toutes les normales.

Pour imbriquer les données, vous devez d'abord les placer dans un seul tableau (ou vecteur) afin que chaque sommet répète le motif PPPTTNNN. Où PPP sont les flotteurs à trois positions, TT sont les deux flotteurs texcoord, et NNN sont les trois flotteurs normaux.

Il ressemblerait à quelque chose comme ça (en utilisant des types de faux, les valeurs et l'espacement pour illustrer le modèle):

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 
    ... 
}; 

Disons que vous mettez tout dans un seul vecteur appelé vertices, vous pouvez télécharger avec une seule commande:

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

Vous pouvez aussi mettre chaque attribut dans son propre VBO. Comment vous décidez de stocker les données sur le GPU est en définitive à vous.Si vous stockez volontairement les données comme vous l'avez, faites-le moi savoir dans les commentaires et je mettrai à jour la réponse.

Ok, maintenant les bits de shader.

Disons que vous avez un vertex shader qui ressemble à ceci:

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

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

Et un fragment shader qui ressemble à ceci:

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

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

Ensuite, vous voulez les glVertexAttribPointer appels suivants:

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); 

Remarquez comment le premier paramètre à chaque appel est un autre nombre. Ceci correspond à position, texcoord, normal respectivement dans le vertex shader.

De même, les coordonnées de texture sont typiquement seulement une paire de flottants (par exemple vec2 texcoord), donc j'ai changé le deuxième paramètre en 2 pour l'appel texcoord.

Enfin, le dernier paramètre, lors de l'utilisation d'un tableau entrelacé, n'a besoin que de spécifier le décalage par sommet. Ainsi, nous obtenons 0, 3, et 5 pour le décalage de position, le décalage de la texcoord et le décalage normal respectivement.

J'espère que cela vous mènera où vous voulez être. Pour plus d'informations, consultez le docs.gl page on glVertexAttribPointer.

+0

Merci pour la réponse! Je vais mettre à jour ma question avec les shaders! La façon dont j'obtiens les données du fichier obj facilite l'ajout des données au lieu de l'entrelacer. – sheep