ibispaintのopengles2.0

49
株式会社アイビス 神谷栄治 ibisPaintOpenGL ES 2.0 12428日土曜日

Upload: eiji-kamiya

Post on 05-Dec-2014

14.550 views

Category:

Documents


3 download

DESCRIPTION

iPhone Dev勉強会 東京 2012/4/14で発表した資料です。

TRANSCRIPT

Page 1: IbisPaintのOpenGLES2.0

株式会社アイビス 神谷栄治

ibisPaintのOpenGL ES 2.0

12年4月28日土曜日

Page 2: IbisPaintのOpenGLES2.0

自己紹介•株式会社アイビス (社員70名ほど)• iPhone, iPad, Android, タブレット, Webシステムの受託開発など

•代表取締役社長 神谷栄治

•ハンドル:かみやん

• Twitter:    @kamiyan

•自称、ハッカー社長 初めて言ってみたけど( ´Д`)y━・~~

12年4月28日土曜日

Page 3: IbisPaintのOpenGLES2.0

自称ハッカー社長•小学生:プログラミング、BASIC、Z80アセンブラ

•中学生:初の原稿料をもらう

•大学生:3D野郎、Direct3D、C++、日本初FTPソフト小次郎プチヒット、機会学習、遺伝的プログラミング

•サラリーマン:3D CAD作り、OpenGL、C++

•アイビス設立(26歳):ibisBrowser、ibisMail、ibisPaint、Java、C++、Objective-C、ロボット作り

•高校生:恋愛♡ ( ´Д`)y━・~~12年4月28日土曜日

Page 4: IbisPaintのOpenGLES2.0

プログラミングの醍醐味

高速化!たまんねぇ~( ´Д`)y━・~~

12年4月28日土曜日

Page 5: IbisPaintのOpenGLES2.0

アプリの紹介

• ibisMail for iPad

•こちらも国内有料総合1位獲得。

• ibisPaint(アイビスペイント)

•こちらも国内有料総合1位獲得。

• ibisMail for iPhone(アイビスメール)

•世界初のメールアプリ。国内有料総合1位獲得。

3冠!!12年4月28日土曜日

Page 6: IbisPaintのOpenGLES2.0

ibisPaintの企画• iOS4.2リリースによりAVFoundationでmovファイルの作成ができることが分かる!(2010/12)

•作画行程をmovファイルにエンコーディングしてYouTubeにアップロードして共有したら楽しいんじゃね?!

•ウィンドウやツールの変化も記録したいよね!

•高速だし、OpenGLに決定~!

•「ソーシャルお絵描きアプリ ibisPaint」バカ受け間違えなし!( ´Д`)y━・~~

12年4月28日土曜日

Page 7: IbisPaintのOpenGLES2.0

ibispaint.com

完成!

PHPは嫌い ( ´Д`)y━・~~JavaServlet+JSP+MySQL12年4月28日土曜日

Page 8: IbisPaintのOpenGLES2.0

アプリ動作デモ

AppStoreで「ibisPaint」で検索して「ibisPaint X」をダウンロードください。無料。iPad / iPhone両対応の

ユニバーサルアプリです。

デモ中~( ´Д`)y━・~~

12年4月28日土曜日

Page 9: IbisPaintのOpenGLES2.0

•超高速! iPad(3rd Gen)なら4コア!

• Core GraphicsやCore Imageよりも低レベルライブラリ

• AndroidやWindowsなど他のプラットフォームにも移植しやすい

•漢は黙ってC++

OpenGL ESのメリット

普段はJava使いだけどな~ ( ´Д`)y━・~~

12年4月28日土曜日

Page 10: IbisPaintのOpenGLES2.0

• GLES1.0は固定パイプライン、GLES2.0はプログラマブル

• GLES1.0は用意された描画パターンから選ぶ

• GLES2.0は1pixelごとの色の計算をどうするかをC言語風の専用言語(シェーダー言語)で書く。

OpenGL ES1.0と2.0の違い(1)

12年4月28日土曜日

Page 11: IbisPaintのOpenGLES2.0

OpenGL ES1.0と2.0の違い(2)• 1pixelごとにmain()関数がコールされる感じ。

•マルチコアGPUで並列処理!PCの世界だと1000コアとか。

• GLES2.0は行列計算APIがない(削除しなくてもよかったのでは。。)

•とにかく、かなり違う!

とにかくって小学生かよ ( ´Д`)y━・~~12年4月28日土曜日

Page 12: IbisPaintのOpenGLES2.0

頂点シェーダーとフラグメントシェーダー

•頂点シェーダー(Vertex Shader, vsh)は、頂点位置、頂点の色、頂点のテクスチャ座標などを決める

•フラグメントシェーダー(Fragment Shader, fsh)は、1pixel

ごとの色を決める

• ibisPaintは2Dのアプリのため頂点シェーダーは、ほとんど何もしていない

•フラグメントシェーダーでいろいろ出来る。

12年4月28日土曜日

Page 13: IbisPaintのOpenGLES2.0

CPUメモリとGPUメモリ

•メインメモリからGPUメモリへ書き込みはglTexImage2D()

•GPUメモリからメインメモリへ読み込みはglReadPixels()

•GPUメモリのポインタ等は得られないのでCPUが直接readしたりwriteしたりは出来ない•glTexImage2D()やglReadPixels()は重い(20msぐらい)ので注意•バックグラウンドThreadから読み書きしてはいけない

メインメモリ GPUメモリ

CPU GPU

12年4月28日土曜日

Page 14: IbisPaintのOpenGLES2.0

GPUのメモリ• レンダーバッファ

• 最終描画先であり、アルファプレーンがない、裏画面と表画面用の2枚があり、基本は裏画面に描画してフリップで交換する([EAGLContext presentRenderBuffer :])

• フレームバッファ

• カラーバッファ、Zバッファ、ステンシルバッファなどを持つ

• ibisPaintでは2Dのためカラーバッファのみ使用、テクスチャバッファとして使用

12年4月28日土曜日

Page 15: IbisPaintのOpenGLES2.0

フレームバッファーオブジェクト• Frame Buffer Object(FBO)

•昔はテクスチャバッファは読み取り専用でGPUがそのバッファに描画することができなかったが、FBOによりテクスチャバッファにレンダリングできるようになった。

•動的テクスチャが可能になった!

• ibisPaintではレイヤーのラスターデータはFBO。

12年4月28日土曜日

Page 16: IbisPaintのOpenGLES2.0

FBO生成• glGenTextures(); //テクスチャバッファ生成

• glGenFramebuffers(); //フレームバッファ生成

• glBindTexture(); //カレントテクスチャとする

• glBindFramebuffer(); //カレントフレームバッファとする

• glFramebufferTexture2D(); //フレームバッファとテクスチャバッファをひも付ける

• glCheckFramebufferStatus(); //整合性が取れているか確認

12年4月28日土曜日

Page 17: IbisPaintのOpenGLES2.0

レンダーバッファの生成• glGenRenderbuffers(); //レンダーバッファ生成

• glGenFramebuffers(); //フレームバッファ生成

• glBindRenderbuffer(); //カレントレンダーバッファとする

• glBindFramebuffer(); //カレントフレームバッファとする

• glFramebufferRenderbuffer(); //フレームバッファとレンダーバッファをひも付け

12年4月28日土曜日

Page 18: IbisPaintのOpenGLES2.0

フレームバッファの切替

フレームバッファ レンダーバッファ

フレームバッファ テクスチャバッファ描画命令

•glBindFramebuffer();で描画先を切り替え、実画面とテクスチャバッファを透過的に扱うことができる

12年4月28日土曜日

Page 19: IbisPaintのOpenGLES2.0

ibisPaintでのFBOの例

ブラシパターンテクスチャ

レイヤー(FBO)

レイヤーに描画

レイヤー(FBO)レンダーバッファ(裏画面)に描画

レイヤーを描画

入力テクスチャ出力先

フレームバッファ

STEP1

STEP2

12年4月28日土曜日

Page 20: IbisPaintのOpenGLES2.0

描画命令(プリミティブ)• 矩形を描け、矩形を塗りつぶせ、円を描け、多角形を描け、ベジェ曲線を描けとかはない!

• 点、線分、三角形の描画のみ(漢らしい!)

• 描画命令は glDrawArrays() or glDrawElements()

#define GL_POINTS 点列#define GL_LINES 線分列#define GL_LINE_LOOP 閉じたポリライン#define GL_LINE_STRIP 折れ線#define GL_TRIANGLES 三角形列#define GL_TRIANGLE_STRIP つながった三角形列(ストリップ)#define GL_TRIANGLE_FAN つながった三角形列(ファン)

12年4月28日土曜日

Page 21: IbisPaintのOpenGLES2.0

描画命令(表と裏)•右回り(Clockwise)が表、左回り(Counterclockwise)が裏?

•右回りが裏、左回りが表?

1

23

1

2 3

座標系によるけど裏表を間違えると見えないので注意glFrontFace(GL_CW); or glFrontFace(GL_CCW);で設定可能

12年4月28日土曜日

Page 22: IbisPaintのOpenGLES2.0

つながった三角形列1 2, 4

矩形を描くのに 3, 6 5GL_TRIANGLESだと6頂点をGPUへ送る

1 2

3 4GL_TRIANGLE_STRIPだと4頂点をGPUへ送るだけで済む(2/3の転送量)

1.5倍高速化!

トライアングルストリップ

12年4月28日土曜日

Page 23: IbisPaintのOpenGLES2.0

つながった三角形列(2)

こういうポリゴンデータはよくある。上の例では16ポリゴン。GL_TRIANGLESだと16x3頂点の48頂点をGPUへ送る。

1

2

3

4 6 8 10 12 14 16 18

5 7 9 11 13 15 17GL_TRIANGLE_STRIPの場合は、18頂点。ポリゴン数が多い場合1/3に減る。

3倍高速化!12年4月28日土曜日

Page 24: IbisPaintのOpenGLES2.0

つながった三角形列(3)

こういうポリゴンデータはよくある。GL_TRIANGLE_STRIPを2回描画?→NO。縮退(面積0の三角形を描画する)を使うことで1回の描画

16 18

17

19,20API呼び出しがn回から1回へ高速化

12年4月28日土曜日

Page 25: IbisPaintのOpenGLES2.0

頂点フォーマット(PC)

•頂点のデータの型はアプリケーションが決める

• PC:頂点位置P(x,y,z), 頂点カラー C(r,g,b,a)

引用 http://openglut.sourceforge.net/redbook_smooth.png

間の色は線形補完12年4月28日土曜日

Page 26: IbisPaintのOpenGLES2.0

頂点フォーマット(PT)• PT:頂点位置P(x,y,z)とテクスチャ座標T(u,v)

•四角い画像も三角形2枚で描く•テクスチャ画像は、RGBA 8-8-8-8bitもOK

•ピクセルごとにアルファ値が違うものもOK

•PNGをテクスチャーバッファにロードするのがよい•頂点カラーCは、C(1.0, 1.0, 1.0, 1.0)とみなされる。

•アルファ値がある場合のブレンドは、glBlendFunc()で設定可能だが普通アルファブレンディング(Src * α + Dst * (1-α))しか使わない。

12年4月28日土曜日

Page 27: IbisPaintのOpenGLES2.0

頂点フォーマット(PCT)• PCT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ座標T(u,v)

PCだけで描ける マスクテクスチャ

乗算

出力乗算のところはフラグメントシェーダでカスタマイズ可能

12年4月28日土曜日

Page 28: IbisPaintのOpenGLES2.0

頂点フォーマット(PCTT)• PCTT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ座標T1(u,v), テクスチャ座標T2(u,v)

•応用:えんぴつ、クレヨン、画用紙

カレントカラー カレントブラシパターン

カレント背景パターン

合成12年4月28日土曜日

Page 29: IbisPaintのOpenGLES2.0

頂点フォーマット(PCTT)(2)•クレヨン •背景テクスチャは、シームレステク

スチャにする。作り方は「シームレステクスチャ」で検索。•背景テクスチャのテクスチャ座標は、描画位置Pに比例して変化させて、背景テクスチャが固定されているように見えるようにする。

12年4月28日土曜日

Page 30: IbisPaintのOpenGLES2.0

頂点フォーマット(PCTT)(3)

•ブラシパターンは、テクスチャ座標を固定(普通は、0.0 or 1.0)にし、ペンを走らせたときにペンが動いて見える。•背景テクスチャのテクスチャラップモードは、GL_REPEATにする。

•頂点フォーマットとしては、テクスチャの参照はPCTTのように2枚だけでなくたくさん参照可能(8枚くらいはいけると思う)

12年4月28日土曜日

Page 31: IbisPaintのOpenGLES2.0

アニメーションの例• 頂点位置Pを平行移動だとスライドイン、スライドアウトアニメーション

• 頂点位置Pを拡大縮小だと、ズームイン、ズームアウトアニメーション

• 頂点位置Pを回転させると、回転アニメーション(ibisPaintではレイヤーの回転やフォトライブラリインポート時の回転で利用)

• 頂点カラーCのアルファ値を変化させるとフェードインフェードアウト

• テクスチャ座標のT(u, v)を変化させて絵柄をスクロールさせるアニメーション

12年4月28日土曜日

Page 32: IbisPaintのOpenGLES2.0

選択範囲アニメーション•選択範囲を表す折れ線は、

GL_LINE_STRIP

•そこに□□■■の4pixelのテクスチャを設定

•アニメーションとしてLINE STRIPのテクスチャ座標T(u,v)のuを0.25づつずらすことで、破線がアニメーション

マジックワンド

12年4月28日土曜日

Page 33: IbisPaintのOpenGLES2.0

シェーダの準備• glCreateProgram(); //シェーダプログラムの生成

• glCreateShader(); //シェーダの生成(GL_VERTEX_SHADER or

GL_FRAGMENT_SHADER)

• glShaderSource();// シェーダソースコードの指定

• glCompleShader();// ソースのコンパイル

• glGetShaderiv(GL_COMPILE_STATUS);//コンパイル結果の取得

なんとコンパイラ内蔵!GPUのドライバがコンパイルする!

12年4月28日土曜日

Page 34: IbisPaintのOpenGLES2.0

シェーダの準備(2)• glAttachShader(vsh); //頂点シェーダをセット

• glAttachShader(fsh); //フラグメントシェーダをセット

• glLinkProgmram(); //vshとfshをリンク

• glGetProgramiv(); //リンク結果を取得

• glUseProgram(); //カレントプログラムとする

なんとリンクもする!12年4月28日土曜日

Page 35: IbisPaintのOpenGLES2.0

シェーダの準備(3)

glCreateProgram()

glCreateShader(vsh) glCreateShader(fsh)

glShaderSource(vsh) glShaderSource(fsh)

glCompileShader(vsh) glCompileShader(fsh)

glGetShaderiv(vsh) glGetShaderiv(fsh)

glAttachShader(vsh) glAttachShader(fsh)

glLinkProgram()

glGetProgramiv()

ビルドフロー

12年4月28日土曜日

Page 36: IbisPaintのOpenGLES2.0

頂点シェーダソース(1)• PCT(位置P, カラーC, テクスチャ座標T)の例

attribute vec2 a_position;attribute vec2 a_texCoord;attribute vec4 a_color ;uniform mat4 u_matrix;varying vec2 v_texCoord;varying vec4 v_color ;

void main(){ gl_Position = u_matrix * vec4(a_position, 0.0, 1.0); v_texCoord = a_texCoord; v_color = a_color ;}

アトリビュート変数

ユニフォーム変数バリイング変数

}

}

位置とカラーとテクスチャ座標を入力してfshへ渡す12年4月28日土曜日

Page 37: IbisPaintのOpenGLES2.0

頂点シェーダソース(2)• PCT(位置P, カラーC, テクスチャ座標T)の例

attribute vec2 a_position;attribute vec2 a_texCoord;attribute vec4 a_color ;

} アトリビュート変数

•アトリビュート変数とは、glDrawArrays()から来る値(CPU側がセットした値)。•頂点シェーダからみると入力変数の宣言•お絵描きアプリのため、a_positionが2次元(vec2

型)

12年4月28日土曜日

Page 38: IbisPaintのOpenGLES2.0

頂点シェーダソース(3)• PCT(位置P, カラーC, テクスチャ座標T)の例

uniform mat4 u_matrix; ユニフォーム変数

•ユニフォーム変数は、汎用のCPU側から来る変数(CPU側でセット)

•上図では、4x4行列を渡している•整数、浮動小数、ベクトル、行列、テクスチャなどをCPUから渡すことが可能•全GPUコアから参照されるためRead Only

12年4月28日土曜日

Page 39: IbisPaintのOpenGLES2.0

頂点シェーダソース(4)• PCT(位置P, カラーC, テクスチャ座標T)の例

varying vec2 v_texCoord;varying vec4 v_color ; バリイング変数}

•バリイング変数は、頂点シェーダからフラグメントシェーダへ情報を伝達するための変数•頂点シェーダから見ると出力変数•フラグメントシェーダから見ると入力変数

12年4月28日土曜日

Page 40: IbisPaintのOpenGLES2.0

頂点シェーダソース(5)• PCT(位置P, カラーC, テクスチャ座標T)の例

void main(){ gl_Position = u_matrix * vec4(a_position, 0.0, 1.0); v_texCoord = a_texCoord; v_color = a_color ;}

•1頂点ごとにmain()関数が呼ばれる•上図、アトリビュート変数のa_positionを4次元に拡張し、u_matrixを乗算して、gl_Positionとする•gl_Positionは、頂点シェーダの出力変数(固定)

•上図、テクスチャ座標とカラーはそのままフラグメントシェーダへ転送

12年4月28日土曜日

Page 41: IbisPaintのOpenGLES2.0

フラグメントシェーダソース(1)• PCT(位置P, カラーC, テクスチャ座標T)の例

varying vec2 v_texCoord;varying vec4 v_color ;uniform sampler2D u_texture;void main(){ vec4 tex = texture2D(u_texture, v_texCoord); gl_FragColor = v_color * tex;}

•v_texCoord, v_colorはバリイング変数で頂点シェーダからの入力(線形補完済み)•u_textureは、ユニホーム変数でsampler2D型。CPU側からセット

12年4月28日土曜日

Page 42: IbisPaintのOpenGLES2.0

フラグメントシェーダソース(2)• PCT(位置P, カラーC, テクスチャ座標T)の例

void main(){ vec4 tex = texture2D(u_texture, v_texCoord); gl_FragColor = v_color * tex;}•main()関数は1pixelごとに呼ばれる•texture2D()組み込み関数は、sampler2D型とテクスチャ座標を入力し、そのテクセルカラーを得る関数•texはローカル変数•gl_FragColorは、フラグメントシェーダの最終出力先変数(固定)•上図では、テクスチャカラーと頂点カラーを乗算している

12年4月28日土曜日

Page 43: IbisPaintのOpenGLES2.0

シェーダ言語の注意事項• 色を参照するのは頂点カラーやテクスチャであり、出力先のフレームバッファの色は取れない。なぜならフラグメントシェーダのmain()は複数のGPUコアで並列に実行され、その実行順序が未定義であるため。

• ユニフォーム変数はCPU側からセットするがシェーダ言語側からみると定数。

• if()は使えるが、for()はループ回数が定数のもののみ。

• 色の計算やテクスチャ座標は浮動小数で計算されているが浮動小数内の計算誤差はやむを得ない

• iOSシミュレータではほぼ動かず

12年4月28日土曜日

Page 44: IbisPaintのOpenGLES2.0

ぼかしフィルタ(1)

• Blur Shaderを作成する

• STEP1~2を繰り返すとどんどんぼける

FBOa最終出力先

一時的にbindTexture()で入力側へ

FBObテンポラリFBO

bindFramebuffer()で出力先とする

COPY

FBObbindTexture()で入力側へ

blur shaderFBOa

bindFramebuffer()で出力先とする

STEP1

STEP2

12年4月28日土曜日

Page 45: IbisPaintのOpenGLES2.0

ぼかしフィルタソース

attribute vec2 a_position;attribute vec2 a_texCoord;uniform mat4 u_matrix;uniform vec2 u_pixel_tex;//1pxがtex coordでいくつかvarying vec2 v_texCoord;varying vec2 v_texCoordU;varying vec2 v_texCoordL;varying vec2 v_texCoordR;varying vec2 v_texCoordD;void main(void){ gl_Position = u_matrix * vec4(a_position, 0.0, 1.0); v_texCoord = a_texCoord; v_texCoordU = a_texCoord + vec2(0.0, -u_pixel_tex.y); v_texCoordL = a_texCoord + vec2(-u_pixel_tex.x, 0.0); v_texCoordR = a_texCoord + vec2( u_pixel_tex.x, 0.0); v_texCoordD = a_texCoord + vec2(0.0, u_pixel_tex.y);}

varying vec2 v_texCoord;varying vec2 v_texCoordU;varying vec2 v_texCoordL;varying vec2 v_texCoordR;varying vec2 v_texCoordD;uniform sampler2D u_texture;void main(){ vec4 tex = texture2D(u_texture, v_texCoord); vec4 texU = texture2D(u_texture, v_texCoordU); vec4 texL = texture2D(u_texture, v_texCoordL); vec4 texR = texture2D(u_texture, v_texCoordR); vec4 texD = texture2D(u_texture, v_texCoordD); vec4 tex2 = tex + texU + texL + texR + texD; gl_FragColor = tex2 / 5.0;}

BlurShader.vsh BlurShader.fsh

•アルゴリズム:カレント点、一つ上の点、左の点、右の点、下の点の5点の色を足して5で割る

12年4月28日土曜日

Page 46: IbisPaintのOpenGLES2.0

フラグメントシェーダ応用

•ぼかし以外も、グレースケール化とか、明度、彩度、色調とか、コントラストとか、なんでもOK

• InstagramもiPhotoもOpenGL ES2.0を使っている

•フィルタ系が全部、超高速!!

12年4月28日土曜日

Page 47: IbisPaintのOpenGLES2.0

ibisPaintでの性能

• iPad2、1024x768(0.78Mpixels)で、レイヤー6枚で60fps!!

• iPad (3rd Gen)、2048x1536(3.14Mpixels)で、レイヤー6枚で60fps!!

60fpsを死守せよ!!

12年4月28日土曜日

Page 48: IbisPaintのOpenGLES2.0

まとめ(1)

•OpenGLは、低レベルAPIなので高速!

• GPUコアは年々増えていく(PCでは1000コア)

•フレームバッファオブジェクトでテクスチャバッファに書き込めるようになった(多段レンダリング)

•フラグメントシェーダを使うと色々なフィルタが超高速に動く

12年4月28日土曜日

Page 49: IbisPaintのOpenGLES2.0

まとめ(2)

• ibisPaintは60fpsで動いている。60fpsを死守せよ!

•プログラミングの醍醐味は高速化!たまんねぇ~

( ´Д`)y━・~~

• ibisPaint Xは無料でiPhone / iPadのユニバーサルアプリ

ダウンロードしてね~ ( ´Д`)y━・~~

あとでShideShareに上げておきます。

ご清聴ありがとございました。12年4月28日土曜日