よく見かける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の初期化」
で、解説しているので、そちらを参照のこと。
・・・簡単ですよね?
コントロールの再描画を行うイベント内で行います。
つまり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をやるのに別に敷居が高いわけではないのですよ。