android應用開發揭秘第13章01示例,移動圖像,opengl繪制星星問題解決!

根據書上教程運行代碼報錯,2.2的黑屏無效果,4.1的閃退。後研究發現,問題出在在一個物體同時啟用瞭顏色數組和紋理,註釋掉

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

運行即可。

核心代碼如下

package com.xieyuan.test;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Random;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Intent;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class GLRender implements Renderer{

	private final static int ONE=0x10000;
	
	//星星總數
	private final static int NUM=50;
	//存放星星的數組
	private Star[] stars=new Star[NUM];
	
	//閃爍的星星
	boolean twinkle=true;
	
	//離觀察者的距離
	float ZOOM=-10f;
	//星星的傾角
	float tilt=90f;
	//閃爍星星的自轉
	float spin;
	
	private boolean key;
	Random random=new Random();
	
	//紋理ID
	private int texture;
	
	IntBuffer coord=GLNioUtil.IntBufferUtil(new int[]{
			0,0,ONE,0,ONE,ONE,0,ONE
	});
	IntBuffer vertexs=GLNioUtil.IntBufferUtil(new int[]{
			-ONE-ONE,0,
			ONE,-ONE,0,
			ONE,ONE,0,
			-ONE,ONE,0
	});
	ByteBuffer indices=GLNioUtil.ByteBufferUtil(new byte[]{
			1,0,2,3
	});
	
	
	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		//啟用陰影平滑
		gl.glShadeModel(GL10.GL_SMOOTH);
		//清除屏幕為黑色背景
		gl.glClearColor(0f, 0f, 0f, 0f);
		//透視修正
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		
		//創建紋理
		IntBuffer intBuffer=IntBuffer.allocate(1);
		gl.glGenTextures(1, intBuffer);
		texture=intBuffer.get();
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap[3], 0);
		
		//啟用紋理映射
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glShadeModel(GL10.GL_SMOOTH);
		gl.glClearColor(0f, 0f, 0f, 0.5f);
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		//設置混色函數
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
		//啟用混色
		gl.glEnable(GL10.GL_BLEND);
		
		for(int i=0;i<NUM;i++){
			Star star=new Star();
			star.angle=0f; //所有星星的角度都是從0開始
			star.dist=(float)i/(float)NUM*5.0f; //計算星星裡中間的距離
			star.r=random.nextInt(256);			// 為star[loop]設置隨機紅色分量
			star.g=random.nextInt(256);			// 為star[loop]設置隨機紅色分量
			star.b=random.nextInt(256);			// 為star[loop]設置隨機紅色分量
			stars[i] = star;
		}
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		float ratio=(float)width/(float)height;
		//設置場景大小
		gl.glViewport(0, 0, width, height);
		//設置投影舉證
		gl.glMatrixMode(GL10.GL_PROJECTION);
		//重置投影矩陣
		gl.glLoadIdentity();
		//設置視口大小
		gl.glFrustumf(-ratio, ratio, -1,1, 1, 10);
		//設置模型觀察矩陣
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		//清除屏幕和深度緩存
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
		//選擇紋理
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
		for(int i=0;i<NUM;i++){
			gl.glLoadIdentity();
			// 深入屏幕裡面
			gl.glTranslatef(0f, 0f, ZOOM);
			// 傾斜視角
			gl.glRotatef(tilt, 1f, 0f, 0f);
			// 旋轉至當前所畫星星的角度
			gl.glRotatef(stars[i].angle,0f,1f,0f);
			// 沿X軸正向移動
			gl.glTranslatef(stars[i].dist, 0f, 0f);
			// 取消當前星星的角度
			gl.glRotatef(-stars[i].angle, 0f, 1f, 0f);
			// 取消屏幕傾斜
			gl.glRotatef(-tilt, 1f, 0f, 0f);
			
			//設置頂點數組
			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			//設置顏色數組
			//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
			
			gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
			
			// 啟用閃爍效果
			if(twinkle){
				// 使用byte型數值指定一個顏色
				gl.glColor4f((float)stars[NUM-i-1].r/255f,
						(float)stars[NUM-i-1].g/255f,
						(float)stars[NUM-i-1].b/255f,
						1f
						);
				gl.glVertexPointer(3, GL10.GL_FIXED, 0,vertexs);
				gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, coord);
				
				coord.position(0);
				vertexs.position(0);
				indices.position(0);
				
				//gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
				gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE,indices);				
	
				gl.glFinish();
			}
			//繞z軸旋轉星星
			gl.glRotatef(spin, 0f,0f,1f);
			// 使用byte型數值指定一個顏色
			gl.glColor4f((float)stars[(NUM-i)-1].r/255.0f,(float)stars[(NUM-i)-1].g/255.0f,(float)stars[(NUM-i)-1].b/255.0f,1.0f);
			gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertexs);
			gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, coord);
			

			coord.position(0);
			vertexs.position(0);
			indices.position(0);
				
	
		    //繪制正方形結束
		    gl.glFinish();
		    
		   // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
		    //取消頂點數組
		    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		    
			spin+=0.01f;					// 星星的公轉
			stars[i].angle+=(float)(i)/(float)NUM;		// 改變星星的自轉角度
			stars[i].dist-=0.01f;				// 改變星星離中心的距離

			if (stars[i].dist<0.0f)			// 星星到達中心瞭麼
			{
				stars[i].dist+=5.0f;			// 往外移5個單位
				stars[i].r=random.nextInt(256);		// 賦一個新紅色分量
				stars[i].g=random.nextInt(256);		// 賦一個新綠色分量
				stars[i].b=random.nextInt(256);		// 賦一個新藍色分量
			}


		}
		
	}
	
}

class Star{
	int r,g,b;
	float dist;  //星星距離中心的距離
	float angle=0f; //當前星星所處的角度
}

效果:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *