PDA

View Full Version : Setting normals for a 3D Cube

Nanashi
06-24-2015, 02:11 PM
Hello!
So im a fresh beginner of opengl programming and im confronted with a simple problem.
I have a cube with a texture. Now i want it to react to lighting. For that i have to give the cube some normals.

Here are my cube functions:

GLuint VertexArrayIDSolidCube = 0;

static void createCube()
{
GLuint vertexbuffer;
GLuint normalbuffer;

glGenVertexArrays(1, &VertexArrayIDSolidCube);
glBindVertexArray(VertexArrayIDSolidCube);

// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, -1.0f,-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, // Left Side

-1.0f,-1.0f,-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,-1.0f, // Left Side
1.0f, 1.0f,-1.0f, -1.0f,-1.0f,-1.0f, -1.0f, 1.0f,-1.0f, // Back Side
1.0f,-1.0f, 1.0f, -1.0f,-1.0f,-1.0f, 1.0f,-1.0f,-1.0f, // Bottom Side
1.0f, 1.0f,-1.0f, 1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f, // Back Side
1.0f,-1.0f, 1.0f, -1.0f,-1.0f, 1.0f, -1.0f,-1.0f,-1.0f, // Bottom Side
-1.0f, 1.0f, 1.0f, -1.0f,-1.0f, 1.0f, 1.0f,-1.0f, 1.0f, // Front Side
1.0f, 1.0f, 1.0f, 1.0f,-1.0f,-1.0f, 1.0f, 1.0f,-1.0f, // Right Side
1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-1.0f, 1.0f, // Right Side
1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-1.0f, -1.0f, 1.0f,-1.0f, // Top Side
1.0f, 1.0f, 1.0f, -1.0f, 1.0f,-1.0f, -1.0f, 1.0f, 1.0f, // Top Side
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,-1.0f, 1.0f // Front Side
};

glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

static const GLfloat normals[] = {
-1.0f, 0.0f, 0.0f, // Left Side
0.0f, 0.0f, -1.0f, // Back Side
0.0f,-1.0f, 0.0f, // Bottom Side
0.0f, 0.0f, -1.0f, // Back Side
-1.0f, 0.0f, 0.0f, // Left Side
0.0f, -1.0f, 0.0f, // Bottom Side
0.0f, 0.0f, 1.0f, // front Side
1.0f, 0.0f, 0.0f, // right Side
1.0f, 0.0f, 0.0f, // right Side
0.0f, 1.0f, 0.0f, // top Side
0.0f, 1.0f, 0.0f, // top Side
0.0f, 0.0f, 1.0f, // front Side

};

glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW);

glEnableVertexAttribArray(0); //
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);

// 2nd attribute buffer : normals
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glEnableVertexAttribArray(1); //
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);

glBindVertexArray(0);
}

void drawCube()
{
if (!VertexArrayIDSolidCube)
{
createCube();
}

// Draw the triangles !
glBindVertexArray(VertexArrayIDSolidCube);
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
}

The result is, that it somewhat messes up my texture and it still doesnt react to lighting.
Now when i try setting the attribute number of the normals from 1 to 2, my texture disappears, and only some triangles show light and definetly not how its supposed to be.

Im assuming i have to set up some indices?
But i have no clue how that works.

I'd really appreciate any help.

Greetings.

GClements
06-24-2015, 05:07 PM
For a flat-shaded cube, you need 24 distinct vertices (4 per face), each of which needs a position, a normal, and texture coordinates, i.e. each attribute array needs to contain 24 vectors (3-element vectors for position and normal, 2-element vectors for texture coordinates).

If you're using triangles, you either need to duplicate the shared vertices, resulting in 36 vertices (3 per triangle, 6 per face), or use glDrawElements() with 36 indices (so you only need to duplicate the indices of shared vertices, rather than duplicating the attribute data).

(It is actually possible to reduce the number of vertices, but that adds complexity, and you need to get the simple version working first).

Also, I'd suggest that you don't hard-code attribute indices. Use glGetAttribLocation() even if the shader uses layout(location=) qualifiers on the attributes. This avoids having to chase down errors when you change the shader but not the program or vice-versa. If you need to force specific attribute locations (e.g. to ensure that multiple shaders use the same locations for the same attributes), define named constants and use glBindAttribLocation().

Nanashi
06-24-2015, 05:41 PM
Ah yeah. Honestly i figured it out like a second ago. For me it was logical, that you give a face a normal vector. After some trying i realized that you have to apply the normals to the verticles.

I will also think about your other hints.

Thanks for your help =)

greetings