[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
SlideShare a Scribd company logo
ibisPaintのOpenGL ES 2.0
              株式会社アイビス 神谷栄治




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


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

  • ハンドル:かみやん


  • Twitter:       @kamiyan

  • 自称、ハッカー社長                              初めて言って
                                        みたけど( ´Д`)y━・~~
12年4月28日土曜日
自称ハッカー社長
  • 小学生:プログラミング、BASIC、Z80アセンブラ

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


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

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

  •   アイビス設立(26歳):ibisBrowser、ibisMail、ibisPaint、
      Java、C++、Objective-C、ロボット作り
                     • 高校生:恋愛♡ ( ´Д`)y━・~~
12年4月28日土曜日
プログラミングの醍醐味



          高速化!
                    たまんねぇ∼( ´Д`)y━・~~
12年4月28日土曜日
アプリの紹介
              • ibisMail   for iPhone(アイビスメール)

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

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

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

                • こちらも国内有料総合1位獲得。
                                                 3冠!!
12年4月28日土曜日
ibisPaintの企画
  • iOS4.2リリースによりAVFoundationでmovファイルの作
     成ができることが分かる!(2010/12)

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

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

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

  • 「ソーシャルお絵描きアプリ     ibisPaint」
                 バカ受け間違えなし!( ´Д`)y━・~~
12年4月28日土曜日
ibispaint.com


                           完成!
   JavaServlet+JSP+MySQL   PHPは嫌い ( ´Д`)y━・~~
12年4月28日土曜日
アプリ動作デモ


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




    AppStoreで「ibisPaint」で検索して「ibisPaint X」を
 ダウンロードください。無料。iPad / iPhone両対応の
              ユニバーサルアプリです。

12年4月28日土曜日
OpenGL ESのメリット

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

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

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

     しやすい

  • 漢は黙ってC++

                     普段はJava使いだけどな∼ ( ´Д`)y━・~~
12年4月28日土曜日
OpenGL ES1.0と2.0の違い(1)

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


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


  • GLES2.0は1pixelごとの色の計算をどうするかをC言語風

     の専用言語(シェーダー言語)で書く。




12年4月28日土曜日
OpenGL ES1.0と2.0の違い(2)
  • 1pixelごとにmain()関数がコールされる感じ。


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

     か。

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

     のでは。。)

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


              とにかくって小学生かよ ( ´Д`)y━・~~
12年4月28日土曜日
頂点シェーダーと
              フラグメントシェーダー
  • 頂点シェーダー(Vertex   Shader, vsh)は、頂点位置、頂点
     の色、頂点のテクスチャ座標などを決める

  • フラグメントシェーダー(Fragment    Shader, fsh)は、1pixel
     ごとの色を決める

  • ibisPaintは2Dのアプリのため頂点シェーダーは、ほとん

     ど何もしていない

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

12年4月28日土曜日
CPUメモリとGPUメモリ
               メインメモリ           GPUメモリ




                 CPU              GPU


  •メインメモリからGPUメモリへ書き込みはglTexImage2D()
  •GPUメモリからメインメモリへ読み込みはglReadPixels()
  •GPUメモリのポインタ等は得られないのでCPUが直接readし
  たりwriteしたりは出来ない
  •glTexImage2D()やglReadPixels()は重い(20msぐらい)ので注意
  •バックグラウンドThreadから読み書きしてはいけない
12年4月28日土曜日
GPUのメモリ
  •   レンダーバッファ

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

  •   フレームバッファ

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

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

12年4月28日土曜日
フレームバッファーオブジェクト
  • Frame     Buffer Object(FBO)

  • 昔はテクスチャバッファは読み取り専用でGPUがその

     バッファに描画することができなかったが、FBOによ
     りテクスチャバッファにレンダリングできるように
     なった。

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


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


12年4月28日土曜日
FBO生成
    •   glGenTextures(); //テクスチャバッファ生成

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

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

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

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

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

12年4月28日土曜日
レンダーバッファの生成
  • glGenRenderbuffers(); //レンダーバッファ生成


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


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


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


  • glFramebufferRenderbuffer(); //フレームバッファとレン

     ダーバッファをひも付け

12年4月28日土曜日
フレームバッファの切替
                       フレームバッファ      レンダーバッファ
  描画命令
                       フレームバッファ テクスチャバッファ


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


12年4月28日土曜日
ibisPaintでのFBOの例
                                         出力先
                 入力テクスチャ
                                       フレームバッファ




         STEP1               レイヤーに描画
                 ブラシパターン
                                       レイヤー(FBO)
                  テクスチャ




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




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

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

   •   描画命令は 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日土曜日
描画命令(表と裏)
  • 右回り(Clockwise)が表、左回り(Counterclockwise)が裏?


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


                  1                    1




              3       2         2             3

     座標系によるけど裏表を間違えると見えないので注意
     glFrontFace(GL_CW); or glFrontFace(GL_CCW);で設定可能
12年4月28日土曜日
つながった三角形列
              トライアングルストリップ

                              1       2, 4


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


                              1         2

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


                              1.5倍高速化!
12年4月28日土曜日
つながった三角形列(2)

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


     2        4       6    8     10   12    14    16   18


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



                                           3倍高速化!
12年4月28日土曜日
つながった三角形列(3)


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

                                                  17

19,20
                      API呼び出しがn回から1回へ高速化
12年4月28日土曜日
頂点フォーマット(PC)
  • 頂点のデータの型はアプリケーションが決める


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




                                                                      間の色は線形補完
              引用 http://openglut.sourceforge.net/redbook_smooth.png

12年4月28日土曜日
頂点フォーマット(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日土曜日
頂点フォーマット(PCT)
  • PCT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ

     座標T(u,v)




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



                                乗算

                                出力
                                   乗算のところはフラグメント
                                   シェーダでカスタマイズ可能
12年4月28日土曜日
頂点フォーマット(PCTT)
  • PCTT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ

     座標T1(u,v), テクスチャ座標T2(u,v)

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




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

                      合成
12年4月28日土曜日
頂点フォーマット(PCTT)(2)
  • クレヨン
              •背景テクスチャは、シームレステク
              スチャにする。作り方は「シームレス
              テクスチャ」で検索。
              •背景テクスチャのテクスチャ座標
              は、描画位置Pに比例して変化させ
              て、背景テクスチャが固定されている
              ように見えるようにする。




12年4月28日土曜日
頂点フォーマット(PCTT)(3)

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

   •頂点フォーマットとしては、テクスチャの参照はPCTTの
   ように2枚だけでなくたくさん参照可能(8枚くらいはいけ
   ると思う)
12年4月28日土曜日
アニメーションの例
  •   頂点位置Pを平行移動だとスライドイン、スライドアウトアニメー
      ション

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

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

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

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

12年4月28日土曜日
選択範囲アニメーション
                • 選択範囲を表す折れ線は、

                 GL_LINE_STRIP

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


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




12年4月28日土曜日
シェーダの準備
  •   glCreateProgram(); //シェーダプログラムの生成

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

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

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

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

                 なんとコンパイラ内蔵!
              GPUのドライバがコンパイルする!
12年4月28日土曜日
シェーダの準備(2)
  • glAttachShader(vsh); //頂点シェーダをセット


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


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


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


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



               なんとリンクもする!
12年4月28日土曜日
シェーダの準備(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日土曜日
頂点シェーダソース(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日土曜日
頂点シェーダソース(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日土曜日
頂点シェーダソース(3)
  • PCT(位置P, カラーC, テクスチャ座標T)の例

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

     •ユニフォーム変数は、汎用のCPU側から来る
     変数(CPU側でセット)
     •上図では、4x4行列を渡している
     •整数、浮動小数、ベクトル、行列、テクス
     チャなどをCPUから渡すことが可能
     •全GPUコアから参照されるためRead Only
12年4月28日土曜日
頂点シェーダソース(4)
  • PCT(位置P, カラーC, テクスチャ座標T)の例

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

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


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

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

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

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

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


12年4月28日土曜日
ぼかしフィルタ(1)
  STEP1                               COPY
                      FBOa                       FBOb
                     最終出力先                     テンポラリFBO
              一時的にbindTexture()で入力側へ     bindFramebuffer()で出力先とする



  STEP2
                                 blur shader
                          FBOb                         FBOa
                 bindTexture()で入力側へ      bindFramebuffer()で出力先とする


   • Blur     Shaderを作成する

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

12年4月28日土曜日
ぼかしフィルタソース
  •アルゴリズム:カレント点、一つ上の点、左の
  点、右の点、下の点の5点の色を足して5で割る
BlurShader.vsh                                               BlurShader.fsh
attribute vec2 a_position;                                 varying vec2 v_texCoord;
attribute vec2 a_texCoord;                                 varying vec2 v_texCoordU;
uniform mat4 u_matrix;                                     varying vec2 v_texCoordL;
uniform vec2 u_pixel_tex;//1pxがtex coordでいくつか              varying vec2 v_texCoordR;
varying vec2 v_texCoord;                                   varying vec2 v_texCoordD;
varying vec2 v_texCoordU;                                  uniform sampler2D u_texture;
varying vec2 v_texCoordL;                                  void main(){
varying vec2 v_texCoordR;                                  	

  vec4 tex = texture2D(u_texture, v_texCoord);
varying vec2 v_texCoordD;                                  	

  vec4 texU = texture2D(u_texture, v_texCoordU);
void main(void){                                           	

  vec4 texL = texture2D(u_texture, v_texCoordL);
	

  gl_Position = u_matrix * vec4(a_position, 0.0, 1.0);  	

  vec4 texR = texture2D(u_texture, v_texCoordR);
	

  v_texCoord = a_texCoord;                              	

  vec4 texD = texture2D(u_texture, v_texCoordD);
	

  v_texCoordU = a_texCoord + vec2(0.0, -u_pixel_tex.y); 	

  vec4 tex2 = tex + texU + texL + texR + texD;
	

  v_texCoordL = a_texCoord + vec2(-u_pixel_tex.x, 0.0); 	

  gl_FragColor = tex2 / 5.0;
	

  v_texCoordR = a_texCoord + vec2( u_pixel_tex.x, 0.0);
                                                           }
	

   v_texCoordD = a_texCoord + vec2(0.0, u_pixel_tex.y);
}
12年4月28日土曜日
フラグメントシェーダ応用

  • ぼかし以外も、グレースケール化とか、明度、彩度、

     色調とか、コントラストとか、なんでもOK

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

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




12年4月28日土曜日
ibisPaintでの性能
  • iPad2、1024x768(0.78Mpixels)で、レイヤー6枚で

     60fps!!

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



                60fpsを死守せよ!!

12年4月28日土曜日
まとめ(1)
  • OpenGLは、低レベルAPIなので高速!


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


  • フレームバッファオブジェクトでテクスチャバッファ

     に書き込めるようになった(多段レンダリング)

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

     速に動く

12年4月28日土曜日
まとめ(2)
  • ibisPaintは60fpsで動いている。60fpsを死守せよ!


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

      ( ´Д`)y━・~~

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

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

              あとでShideShareに上げておきます。
               ご清聴ありがとございました。
12年4月28日土曜日

More Related Content

IbisPaintのOpenGLES2.0

  • 1. ibisPaintのOpenGL ES 2.0 株式会社アイビス 神谷栄治 12年4月28日土曜日
  • 2. 自己紹介 • 株式会社アイビス (社員70名ほど) • iPhone, iPad, Android, タブレット, Webシステムの受託開発など • 代表取締役社長 神谷栄治 • ハンドル:かみやん • Twitter:    @kamiyan • 自称、ハッカー社長 初めて言って みたけど( ´Д`)y━・~~ 12年4月28日土曜日
  • 3. 自称ハッカー社長 • 小学生:プログラミング、BASIC、Z80アセンブラ • 中学生:初の原稿料をもらう • 大学生:3D野郎、Direct3D、C++、日本初FTPソフト小次 郎プチヒット、機会学習、遺伝的プログラミング • サラリーマン:3D CAD作り、OpenGL、C++ • アイビス設立(26歳):ibisBrowser、ibisMail、ibisPaint、 Java、C++、Objective-C、ロボット作り • 高校生:恋愛♡ ( ´Д`)y━・~~ 12年4月28日土曜日
  • 4. プログラミングの醍醐味 高速化! たまんねぇ∼( ´Д`)y━・~~ 12年4月28日土曜日
  • 5. アプリの紹介 • ibisMail for iPhone(アイビスメール) • 世界初のメールアプリ。国内有料総合1位獲 得。 • ibisMail for iPad • こちらも国内有料総合1位獲得。 • ibisPaint(アイビスペイント) • こちらも国内有料総合1位獲得。 3冠!! 12年4月28日土曜日
  • 6. ibisPaintの企画 • iOS4.2リリースによりAVFoundationでmovファイルの作 成ができることが分かる!(2010/12) • 作画行程をmovファイルにエンコーディングして YouTubeにアップロードして共有したら楽しいんじゃ ね?! • ウィンドウやツールの変化も記録したいよね! • 高速だし、OpenGLに決定∼! • 「ソーシャルお絵描きアプリ ibisPaint」 バカ受け間違えなし!( ´Д`)y━・~~ 12年4月28日土曜日
  • 7. ibispaint.com 完成! JavaServlet+JSP+MySQL PHPは嫌い ( ´Д`)y━・~~ 12年4月28日土曜日
  • 8. アプリ動作デモ デモ中∼( ´Д`)y━・~~ AppStoreで「ibisPaint」で検索して「ibisPaint X」を ダウンロードください。無料。iPad / iPhone両対応の ユニバーサルアプリです。 12年4月28日土曜日
  • 9. OpenGL ESのメリット • 超高速! iPad(3rd Gen)なら4コア! • Core GraphicsやCore Imageよりも低レベルライブラリ • AndroidやWindowsなど他のプラットフォームにも移植 しやすい • 漢は黙ってC++ 普段はJava使いだけどな∼ ( ´Д`)y━・~~ 12年4月28日土曜日
  • 10. OpenGL ES1.0と2.0の違い(1) • GLES1.0は固定パイプライン、GLES2.0はプログラマブル • GLES1.0は用意された描画パターンから選ぶ • GLES2.0は1pixelごとの色の計算をどうするかをC言語風 の専用言語(シェーダー言語)で書く。 12年4月28日土曜日
  • 11. OpenGL ES1.0と2.0の違い(2) • 1pixelごとにmain()関数がコールされる感じ。 • マルチコアGPUで並列処理!PCの世界だと1000コアと か。 • GLES2.0は行列計算APIがない(削除しなくてもよかった のでは。。) • とにかく、かなり違う! とにかくって小学生かよ ( ´Д`)y━・~~ 12年4月28日土曜日
  • 12. 頂点シェーダーと フラグメントシェーダー • 頂点シェーダー(Vertex Shader, vsh)は、頂点位置、頂点 の色、頂点のテクスチャ座標などを決める • フラグメントシェーダー(Fragment Shader, fsh)は、1pixel ごとの色を決める • ibisPaintは2Dのアプリのため頂点シェーダーは、ほとん ど何もしていない • フラグメントシェーダーでいろいろ出来る。 12年4月28日土曜日
  • 13. CPUメモリとGPUメモリ メインメモリ GPUメモリ CPU GPU •メインメモリからGPUメモリへ書き込みはglTexImage2D() •GPUメモリからメインメモリへ読み込みはglReadPixels() •GPUメモリのポインタ等は得られないのでCPUが直接readし たりwriteしたりは出来ない •glTexImage2D()やglReadPixels()は重い(20msぐらい)ので注意 •バックグラウンドThreadから読み書きしてはいけない 12年4月28日土曜日
  • 14. GPUのメモリ • レンダーバッファ • 最終描画先であり、アルファプレーンがない、裏画面と表画 面用の2枚があり、基本は裏画面に描画してフリップで交換 する([EAGLContext presentRenderBuffer:]) • フレームバッファ • カラーバッファ、Zバッファ、ステンシルバッファなどを持つ • ibisPaintでは2Dのためカラーバッファのみ使用、テクスチャ バッファとして使用 12年4月28日土曜日
  • 15. フレームバッファーオブジェクト • Frame Buffer Object(FBO) • 昔はテクスチャバッファは読み取り専用でGPUがその バッファに描画することができなかったが、FBOによ りテクスチャバッファにレンダリングできるように なった。 • 動的テクスチャが可能になった! • ibisPaintではレイヤーのラスターデータはFBO。 12年4月28日土曜日
  • 16. FBO生成 • glGenTextures(); //テクスチャバッファ生成 • glGenFramebuffers(); //フレームバッファ生成 • glBindTexture(); //カレントテクスチャとする • glBindFramebuffer(); //カレントフレームバッファとする • glFramebufferTexture2D(); //フレームバッファとテクスチャ バッファをひも付ける • glCheckFramebufferStatus(); //整合性が取れているか確認 12年4月28日土曜日
  • 17. レンダーバッファの生成 • glGenRenderbuffers(); //レンダーバッファ生成 • glGenFramebuffers(); //フレームバッファ生成 • glBindRenderbuffer(); //カレントレンダーバッファとする • glBindFramebuffer(); //カレントフレームバッファとする • glFramebufferRenderbuffer(); //フレームバッファとレン ダーバッファをひも付け 12年4月28日土曜日
  • 18. フレームバッファの切替 フレームバッファ レンダーバッファ 描画命令 フレームバッファ テクスチャバッファ •glBindFramebuffer();で描画先を切り替 え、実画面とテクスチャバッファを透過 的に扱うことができる 12年4月28日土曜日
  • 19. ibisPaintでのFBOの例 出力先 入力テクスチャ フレームバッファ STEP1 レイヤーに描画 ブラシパターン レイヤー(FBO) テクスチャ STEP2 レイヤーを描画 レンダーバッファ レイヤー(FBO) (裏画面)に描画 12年4月28日土曜日
  • 20. 描画命令(プリミティブ) • 矩形を描け、矩形を塗りつぶせ、円を描け、多角形を描け、ベ ジェ曲線を描けとかはない! • 点、線分、三角形の描画のみ(漢らしい!) • 描画命令は 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日土曜日
  • 21. 描画命令(表と裏) • 右回り(Clockwise)が表、左回り(Counterclockwise)が裏? • 右回りが裏、左回りが表? 1 1 3 2 2 3 座標系によるけど裏表を間違えると見えないので注意 glFrontFace(GL_CW); or glFrontFace(GL_CCW);で設定可能 12年4月28日土曜日
  • 22. つながった三角形列 トライアングルストリップ 1 2, 4 矩形を描くのに 3, 6 5 GL_TRIANGLESだと6頂点をGPUへ送る 1 2 3 4 GL_TRIANGLE_STRIPだと4頂点をGPUへ 送るだけで済む(2/3の転送量) 1.5倍高速化! 12年4月28日土曜日
  • 23. つながった三角形列(2) こういうポリゴンデータはよくある。上の例では16ポリゴン。 GL_TRIANGLESだと16x3頂点の48頂点をGPUへ送る。 2 4 6 8 10 12 14 16 18 1 3 5 7 9 11 13 15 17 GL_TRIANGLE_STRIPの場合は、18頂点。ポリゴン数が多い場合1/3に減る。 3倍高速化! 12年4月28日土曜日
  • 24. つながった三角形列(3) こういうポリゴンデータはよくある。GL_TRIANGLE_STRIPを2回描画? →NO。縮退(面積0の三角形を描画する)を使うことで1回の描画 16 18 17 19,20 API呼び出しがn回から1回へ高速化 12年4月28日土曜日
  • 25. 頂点フォーマット(PC) • 頂点のデータの型はアプリケーションが決める • PC:頂点位置P(x,y,z), 頂点カラー C(r,g,b,a) 間の色は線形補完 引用 http://openglut.sourceforge.net/redbook_smooth.png 12年4月28日土曜日
  • 26. 頂点フォーマット(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日土曜日
  • 27. 頂点フォーマット(PCT) • PCT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ 座標T(u,v) PCだけで描ける マスクテクスチャ 乗算 出力 乗算のところはフラグメント シェーダでカスタマイズ可能 12年4月28日土曜日
  • 28. 頂点フォーマット(PCTT) • PCTT:頂点位置P(x,y,z), 頂点カラーC(r,g,b,a), テクスチャ 座標T1(u,v), テクスチャ座標T2(u,v) • 応用:えんぴつ、クレヨン、画用紙 カレントカラー カレントブラシ カレント背景 パターン パターン 合成 12年4月28日土曜日
  • 29. 頂点フォーマット(PCTT)(2) • クレヨン •背景テクスチャは、シームレステク スチャにする。作り方は「シームレス テクスチャ」で検索。 •背景テクスチャのテクスチャ座標 は、描画位置Pに比例して変化させ て、背景テクスチャが固定されている ように見えるようにする。 12年4月28日土曜日
  • 30. 頂点フォーマット(PCTT)(3) •ブラシパターンは、テクスチャ座標 を固定(普通は、0.0 or 1.0)にし、ペ ンを走らせたときにペンが動いて見え る。 •背景テクスチャのテクスチャラップ モードは、GL_REPEATにする。 •頂点フォーマットとしては、テクスチャの参照はPCTTの ように2枚だけでなくたくさん参照可能(8枚くらいはいけ ると思う) 12年4月28日土曜日
  • 31. アニメーションの例 • 頂点位置Pを平行移動だとスライドイン、スライドアウトアニメー ション • 頂点位置Pを拡大縮小だと、ズームイン、ズームアウトアニメーション • 頂点位置Pを回転させると、回転アニメーション(ibisPaintではレイ ヤーの回転やフォトライブラリインポート時の回転で利用) • 頂点カラーCのアルファ値を変化させるとフェードインフェードアウ ト • テクスチャ座標のT(u, v)を変化させて絵柄をスクロールさせるアニ メーション 12年4月28日土曜日
  • 32. 選択範囲アニメーション • 選択範囲を表す折れ線は、 GL_LINE_STRIP • そこに□□■■の4pixelのテクスチャを設定 • アニメーションとしてLINE STRIPのテク マジックワンド スチャ座標T(u,v)のuを0.25づつずらすこ とで、破線がアニメーション 12年4月28日土曜日
  • 33. シェーダの準備 • glCreateProgram(); //シェーダプログラムの生成 • glCreateShader(); //シェーダの生成(GL_VERTEX_SHADER or GL_FRAGMENT_SHADER) • glShaderSource();// シェーダソースコードの指定 • glCompleShader();// ソースのコンパイル • glGetShaderiv(GL_COMPILE_STATUS);//コンパイル結果の取得 なんとコンパイラ内蔵! GPUのドライバがコンパイルする! 12年4月28日土曜日
  • 34. シェーダの準備(2) • glAttachShader(vsh); //頂点シェーダをセット • glAttachShader(fsh); //フラグメントシェーダをセット • glLinkProgmram(); //vshとfshをリンク • glGetProgramiv(); //リンク結果を取得 • glUseProgram(); //カレントプログラムとする なんとリンクもする! 12年4月28日土曜日
  • 35. シェーダの準備(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日土曜日
  • 36. 頂点シェーダソース(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日土曜日
  • 37. 頂点シェーダソース(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日土曜日
  • 38. 頂点シェーダソース(3) • PCT(位置P, カラーC, テクスチャ座標T)の例 uniform mat4 u_matrix; ユニフォーム変数 •ユニフォーム変数は、汎用のCPU側から来る 変数(CPU側でセット) •上図では、4x4行列を渡している •整数、浮動小数、ベクトル、行列、テクス チャなどをCPUから渡すことが可能 •全GPUコアから参照されるためRead Only 12年4月28日土曜日
  • 39. 頂点シェーダソース(4) • PCT(位置P, カラーC, テクスチャ座標T)の例 varying vec2 v_texCoord; varying vec4 v_color; } バリイング変数 •バリイング変数は、頂点シェーダからフラグメ ントシェーダへ情報を伝達するための変数 •頂点シェーダから見ると出力変数 •フラグメントシェーダから見ると入力変数 12年4月28日土曜日
  • 40. 頂点シェーダソース(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日土曜日
  • 41. フラグメントシェーダソース(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日土曜日
  • 42. フラグメントシェーダソース(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日土曜日
  • 43. シェーダ言語の注意事項 • 色を参照するのは頂点カラーやテクスチャであり、出力先のフレーム バッファの色は取れない。なぜならフラグメントシェーダのmain()は複 数のGPUコアで並列に実行され、その実行順序が未定義であるため。 • ユニフォーム変数はCPU側からセットするがシェーダ言語側からみる と定数。 • if()は使えるが、for()はループ回数が定数のもののみ。 • 色の計算やテクスチャ座標は浮動小数で計算されているが浮動小数内 の計算誤差はやむを得ない • iOSシミュレータではほぼ動かず 12年4月28日土曜日
  • 44. ぼかしフィルタ(1) STEP1 COPY FBOa FBOb 最終出力先 テンポラリFBO 一時的にbindTexture()で入力側へ bindFramebuffer()で出力先とする STEP2 blur shader FBOb FBOa bindTexture()で入力側へ bindFramebuffer()で出力先とする • Blur Shaderを作成する • STEP1∼2を繰り返すとどんどんぼける 12年4月28日土曜日
  • 45. ぼかしフィルタソース •アルゴリズム:カレント点、一つ上の点、左の 点、右の点、下の点の5点の色を足して5で割る BlurShader.vsh BlurShader.fsh attribute vec2 a_position; varying vec2 v_texCoord; attribute vec2 a_texCoord; varying vec2 v_texCoordU; uniform mat4 u_matrix; varying vec2 v_texCoordL; uniform vec2 u_pixel_tex;//1pxがtex coordでいくつか varying vec2 v_texCoordR; varying vec2 v_texCoord; varying vec2 v_texCoordD; varying vec2 v_texCoordU; uniform sampler2D u_texture; varying vec2 v_texCoordL; void main(){ varying vec2 v_texCoordR; vec4 tex = texture2D(u_texture, v_texCoord); varying vec2 v_texCoordD; vec4 texU = texture2D(u_texture, v_texCoordU); void main(void){ vec4 texL = texture2D(u_texture, v_texCoordL); gl_Position = u_matrix * vec4(a_position, 0.0, 1.0); vec4 texR = texture2D(u_texture, v_texCoordR); v_texCoord = a_texCoord; vec4 texD = texture2D(u_texture, v_texCoordD); v_texCoordU = a_texCoord + vec2(0.0, -u_pixel_tex.y); vec4 tex2 = tex + texU + texL + texR + texD; v_texCoordL = a_texCoord + vec2(-u_pixel_tex.x, 0.0); gl_FragColor = tex2 / 5.0; v_texCoordR = a_texCoord + vec2( u_pixel_tex.x, 0.0); } v_texCoordD = a_texCoord + vec2(0.0, u_pixel_tex.y); } 12年4月28日土曜日
  • 46. フラグメントシェーダ応用 • ぼかし以外も、グレースケール化とか、明度、彩度、 色調とか、コントラストとか、なんでもOK • InstagramもiPhotoもOpenGL ES2.0を使っている • フィルタ系が全部、超高速!! 12年4月28日土曜日
  • 47. ibisPaintでの性能 • iPad2、1024x768(0.78Mpixels)で、レイヤー6枚で 60fps!! • iPad (3rd Gen)、2048x1536(3.14Mpixels)で、レイヤー6枚 で60fps!! 60fpsを死守せよ!! 12年4月28日土曜日
  • 48. まとめ(1) • OpenGLは、低レベルAPIなので高速! • GPUコアは年々増えていく(PCでは1000コア) • フレームバッファオブジェクトでテクスチャバッファ に書き込めるようになった(多段レンダリング) • フラグメントシェーダを使うと色々なフィルタが超高 速に動く 12年4月28日土曜日
  • 49. まとめ(2) • ibisPaintは60fpsで動いている。60fpsを死守せよ! • プログラミングの醍醐味は高速化!たまんねぇ∼ ( ´Д`)y━・~~ • ibisPaint Xは無料でiPhone / iPadのユニバーサルアプリ ダウンロードしてね∼ ( ´Д`)y━・~~ あとでShideShareに上げておきます。 ご清聴ありがとございました。 12年4月28日土曜日