46
Android OpenGL/ES ハンズオン Smart.LABO 丹所 育男(tan1234jp) 1

Android OpenGL HandsOn

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Android OpenGL HandsOn

AndroidOpenGL/ES ハンズオン

Smart.LABO丹所 育男(tan1234jp)

1

Page 2: Android OpenGL HandsOn

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

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

• Twitter : @tan1234jp

2

Page 3: Android OpenGL HandsOn

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

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

3

Page 4: Android OpenGL HandsOn

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

• 点• 直線• 三角形

Canvas OpenGL/ES

4

Page 5: Android OpenGL HandsOn

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

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

5

Page 6: Android OpenGL HandsOn

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

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

6

Page 7: Android OpenGL HandsOn

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

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

OpenGL_Sample

7

Page 8: Android OpenGL HandsOn

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

com.example.opengl_sample

8

Page 9: Android OpenGL HandsOn

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

Page 10: Android OpenGL HandsOn

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

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

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

10

Page 11: Android OpenGL HandsOn

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

Page 12: Android OpenGL HandsOn

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

12

Page 13: Android OpenGL HandsOn

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

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

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

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

13

Page 14: Android OpenGL HandsOn

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

onSurfaceCreated

onSurfaceChanged

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

端末依存14

Page 15: Android OpenGL HandsOn

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

メソッド名 役割

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

15

Page 16: Android OpenGL HandsOn

コード解説• 描画クリア

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

メソッド名 役割

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

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

16

Page 17: Android OpenGL HandsOn

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

ViewSurfaceView OpenGL

原点(0,0)

原点(0,0)

(480,0)

(0,854)

(1,0)(-1,0)

(0,1)

(0,-1)

(Xperiaの場合)

17

Page 18: Android OpenGL HandsOn

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

HT-03A Xperia

480px

320px

854px

480px

18

Page 19: Android OpenGL HandsOn

三角形を描画する• 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

Page 20: Android OpenGL HandsOn

三角形を描画する• 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

Page 21: Android OpenGL HandsOn

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

21

Page 22: Android OpenGL HandsOn

コード解説• 座標の設定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

Page 23: Android OpenGL HandsOn

コード解説• 座標配列を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

Page 24: Android OpenGL HandsOn

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

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

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

24

Page 25: Android OpenGL HandsOn

Androidアーキテクチャ

25

Page 26: Android OpenGL HandsOn

コード解説• 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

Page 27: Android OpenGL HandsOn

(発展)四角形を描画する• 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

Page 28: Android OpenGL HandsOn

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

28

Page 29: Android OpenGL HandsOn

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

29

Page 30: Android OpenGL HandsOn

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

+ =

30

Page 31: Android OpenGL HandsOn

(発展)四角形を描画する• 重複している座標がある! 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

Page 32: Android OpenGL HandsOn

(発展)四角形を描画する• 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

Page 33: Android OpenGL HandsOn

(発展)四角形を描画する• 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

Page 34: Android OpenGL HandsOn

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

34

Page 35: Android OpenGL HandsOn

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

Page 36: Android OpenGL HandsOn

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

Page 37: Android OpenGL HandsOn

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

④ ③

①②

37

Page 38: Android OpenGL HandsOn

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

①②

③④

38

Page 39: Android OpenGL HandsOn

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

④ ③

39

Page 40: Android OpenGL HandsOn

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

④ ③

② ① ② ①

③④

40

Page 41: Android OpenGL HandsOn

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

③④

41

Page 42: Android OpenGL HandsOn

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

42

Page 43: Android OpenGL HandsOn

色をつける• 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

Page 44: Android OpenGL HandsOn

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

44

Page 45: Android OpenGL HandsOn

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

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

メソッド名 役割

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

45

Page 46: Android OpenGL HandsOn

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

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

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

46