Saturday, January 31, 2015

Google ANGLEでWindows上でOpenGL ESを使う簡単な方法

AndroidでOpenGL ESを使ったアプリを開発する際にAPKを生成してデバイスに転送しながらデバッグするのは非効率です。そこで、Windows上でもOpenGL ESを実行できるようにしてゲームエンジン部を共通化しておくと便利です。

直接WindowsのOpenGLを動かせるようにしてもよいのですが、下位でDirectXを呼ぶANGLEで組むとIntel GPAやNVIDIA Nsightでデバッグできるメリットも得られます。

ところで、最近 git clone https://chromium.googlesource.com/angle/angle からcloneするだけではVisual Studioのslnファイルが得られなくなっているようです。以下のページで説明されているようにdepot_toolsという独自の環境を構築する必要があります。

https://code.google.com/p/angleproject/wiki/DevSetup

しかし、とりあえず最新でなくてもいいので以前のように手間をかけずに手軽に実行したい場合はslnを含む最後のブランチである"2214"をチェックアウトするといいです。 git bashより以下のように入力します。

1. git clone https://chromium.googlesource.com/angle/angle
2. git branch 2214 origin/chromium/2214
3. git checkout 2214

これで2214 ブランチをチェックアウトできました。
angle\projects\build\all.sln が生成されているのでビルドします。
   
なぜかessl_to_glsl, essl_to_hlslという二つのプロジェクトからエラーが出ますが、気にしないことにします。

 



自分のプロジェクトの必要に応じてヘッダとライブラリを設定します。こうして作ったプロジェクトをGitHubにアップしておきました。

Thursday, January 29, 2015

std::regexを使い、自力でOpenGL(WGL)バインド

WindowsでOpenGLを使う為にはwglGetProcAddress関数でAPIの関数ポインタを収集しなければなりません。文字列処理に長けたスクリプト言語でパーサを作って https://www.opengl.org/registry/ のヘッダからCのソースを生成するのが一般的かと思いますが、Visual Studio 2013でregexがstd::regexに移動していたのでC++だけでやってみることにします。
struct GLFunc
{
GLFunc(){}
GLFunc(const GLFunc& r) {
*this = r;
}
const GLFunc& operator=(const GLFunc& r) {
name = r.name;
decl = r.decl;
caster = r.caster;
return *this;
}
std::string name;
std::string decl;
std::string caster;
};
std::vector<GLFunc> glFuncs;
void ParseHeader(const char* healderFileName, const char* regExp, const char* conventions)
{
char* h = (char*)LoadFile(healderFileName);
std::string str = h;
std::regex pattern(regExp);
auto funcBegin = std::sregex_iterator(str.begin(), str.end(), pattern);
auto End = std::sregex_iterator();
int dist = std::distance(funcBegin, End);
printf("%d functions found in %s\n", dist, healderFileName);
int i = 0;
for (auto it = funcBegin; it != End; it++) {
std::smatch m = *it;
if (m.size() < 4) {
continue;
}
GLFunc func;
func.name = m[2].str();
func.decl = m[1].str() + "(" + conventions + "*" + m[2].str() + ")" + m[3].str();
func.caster = m[1].str() + "(" + conventions + "*)" + m[3].str();
glFuncs.push_back(func);
printf("\r%d/%d", ++i, dist);
}
printf("\n");
free(h);
}
int _tmain(int argc, _TCHAR* argv[])
{
ParseHeader("glheaders/glcorearb.h", "^GLAPI\\s+([\\w\\s\\*]+)APIENTRY\\s+(gl\\w+)\\s*(\\(.*\\))", "APIENTRY");
ParseHeader("glheaders/wglext.h", "^(\\w+(?:\\s+\\w+)*\\s+)WINAPI\\s+(wgl\\w+)\\s*(\\(.*\\))", "WINAPI");
return 0;
}
view raw wgl_grabber.cpp hosted with ❤ by GitHub
追加ライブラリ無しで正規表現が書けました。

STLに慣れているとstd::sregex_iteratorが奇妙に見えますが、これで複数のOpenGL関数定義を巡回させます。std::regex_matchでも正規表現を実行できますが、こちらは最初の一回しかマッチさせられません。マッチ結果はstd::smatchを使って戻り値、関数名、引数リストを取り出します。

GitHubはここです。