Open GL ES 2.0 Android Shading

Я пытаюсь реализовать 3D-приложение для Android, и у меня возникают проблемы при рисовании 3D-объектов, таких как, например, конус. Проблема в том, что я не могу заметить переходы между разными гранями, все они нарисованы одинаковым цветом. Я думаю, что мне нужно добавить заливку в полигоны, но я не могу найти учебник, показывающий мне, как мне это сделать. это код, который я использую, чтобы нарисовать конус.

public class Cone{
float baseSize = 0f;
float height = 0f;
protected final float[] mTransformMatrix = new float[16];
private FloatBuffer vertexBuffer;
private final int mProgram;
private final String vertexShaderCode =
        // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform mat4 uMVPMatrix;" +
                "attribute vec4 vPosition;" +
                "void main() {" +
                // the matrix must be included as a modifier of gl_Position
                // Note that the uMVPMatrix factor *must be first* in order
                // for the matrix multiplication product to be correct.
                "  gl_Position = uMVPMatrix * vPosition;" +
                "}";

// Use to access and set the view transformation
private int mMVPMatrixHandle;
private final String fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}";

// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float topCoords[] = new float[30];
static float baseCoords[] = new float[30];
static float lineCoords[] = new float[96];
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 1f, 0f, 0f, 1.0f };
float linecolor[] = { 1f, 1f, 1f, 1.0f };

public Cone(float baseSize , float height) {
    this.baseSize = baseSize;
    this.height = height;
    float ang = (float) ((2*Math.PI) / 8);
    Matrix.setIdentityM(mTransformMatrix, 0);
    // initialize vertex byte buffer for shape coordinates
    ByteBuffer bb = ByteBuffer.allocateDirect(
            // (number of coordinate values * 4 bytes per float)
            (topCoords.length * 2 + lineCoords.length) * 4);
    // use the device hardware's native byte order
    bb.order(ByteOrder.nativeOrder());

    // create a floating point buffer from the ByteBuffer
    vertexBuffer = bb.asFloatBuffer();
    // add the coordinates to the FloatBuffer
    topCoords[0] = 0;
    topCoords[1] = height;
    topCoords[2] = 0;
    baseCoords[0]= 0;
    baseCoords[1]= 0;
    baseCoords[2]= 0;
    for(int i=1; i < 10;i++) {
        topCoords[i*3] = this.baseSize * (float) Math.cos(i*ang);
        topCoords[i*3 + 1] = 0;
        topCoords[i*3 + 2] = this.baseSize * (float) Math.sin(i*ang);

        baseCoords[i*3] = this.baseSize * (float) Math.cos(i*ang);
        baseCoords[i*3 + 1] = 0;
        baseCoords[i*3 + 2] = this.baseSize * (float) Math.sin(i*ang);

    }
    for (int i = 0 ; i < 8 ; i ++) {
        lineCoords[i*6] = 0;
        lineCoords[i*6 + 1] = height;
        lineCoords[i*6 + 2] = 0;
        lineCoords[i*6 + 3] = this.baseSize *(float) Math.cos((i+1)*ang);
        lineCoords[i*6 + 4] = 0;
        lineCoords[i*6 + 5] = this.baseSize * (float) Math.sin((i+1)*ang);

    }
    int j = 0;
    for (int i = 8 ; i < 16 ; i++){
        lineCoords[i*6] = this.baseSize *(float) Math.cos((j+1)*ang);
        lineCoords[i*6 + 1] = 0;
        lineCoords[i*6 + 2] = this.baseSize * (float) Math.sin((j+1)*ang);

        lineCoords[i*6 + 3] = this.baseSize *(float) Math.cos((j+2)*ang);
        lineCoords[i*6 + 4] = 0;
        lineCoords[i*6 + 5] = this.baseSize * (float) Math.sin((j+2)*ang);
        j++;
    }



    vertexBuffer.put(topCoords);
    vertexBuffer.put(baseCoords);
    vertexBuffer.put(lineCoords);
    // set the buffer to read the first coordinate
    vertexBuffer.position(0);

    int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
            vertexShaderCode);
    int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
            fragmentShaderCode);

    // create empty OpenGL ES Program
    mProgram = GLES20.glCreateProgram();

    // add the vertex shader to program
    GLES20.glAttachShader(mProgram, vertexShader);

    // add the fragment shader to program
    GLES20.glAttachShader(mProgram, fragmentShader);

    // creates OpenGL ES program executables
    GLES20.glLinkProgram(mProgram);
}
private int mPositionHandle;
private int mColorHandle;

private final int topVertexCount = topCoords.length / COORDS_PER_VERTEX;
private final int lineVertexCount = lineCoords.length / COORDS_PER_VERTEX;


private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

public void draw(float[] mvpMatrix) {
    // Add program to OpenGL ES environment
    GLES20.glUseProgram(mProgram);

    // get handle to vertex shader's vPosition member
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);
    // get handle to fragment shader's vColor member
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    // Set color for drawing the cone
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);

    // get handle to shape's transformation matrix
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the cone
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, topVertexCount);
    //Draw base
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, topVertexCount, topVertexCount);
    //Draw cone lines

    GLES20.glUniform4fv(mColorHandle, 1, linecolor, 0);
    GLES20.glDrawArrays(GLES20.GL_LINES, topVertexCount*2, lineVertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);

}

}

Спасибо за помощь

1 ответ

Ваш фрагментный шейдерный код действительно назначает один и тот же цвет каждому фрагменту процесса. Есть несколько способов добавить "освещение" в вашу сцену. "Шейдинг Гуро" является одним из самых простых в реализации, с современными шейдерами. Он интерполирует нормаль в каждой вершине треугольника поперек треугольника и вычисляет интенсивность света на основе направления света. В современных языках шейдинга (включая OpenGL ES 2) эта интерполяция сделана для вас.

Существует много других возможных моделей освещения, однако большинство (если не все, включая затенение Гуро) потребуют, чтобы вы генерировали нормали вершин, чего вы не делаете в своем коде генерации конусной сетки.

Другие вопросы по тегам