Windows では、ウィンドウのデバイス・コンテキスト(Window DC)を使用して画面を作成します。
Android ネイティブアプリでは、デバイスの画面サイズ(物理的な大きさ)や解像度(ピクセル数)が多種多様であることなどから、 OpenGL というグラフィック・ライブラリの機能限定版(表現が不正確?)、 OpenGL ES(Wikipedia、 Android Developers) を使用して、画面を作成することになります。
それは、基本的には何もかも Windows での画面描画と異なるものなので、少しづつ勉強するしかなさそうです。
ここでは、まずその基本的な、OpenGL ES の使用準備、 Visual C++ 2015/2019 で自動生成される描画コードの背景の色指定、 および画面への反映手順だけを記載しています。 このページでは、新しく何かを描画することはありません。
基本知識を得てから、ビットマップ画像の描画などに進む予定です。
このページ、および開発関連ページは、主に PC 向けデザインとなっております。 画面サイズの小さいスマホでは、快適な表示が得られませんので、ご了承ください。
ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
また、本サイトが初めての方は、まずこのページの注意事項をご覧ください。
投稿 October 17, 2018、更新 February 25, 2020
この部分は、他のすべての OpenGL ES 関数を使うための共通の準備となります。
この記事を作成した当時は、Visual C++ 2015 を使用していましたが、 Visual C++ Community 2019 でも同一でしたので、特に影響はありません。
なお、Visual Studio Community 2019 は、マイクロソフト・アカウントがあれば、個人での開発に無償で利用できるバージョンです。 Visual Studio Community 2019 のインストールについては、 いずれも旧バージョンとの共存インストールで、 C ドライブにすべてインストールする(標準的な) 「VS Community 2019 を共存インストールする」(ノート PC)と、 C ドライブの SSD に最小限にインストールし、あとは D ドライブの HDD を指定している 「VS Community 2019 を共存インストールする(デスクトップ)」 に書いています。
ソリューション エクスプローラーから <プロジェクト名>.NativeActivity のプロパティを見ると、 「リンカー」の「入力」にある「ライブラリの依存ファイル」で、 GLESv1_CM と EGL が追加指定されていますが、 プロジェクトを新規作成したときに自動的に設定されているようです。 特に追加や書き換えは必要なさそうです。
インクルードファイルなどを見ると、関数の定義を含む gl.h が必要となりますが、 pch.h に以下の行があるので、こちらも特に何も考える必要はなさそうです。
#include <EGL/egl.h> #include <GLES/gl.h>
どうやら、自動生成されたコードがすべてのセットアップを設定してくれているようですから、 特に何かを追加したりする必要はないようです。
投稿 October 17, 2018、部分訂正 February 25, 2020
自動生成されたコードそのままの状態では、次のような流れで画面描画しています。
まずは、main.cpp の engine_init_display 関数で、「OpenGL ES と EGL の初期化」が行われています。
この関数は、
アプリ実行中の画面の描画は、main.cpp のメインループから呼び出される、engine_draw_frame 関数が行います。
engine_draw_frame 関数を見ると、 こんなコードがあります。
// 色で画面を塗りつぶします。 glClearColor(((float)engine->state.x) / engine->width, engine->state.angle, ((float)engine->state.y) / engine->height, 1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(engine->display, engine->surface);
自動生成されたコードでは、glClearColor 関数で塗りつぶし色を指定し、 glClear 関数で背景を指定色で塗りつぶします。 この段階では画面には反映されていなく、eglSwapBuffers 関数呼び出し時点で、画面に反映されるということです。
詳細は、次のセクションに記述しています。
APP_CMD_TERM_WINDOW メッセージを受領すると呼び出される engine_term_display 関数は、 このままでも良さそうです。
投稿 October 17, 2018、追記 March 6, 2021
Windows では、32 ビットカラーの場合、R、G、B 要素それぞれ 0 〜 255 の 256 段階で表現しています。 しかし OpenGL ES では、R、G、B 要素を 0 〜 1 の間の小数で指定することになっています。
例えば、画面を指定の色でクリアする部分を見てみます。
glClearColor(red, green, blue, 1.0); glClear(GL_COLOR_BUFFER_BIT);
glClearColor 関数は、 OpenGL ES のクリア色指定関数です。 引数の最初の 3 つ、red、green、blue は float 型です。 GLclampf 型と書かれているものもありますが、 これは khronos_float_t 型であり、定義をたどると float 型と同じです。 次の glClear 関数で画面をクリアしていますが、そのときの色を指定している、ということになります。
なお、実際にはこれらの関数を実行しても、(そのタイミングでは)画面は更新されません。
メインループから呼び出す engine_draw_frame 関数の最後に自動生成されている、
eglSwapBuffers(engine->display, engine->surface);
が実行されて初めて、画面が更新されます。
なお、glClearColor 関数に第 4 引数として渡している 1.0 はアルファチャンネル値、すなわち透過度合で、1.0 は透過なしです。 背景色のクリアには 1.0 しか使わないのではないかと思いますが、 他のものを描画したあと、全体を暗くするなどのときには、アルファチャンネルに小さい値を指定すると簡単なのかも知れません。
最初から各要素を割合で指定するならそれでいいのですが(それはそれでわかりやすいと思いますが)、 Windows プログラマとしては、やはり RGB( 255, 255, 255) の形式で指定したいものです。
今のところ背景のクリア以外には色を直接指定するケースは
自分で使う関数なので、範囲外指定やエラーチェックはしていません。
void clear256(int red, int green, int blue) { GLclampf red_f = (GLclampf)red / 255.0f; GLclampf green_f = (GLclampf)green / 255.0f; GLclampf blue_f = (GLclampf)blue / 255.0f; glClearColor(red, green, blue, 1.0); glClear(GL_COLOR_BUFFER_BIT); }
単純に、0 が 0.0、255 が 1.0 になるように、255.0f で割っているだけです。 .0f の部分は、float 型を明示するために付けています。 ちょっとだけ気にしないと、整数型で計算してしまう式になる場合があるかも知れません。
第 4 引数はアルファ値ですので、常に 1.0 の不透明を指定、すなわち塗りつぶしとしています。
ここから画面に画像を描画するためには、 「テクスチャ」を作成し、面を作成して貼り付けないといけないようです。 まずは、テスクチャ作成ができなくてはいけません。 下記で検討しています。
OpenGL ES:24 ビット BMP 画像を読み込む
OpenGL ES で画面表示するために、まずはビットマップ画像をメモリに取り込む処理について、書いています。
ここから描画処理に続きます。
VS2019 での Android ネイティブアプリ開発、再スタートの開始ページです。
ネイティブアプリに Java クラスを実装し、JNI を利用して C/C++ コードから Java コードを呼び出す方法について、書いています。
Android 開発に関する記事をまとめた Android 開発トップ もご覧ください。