PDA

View Full Version : A few questions from a newbie



Dexter90
04-23-2015, 11:50 AM
Hello

I've recently started to use open gl and I've been expericing a few difficulties to get into into. I'm "playing around" with some .obj and .mtl loaders. I want to load them to my screen and apply them some transformations like lightning, textures and stuff like that using shaders and so on.

I can load a few objs correctly, like the models from hammer and pawn, they have the right shape etc, but models that have more faces don't look good. I can load them but then look flateneed. I've been loading pencil or archer and they just don't look good.

Also, I don't understand how can apply to the hammer 2 different textures. For example, I want the cable to have a texture, but I want the head to have another.

For now I'm creating 3 buffers, one with the vertices faces, one with the textures and one with the normals and then I'm loading them all. I can share some pieces of my code, but here it is my loadObj:


// make and bind the VAO
glGenVertexArrays(1, &gVAO);
glBindVertexArray(gVAO);

// make and bind the VBO
glGenBuffers(1, &gVBO);
glBindBuffer(GL_ARRAY_BUFFER, gVBO);
glBufferData(GL_ARRAY_BUFFER, f.vertices.size() *sizeof(glm::vec3), &f.vertices[0], GL_STATIC_DRAW);

// connect the xyz to the "vert" attribute of the vertex shader
glEnableVertexAttribArray(gProgram->attrib("vert"));
glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL);

GLuint texturesVerts;
glGenBuffers(1, &texturesVerts);
glBindBuffer(GL_ARRAY_BUFFER, texturesVerts);
glBufferData(GL_ARRAY_BUFFER, f.textures.size() *sizeof(TextureC), &f.textures[0], GL_STATIC_DRAW);

// connect the uv coords to the "vertTexCoord" attribute of the vertex shader
glEnableVertexAttribArray(gProgram->attrib("vertTexCoord"));
//glVertexAttribPointer(gProgram->attrib("vertTexCoord"), 2, GL_FLOAT, GL_TRUE, 5 * sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
glVertexAttribPointer(gProgram->attrib("vertTexCoord"), 2, GL_FLOAT, GL_FALSE, 0, NULL);

GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, f.normals.size() *sizeof(Normal), &f.normals[0], GL_STATIC_DRAW);

glEnableVertexAttribArray(gProgram->attrib("vertNormal"));
glVertexAttribPointer(gProgram->attrib("vertNormal"), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

// unbind the VAO
glBindVertexArray(0);

my "F" has 5 vectores. One with all the faces with their vertices, textures and normals separated by materials. One with all the materials separated by name. One with all the vertices, other with all the textures and other will all the normals.

Any help would be very welcome. Thank you in advance.

Alfonse Reinheart
04-23-2015, 12:38 PM
I can load a few objs correctly, like the models from hammer and pawn, they have the right shape etc, but models that have more faces don't look good. I can load them but then look flateneed. I've been loading pencil or archer and they just don't look good.

It's not really clear what you mean by "flattened". A picture could be quite helpful.


Also, I don't understand how can apply to the hammer 2 different textures. For example, I want the cable to have a texture, but I want the head to have another.

There are several ways to go about that. The most traditional way is to make this two objects. One that gets a wood texture and the other that gets a metal texture. I don't work with .obj files, so I don't know if it's possible to have separate, named meshes in the same file. But most 3D modelling packages give you some way to assign different faces in the same "model" to different textures. The exporter generally sorts them out, collating faces that use the same texture to particular meshes within a conceptual "model". Here, you have to issue two separate rendering commands, swapping the textures between the two.

Alternatively, one can use a texture atlas (https://en.wikipedia.org/wiki/Texture_atlas), where the wood and hammer-head texture are both in the same actual texture. The individual faces are simply mapped to different parts of the same texture. With this technique, you issue only one rendering command, since both parts of the mesh use the same texture.

A more modern approach to texture atlases is to use array textures (https://www.opengl.org/wiki/Array_Texture), which more or less combines the above. Here, your texture coordinates are three-dimensional. The third dimension selects which "page" in the array of textures to use. So one page is for the wooden handle, and another page is for the metal hammer-head. But because array textures store both textures in the same OpenGL texture object, you still only issue one rendering command.

GClements
04-23-2015, 12:41 PM
Also, I don't understand how can apply to the hammer 2 different textures. For example, I want the cable to have a texture, but I want the head to have another.
The simple way is to split the model into multiple parts such that each part has a single texture, and render each part separately.

The efficient way is to use either a texture atlas (multiple textures packed into a single texture, with the texture coordinates adjusted accordingly) or an array texture (or an array of samplers) with the texture ID stored either in the third component of the texture coordinates or in a separate attribute. Either approach will require splitting the mesh along texture seams (where the faces on either side of an edge have different textures).

Dexter90
04-23-2015, 01:09 PM
Here's some examples of my obj loader.

Like I said, hammer looks ok, but I'm not applying the texture correcly in the head, I need to calculate something the Ka, Kd etc from the mtl's to apply it but I really don't understand why.

The other 2 are horrible. Flattened and with a very wierd rotation (all the objects rotate) with very low fps.

1761

reader1
04-23-2015, 06:32 PM
you may choose suitable angle of projection ro look more stero. and suitable coordinate. try to use different arguments of glLookat.

Dexter90
04-25-2015, 05:27 AM
you may choose suitable angle of projection ro look more stero. and suitable coordinate. try to use different arguments of glLookat.

glm::mat4 camera = glm::lookAt(cameraCenter, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
gProgram->setUniform("camera", camera);

I'm using this lookat, do you think this the the problem for the flattened surfaces?