せっかく強力なVGAを積んでるのにゲームにしか使えないなんて...
という訳でまずは、サンプルから。
インストールしたフォルダ(C:\Program Files\Borland\CBuilder6\Examples\OpenGL)の下に
「Drawing」と「Rotate」というOpenGLのサンプルがあります。
今回は「Drawing」を参考にしつつ...最もシンプルなコードで。
<GlSkel.h>
//---------------------------------------------------------------------------
#ifndef GlSkelH
#define GlSkelH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <gl\gl.h> // OpenGL用のヘッダを忘れずに
//---------------------------------------------------------------------------
class TFormMain : public TForm
{
__published:
void __fastcall FormResize(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
private:
HDC hdc;
HGLRC hrc;
__fastcall TFormMain(TComponent* Owner);
void __fastcall IdleLoop(TObject*, bool&);
void __fastcall RenderGLScene();
void __fastcall SetPixelFormatDescriptor();
void __fastcall DrawObjects();
void __fastcall SetupLighting();
};
//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif
<GlSkel.cpp>
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GlSkel.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------
// コンストラクタ
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
// アイドル中の実行
Application->OnIdle = IdleLoop;
}
//---------------------------------------------------------------------------
// フォーム開始
void __fastcall TFormMain::FormCreate(TObject *Sender)
{
hdc = GetDC(Handle); // デバイスコンテキスト取得
SetPixelFormatDescriptor(); // ピクセルフォーマットの設定
hrc = wglCreateContext(hdc); // レンダリングコンテキスト作成
if(hrc == NULL){
ShowMessage("レンダリングコンテキスト作成失敗");
}
// 取得したレンダリングコンテキストに対してカレント設定
if(wglMakeCurrent(hdc, hrc) == false){
ShowMessage("wglMakeCurrent失敗");
}
// 深度バッファ有効
glEnable(GL_DEPTH_TEST);
// glClearでクリアする色を設定
glClearColor(0.0, 0.0, 0.0, 1.0);
// 照明と素材の設定
SetupLighting();
}
//---------------------------------------------------------------------------
// ピクセルフォーマットの設定
void __fastcall TFormMain::SetPixelFormatDescriptor()
{
// ココはとりあえず、おまじないとして。
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,
};
int PixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, PixelFormat, &pfd);
}
//---------------------------------------------------------------------------
// 照明と素材の設定
void __fastcall TFormMain::SetupLighting()
{
// 素材に対する環境光、拡散光、鏡面光、光沢を設定
GLfloat MaterialAmbient[] = {0.5, 0.5, 0.5, 1.0};
GLfloat MaterialDiffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat MaterialSpecular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat MaterialShininess[] = {50.0};
// 照明の位置
GLfloat AmbientLightPosition[] = {0.5, 1.0, 1.0, 0.0};
// 環境光の設定
GLfloat LightAmbient[] = {0.5, 0.5, 0.5, 1.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, MaterialAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, MaterialDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, MaterialSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, MaterialShininess);
glLightfv(GL_LIGHT0, GL_POSITION, AmbientLightPosition);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightAmbient);
glEnable(GL_LIGHTING); // 照明を有効
glEnable(GL_LIGHT0); // 照明0を有効
glEnable(GL_COLOR_MATERIAL); // 素材の色設定を有効
// 素材の表面に環境光と拡散光を有効にします
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glShadeModel(GL_SMOOTH); // ポリゴンを滑らかに見せる
}
//---------------------------------------------------------------------------
// リサイズ処理
void __fastcall TFormMain::FormResize(TObject *Sender)
{
float nRange = 3.0;
// クライアント領域をビューポートとします
int w = ClientWidth;
int h = ClientHeight;
if(w == 0) w = 1;
if(h == 0) h = 1;
// ビューポートの設定
glViewport(0, 0, w, h);
// 視野を設定する際は投影行列に切り替えます
glMatrixMode(GL_PROJECTION);
// 単位行列に設定
glLoadIdentity();
// 視野を設定
if(w <= h){
// 正射影で設定(視野=視体積を左,右,下,上,手前,奥の順に設定)
glOrtho(-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
}
else{
glOrtho(-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
}
// ポリゴンを描画するにはモデルビュー行列に切り替えます
glMatrixMode(GL_MODELVIEW);
// 単位行列に設定
glLoadIdentity();
}
//---------------------------------------------------------------------------
// フォーム終了
void __fastcall TFormMain::FormDestroy(TObject *Sender)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hrc);
}
//---------------------------------------------------------------------------
// 描画ループ(アイドル中はココが呼ばれ続けます)
void __fastcall TFormMain::IdleLoop(TObject*, bool& done)
{
done = false;
RenderGLScene(); // 描画部
SwapBuffers(hdc); // バッファを切替
}
//---------------------------------------------------------------------------
// 描画
void __fastcall TFormMain::RenderGLScene()
{
// 描画された絵を毎回消します
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(1, 0, 1, 0); // Y軸を基準に1度ずつ回ります
glBegin(GL_TRIANGLES); // 三角形を描く
glColor3f(1,0,0); // 色は赤で
glVertex3f(0,0,0); // 座標x=0,y=0,z=0と
glVertex3f(1,0,0); // 座標x=1,y=0,z=0と
glVertex3f(0,1,0); // 座標x=0,y=1,z=0を結んだ三角形を
glEnd(); // 描画します
glFlush(); // これまでのOpenGLコマンド実行
}
//---------------------------------------------------------------------------
と..まぁ新しい事がワンサカ出てきましたね..
←実行すると赤い三角形がグリグリ回ってます。
ま、詳しい事は追々と..