3
0

More than 1 year has passed since last update.

GLUTの初期設定と意外な点について

Posted at

はじめに

もともとゲーム制作体験記を書こうとしていたのですが、冗長になって飽きてしまいました.
体験記はクリスマスに友達と過ごしたいねという願いとともに焼却処分しておきます。

さて、4JでGLUTを履修するのですが、意外と呪文のような場所が多くありましたよね。その中で今回はGLUTの初期設定に的を絞ってお話ししていこうと思います。

GLUTの初期設定を復習する

GLUTではmain関数内の最初で初期設定としてこんな感じのコードを書きます。
4J・5Jの方々は何となく覚えているでしょうか。

int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowSize (WINDOW_INIT_WIDTH, WINDOW_INIT_HEIGHT);
glutCreateWindow ("Simple Multi-Functional Clock");
glutInitDisplayMode (GLUT_ALPHA | GLUT_RGBA);
glClearColor (0.45, 0.72, 0.89, 1.0);
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// この先にコールバック関数の宣言やglutMainLoop()が続く
}

各関数でやっていることは大体こんな感じになります(筆者のアナログ時計レポート参考)。

  • glutInit関数 GLUTライブラリの初期化, ウインドウシステムに対しセッションの掛け合わせを行う.

  • glutInitWindowSize関数 GUIのウインドウの起動時のサイズを設定. ここではウインドウサイズの幅と高さに, 定数として事前に定義した値を指定している.

  • glutCleate関数 ウインドウの生成が行われる. 引数としてアプリケーションの名前を渡す.

  • glutInitDisplayMode関数 GLUTの表示モードの初期設定を行う. この関数は, 引数に表示モードを指定する. 複数の表示モードを指定する際には論理和を使用する.

  • glutEnable関数 OpenGLの各種機能の有効化. <-> glutDisable関数

    • ex1. GL_BLEND カラーバッファに色情報を書き込む際の混合処理を行う(半透明な物体を描画する時用)
    • ex2. GL_TEXTURE2D テクスチャリング(図形にテクスチャを貼り付けて描画)するときに利用
  • glutBlendFunc関数 混合処理の計算方法を指定. 計算方法の種類は様々. (ここでは省略)

  • glTexEnvf関数 テクスチャ環境の変数を指定する。

下3つは確か画像貼り付けに用いた記憶があります。

本題:glutInitDisplayModeの意外な事実

さて、glutInitDisplayMode関数ですが、「透明モードを用いないときはGLUT_RGB, 透明モードを用いるときはGLUT_RGBA | GLUT_ALPHAとする」とよく言われます。 こんな感じですね。

glutInitDisplayMode(GLUT_RGB); //RGB
glutInitDisplayMode(GLUT_ALPHA | GLUT_RGBA); //RGBA

これですが、実はGLUT_RGBAGLUT_RGB必要ありません

実際に筆者自身で値を表示させてみた結果ですが、このようになりました。1
ちなみに説明は公式のリファレンスページをみて簡単に書いたものになります。
ちゃんとした説明を見たい場合にはサイトを見てください。

モード名 説明
GLUT_RGBA RGBAモード 0
GLUT_RGB RGBAのエイリアス 0
GLUT_SINGLE 単一バッファウインドウ 0
GLUT_INDEX カラーインデックスモード 1
GLUT_DOUBLE ダブルバッファウインドウ 2
GLUT_ACCUM 蓄積バッファウインドウ 4
GLUT_ALPHA アルファ値を含むウインドウ 8
GLUT_DEPTH デプスバッファ付きのウインドウ 16
GLUT_STENCIL ステンシルバッファ付きのウインドウ 32
GLUT_MULTISAMPLE マルチサンプリングのサポート 128
GLUT_STEREO ステレオウインドウ 256
GLUT_LUMINANCE 輝度カラーモデルのウインドウ 512

さて、先ほどこの関数については次のように説明をしました。

glutInitDisplayMode関数 GLUTの表示モードの初期設定を行う. この関数は, 引数に表示モードを指定する. 複数の表示モードを指定する際には論理和を使用する.

はい。複数指定の場合は「論理和」を使用するという点です。

ここでもう一度モードの表を見てみましょう。指定するモードに対応する値はすべて2の累乗で表される値になっています。つまり、「どこか1つのビットだけが1」になるように設定されています。論理和を行うことで、 複数のモードを指定すると「各モードに対応したビット」が複数1になる、それによってモードの判別をしていると推測できます。

話をもとに戻しますが、今回GLUT_RGBAGLUT_RGBも値が0になっているため、どちらを指定してもよい。なんなら指定しなくてもよい。ということになります。

透過モードの正体

さっきの話を踏まえると、このような引数の渡し方も大丈夫だよ~ということになります。

glutInitDisplayMode(0); //RGB
glutInitDisplayMode(GLUT_RGB); //RGB
glutInitDisplayMode(GLUT_ALPHA); //RGBA

つまり、実際の透過モードの判定はGLUT_RGBAが指定されているかではなく, GLUT_ALPHAが指定されているかどうか、つまり下から4ビット目($2^{4-1}=8$)に1が立っているかどうかにあるということになります。

ダブルバッファリング (片方のバッファを画面表示としてもう一方を描画用として交互に切り替える方法、画面のちらつきを軽減する) の設定を行うときには GLUT_DOUBLEを指定しているのにその反対、GLUT_SINGLEは指定しなくてよいというのも(多分)同じ理屈です。

まとめ

今回はGLUT_RGBAGLUT_RGBも値は0だよ!複数モード指定の時は論理和を取るとどうせなくなっちゃうからそもそもいらないよ!ということを記事にしていきました。ただし、ここで私の言いたいことは別にあります。
じゃあ、このコードをぱっと見で理解できますか?ということです。

glutInitDisplayMode(0);

逆に、最初の例の場合は、コメントのような意味としてとらえることができます.
どちらが良いかはあなた次第になります。

// 「RGBモード有効」
glutInitDisplayMode(GLUT_RGB);
// 「RGBAモード有効」そのため、「ALPHAチャネルも有効」
glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA); 
// 「ALPHAチャネル有効」だけでも伝わるかもしれない
glutInitDisplayMode(GLUT_ALPHA);

おわりに

皆さんは「これは書く必要がないから消した」、「こう書いたらかっこいい」でプログラミングをしていませんか?
プログラムにつけるコメントもそうです。「自分が分かっているし面倒だからこれは書かなくてもいい。」「自分が分かっているから相手もすぐ理解できるはずだ。」と思うのは命取りになります。共同開発は言わずもがな、個人開発でももしかしたら忘れたころに手直しするかもしれないです。そういったときに例えばこの記事の内容、覚えているでしょうか?あ、そうだ。ねえ、ねこみみ君、これ書いてるけど君もだからね?結局コメントも書かずに脳筋コーディングしてC-CRAFT手直しできなかったでしょ^*。今、学生のうちにプログラムにコメントを付ける、丁寧なコーディングをすることを心掛けることは大切だよ。というお話でした。

以上になります。良いクリスマスライフを!(うっ何かが刺さったような)。
アドベントカレンダー書くのは難しいね。

  1. あの、64ってないんですか?え、64って使われてないんですか?かわいそうじゃないんですか?(うるさい)

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0