0
\$\begingroup\$

I've been following this tutorial on OpenGL and LWJGL and at some point three different lists are introduced without really explaining how they interact with each other. Can someone explain how it works?

float[] positions = new float[] {
    -0.5f,  0.5f,  0.5f, // V0
    -0.5f, -0.5f,  0.5f, // V1
     0.5f, -0.5f,  0.5f, // V2
     0.5f,  0.5f,  0.5f, // V3
    -0.5f,  0.5f, -0.5f, // V4
     0.5f,  0.5f, -0.5f, // V5
    -0.5f, -0.5f, -0.5f, // V6
     0.5f, -0.5f, -0.5f, // V7
    
    // For text coords in top face
    -0.5f, 0.5f, -0.5f, // V8: V4 repeated
     0.5f, 0.5f, -0.5f, // V9: V5 repeated
    -0.5f, 0.5f,  0.5f, // V10: V0 repeated
     0.5f, 0.5f,  0.5f, // V11: V3 repeated

    // For text coords in right face
    0.5f,  0.5f, 0.5f, // V12: V3 repeated
    0.5f, -0.5f, 0.5f, // V13: V2 repeated

    // For text coords in left face
    -0.5f,  0.5f, 0.5f, // V14: V0 repeated
    -0.5f, -0.5f, 0.5f, // V15: V1 repeated

    // For text coords in bottom face
    -0.5f, -0.5f, -0.5f, // V16: V6 repeated
     0.5f, -0.5f, -0.5f, // V17: V7 repeated
    -0.5f, -0.5f,  0.5f, // V18: V1 repeated
     0.5f, -0.5f,  0.5f, // V19: V2 repeated
};

float[] texturePos = new float[]{
    // Front Face
    0.0f, 0.0f,
    0.0f, 0.5f,
    0.5f, 0.5f,
    0.5f, 0.0f,
    
    // Behind Face
    0.0f, 0.0f,
    0.5f, 0.0f,
    0.0f, 0.5f,
    0.5f, 0.5f,
    
    // Top Face
    0.0f, 0.5f,
    0.5f, 0.5f,
    0.0f, 1.0f,
    0.5f, 1.0f,

    // Right Face
    0.0f, 0.0f,
    0.0f, 0.5f,

    // Left Face
    0.5f, 0.0f,
    0.5f, 0.5f,

    // Bottom Face
    0.5f, 0.0f,
    1.0f, 0.0f,
    0.5f, 0.5f,
    1.0f, 0.5f,
};

int[] indexes = new int[]{
    0,  1,  3,  3,  1,  2,  // Front face
    8,  10, 11, 9,  8,  11, // Top Face
    12, 13, 7,  5,  12, 7,  // Right face
    14, 15, 6,  4,  14, 6,  // Left face
    16, 18, 19, 17, 16, 19, // Bottom face
    4,  6,  7,  5,  4,  7   // Back face
};

For example, why are there only 2 vertices in the Right and Left face of the texture coords? Also, I've noticed that the texture I'm drawing on a cube is insideout on those faces. Could that be the reason?

Thanks in advance.

\$\endgroup\$
0
\$\begingroup\$

In the graphics pipeline, we need a vertex for each distinct combination of attributes, like position, texture coordinate, normal vectors, etc.

So if you have two faces meeting at a corner, and on one face that corner should show the bottom-right part of the texture, but on the other face that corner should show the bottom-left part of the texture, then you actually need two vertices there. Both with the same position, but with different texture coordinates, one for each face to use. This is how we make what we call a texturing or UV mapping seams, where different parts of the texture get mapped to adjacent parts of the geometry.

That's why, even though a cube only has 8 corners, we have a list of 20 vertices here: 20 positions, and 20 texture coordinates matching them. Some of the positions and texture coordinates need to be repeated in different combinations to get the texture wrapping around the cube as desired.

Note that this is still less than the full 24 (6 x 4) we'd get if we wanted 4 unique vertices for every face, so we're still sharing some of the vertices. It looks like the author of this data decided that the mirrored texture was "good enough" for their needs, so they let two of the faces stay back-to-front to save 4 vertices.

When we draw this geometry, we start with the index buffer. We read out three consecutive indices, and that tells us which three vertices, in which order, make up one triangle.

So the first triangle uses vertices 0, 1, and 3 - that's the first, second, and fourth items in the positions and texturePos lists. Then the next triangle uses vertex 3 and 1 again (the shared diagonal across the middle of the face), and vertex 2 (the opposite corner).

The order of the vertices is important in that it tells the GPU which way the triangle should face: 0, 1, 3 faces out, while inverting any two indices like 0, 3, 1 would make the triangle face inward. This order is called the "winding", for the way our iteration winds around the triangle's perimeter.

You can see in these lines:

12, 13, 7,  5,  12, 7,  // Right face
14, 15, 6,  4,  14, 6,  // Left face

that the left and right faces still have 6 indices = 2 triangles each, and they touch 4 distinct vertices, not just two.

But two corners of each of those faces, 5 and 7 for the right face, and 4 and 6 for the left face, are shared with the back face:

4,  6,  7,  5,  4,  7   // Back face

So that's why there's only two unique vertices' worth of position and texture coordinate information set aside for them in the lists above. They re-use two of the back face's vertices each.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you so much for you answer! I tried adding the two vertices that were omitted since I don't want a mirrored texture but the cube is not rendering well anymore (the cube is there but the texture coordinates are wrong apart of the front face). Here's the code on pastebin (Basically I've added the four missing vertices and reassigned all of the indices, but it still looks wrong, as if the textures were "bound" to the wrong positions). \$\endgroup\$
    – xGolden
    Jul 25 at 14:27
  • \$\begingroup\$ I got it in the end. I had to adjust the texture's vertices as well so that every one of them would be the part of the texture image that was supposed to be at that vertex. Here's the final code if anyone needs a look: pastebin link. \$\endgroup\$
    – xGolden
    Jul 25 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.