TOP

ABOUT

PROGRAM

DIALY







C#でOpenGL (2)

 1.はじめに…
 前回はGLUT使ちゃったんですが…,今回はGLUT使わずに作ってみます。




 2.Windowsフォームアプリケーションを作る
 前回GLUTを使ってフォームの作成やらをやったんですが…,C#を使っているのにGLUTを使うのはいかがなものかと思います。
 そんなわけで,今回はWindowsフォームアプリケーションでプログラムを作ってみます。今回もTaoFrameworkを使いますが,Taoに付属しているGLUTは使いません。
 まずは,Visual Studioを立ち上げて,プロジェクトを作ります。Windowsフォームアプリケーションを選択して,プロジェクトを作ってください。



選択すると,Visual Studioの方でガガッとコードを作ってくれます。次に,ソリューションエクスプローラーで,作成したプロジェクトを右クリックします。「追加→新しい項目」を選択します。
すると,下のようなダイアログが出てくるので,左側にあるカテゴリから「Visual C#アイテム→Windows Forms」を選択。右側に書いてあるテンプレートの中から「ユーザーコントロール」を選択し,適当に名前を付けて,追加ボタンを押します。



追加ボタンを押すとソリューションエクスプローラーが,下のようになると思います。ユーザーコントロールの名前はGLUserContorlにしてみました。



この状態で,一回ビルドします。変なことをしていなければ,すんなりビルドできるはずです。
ビルドが終わったら,次は,ソリューションエクスプローラーからForm1.csをダブルクリックします。
 次に,"Form1.cs[デザイン]"のタブが表示されている状態で,ツールボックスを表示させます。通常は,画面の端の方にあるはずですが,なければメニューから「表示→ツールボックス」を選択して表示されてください。ビルドを終えると,ツールボックスの一覧の中に,先ほど追加したユーザーコントロールの名前があるはずです。下の画像のでは,GLUserContorlがそれに当たります。



先ほど追加したユーザーコントロールをフォームに適当に貼り付けます。次に,貼り付けたユーザーコントロールが選択されている状態で,右クリックし,プロパティを選択します。下のような,プロパティのウィンドウが出てくるはずなので,Dockの項目をFillに変更します。



 Dockの項目をFillに変更すると,"Form1.cs[デザイン]"のタブに表示されているフォームが下のような感じになると思います。



あとは,前回と同じように,ソリューションエクスプローラーを再び開いて,参照設定を右クリックして,参照の追加を選択します。参照に追加するのは,「Tao Framework OpenGL Binding for .NET」と「Tao Framework Window Platform API for .NET」の2つです。
これで一応,下準備は完了です。あとはコードの方を修正していきます。

まず,GLUserControl.csを開いて,コードを以下のように変更します。

00009:  #endregion
00010:  
00011:  #region Using Statements
00012:  //
00013:  // Using Statements
00014:  //
00015:  using System;
00016:  using System.Drawing;
00017:  using System.Windows.Forms;
00018:  using Tao.OpenGl;
00019:  using Tao.Platform.Windows;
00020:  #endregion
00021:  
00022:  namespace Asura
00023:  {
00024:  	public partial class GLUserControl : UserControl
00025:  	{
00026:  		#region Fields
00027:  		//
00028:  		// Fields
00029:  		//
00030:  		private IntPtr hRC = IntPtr.Zero;
00031:  		private IntPtr hDC = IntPtr.Zero;
00032:  
00033:  		#endregion
00034:  
00035:  		/// <summary>
00036:  		/// コンストラクタ
00037:  		/// </summary>
00038:  		public GLUserControl()
00039:  		{
00040:  			InitializeComponent();
00041:  		}
00042:  
00043:  		/// <summary>
00044:  		/// 生成時の処理
00045:  		/// </summary>
00046:  		/// <param name="e"></param>
00047:  		protected override void OnHandleCreated(EventArgs e)
00048:  		{
00049:  			base.OnHandleCreated(e);
00050:  
00051:  			this.SetStyle(ControlStyles.UserPaint, true);
00052:  			this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
00053:  			this.SetStyle(ControlStyles.DoubleBuffer, false);
00054:  			this.SetStyle(ControlStyles.Opaque, true);
00055:  			this.SetStyle(ControlStyles.ResizeRedraw, true);
00056:  
00057:  			SetupPixelFormat();	//ピクセルフォーマットの設定
00058:  			SetupOpenGL();		//OpenGLの初期設定
00059:  		}
00060:  
00061:  		/// <summary>
00062:  		/// ピクセルフォーマットの設定をする
00063:  		/// </summary>
00064:  		private void SetupPixelFormat()
00065:  		{
00066:  			//PIXELFORMATDESCRIPTORの設定
00067:  			Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR();
00068:  			pfd.dwFlags = Gdi.PFD_SUPPORT_OPENGL |
00069:  				Gdi.PFD_DRAW_TO_WINDOW |
00070:  				Gdi.PFD_DOUBLEBUFFER;
00071:  			pfd.iPixelType = Gdi.PFD_TYPE_RGBA;
00072:  			pfd.cColorBits = 32;
00073:  			pfd.cAlphaBits = 8;
00074:  			pfd.cDepthBits = 16;
00075:  
00076:  			//デバイスコンテキストハンドルの収録
00077:  			this.hDC = User.GetDC(this.Handle);
00078:  
00079:  			//ピクセルフォーマットを選択
00080:  			int pixelFormat = Gdi.ChoosePixelFormat(this.hDC, ref pfd);
00081:  			if (pixelFormat == 0)
00082:  				throw new Exception("Error: Cant't Find A Suitable PixelFormat.");
00083:  
00084:  			//ピクセルフォーマットを設定
00085:  			if (!Gdi.SetPixelFormat(this.hDC, pixelFormat, ref pfd))
00086:  				throw new Exception("Error: Cant't Set The PixelFormat."); 
00087:  
00088:  			//レンダリングコンテキストを生成
00089:  			this.hRC = Wgl.wglCreateContext(this.hDC);
00090:  			if (this.hRC == IntPtr.Zero)
00091:  				throw new Exception("Error: Cant Create A GLRendering Context.");
00092:  
00093:  			//レンダリングコンテキストをカレントにする
00094:  			Wgl.wglMakeCurrent(this.hDC, this.hRC);
00095:  
00096:  			//GLエラーのチェック
00097:  			int err = Gl.glGetError();
00098:  			if (err != Gl.GL_NO_ERROR)
00099:  				throw new Exception("GL Error:" + err.ToString());
00100:  
00101:  		}
00102:  
00103:  		/// <summary>
00104:  		/// OpenGLの初期設定
00105:  		/// </summary>
00106:  		private void SetupOpenGL()
00107:  		{
00108:  			//バッファをクリアする色
00109:  			Gl.glClearColor(0.3f, 0.3f, 1.0f, 1.0f);
00110:  
00111:  			//深度テストを有効
00112:  			Gl.glEnable(Gl.GL_DEPTH_TEST);
00113:  			Gl.glDepthFunc(Gl.GL_LEQUAL);
00114:  
00115:  			//スムースシェイディング
00116:  			Gl.glShadeModel(Gl.GL_SMOOTH);	
00117:  		}
00118:  
00119:  		/// <summary>
00120:  		/// 後片付け
00121:  		/// </summary>
00122:  		private void ReleaseOpenGL()
00123:  		{
00124:  			Wgl.wglMakeCurrent(this.hDC, IntPtr.Zero);
00125:  			Wgl.wglDeleteContext(this.hRC);
00126:  		}
00127:  
00128:  		/// <summary>
00129:  		/// 描画処理
00130:  		/// </summary>
00131:  		/// <param name="e"></param>
00132:  		protected override void OnPaint(PaintEventArgs e)
00133:  		{
00134:  			//レンダリングコンテキストをカレントにする
00135:  			Wgl.wglMakeCurrent(this.hDC, this.hRC);
00136:  
00137:  			//バッファをクリア
00138:  			Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
00139:  
00140:  			//ビューポートの設定
00141:  			Gl.glViewport(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
00142:  
00143:  			//射影行列の設定
00144:  			Gl.glMatrixMode(Gl.GL_PROJECTION);
00145:  			Gl.glLoadIdentity();
00146:  
00147:  			//モデルビュー行列の設定
00148:  			Gl.glMatrixMode(Gl.GL_MODELVIEW);
00149:  			Gl.glLoadIdentity();			
00150:  
00151:  			//三角形を描画
00152:  			Gl.glBegin(Gl.GL_TRIANGLES);
00153:  			Gl.glColor3f(1.0f, 0.0f, 0.0f);
00154:  			Gl.glVertex3f(-0.5f, -0.5f, 0.0f);
00155:  			Gl.glColor3f(0.0f, 1.0f, 0.0f);
00156:  			Gl.glVertex3f(0.0f, 0.5f, 0.0f);
00157:  			Gl.glColor3f(0.0f, 0.0f, 1.0f);
00158:  			Gl.glVertex3f(0.5f, -0.5f, 0.0f);
00159:  			Gl.glEnd();
00160:  
00161:  			//ダブルバッファ
00162:  			Wgl.wglSwapBuffers(this.hDC);
00163:  		}
00164:  
00165:  	}
00166:  }
デフォルトだと,色々とusingされていますが,上のコードの例では最低限必要なものにしています。
一度,GLUTを使わずにOpenGLのウィンドウを作ったことがある人なら,大体分かると思います。やっているのは,ピクセルフォーマットを設定して,OpenGLの初期設定を行って,レンダリングコンテキストをカレントにしてから描画するという当たり前のことです。難しいことは無いんじゃないかと思います。
あとは,GLUserContorl.Designer.csを開いて以下のコードの22行目のように,後始末をするメソッドを一行付け足してやります。

00001:  namespace Asura
00002:  {
00003:  	partial class GLUserControl
00004:  	{
00005:  		/// <summary> 
00006:  		/// 必要なデザイナ変数です。
00007:  		/// </summary>
00008:  		private System.ComponentModel.IContainer components = null;
00009:  
00010:  		/// <summary> 
00011:  		/// 使用中のリソースをすべてクリーンアップします。
00012:  		/// </summary>
00013:  		/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
00014:  		protected override void Dispose(bool disposing)
00015:  		{
00016:  			if (disposing && (components != null))
00017:  			{
00018:  				components.Dispose();
00019:  			}
00020:  
00021:  			//後片付け
00022:  			this.ReleaseOpenGL();
00023:  
00024:  			base.Dispose(disposing);
00025:  		}
00026:  
00027:  		#region コンポーネント デザイナで生成されたコード
00028:  
00029:  		/// <summary> 
00030:  		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を 
00031:  		/// コード エディタで変更しないでください。
00032:  		/// </summary>
00033:  		private void InitializeComponent()
00034:  		{
00035:  			components = new System.ComponentModel.Container();
00036:  			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
00037:  		}
00038:  
00039:  		#endregion
00040:  	}
00041:  }
あとは,この状態でビルドして,実行すれば三角形が表示されるフォームが出てくると思います。
ちなみに,今回のプログラムは,「一歩、二歩、散歩。」さんのページを基にして作ってみました。
まぁ,中身はまんま…って感じですが,勘弁してください。


 Download
本ソースコードおよびプログラムを使用したことによる如何なる損害も製作者は責任を負いません。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2008 SP1 Professional, Tao Framework 2.1.0を用いています。