OpenGLスターターコード


OpenGLSimpleAdapterを使って、OpenGLを使った描画が簡単にできるようになったのはいいが、OpenGLを使った本格シーン描画コードがとりあえずいきなり欲しい、カメラとかライトとかマテリアルとかテクスチャとかきまりきった初期化コードを1から毎回書くのはいやだ、だから挫折するんだ、すでにそこにあって描画確認できてそれを少しずつ変えていけるような、スターター(starter)となるコードが欲しい、そんなおんぶにだっこのないものねだりでわがままな君たちのために以下コードをメモしておくぞ。
これは、

  1. ビューポート定義
  2. 視体積定義
  3. カメラ設定(説明どおりにコメントを外せば簡易マウス操作も可能)
  4. ライト設定
  5. マテリアル設定
  6. テクスチャ設定
  7. テクスチャつきの最小四角モデル(上図)描画

がいきなりとりあえず実現されているので、用のあるとこだけ使って、自分のプログラムにしていけばいいだけという便利コードだよ。
以下のコードはWindowsFormの場合だけどMFCとかでも全然同じだ。
OpenGLSimpleAdapter*を、m_oglとしてnew済み(OpenGLSimpleAdapterをマネージドクラスにしてgcnewでもいいかもね)のフォームの中に、panel1があるとき、FormのPaintイベントハンドラを以下のようにオーバーライドするだけだ。
冒頭の図のような表示が得られるはずだ。

private: System::Void Form1_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e)
{
m_ogl->BeginRender();
{
	//
	// ●OpenGL初期化glBegin()までのデフォルトコード
	//
	glClearColor( 0, 0, 0, 0 );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	// ビューポートと視体積
	{
          float aspect_ratio;
          {
#if 01
            // MFCとかの場合
            CRect rect;
            {
              const CWnd& w = this->m_picbox;//←ここ、ダイアログなのか何かその中の部品なのかで変わってきます。
              w.GetClientRect( &rect );
            }
            glViewport( rect.left, rect.top, rect.Width(), rect.Height() );
            aspect_ratio = rect.Width() / (float)rect.Height();
#else
            // CLIとかだったら例えばフォーム上に panel1 が置いてあったとして、
            float width = panel1->Width;
            float height = panel1->Height;
            glViewport( 0 ,0, width, height );
            aspect_ratio = width/height;
#endif
          }

          glMatrixMode( GL_PROJECTION );
          float h = 1.0;
          float nc = 2.0;
          float fc = 9900;
          glLoadIdentity();
          glFrustum( -aspect_ratio*h, aspect_ratio*h, -h, h, nc, fc );
	}
	// モデルビューマトリクス
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	// カメラ描画
	glTranslatef( 0,0,-10 );
	//glTranslatef( 0, 0, -m_radii );// m_radii はマウスホイールで更新してもいいし、
	//glRotatef( m_tht, 1,0,0 );// m_phiはマウス座標水平移動で更新
	//glRotatef( m_phi, 0,1,0 );// m_thtはマウス座標垂直移動で更新

	// デプステスト有効
	glEnable( GL_DEPTH_TEST );
	glDepthFunc( GL_LEQUAL );
	//
	{
		// ライト設定
		GLfloat spc0[]	={1.0f, 1.0f, 1.0f, 1.0f};
		GLfloat diff0[]	={0.99f, 0.99f, 0.99f, 1.0f};
		GLfloat amb0[]	={0.99f, 0.99f, 0.99f, 1.0f};
		//		GLfloat pos0[]	={ 0,-1,0, 1};// 4つ目の値は1⇒点光源
		GLfloat pos0[]	={ 0,15,0, 1};// 4つ目の値は1⇒点光源
		//glLightfv(GL_LIGHT0, GL_SPECULAR, spc0);
		glLightfv(GL_LIGHT0, GL_AMBIENT, amb0);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, diff0);
		glLightfv(GL_LIGHT0, GL_POSITION, pos0);
		glEnable( GL_LIGHT0 );
	}
	//
	{
		// マテリアル設定
		GLfloat c0[]={1, 1, 1, 1};
		GLfloat c[]={1, .7, .7, 1};
		GLfloat c1[]={.1, .1, .1, 1};
		//glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, c0 );
		glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, c );
		glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, c1 );
		glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 50.0 );
	}


	// ここから描画開始します
	// 
	glEnable( GL_LIGHTING );
	// グリッド
	{
		GLfloat c[]={ 0,.4,0, 1};
		glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, c );

		const int res =10;
		glNormal3f( 0,1,0 );
		for( int i=-res; i<res; ++i ){
			glBegin( GL_TRIANGLE_STRIP );
			for( int j=-res; j<=res; ++j ){
				glVertex3f( i*10, -10, j*10 );
				glVertex3f( (i+1)*10, -10, j*10 );
			}// j
			glEnd();	
		}// i
	}

	{
		// マテリアル設定
		GLfloat c[]={1, 1, 1, 1};
		glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, c );
	}


	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glEnable( GL_TEXTURE_2D );
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
	GLuint texture;
	glGenTextures( 1, &texture );
	glBindTexture( GL_TEXTURE_2D, texture );
	const int w = 256;
	const int h = 256;
	GLubyte buf[ h ][ w ][ 3 ];
	{
		for( int i=0; i<h; ++i ){
			for( int j=0; j<w; ++j ){
				buf[ i ][ j ][ 0 ] = j*.5+ (( (i/20+j/20)&1 )? 128: 0 );
				buf[ i ][ j ][ 1 ] = i;
				buf[ i ][ j ][ 2 ] = 0;
			}// j
		}// i
	}
	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 
		0, GL_RGB, GL_UNSIGNED_BYTE, buf );
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glBegin( GL_TRIANGLE_STRIP );
	{
		const float a=3;
		glTexCoord2f( 0, 0 );		glVertex3f(-a, -a, 0 );
		glTexCoord2f( 1, 0 );		glVertex3f(a, -a, 0 );
		glTexCoord2f( 0, 1 );		glVertex3f(-a, a, 0 );
		glTexCoord2f( 1, 1 );		glVertex3f(a, a, 0 );
	}
	glEnd();
	glDisable( GL_TEXTURE_2D );
}
m_ogl->EndRender();
}