Ryuz's tech blog

FPGAなどの技術ブログ

もしもfopenがOpenGL風だったら

はじめに

最近、Ultra96V2 で Mali-400 使ってみようと思い、Rust の勉強ついでに久しぶりに OpenGL を触っています。

対応しているのが OpenGL ES 2.0 なので、古い書き方も出来なければ最新と言うわけでもない微妙な環境です。

当然 DirectX も Vulkan も動かないので、Open GL の流儀で書くしかないのですが、ふと OpenGL のプログラミングポリシーってやっぱりすごくクセがあるなと感じたので少しジョークめいた記事にしてみました。

あくまで個人の感想であって、完全に与太話のネタ記事なので、あまり深くは突っ込まないで下さね。

OpenGL のコンテキスト依存の書き方

初期の OpenGL の書き方であるが、こんな感じで3角形が書けていました。

glBegin(GL_TRIANGLES);
glVertex3f(0 , 0, 0);
glVertex3f(10, 10, 5);
glVertex3f(2, 5, 1);
glEnd();

新しい OpenGL では glBegin(), glEnd() は使わないことになっていますが、環境次第ではいまだにちゃんと使えるので、とりあえずハードウェアの仕組みとか面倒事は後回しにして「まずCGの本質的な仕組みを学びたい」という初心者には実は結構オススメな良APIだったりもします。

でも、今日取り上げるのはこのコンテキスト依存の書き方を他でもやったらどうなるかというネタです。

(まあ、当のOpenGL自体も、ハードウェアの差異を吸収する役割を背負わされたまま進化したので、(このあたり)https://cpplover.blogspot.com/2014/05/opengl.htmlとかで辛辣に書かれていたりもするようですが、それはそれで言いたいことは結構よくわかったりもします)。

もしも fopen が OpenGL 風だったら

という事で今日の本題のジョーク記事です。

例えば C言語の fopen でプログラムするとき普通こんな感じですよね?

FILE* fp = fopen("file.txt", "wb");
fwrite(buf, 1, 10, fp);
fclose(fp);

buf の中身を10バイトファイルに書く想定です(エラーチェックが無いのはわざとです)。

これがもし OpenGL 風のAPIだったらならこんな感じでしょうか?

fileOpen("file.txt", "wb");
fileWrite(buf, 10);
fileClose();

なんからくちんになりましたね。初心者にもオススメないい感じ。

でももしファイルが2個同時に開きたいときは?

従来なら

FILE fp1 = fopen("file.txt", "rb");
FILE fp2 = fopen("file.txt", "wb");
fread(buf, 1, 10, fp1);
fwrite(buf, 1, 10, fp2);
fclose(fp1);
fclose(fp2);

が、OpenGL風だときっとこんな感じというのが以下です。

fileInt fpo[2]
fileGenPointer(2, &fpo); // ファイルポインタオブジェクト生成
fileBindPointer(fpo[0]);
fileOpen("file1.txt", "rb");
fileBindPointer(fpo[1]);
fileOpen("filew.txt", "wb");
fileBindPointer(fpo[0]);
fileRead(buf, 10);
fileBindPointer(fpo[1]);
fileWrite(buf, 10);
fileBindPointer(fpo[0]);
fileClose();
fileBindPointer(fpo[1]);
fileClose();
fileDeletePointer(2, &fpo);

ははははは。まさにジョークです。

ただ実際、OpenGL でも、複数のテクスチャとか頂点バッファとか管理しつつ、複数のWindow開いたり、マルチスレッドしたりとあれこれやり始めると、今どれが何をbindしてるのかわかんなくなったりとか、ずっと前でbindしたまま戻し忘れていたものが全然違う箇所で悪さしたりとか、まあジョークじゃすまないことも起こっちゃってたりもします。

架空の話ですがもしも OpenGL が fopen 的だったら

glHandle h = glBegin(GL_TRIANGLES); // もしハンドル返したら
glVertex3f(h, 0 , 0, 0);
glVertex3f(h, 10, 10, 5);
glVertex3f(h, 2, 5, 1);
glEnd(h);  // ここでハンドルクローズ

となり、まあ確かにこれはこれでちょっと嫌なのですが、それでもこうなってれば様々な機能が追加された今でも、もう少し混乱少なかったのではないかと思ってみる次第で....

とはいえ、エッジデバイス含めて最も広い移植範囲をもっているのが OpenGL なので、そういう意味ではすごい規格なのですよね。