本节我们来学习一下光照基础的知识,理解了原作者的讲解,我们就应该能提炼出本节的重点就是冯氏光照模型。之前我们已经说过了,后面的效果实现都是把前人总结好的原理计算出来。冯氏光照模型介绍如下:
上面的四张效果图看着就非常明显了,第一张是环境光,第二张是漫反射,第三张是镜面反射,第四张是所有效果的综合,也就是我们眼睛看到的效果。颜色的处理是在片段着色器中,分别把三部分反射因子相加,然后乘以物体本身的颜色就完成了,代码实现如下:
本节我们最终实现的效果图如下:
我们画了四个立方体,中间这个就是冯氏光照模式的最终效果,中间正上方的是单独镜面反射的效果,中间右上的环境光 + 漫反射的效果,左下角的是单独环境光的效果。我们把光源的颜色设置为白色,可以看到最终的效果才更接近实际情况,不会像单独环境光或者漫反射那样整体是一个颜色。
我们再加上纹理看一下效果:
有了纹理采样,细节更加突出,有点小兴奋。不过大家看看B站上那些Opengl作出来的游戏效果,就会发现,我们现在作的所有都是小菜,真的太菜了,但是也不要紧,当前的基础积累就是以后万丈高楼的根基。
本节的效果有三个类:GlLightRender、LightCube、LightLight,GlLightRender类和上一节基本完全相同,还是提供绘制的流程;LightCube绘制立方体;LightLight绘制光源。我们先来看一下LightLight类,完整源码如下:
package com.opengl.learn.aric.light;
import android.content.Context;
import android.opengl.GLES32;
import android.opengl.Matrix;
import com.opengl.learn.OpenGLUtils;
import com.opengl.learn.R;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_STATIC_DRAW;
import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glGetUniformLocation;
public class LightLight {
private final float[] mVerticesData =
{
// back face
0.5f, 0.5f, -0.5f, // (5) Top-right far
0.5f, -0.5f, -0.5f, // (7) Bottom-right far
-0.5f, -0.5f, -0.5f, // (6) Bottom-left far
-0.5f, -0.5f, -0.5f, // (6) Bottom-left far
-0.5f, 0.5f, -0.5f, // (4) Top-left far
0.5f, 0.5f, -0.5f, // (5) Top-right far
// front face
-0.5f, 0.5f, 0.5f, // (0) Top-left near
-0.5f, -0.5f, 0.5f, // (2) Bottom-left near
0.5f, -0.5f, 0.5f, // (3) Bottom-right near
0.5f, -0.5f, 0.5f, // (3) Bottom-right near
0.5f, 0.5f, 0.5f, // (1) Top-right near
-0.5f, 0.5f, 0.5f, // (0) Top-left near
// left face
-0.5f, 0.5f, -0.5f, // (4) Top-left far
-0.5f, -0.5f, -0.5f, // (6) Bottom-left far
-0.5f, -0.5f, 0.5f, // (2) Bottom-left near
-0.5f, -0.5f, 0.5f, // (2) Bottom-left near
-0.5f, 0.5f, 0.5f, // (0) Top-left near
-0.5f, 0.5f, -0.5f, // (4) Top-left far
// right face
0.5f, 0.5f, 0.5f, // (1) Top-right near
0.5f, -0.5f, 0.5f, // (3) Bottom-right near
0.5f, -0.5f, -0.5f, // (7) Bottom-right far
0.5f, -0.5f, -0.5f, // (7) Bottom-right far
0.5f, 0.5f, -0.5f, // (5) Top-right far
0.5f, 0.5f, 0.5f, // (1) Top-right near
// bottom face
-0.5f, -0.5f, 0.5f, // (2) Bottom-left near
-0.5f, -0.5f, -0.5f, // (6) Bottom-left far
0.5f, -0.5f, -0.5f, // (7) Bottom-right far
0.5f, -0.5f, -0.5f, // (7) Bottom-right far
0.5f, -0.5f, 0.5f, // (3) Bottom-right near
-0.5f, -0.5f, 0.5f, // (2) Bottom-left near
// top face
-0.5f, 0.5f, -0.5f, // (4) Top-left far
-0.5f, 0.5f, 0.5f, // (0) Top-left near
0.5f, 0.5f, 0.5f, // (1) Top-right near
0.5f, 0.5f, 0.5f, // (1) Top-right near
0.5f, 0.5f, -0.5f, // (5) Top-right far
-0.5f, 0.5f, -0.5f, // (4) Top-left far
};
public static final float[] mLightColorsData = {1.0f, 1.0f, 1.0f};
public static final float[] mLightPosData = {0f, 0f, 5.0f};
private static final String TAG = LightLight.class.getSimpleName();
private static final int BYTES_PER_FLOAT = 4;
private static final int BYTES_PER_SHORT = 2;
private static final int POSITION_COMPONENT_COUNT = 3;
private static final int COLOR_COMPONENT_COUNT = 3;
private static final int TEXTURE_COMPONENT_COUNT = 2;
private static final int INDEX_COMPONENT_COUNT = 1;
private static final int MATRIX_LENGHT = 16;
private Context mContext;
private int mLightProgram;
p