学习OpenGL ES for Android(九)—简单光照

从这篇开始学习光照相关的知识,可以先阅读文档https://learnopengl-cn.github.io/02%20Lighting/01%20Colors/,了解光照的相关概念。

光照至少需要一个光源和一个物体才能显示出的效果,那么我们就需要定义光源和物体的顶点位置和颜色,参考我们实现立方体的文章添加立方体并设置颜色,设置光源的颜色是白色,设置物体本来的颜色是橘色,那么光源照射之后的颜色就是两种颜色的叠加,我们直接设置颜色,物体着色器的代码如下,

        vertexShaderCode =
                "uniform mat4 uMVPMatrix;" +
                        "attribute vec4 aPosition;" +
                        "varying vec3 lColor;" +
                        "varying vec3 oColor;" +
                        "void main() {" +
                        "  gl_Position = uMVPMatrix * aPosition;" +
                        "  lColor = vec3(1.0, 1.0, 1.0);" +
                        "  oColor = vec3(1.0, 0.5, 0.31);" +
                        "}";
        fragmentShaderCode =
                "precision mediump float;" +
                        "varying vec3 lColor;" +
                        "varying vec3 oColor;" +
                        "void main() {" +
                        "  gl_FragColor = vec4(lColor * oColor, 1.0);" +
                        "}";

使用光照颜色(lColor)和物体颜色(oColor)叠加相乘后生成物体的颜色。

这次我们设置观察点在右上方,可以看到立方体的右上角,

Matrix.setLookAtM(viewMatrix, 0, 0.8f, 0.8f, 4f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

因为这次要绘制物体和光源两个立方体,所以还有设置光源着色器代码,因为是个纯白色的比较简单,这里不再赘述,最后附上代码

@Override
    public void onDrawFrame(GL10 gl) {
        super.onDrawFrame(gl);
        // ---------- 绘制物品 ---------------
        int shaderProgram = OpenGLUtil.createProgram(vertexShaderCode, fragmentShaderCode);
        GLES20.glUseProgram(shaderProgram);
        // 传入顶点坐标
        int positionHandle = GLES20.glGetAttribLocation(shaderProgram, "aPosition");
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT,
                false, 3 * 4, OpenGLUtil.createFloatBuffer(CubeCoords));

        int mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, vPMatrix, 0);

        // 绘制顶点
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indices.length,
                GLES20.GL_UNSIGNED_SHORT, OpenGLUtil.createShortBuffer(indices));

        // ---------- 绘制光源 ---------------
        int lightProgram = OpenGLUtil.createProgram(vertexLightShaderCode, fragmentLightShaderCode);
        GLES20.glUseProgram(lightProgram);
        // 传入顶点坐标
        int lightPositionHandle = GLES20.glGetAttribLocation(lightProgram, "aPosition");
        GLES20.glEnableVertexAttribArray(lightPositionHandle);
        GLES20.glVertexAttribPointer(lightPositionHandle, 3, GLES20.GL_FLOAT,
                false, 3 * 4,  OpenGLUtil.createFloatBuffer(CubeCoords));

        int mMVPMatrixHandle1 = GLES20.glGetUniformLocation(lightProgram, "uMVPMatrix");
        // 移动光源的位置
        Matrix.translateM(vPMatrix2, 0, 0.7f, 0.8f, 0f);
        // 缩放光源
        Matrix.scaleM(vPMatrix2, 0, 0.1f, 0.1f, 0.1f);
        // 计算
        //Matrix.multiplyMM(vPMatrix, 0, tempMatrix, 0, translateMatrix, 0);
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle1, 1, false, vPMatrix2, 0);

        // 绘制顶点
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indices.length,
                GLES20.GL_UNSIGNED_SHORT, OpenGLUtil.createShortBuffer(indices));

        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(lightPositionHandle);
    }

效果图如下,

我们看到物体整体颜色一样,和现实世界的光照效果还是有差异的。现实世界的效果应该是背面比较比较暗的,还有光线的强弱,光源的颜色等等,这些都是以后学习的内容。

本章源码地址https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/renderer/light/LightRenderer.java

发布了53 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jklwan/article/details/103617158