Question

I drew a cube in openGL es 2.0. Right now it has just two faces, for testing purposes(the front and the back). So basically there are two planes in space, both with the same color.

Now I want to apply a different color to each face. I tought that expanding the color array was sufficient, but the colors are not changing (there's just the original color). Do I have to change the shader? Or pass a specific function to the draw method? The class should explain better

public class Cube {

private FloatBuffer mVer;
private FloatBuffer colMem;
private ShortBuffer ordVer;

private float vertici[] = {
        -0.2f, 0.2f, 0.2f, //p1 upper left front plane (0)
        -0.2f, -0.2f, 0.2f,  //p2 lower left front plane (1)
        0.2f,  -0.2f, 0.2f,  //p3 lower right front plane (2)
        0.2f, 0.2f, 0.2f,  //p4 upper right front plane (3)

        -0.2f, 0.2f, -0.2f, //p1 upper left front plane (4)
        -0.2f, -0.2f, -0.2f,  //p2 lower left front plane (5)
        0.2f,  -0.2f, -0.2f,  //p3 lower right front plane (6)
        0.2f, 0.2f, -0.2f,  //p4 upper right front plane (7)



        };

private short order[] = {
        0, 1, 2, 0, 2, 3, //front face
        7, 6, 5, 7, 5, 4, //back face
        //3, 2, 6, 3, 6, 7, //right face 
       // 0, 1, 5, 0, 5, 4 //left face 
        };

private float color [] = { 
        0.8f, 0.8f, 0.1f, 1.0f,//color1
        0.8f, 0.8f, 0.1f, 1.0f,
        0.8f, 0.8f, 0.1f, 1.0f,
        0.8f, 0.8f, 0.1f, 1.0f,

        0.1f, 0.2f, 0.5f, 1.0f,//color2
        0.1f, 0.2f, 0.5f, 1.0f,
        0.1f, 0.2f, 0.5f, 1.0f,
        0.1f, 0.2f, 0.5f, 1.0f
        };

private final String vertCode = 
        "uniform mat4 uMVPMatrix;"+
        "attribute vec4 vPosition;"+
        "void main() {"+
        "gl_Position = uMVPMatrix * vPosition;"+
        "}";

private final String fragCode = 
        "precision mediump float;"+
        "uniform vec4 vColor;"+
        "void main() {"+
        "gl_FragColor = vColor;"+
        "}";

private int prog;

private int pos;
private int col;
private int mHandle;



public Cube () {

    mVer = ByteBuffer.allocateDirect(vertici.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

    mVer.put(vertici).position(0);

    ordVer = ByteBuffer.allocateDirect(order.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();

    ordVer.put(order).position(0);

    colMem = ByteBuffer.allocateDirect(color.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

    colMem.put(color).position(0);

    int vertexShader = Render.loadShader (GLES20.GL_VERTEX_SHADER, vertCode);
    int fragmentShader = Render.loadShader (GLES20.GL_FRAGMENT_SHADER, fragCode);

    prog = GLES20.glCreateProgram();
    GLES20.glAttachShader(prog, vertexShader);
    GLES20.glAttachShader(prog, fragmentShader);
    GLES20.glLinkProgram(prog);


}

public void draw (float[] mVMatrix) {


    GLES20.glUseProgram(prog);

    pos = GLES20.glGetAttribLocation(prog, "vPosition");

    GLES20.glEnableVertexAttribArray(pos);

    GLES20.glVertexAttribPointer(pos, 3, GLES20.GL_FLOAT, false, 12, mVer);

    col = GLES20.glGetUniformLocation(prog, "vColor");

    GLES20.glUniform4fv(col, 1, color, 0);

    mHandle = GLES20.glGetUniformLocation(prog, "uMVPMatrix");

    GLES20.glUniformMatrix4fv(mHandle, 1, false, mVMatrix, 0);

    GLES20.glEnable(GLES20.GL_CULL_FACE);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, order.length, GLES20.GL_UNSIGNED_SHORT, ordVer);

    GLES20.glDisableVertexAttribArray(pos);

}

}

Was it helpful?

Solution

You have a few options:

  • If you want to pass in the color as a uniform, which seems to be where you were headed, you need to draw each face with a separate draw call. You can't just pass in an array of colors for the uniform, and expect the colors to be applied to the triangles in order. You would call glUniform4v with the first color, call glDrawElements with just the indices f the first face, and then repeat these two calls for each face. This is fairly inefficient.
  • You make the colors an attribute instead of a uniform, very similar to what you do for the vertex positions. You have to be careful when using this approach because you need an OpenGL vertex for each combination of position and color. For a cube, you typically end up with 24 vertices. You should be able to find details if you search for older questions about similar topics.

There's another method called "instanced rendering" that could be applied, but that is only available in ES 3.0.

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