
OpenGLは機種やOSによらない汎用の三次元グラフィック言語で、Windowsからも使えるようになってきています(95では正式にはOSR2から)。デルファイでもOpenGLを使用するためにOpenGL.pasというユニットが用意されています。 デルファイでOpenGLを使うメリットはいくつかあります。
まずVCLによってグラフィックがカプセル化されているため、ウィンドウに関するプログラムを作る手間がありません。さらに、Cと違って、大文字・小文字を区別する必要がありません。そのため、C++で作るときに比べて、少ない手間で、OpenGLが使えると思います。 このページではOpenGLを使うときの、デルファイ特有の問題について述べたいと思います。OpenGL自体については、さらに他の参考書をご覧ください。
OpenGLとデルファイを結びつける部分は、OpenGLではなく、win32で扱っているため、デルファイのヘルプには日本語の説明がありません。win32の中にあるOpenGL用の関数(wgl....という名前)をいくつか使う必要があります。 それらの関数では、「デバイスコンテキスト」や「レンダリングコンテキスト」という値を使って、どこに、どのように表示するかを指定しています。基本として、それらの値を実際にプログラム内で扱った例を示します。
しかし、このような値を自分で管理するのは面倒ですし、間違えればエラーの原因になりかねません。そこで、それらの値を隠しておくために簡単なクラスを作成しました。
・OpenGLとのインターフェースをクラス(TGLdelphi)にするユニット
ただし、256色モードでは、パレットを扱わなければならず、それだけ難しくなり、また遅くなりますので、ここではすべてフルカラーモードでウィンドウズを使うものとします。
a.まず、上記のユニット(Gldelphi.pas)をプロジェクトに追加します。
b.フォームのUses節に「opengl, gldelphi」の二つを付け加えます。
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Buttons, StdCtrls, opengl, gldelphi;
のようになります。
c.最初のvar節に、変数名を定義します。
var
Form1: TForm1;
g:tgldelphi;<−ここ
Implementation
.....
のようになります。
d.必要なときまでにオブジェクトのインスタンスを作ります。
G:=TGLdelphi.create;
同じオブジェクトを何度も作らないために、
フォームができるときに一度だけ実行するのが望ましいです。
procedure TForm1.FormCreate(Sender: TObject);
begin
g:=tgldelphi.create;
end;
このような形でformcreateに結び付けておくのがよいと思います。
* ここまで作ったらあとは実際に使う場面で、設定を行います。
e.まずどこに絵を描くかを指定します。具体的には、メンバ関数Open(hdc)で、
デバイスコンテキストを指定します。というと難しそうですが、
・フォーム1に書きたいとき
G.open(form1.canvas.handle);
・イメージに書きたいとき
G.open(image1.canvas.handle);
のようにすればOKです。
* ここで、OpenGLで絵を書きます。書き終わったらcloseで閉じます。
glclearcolor(0,0,0,0);
glclear(.....
.....
glfinish;
G.close;
フォームにボタンを一つつけたものを用意してください。
そしてボタンを押したときに絵を書きます。
a.画面を黒で消去するだけ…
Procedure Form1.Button1Click(Sender:Tobject);
Begin
G.open(form1.canvas.handle);{書き込み先をフォーム1に指定}
glclearcolor(0,0,0,0); {画面消去の色RGBAの順に0−1で指定}
glclear(GL_COLOR_BUFFER_BIT);{画面消去の実行}
glfinish;{コマンドの実行待ち}
G.close;
End;
一般にはGlflush;がコマンドの実行につかわれますが、特にデルファイの統合環境上で使うときには、Glfinish;をつかって、実行の終了を待たないと、エラーが出ることがあるようです。コンパイルしたexeファイルでは、気にしなくてもいいようです。
b.三角形を書く例
Procedure Form1.Button1Click(Sender:Tobject);
Begin
G.open(form1.canvas.handle);{書き込み先をフォーム1に指定}
glclearcolor(0,0,0,0); {画面消去の色RGBAの順に0−1で指定}
glclear(GL_COLOR_BUFFER_BIT);{画面消去の実行}
glcolor3f(0,0,1);{図形を青で書く}
glBegin(GL_TRIANGLES);{次に指定する点を三角形にする}
glvertex2f(-0.75,-0.75);
glvertex2f(0,0.75);
glvertex2f(0.75,0.75);{点の座標−1から1の間を取る}
glend;
glfinish;{コマンドの実行待ち}
G.close;
End;
*速いOpenGLがシリコングラフィクス社から配布されていますので、ダウンロードされることをお勧めします。(http://www.sgi.com/)
*イメージ(たとえばimage1.canvas.handleとして)を使うと、イメージのほうで画面サイズの変換やバッファリングをしてくれます。 しかし、書き換えのたびに
image1.refresh;
として、再表示が必要となります。また、速度が非常に落ちます。そのため、静止画はimageコンポーネントでよいと思いますが、動画はformに直接書き込んだほうがよいと考えます。
*動画の表示のときに表示用と書き込み用にダブルバッファを使うときことができます。 最初の設定で、open(hdc)のかわりにopenswap(hdc)を使ってください。 メンバ関数 swapによって「表」と「裏」の画像が瞬時に切り替わります。 逆にswapを付け加えるのを忘れると何も表示されなくなりますのでご注意ください。