C# + OpenGLの
                      基本


よく見かけるOpenGLのサンプルプログラムは、たいていC or C++ とGLUTで書かれていることが多いわけですが、
しかし、C#だとだいぶ勝手が違ってくるし、GLUTなど必要ないと思うのですよ。

そもそも、GLUTは、
ウィンドウの生成うんぬんが結構面倒でややこしくてOpenGLの学習の妨げになるから、
その辺りを簡略化して、お手軽にOpenGLを始められるようにしてしまおう、
というモノ。

しかし、C#を含めて、.NET Frameworkでプログラミングをする場合、
ウィンドウの生成やらイベントの扱いなどは、かなり簡単にできるようになっているので、
別にわざわざ簡略化するほどのモノは何もないわけで。
初期化についてもここで扱っているように、全く難しくない。
つまり、GLUTは必要ないのです。


さて、
では、GLUTでやっていたことは、どうすればC#でできるのか?

・・・OpenGLに手を出そうと思うぐらいなのだから、
そのぐらいはすぐに見当がつきますよね?

と、思うのですが、まぁ、一応、簡単に。


ウィンドウ(フォーム)の生成

基本の基本。
これがわからないのなら、まずはC#自体の方を勉強するべきかと。
・・・特に説明は要らないですよね?

System.Windows.Forms.Form form1 = new Form1();

以上。
ま、この辺りはVisual Studioが勝手にコードを生成してくれるので、
自分で書くことも少ないのですが。


OpenGLの初期化

初期化については、
OpenGLの初期化
で、解説しているので、そちらを参照のこと。


・・・簡単ですよね?


シーンの描画はどうするのか?

コントロールの再描画を行うイベント内で行います。
つまりOnPaintイベントをオーバーライドするか、
Paintイベントにイベントハンドラを追加します。
強制的にコントロールに再描画をさせるには、
Invalidate()メソッドを使います。

それと、OnPaintBackgroundイベントをオーバーライドして、
呼び出されても何もせずに返すようにしておきます。
これは、コントロールのバックグラウンドを描画するイベントを無視して
OpenGLでの描画以外は行われないようにしておくためです。

その1.OnPaintイベントをオーバーライドする。
例:

Form1 : Form
{
...

    protected override void OnPaint( PaintEventArgs e )
    {
        //シーンの描画
        this.Draw();
    }

    /// <summery>
    /// シーンを描画するメソッド。
    /// </summery>
    private void Draw()
    {
        context.MakeCurrent();
        //シーンの描画

        gl.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
        gl.Matrixmode( MatrixMode.Modelview );
        gl.LoadIdentity();

        gl.Begin( BeginMode.Triangles );
        gl.Veretex3( v1 );
        gl.Veretex3( v2 );
        gl.Veretex3( v3 );

        ...

        gl.End();

        context.SwapBuffers();
    }
}

その2.Paintイベントにイベントハンドラを追加する。
例 :

Form1 : Form
{
    Panel panel1 = new Panel();
    ...
    
    public Form1()
    {
        ...
        
        // panel1にペイントイベントハンドラを追加。
        panel1.Paint += new PaintEventHandler( Panel1_Paint );
        
        ...
    }
    
    /// <summery>
    /// ペイントイベントハンドラ。
    /// </summery>
    private void Panel1_Paint( object sender, PaintEventArgs e )
    {
        //ここにシーンの描画を記述します。
    }
    
}

ウィンドウのリサイズ時の処理とか、 初期設定とかは?

シーンの描画と同様に、コントロールのイベントを利用します。
OnResizeイベント内でリサイズ時の処理を、
初期設定は、コンストラクタとかForm.OnLoadイベントあたりでやるのが無難でしょうね。


マウスイベントやキーイベントは?

MouseDownとかKeyDownとか、
いろいろなイベントが用意されているので、
それぞれのイベントハンドラの中でやりたいことを書けばOK。

イベントの処理の最後あたりに再描画を行えば、
表示内容をキーやマウスで操作するようなこと
(視点の移動とか、モデルorキャラクタの操作とか)
ができますよね?


アニメーションは?

一番簡単なのは、Timerコントロールを使う方法。
設定した時間間隔でTimer.Tickイベントが発生するので、
そのイベント内で描画を行う。
しかし、あまり時間の精度がよくなかったりとか、
インターバルが短すぎると、イベントが処理しきれていないうちに
次から次へとTimer.Tickイベントが発生するような事態があり得る(とってもよろしくない)。
使うなら、簡単なアニメーションのみにとどめるべし。

あとは、自分で描画ループを作ってアニメーションを行うとか。
ただし、この方法の場合は、ループ内で
Application.DoEventsメソッドを呼び出して、ほかのイベントを処理しておくこと。
そうしないと、ループ中は他のボタンとかのコントロールが
(イベントが処理されないので)反応しなくなってしまう。

フレームレートの制御のためには
高い精度で時間を取得する必要がありますが、これには
System.Diagnostics.Stopwatchクラスが使用できます。


まぁ、ある程度C#でWindowsアプリケーションを作ったことがあれば、
この辺の話は、たいして難しくないはずです。

要は、C#でも、初期化する方法さえわかれば、
OpenGLをやるのに別に敷居が高いわけではないのですよ。



<back to OpenGL menu>