Question

To add some lightning to my OpenGL ES20 cube, I need to calculate the normals for each plane. I've found a "tutorial" on lightning, but they simply hard-coded the normals into the cube, which appears to me as not the best option, since it seems limited?

So my approach to the cube is as follows:

private float[] mVertices = {
        -1, -1, -1, // bottom left
        1, -1, -1, // bottom right   back
        1, 1, -1, // top right
        -1, 1, -1, // top left
        -1, -1, 1, // bottom left
        1, -1, 1, // bottom right   front
        1, 1, 1, // top right
        -1, 1, 1 // top left
};

private float[] mColors = {
        0.6f, 0f, 0.6f,
        0.6f, 0f, 0.6f,
        0.6f, 0f, 0.6f,
        0.6f, 0f, 0.6f,

        0.8f, 0f, 0.6f,
        0.8f, 0f, 0.6f,
        0.8f, 0f, 0.6f,
        0.8f, 0f, 0.6f
};

private float[] mNormal = new float[?]; ?

private short[] mIndices = {
        0, 4, 5,
        0, 5, 1,

        1, 5, 6,
        1, 6, 2,

        2, 6, 7,
        2, 7, 3,

        3, 7, 4,
        3, 4, 0,

        4, 7, 6,
        4, 6, 5,

        3, 0, 1,
        3, 1, 2
};

i.e. i have all 8 vertices defined as well as indices, on how to combine them to triangles. To get the normal matrix, I've read that I am supposed to invert the matrix, then transpose it. So I've tried this:

    float[] mTempMatrix = new float[mVertices.length];
    Matrix.invertM(mTempMatrix, 0, mVertices, 0);
    Matrix.transposeM(mNormal, 0, mTempMatrix, 0);

But this is always filled with zeros, and my cube stays black. How example am I supposed to calculate the normal matrix? Should it be something with the model matrix? If yes, where am I supposed to do this, since the only place they are really combined is in the shader? Is there another way to do this which would be more appropriate?

Was it helpful?

Solution

The issue you are facing is that you share vertices between cube faces. The normal is a vector that points othogonal to the plane of the surface.

Consider the top/right/front vertex as an example (that you share with the front, right and top faces).

When used on the front face, the normal needs to point towards you as 0, 0, 1 When used on the right face, the normal needs to point to the right as 1, 0, 0 When used on the top face, the normal needs to point up as 0, 1, 0

So how to reconcile that? You could set the normal for the vertex to point out from the corner, e.g. as 0.707, 0.707, 0.707. That'll most likely give you an interesting lighting effect on the corner but is probably not what you're after.

The other solution is not to re-use the vertices between faces. So you'll need 24 (4 per side) instead of 8. You'll then have 3 versions of each vertex but each one of those now belongs to just one face, hence you can set the normal vector as perpendicular to that face. You'll also be able to set the color for just that face as well since you'll no longer be sharing the vertex with other faces.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top