基于前几章的代码,定义三个球,三个球在位置上有重叠部分。并且三个球颜色不一样。完整代码如下:
public class MyGLSurfaceView extends GLSurfaceView implements Renderer {
public MyGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyGLSurfaceView(Context context) {
super(context);
init();
}
private void init(){
this.setEGLContextClientVersion(1);
this.setRenderer(this);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
initOpenGLVertexs(0, 20) ;//构造第一个形状
initOpenGLVertexs(1, 20) ;//构造第二个形状
initOpenGLVertexs(2, 20) ;//构造第三个形状
initOpenGLMaterial();
}
private FloatBuffer[] vertexBuffer = new FloatBuffer[3] ;
private FloatBuffer[] normalBuffer = new FloatBuffer[3] ;
private int[] vertexCount = new int[3] ;
private void initOpenGLVertexs(int idx, float radius){
float[] vertexArray = new float[]{
/*第一个三角形*/
-radius, radius, 0, /*注意,这里我正方形z轴全为0,也就是正方形位于x-y的平面上*/
radius,-radius, 0,
radius, radius, 0,
/*第二个三角形*/
-radius, radius, 0,
-radius,-radius, 0,
radius,-radius, 0,
};
float[] normalArray = new float[]{
/*第一个三角形*/
0, 0, 1, /*注意,这里我正方形z轴全为0,也就是正方形位于x-y的平面上*/
0, 0, 1,
0, 0, 1,
/*第二个三角形*/
0, 0, 1,
0, 0, 1,
0, 0, 1,
};
vertexCount[idx] = vertexArray.length / 3;
vertexBuffer[idx] = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer[idx].put(vertexArray);
vertexBuffer[idx].position(0);
normalBuffer[idx] = ByteBuffer.allocateDirect(normalArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
normalBuffer[idx].put(normalArray);
normalBuffer[idx].position(0);
}
private List ambient = new ArrayList();
private List diffuse = new ArrayList();
private List specular = new ArrayList();
private List emmissive = new ArrayList();
private List shininess = new ArrayList();
private void initOpenGLMaterial(){
ambient.add(new float[]{0.4f,0.0f,0.0f,0.4f}); //红色,20%透明
ambient.add(new float[]{0.0f,0.4f,0.0f,0.4f}); //绿色,20%透明
ambient.add(new float[]{0.0f,0.0f,0.4f,0.4f});
diffuse.add(new float[]{0.8f,0.0f,0.0f,0.4f});
diffuse.add(new float[]{0.0f,0.8f,0.0f,0.4f});
diffuse.add(new float[]{0.0f,0.0f,0.8f,0.4f});
specular.add(new float[]{0.6f,0.6f,0.6f,0.4f});
specular.add(new float[]{0.6f,0.6f,0.6f,0.4f});
specular.add(new float[]{0.6f,0.6f,0.6f,0.4f});
emmissive.add(new float[]{0.8f,0.0f,0.0f,0.4f});
emmissive.add(new float[]{0.0f,0.8f,0.0f,0.4f});
emmissive.add(new float[]{0.0f,0.0f,0.8f,0.4f});
shininess.add(Float.valueOf(20f));
shininess.add(Float.valueOf(20f));
shininess.add(Float.valueOf(20f));
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES10.glViewport(0, 0, width, height); // 设置视口宽度高度。
//GLES10.glEnable(GLES10.GL_DEPTH_TEST);
/**
* 在透明物体绘制的时候,不能使用深度测试,因为深度测试一旦打开,它会直接使用更暴力的覆盖模式(一旦发现已经有物体更近了)
* 如果一个场景里又有透明物体,又有不透明物体。那就要打开深度测试。
* 同时绘制透明的物体的时候把深度缓存设置为只读,而不透明物体的时候,把深度缓存设置可读可写
* 我们这儿没有不透明物体,直接禁用深度测试就行了。
*/
//开启混合模式
GLES10.glEnable(GLES10.GL_BLEND);
//设置混合公式
GLES10.glBlendFunc(GLES10.GL_SRC_ALPHA, GLES10.GL_ONE_MINUS_SRC_ALPHA);
// {修改投影矩阵
GLES10.glMatrixMode(GLES10.GL_PROJECTION); // 修改投影矩阵
GLES10.glLoadIdentity(); // 复位,将投影矩阵归零
GLU.gluPerspective(gl, 60.0f, ((float) width) / height, 0.1f, 1500f); // 最近和最远可以看到的距离,超过最远将不显示。
// }
GLES10.glEnable(GLES10.GL_LIGHTING);
GLES10.glEnable(GLES10.GL_LIGHT0);
//灯光在身后很有远处
GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_POSITION, new float[]{300, 300, 1000, 0}, 0);
}
private float[] objMoveMatrix = new float[16] ; //物体运动
public void onDrawFrame(GL10 gl) {
GLES10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 清空场景为黑色。
GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);// 清空相关缓存。
//{
GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();//归零模型视图
GLU.gluLookAt(gl, 0, 0, 0, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);//站在原点,往负半轴看去。
//}
GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
GLES10.glEnableClientState(GLES10.GL_NORMAL_ARRAY);
for(int idx=0; idx
解释都在代码里。很多前面几章提到的代码就不作解释了。