OpenGLで描画するための設定をしましょう。
OpenGLの設定を行う場所はとりあえずサーフェイスが作られたタイミングにします。
onSurfaceCreated()が調度良さそうですね。
なお、ここでの設定項目は別の場所でも設定可能です。
// サーフェイスが作られた @Override public void onSurfaceCreated( GL10 gl, EGLConfig config ) { // ディザを無効化 gl.glDisable( GL10.GL_DITHER ); // カラーとテクスチャ座標の補間制度を最も効率的なものにする gl.glHint( GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST ); // バッファクリア時のカラー情報をセット gl.glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); // カリング無効化 gl.glDisable( GL10.GL_CULL_FACE ); // 深度テスト無効化 gl.glDisable( GL10.GL_DEPTH_TEST ); // アルファ有効化 gl.glEnable( GL10.GL_BLEND ); gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); // スムースシェーディングモード gl.glShadeModel( GL10.GL_SMOOTH ); }
次に描画領域の設定を行います。
ここでは、画面比率が変わらないように設定してます。
設定場所はサーフェイスのサイズが変わったタイミングがよさそうです。
// サーフェイスのサイズが変わった @Override public void onSurfaceChanged( GL10 gl, int width, int height ) { Rect recr = new Rect(); m_View.getWindowVisibleDisplayFrame( recr ); final float drawWidth = 400; final float drawHeight = 225; float drawScaleRate = 1.0f; { // 拡大率更新 final float widthScale = width / drawWidth; final float heightScale = height / drawHeight; drawScaleRate = Math.min( widthScale, heightScale ); } final int viewWidth = ( int )( drawWidth * drawScaleRate ); final int viewHeight = ( int )( drawHeight * drawScaleRate ); int drawOffsetX = 0; int drawOffsetY = 0; { // 描画オフセット更新 drawOffsetX = ( int )( width * 0.5f - viewWidth * 0.5f ); drawOffsetY = ( int )( height * 0.5f - viewHeight * 0.5f ); } gl.glViewport( drawOffsetX, drawOffsetY, viewWidth, viewHeight ); gl.glMatrixMode( GL10.GL_PROJECTION ); gl.glLoadIdentity(); gl.glOrthof( 0.0f, drawWidth, drawHeight, 0.0f, 1.0f, 10.0f ); }
最後に、描画時の設定を行います。
画面をクリアしてカメラの設定が主な処理です。
// 描画フレーム @Override public void onDrawFrame( GL10 gl ) { // 描画開始設定 { // クリア gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); // テクスチャ有効化 gl.glActiveTexture( GL10.GL_TEXTURE0 ); // カメラ座標設定 GLU.gluLookAt( gl, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); // 頂点情報有効化 gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); } // ここで描画 }
これで描画の準備ができました。
が、ちょっと待った!
このまま「MainActivity.java」に処理を書いていくとソースコードが見づらくなりそうです。
そこで、この処理を別のクラスにまとめてしまいましょう。
描画周りのクラスが「DrawDevice」です。
詳細は描画クラスを見てください。
このクラスを使うと↓のように簡単に書けます。
// コンストラクタ public MainActivity() { super(); m_View = null; m_DrawDevice = null; } // 作成 @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); m_View = new GLSurfaceView( this ); m_View.setRenderer( this ); m_DrawDevice = new DrawDevice(); setContentView( m_View ); } // サーフェイスが作られた @Override public void onSurfaceCreated( GL10 gl, EGLConfig config ) { m_DrawDevice.Create( gl ); } // サーフェイスのサイズが変わった @Override public void onSurfaceChanged( GL10 gl, int width, int height ) { Rect recr = new Rect(); m_View.getWindowVisibleDisplayFrame( recr ); m_DrawDevice.UpdateDrawArea( gl, width, height, recr.top ); } // 描画フレーム @Override public void onDrawFrame( GL10 gl ) { // シーンの更新 m_DrawDevice.Begin( gl ); { // ここで描画 } m_DrawDevice.End(); } private GLSurfaceView m_View; private DrawDevice m_DrawDevice;
これなら先程よりもソースコードの見通しがいいですね。
こんな感じで機能ごとにクラスにまとめていくのは重要なことです。
「なんか処理が多すぎるなぁ」
という時はメソッドやクラスに抜き出すことを検討すると先が見えてくることが多いです。
では、次こそ何か画面に表示してみましょう!