Android OpenGL HandsOn

Preview:

DESCRIPTION

2012.5.28の勉強会で使用するOpenGLハンズオン用資料

Citation preview

AndroidOpenGL/ES ハンズオン

Smart.LABO丹所 育男(tan1234jp)

1

自己紹介• 丹所 育男(たんしょ いくお)• 春日井市出身・自宅は名古屋市・実家は可児市• 講師→制御系→ネットワーク系→業務系→制御系→システム保守→制御系→業務系→携帯アプリ

• 2011年6月に「SMART.LABO」として独立• Androidアプリの開発がメイン(iPhone,Coronaも)

• Twitter : @tan1234jp

2

OpenGL/ESとは?• OpenGL Embedded Subsetの略• 3Dコンピュータグラフィックス用APIのサブセットで、3D空間に浮かんだ頂点を結んだ図形を描画することに特化している。

• 主に携帯電話などの組み込みシステムや、ゲーム専用機で使われている。→iOS, Android, Symbian OS,→PlayStation3、Nintendo 3DS

3

描画APIのサポート• 点• 直線• 三角形• 四角形• 五角形以上の多角形• 円• 文字

• 点• 直線• 三角形

Canvas OpenGL/ES

4

AndroidのView• Androidには、3種類のViewがある。→View,SurfaceView,GLSurfaceView

• OpenGLでは、GLSurfaceViewを継承したものを使う。

5

GLSurfaceView• OpenGLの描画に特化したView• 描画タイミングは端末依存(プログラマが決めることもできる)

• 別スレッドで動作するため、直接UIに対して変更をかけることは不可

6

OpenGL/ESの初期化• プロジェクトの作成

• バージョンの決定(Ver1.5以降であればOK)

OpenGL_Sample

7

OpenGL/ESの初期化• パッケージ名の設定

com.example.opengl_sample

8

OpenGL/ESの初期化package com.example.opengl_sample;

import android.app.Activity;import android.opengl.GLSurfaceView;import android.os.Bundle;

public class OpenGL_SampleActivity extends Activity { private GLSurfaceView glSurfaceView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); glSurfaceView = new GLSurfaceView(this); glSurfaceView.setRenderer(new GLRenderSample()); setContentView(glSurfaceView); }

エラーとなるが無視

9

OpenGL/ESの初期化 @Override protected void onPause() { super.onPause(); glSurfaceView.onPause(); }

@Override protected void onResume() { super.onResume(); glSurfaceView.onResume(); }

//ここに後でコードを追加します!}

10

OpenGL/ESの初期化GLRenderSampleの作成onResume()の後に以下のコードを追加。

class GLRenderSample implements GLSurfaceView.Renderer {

public void onDrawFrame(GL10 gl) { gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT); }

public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); }

public void onSurfaceCreated(GL10 gl, EGLConfig config) { }

11

OpenGL/ESの初期化• 実行!真っ白な画面になりましたか?

12

コード解説• GLRenderSampleの各メソッド

メソッド名 呼ばれるタイミングonSurfaceCreated(GL10 gl, EGLConfig eglconfig) GLSurfaceView用のメモリ確保が終了

onSurfaceChanged(GL10 gl, int width, int height) 画面サイズが変更された時

onDrawFrame(GL10 gl) 再描画が必要な時

13

コード解説• 各メソッドの呼び出され方

onSurfaceCreated

onSurfaceChanged

onDrawFrame呼び出されるタイミングは

端末依存14

コード解説• 描画範囲の設定

メソッド名 役割

glViewport(int x, int y, int width, int height);OpenGL/ESの描画範囲を指定する。「どの座標(x, y)から、幅width、高さheightまで」を描画範囲とする。

15

コード解説• 描画クリア

• glClearColorの引数の値を適当に変更して、いろいろな色で塗りつぶされることを確認してみてください。

メソッド名 役割

glClearColor(float r, float g, float b, float a);画面全体を塗りつぶす色を決定する。RGBA(Aはアルファ値)を指定する。指定できる範囲は0~1の実数値。

glClear(int mask); 塗りつぶしを実行する。引数にGL_COLOR_BUFFER_BITを指定する。

16

OpenGL/ESの座標系• 座標系の違い

ViewSurfaceView OpenGL

原点(0,0)

原点(0,0)

(480,0)

(0,854)

(1,0)(-1,0)

(0,1)

(0,-1)

(Xperiaの場合)

17

三角形を描画する• 例えば、(0,0),(1,0),(1,1)の3点を結ぶ三角形を描画する場合・・・

HT-03A Xperia

480px

320px

854px

480px

18

三角形を描画する• onDrawFrameを修正 public void onDrawFrame(GL10 gl) { gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f); //第1引数に変更あり! gl.glClear(GL10.GL_COLOR_BUFFER_BIT); float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) }; ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(positions);

19

三角形を描画する• onDrawFrameを修正(続き)

fb.position(0); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); }

20

三角形を描画する• 実行!→水色の背景に白い三角形が表示されましたか?→解像度の違う端末でも同じ画面が表示されましたか?

21

コード解説• 座標の設定float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) };

• 浮動小数の1次元配列で表す• 配列に格納する順番は「頂点1(x,y,z)」「頂点2(x,y,z)」「頂点3(x,y,z)」・・・とする。

22

コード解説• 座標配列をOpenGL/ESに転送

ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);bb.order(ByteOrder.nativeOrder());FloatBuffer fb = bb.asFloatBuffer();fb.put(positions);fb.position(0);

• 座標配列をOpenGL/ESで扱えるメモリ形式に変換

• AndroidでOpenGL/ESを扱う際の「おまじない」。

23

コード解説• OpenGL/ESは、Android RuntimeではなくLibraries群(CPU依存)

• Javaの配列などのデータを、そのままOpenGL/ESへ転送することはできない

• java.nio.* パッケージを使用して、OpenGL/ESから直接参照できるようなデータに変換する必要がある。

24

Androidアーキテクチャ

25

コード解説• GLSurfaceViewに描画するメソッド名 役割

glEnableClientState(int array);

glVertexPointer()で転送するメモリ情報の種類を設定する。引数はいろいろあるが、座標情報を転送する場合は「GL_VERTEX_ARRAY」を指定する。

glVertexPointer(int size, int type, int stride, Buffer pointer);

位置情報を設定する。size : 位置情報の要素数。3次元の場合は3。type : 位置情報の変数の型。stride : 常時0。pointer : OpenGL/ESに転送可能な位置情報

glDrawArrays(int mode, int first, int count);

GLSurfaceViewに描画する。mode : 描画方法を指定する(後ほど説明)first : 描画する位置情報の開始位置。count : 位置情報を使用する数。

26

(発展)四角形を描画する• onDrawFrameを修正 public void onDrawFrame(GL10 gl) { : : float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) 0.0f, 0.0f, 0.0f,//原点(0,0) 0.0f, 1.0f, 0.0f,//上(0,1) 1.0f, 1.0f, 0.0f,//右上(1,1) };

27

(発展)四角形を描画する• onDrawFrameを修正(続き) : : gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3 * 2); }

28

(発展)四角形を描画する• 実行!→水色の背景の右上に、白い四角形が表示されましたか?→解像度の違う端末でも同じ画面が表示されましたか?

29

(発展)四角形を描画する• 三角形を組み合わせれば、どんな多角形でも作成可能

+ =

30

(発展)四角形を描画する• 重複している座標がある! public void onDrawFrame(GL10 gl) { : : float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) 0.0f, 0.0f, 0.0f,//原点(0,0) 0.0f, 1.0f, 0.0f,//上(0,1) 1.0f, 1.0f, 0.0f,//右上(1,1) };

• 座標を使いまわししたい!

31

(発展)四角形を描画する• onDrawFrameを修正 public void onDrawFrame(GL10 gl) { : : float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) // 0.0f, 0.0f, 0.0f,//原点(0,0) 0.0f, 1.0f, 0.0f,//上(0,1) // 1.0f, 1.0f, 0.0f,//右上(1,1) };

32

(発展)四角形を描画する• onDrawFrameを修正(続き)

: :

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //第1・3引数変更 }

33

(発展)四角形を描画する• 実行!→先ほどと同じ画面になりましたか?

34

glDrawArraysの引数• glDrawArrays()の第1引数で指定する値(定数)により、描画方法を変更することができる。引数 説明GL10.GL_POINTS 点

GL10.GL_LINES 直線

GL10.GL_LINE_STRIP 折れ線GL10.GL_TRIANGLES 三角形GL10.GL_TRIANGLE_STRIP 1辺を共有しながら帯状に三角形を描画するGL10.GL_TRIANGLE_FAN 1点を共有しながら扇状に三角形を描画する

35

glDrawArraysの引数• 描画方法の違い public void onDrawFrame(GL10 gl) { : : float positions[] = { 1.0f, 0.0f, 0.0f,//右(1,0) 0.0f, 0.0f, 0.0f,//原点(0,0) 1.0f, 1.0f, 0.0f,//右上(1,1) 0.0f, 1.0f, 0.0f,//上(0,1) }; : : gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //第1・3引数変更 }

①②③④

36

GL_POINTS• 点(1px)を描画する

④ ③

①②

37

GL_LINES• 直線を描画する時に使う• 座標の描画順は、①②→③④→⑤⑥→

①②

③④

38

GL_LINE_STRIP• 直線を描画する時に使う• 座標の描画順は、①②→②③→③④→④⑤→

④ ③

39

GL_TRIANGLE_STRIP• 隣接した三角形を描画する時に使う• 座標の描画順は、①②③→②③④→③④⑤→

④ ③

② ① ② ①

③④

40

GL_TRIANGLE_FAN• 扇形を描画する時に使う• 座標の描画順は、①②③→①③④→①④⑤→

③④

41

GL_TRIANGLE_FAN• 引数を変更して実行すると、右の図形が描画されます。

42

色をつける• onDrawFrameを修正 public void onDrawFrame(GL10 gl) { : : gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb); gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); //追加 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); }

43

色をつける• 実行!→水色の背景の右上に、赤い四角形が表示されましたか?

44

コード解説• 描画色を指定する

• glColor4fの引数の値を適当に変更して、いろいろな色で塗りつぶされることを確認してみてください。

メソッド名 役割

glColor4f(float r, float g, float b, float a);描画色を決定する。RGBA(Aはアルファ値)を指定する。指定できる範囲は0~1の実数値。

45

• 本日のハンズオンはここまでです。お疲れ様でした。

• 今回は、単純に三角形を描画するのみでしたが、任意の場所への描画や回転、拡大・縮小、任意画像の描画などもできます。

• ・・・が、数学(行列)の知識が必要となりますので、次回(?)のハンズオンにできればと思っております。

46

Recommended