OpenGL ES Lighting(矩阵和/或法线问题)

时间:2013-02-10 14:36:14

标签: android opengl-es-2.0

我正在尝试在OpenGL ES中添加每个顶点光源,但我遇到了一些我没有找到解决方案的奇怪问题。

我首先使用Android文档创建形状: http://developer.android.com/training/graphics/opengl/index.html

然后我用学习opengl es来添加lightinh: http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/

所以这是我的渲染器的代码:

@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    // Set the background frame color
    GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    // Enable depth testing
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);

    float[] coords = new float[]{
            -0.5f, 0.5f, 0.5f,
            -0.5f, 0.5f, -0.5f,
            0.5f, 0.5f, -0.5f,
            0.5f , 0.5f, 0.5f,

            -0.5f, 0.5f, 0.5f,
            -0.5f, -0.5f, 0.5f,
            0.5f, -0.5f, 0.5f,
            0.5f , 0.5f, 0.5f
    };

    short[] drawOrder = new short[]{
            0,1,2,
            0,2,3,

            4,5,6,
            4,6,7,
    };

    float[] normals = new float[]{
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,

            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
    };

    float[] colors = new float[]{
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
    };

    testSolid = new Solid(coords, drawOrder, colors, normals);
}

public void onDrawFrame(GL10 unused) {
    float[] lightPos = new float[]{0.5f, 0.5f, -0.5f, 1.0f};

    // Redraw background color
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, 0f, 0f, 2.0f, 0.0f);                       


    Matrix.setIdentityM(mModelMatrix, 0);

    Matrix.multiplyMM(mVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

    Matrix.setIdentityM(mLightModelMatrix, 0);
    Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, lightPos, 0);
    Matrix.multiplyMV(mLightPosInEyeSpace, 0, mVMatrix, 0, mLightPosInWorldSpace, 0);

    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 1.0f, 0.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mLightMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

    // Combine the rotation matrix with the projection and camera view
    Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mLightMatrix, 0);

    // Draw shape
    testSolid.draw(mVMatrix, mMVPMatrix, mLightPosInEyeSpace);
}

public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

然后,我的Solid代码:

  • 首先,我的计划:

        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;" +
        "uniform mat4 uMVMatrix;"+
        "uniform vec3 uLightPos;"+
    
        "attribute vec3 aNormal;" +
        "attribute vec4 aColor;" +
        "attribute vec4 aPosition;" +
    
        "varying vec4 vColor;" +
    
        "void main() {" +
        // the matrix must be included as a modifier of gl_Position
        "  vec3 modelViewVertex = vec3(uMVMatrix * aPosition);"+
        "  vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));"+
        "  float distance = length(uLightPos - modelViewVertex);"+
        "  vec3 lightVector = normalize(uLightPos - modelViewVertex);"+
        "  float diffuse = max(dot(modelViewNormal, lightVector), 0.1);"+
        "  diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));"+
        "  vColor = aColor * diffuse;"+
        "  gl_Position = aPosition * uMVPMatrix;" +
        "}";
    
    private final String fragmentShaderCode =
        "precision mediump float;" +
        "varying vec4 vColor;" +
        "void main() {" +
        "  gl_FragColor = vColor;" +
        "}";
    

我的绘画功能:

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

        // Positions
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");

        GLES20.glEnableVertexAttribArray(mPositionHandle);

        GLES20.glVertexAttribPointer(mPositionHandle, DATA_PER_VERTEX,
                                     GLES20.GL_FLOAT, false,
                                     0, vertexBuffer);
        CubeRenderer.checkGlError(String.format("Positions (%d)", mPositionHandle));

        // Colors
        mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");

        GLES20.glEnableVertexAttribArray(mColorHandle);

        GLES20.glVertexAttribPointer(mColorHandle, 4,
                                     GLES20.GL_FLOAT, false,
                                     0, colorBuffer);
        CubeRenderer.checkGlError(String.format("Colors (%d)", mColorHandle));

        // Normals
        mNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");

        GLES20.glVertexAttribPointer(mNormalHandle, 3,
                                     GLES20.GL_FLOAT, false,
                                     0, normalBuffer);

        GLES20.glEnableVertexAttribArray(mNormalHandle);
        CubeRenderer.checkGlError(String.format("Normals (%d)", mColorHandle));

        // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        CubeRenderer.checkGlError("glGetUniformLocation");
        mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
        CubeRenderer.checkGlError("glGetUniformLocation");
        mLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
        CubeRenderer.checkGlError("glGetUniformLocation");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
        GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
        GLES20.glUniform3f(mLightPosHandle, lightPos[0], lightPos[1], lightPos[2]);
        CubeRenderer.checkGlError("glUniformMatrix4fv");

        // Draw the polygon
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
                              GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

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

但是,当我运行它时,我的结果非常奇怪。

  • 首先,光很昏暗,而且不是很好的地方
  • 其次,我有一个带触摸事件的旋转,如果我旋转我的形状,灯光也会旋转。

您知道这个问题的来源吗?

谢谢。

0 个答案:

没有答案