サンプルプログラム工場

AAKAKA Appで使われているプログラムのサンプルコードをそのまま公開!

サンプルプログラム工場 > android > AndroidのGLES20(OpenGL)を使ってポリゴンを表示するサンプル@tryGLES2001
Google Play AAKAKAxSOFTへ

AndroidのGLES20(OpenGL)を使ってポリゴンを表示するサンプル@tryGLES2001

実行ファイル(APK)やサンプル(zip)をダウンロードする
tryGLES2001の実行イメージtryGLES2001の実行イメージ

OpenGL ES2.0を使ってキューブを描く

大事なところ
GLSurfaceViewを拡張したものをmain.xmlレイアウトで設置したい場合
main.xml内のビューを拡張したビューの名前で上書きする。
android.opengl.GLSurfaceView
↓↓↓
trial.sample.trygles2001.RenderSurfaceView

シェーダーの変数タイプ
attribute
頂点データから読み込まれるもの(頂点バッファとか法線バッファとか)
glVertexAttribPointerでセットしたやつ
uniform
glUniformMatrix4fvとかそのへんでセットした値
varying
頂点シェーダからフラグメントシェーダへ値を渡す時に使う

関連項目
頂点シェーダー
フラグメントシェーダー
Matrix
FloatBuffer
ByteBuffer
glAttachShader
glAttachShader
glLinkProgram

開発環境
Eclipse IDE バージョン: 3.7 Indigo Service Release 1
ターゲットプラットフォーム: 2.3.3
API レベル: 10


package trial.sample.trygles2001;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

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

import android.app.Activity;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;

public class TryGLES2001Activity extends Activity {
	
	private RenderSurfaceView mRenderView;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
    // ///////////
	// ビューを拡張した場合main.XMLのレイアウトに埋め込む
	// この場合はtrial.sample.trygles2000.RenderSurfaceViewとして
	// ビューを作る。
	// GLSurfaceViewをmain.xmlに書いてキャストするとエラー吐くよ
	this.mRenderView = (RenderSurfaceView)this
			.findViewById(R.id.rendersurface1);
	// ///////////
    }
    
    @Override
    public void onResume() {
    	super.onResume();
    	this.mRenderView.onResume();
    }
    
    @Override
    public void onPause() {
    	super.onPause();
    	this.mRenderView.onPause();
    }
}


///////////////////////////////////////////////////////////////////////////
//GLSurfaceViewの拡張
class RenderSurfaceView extends GLSurfaceView {

	public RenderSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);

		// ///////////
		// OpenGL ES2.0を使うためにバージョンを指定する
		this.setEGLContextClientVersion(2);
		// レンダラ―の設定
		this.setRenderer(new SurfaceRenderer());
		// ///////////
	}

	public RenderSurfaceView(Context context) {
		super(context);

		// OpenGL ES2.0を使うためにバージョンを指定する
		this.setEGLContextClientVersion(2);
		this.setRenderer(new SurfaceRenderer());
	}
}


///////////////////////////////////////////////////////////////////////////
//ビュー用のレンダラ―
class SurfaceRenderer implements GLSurfaceView.Renderer {

	private float mAspect;	// アスペクト比
	private float mModelRot; // モデルの回転
	
	// 描画するためのもの
	private int mVertexShaderID;	// 頂点シェーダーID
	private int mFragmentShaderID;	// フラグメントシェーダーID
	private int mProgramID; // プログラムオブジェクトID
	
	// シェーダーに値を送るためのハンドル
	private int mLocModelView;
	private int mLocProj;
	private int mLocPos;
	private int mLocCol;
	
	// 形を表現するためのもの
	private FloatBuffer mVertexBuffer;	// 頂点バッファ
	private ByteBuffer mIndexBuffer;	// インデックスバッファ
	
	// 各行列
	private float[] mModelView = new float[16];	// モデルビュー
	private float[] mProj = new float[16];	// プロジェクション
	
	///////////////////////////////////////////////////////////////////////////
	/** 最初に呼ばれる */
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {

		// シェーダーを初期化する
		this.initShader();
		
		// 頂点配列を有効にする
		GLES20.glEnableVertexAttribArray(this.mLocPos);
		
		// デプスバッファを有効にする
		GLES20.glEnable(GLES20.GL_DEPTH_TEST);

		// 形状データを初期化する
		this.initBuffer();
	}

	// /////////////////////////////////////////////////////////////////////////
	// 頂点バッファ/インデックスバッファを作る
	private void initBuffer() {
		// 頂点バッファを作る
		float[] vertices = {
			1.0f, 1.0f, 1.0f,
			1.0f, 1.0f,-1.0f,
			-1.0f, 1.0f, 1.0f,
			-1.0f, 1.0f,-1.0f,
			1.0f,-1.0f, 1.0f,
			1.0f,-1.0f,-1.0f,
			-1.0f,-1.0f, 1.0f,
			-1.0f,-1.0f,-1.0f,
		};
		this.mVertexBuffer = this.makeFloatBuffer(vertices);
		
		// インデックスバッファを作る
		byte[] indices = {
				0,1,2,3,
				2,3,6,7,
				6,7,4,5,
				4,5,0,1,
				1,5,3,7,
				0,2,4,6,
		};
		this.mIndexBuffer = this.makeByteBuffer(indices);
	}
	
	// /////////////////////////////////////////////////////////////////////////
	// シェーダーを初期化する
	private void initShader() {
		// 頂点シェーダーのコンパイル
		// ※u_XXXXとかa_XXXXとかバインドする変数名に気を付ける
		//   結構間違えることあって2,3時間悩むよ
		String vertexCode = 
			"uniform mat4 u_modelView;"+    
			"uniform mat4 u_proj;"+ 
			"attribute vec4 a_pos;"+  
			"void main(){"+       
			"gl_Position = u_proj * u_modelView * a_pos;"+  
			"}";
		this.mVertexShaderID = this.compileShader(
				GLES20.GL_VERTEX_SHADER, vertexCode);
		
		// フラグメントシェーダーのコンパイル
		String fragmentCode = 
			"precision mediump float;"+     
			"uniform vec4 u_col;"+      
			"void main(){"+   
			"gl_FragColor=u_col;"+     
			"}";
		this.mFragmentShaderID = this.compileShader(
				GLES20.GL_FRAGMENT_SHADER, fragmentCode);
		
		// プログラムオブジェクトを作る
		this.mProgramID = GLES20.glCreateProgram();
		GLES20.glAttachShader(this.mProgramID, this.mVertexShaderID);
		GLES20.glAttachShader(this.mProgramID, this.mFragmentShaderID);
		GLES20.glLinkProgram(this.mProgramID);
		
		// シェーダーに値を送るためのハンドルを取り出す
		// ※u_XXXXとかa_XXXXとかバインドする変数名に気を付ける
		//   結構間違えることあって2,3時間悩むよ
		this.mLocModelView = GLES20.glGetUniformLocation(
				this.mProgramID, "u_modelView");
		this.mLocProj = GLES20.glGetUniformLocation(
				this.mProgramID, "u_proj");
			// 頂点はglGetAttribLocationを使ってセットする
		this.mLocPos = GLES20.glGetAttribLocation(
				this.mProgramID, "a_pos");
		this.mLocCol = GLES20.glGetUniformLocation(
				this.mProgramID, "u_col");
	
		// プログラムオブジェクトを使い始める
		GLES20.glUseProgram(this.mProgramID);
	}
	
	
	///////////////////////////////////////////////////////////////////////////
	/** サーフェイスのサイズ変更時とかに呼ばれる */
	public void onSurfaceChanged(GL10 gl, int width, int height) {
	
		// ビューポートの再設定
		GLES20.glViewport(0, 0, width, height);
		
		// アスペクト比
		this.mAspect = (float)width / (float)height;
	}
	
	
	///////////////////////////////////////////////////////////////////////////
	/** マイフレーム呼ばれるやつ */
	public void onDrawFrame(GL10 gl) {
		// 画面をクリア
		GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.f);
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
	
		// プロジェクション行列
		Matrix.setIdentityM(this.mProj, 0);
		this.Perspective(this.mProj, 45.f, this.mAspect, 1.0f, 100.f);
		// シェーダーに送信
		GLES20.glUniformMatrix4fv(this.mLocProj, 1, false, this.mProj, 0);
		
		
		// ビュー行列
		Matrix.setIdentityM(this.mModelView, 0);
		Matrix.setLookAtM(this.mModelView, 0,
				0.0f, 0.0f, 5.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 1.0f, 0.0f);
		
		
		// モデル変換
		Matrix.rotateM(this.mModelView, 0, this.mModelRot, 1, 1, 0);
		
		
		// シェーダーにモデルビュー行列を送信
		GLES20.glUniformMatrix4fv(this.mLocModelView, 1, false, this.mModelView, 0);
		this.mModelRot++;

		
		// キューブを描くよ
		// 面を描く
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 1.0f, 0.0f, 0.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(0);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
		
		
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 0.0f, 1.0f, 0.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(4);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
		
		
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 0.0f, 0.0f, 1.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(8);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
		
		
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 1.0f, 1.0f, 0.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(12);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
		
		
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 0.0f, 1.0f, 1.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(16);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
		
		
		// 頂点バッファを指定する
		GLES20.glVertexAttribPointer(this.mLocPos, 3,
				GLES20.GL_FLOAT, false, 0, this.mVertexBuffer);
		// 色をセットする
		GLES20.glUniform4f(this.mLocCol, 1.0f, 1.0f, 1.0f, 1.0f);
		// 使い始めるインデックスバッファの先頭を探す
		this.mIndexBuffer.position(20);
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, this.mIndexBuffer);
	}
	
	
	// /////////////////////////////////////////////////////////////////////////
	// プロジェクション行列を作る
	private void Perspective(float[] out, float fov, float aspect, 
			float near, float far) {
		float top = near * (float)Math.tan(Math.toRadians(fov));
		float bottom = -top;
		float left = bottom * aspect;
		float right = top * aspect;
		Matrix.frustumM(out, 0, left, right, bottom, top, near, far);
	}
	
	
	
	///////////////////////////////////////////////////////////////////////////
	// FloatBufferを作って値をセットする
	private FloatBuffer makeFloatBuffer(float[] values) {
		// バッファを作る
		FloatBuffer fb = ByteBuffer.allocateDirect(values.length * 4)
				.order(ByteOrder.nativeOrder())
				.asFloatBuffer();
		// 作ったバッファに値をセットしておく
		fb.put(values)
				.position(0);
		return fb;
	}

	
	///////////////////////////////////////////////////////////////////////////
	// IntBufferを作って値をセットする
	private ByteBuffer makeByteBuffer(byte[] values) {
		ByteBuffer buf = ByteBuffer.allocateDirect(values.length)
				.order(ByteOrder.nativeOrder());
		buf.put(values)
				.position(0);
		return buf;
	}
	

	///////////////////////////////////////////////////////////////////////////
	// シェーダーのソースコードをコンパイルする
	private int compileShader(int type, String code) {
		final int shaderId = GLES20.glCreateShader(type);
		if (shaderId == 0) {
			// シェーダーの領域確保に失敗した
			Log.d("compileShader", "領域確保に失敗");
			return -1;
		}
		// シェーダーをコンパイル
		GLES20.glShaderSource(shaderId, code);
		GLES20.glCompileShader(shaderId);

		// コンパイルが成功したか調べる
		int[] res = new int[1];
		GLES20.glGetShaderiv(shaderId, GLES20.GL_COMPILE_STATUS, res, 0);
		if (res[0] == 0) {
			// 失敗してる
			Log.d("compileShader", GLES20.glGetShaderInfoLog(shaderId));
			return -1;
		}
		return shaderId;
	}
}
APKファイルをダウンロード サンプルプロジェクトをダウンロード

, , , , , ,

OpenGLでGLES1.0じゃなくGLES20を使った一番簡単なサンプル@tryGLES2000a Android OpenGL GLES20でVertexBufferObject(VBO)を使うサンプル@tryGLES2002

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>