从这篇开始学习光照相关的知识,可以先阅读文档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);
}
效果图如下,
我们看到物体整体颜色一样,和现实世界的光照效果还是有差异的。现实世界的效果应该是背面比较比较暗的,还有光线的强弱,光源的颜色等等,这些都是以后学习的内容。