Delphi 独自の OpenGL.pas はバージョン 1.0 であり、現在実際に使用されているものは少なくともバージョン 1.1 であり、Windows の純粋なソフトウェア シミュレーション メソッドもバージョン 1.1 であるため、必要な機能を自分でインポートする必要があります。 Mike Lischke の OpenGL12.pas など、いくつかのオープン ソースの無料ユニットも利用できます。もちろん、自分で書くことで設計をより簡潔にすることができ、高度で完成度が高すぎる巨大なコードの中でエラーを見つける必要がなくなります。
まずは必要なユニット Windows、Messages、OpenGL を導入します
必要な拡張機能を追加します。
定数
//GL_EXT_bgra
GL_BGR_EXT = $80E0;
GL_BGRA_EXT = $80E1;
// ポリゴンのオフセット
GL_POLYGON_OFFSET_UNITS = $2A00;
GL_POLYGON_OFFSET_POINT = $2A01;
GL_POLYGON_OFFSET_LINE = $2A02;
GL_POLYGON_OFFSET_FILL = $8037;
GL_POLYGON_OFFSET_FACTOR = $8038;
手順 glBindTexture(ターゲット: GLEnum; テクスチャ: GLuint);
プロシージャ glDeleteTextures(n: GLsizei; テクスチャ: PGLuint);
プロシージャ glGenTextures(n: GLsizei; テクスチャ: PGLuint);
関数 glIsTexture(テクスチャ: GLuint): 外部 opengl32;
プロシージャ glPolygonOffset(係数、単位: GLfloat);
// このステートメントは OpenGL.pas のバグを修正するために使用されます
関数 gluBuild2DMipmaps(ターゲット: GLEnum; コンポーネント、幅、高さ: GLint; 形式、タイプ: GLEnum; データ: ポインター): GLint; 外部 opengl32;
現在、インターフェースは基本的にバージョン 1.1 にアップグレードされています。他の拡張機能が必要な場合も、同様に追加できます。
次に、OpenGL 描画コンテキスト RC を作成する必要があります。これには、GDI ウィンドウのデバイス コンテキスト DC が必要です。 TForm.Handle プロパティまたは TWinControl の他の Handle プロパティは DC です。次の関数を使用して DC から RC を作成できます。戻り値は RC のハンドルです。これで、OpenGL を使用して描画できるようになります。通常、フォームの OnCreate イベント内で使用できます。この関数のオプションは、深度バッファ、テンプレート バッファ、蓄積バッファ、およびアルファ チャネル値の生成を意味します。
タイプ
TRCOptions = (roDepth、roStencil、roAccum、roAlpha) のセット;
関数 CreateRC(dc: HDC; opt: TRCOptions): HGLRC;
変数
PFDescriptor: TPixelFormatDescriptor;
ピクセル形式: 整数;
始める
FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
PFDescriptor を使用して行う
始める
nSize := SizeOf(PFDescriptor);
nバージョン := 1;
dwFlags := PFD_SUPPORT_OPENGL または PFD_DRAW_TO_WINDOW または PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
roDepth がオプションの場合、cDepthBits := 24;
roStencil がオプションの場合、cStencilBits := 8;
roAccum がオプションの場合、cAccumBits := 64;
iLayerType := PFD_MAIN_PLANE;
終わり;
PixelFormat := ChoicePixelFormat(DC, @PFDescriptor);
Assert(PixelFormat <> 0);
Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
結果 := wglCreateContext(DC);
Assert(結果 <> 0);
wglMakeCurrent(dc, 結果);
終わり;
フォームの OnPaint イベントで描画します。描画が完了したら、画像を表示するために SwapBuffers (dc: HDC) を使用して描画バッファと表示バッファを交換する必要があることに注意してください。 RC と DC を同期できるように、Form の OnResize イベントで glViewport(0, 0, ClientWidth, ClientHeight); を忘れずに呼び出してください。
フォームの OnDestroy イベントで RC を破棄します。
プロシージャ DestroyRC(rc: HGLRC);
始める
rc = 0 の場合は終了します。
wglMakeCurrent(0, 0);
wglDeleteContext(rc);
終わり;
この時点で、OpenGL プログラムのフレームワークはおおよそ形になりました。しかし、解決すべき問題はまだ残っています。
まず、Windows が背景を消去して速度に影響を与えるのを防ぎます。メンバー関数をフォームに追加する
プライベート
プロシージャ WMEraseBkgnd(var メッセージ: TWmEraseBkgnd); メッセージ WM_ERASEBKGND;
プロシージャ TGLWindow.WMEraseBkgnd(var メッセージ: TWmEraseBkgnd);
始める
メッセージ.結果 := 1;
終わり;
第二に、より安全であること。以下のメンバー関数を追加します。
保護された
プロシージャ CreateParams(var Params: TCreateParams);
プロシージャ TGLWindow.CreateParams(var Params: TCreateParams);
始める
継承された。
Params で行うこと
始める
スタイル := スタイル、WS_CLIPCHILDREN、または WS_CLIPSIBLINGS;
WindowClass.Style := CS_VREDRAW または CS_HREDRAW または CS_OWNDC;
終わり;
終わり;
さて、これらの面倒なことは忘れて、素晴らしい 3D ディスプレイを作成できます :)
一言言っておきますが、パフォーマンスに重大な影響を与えるため、1 つのスレッド内に複数の RC を作成しないでください。個人用の OpenGL ウィンドウ コントロールのデモの中には、フォーム上に複数のコントロールを配置するものもありますが、これは実際には良いアイデアではありません。複数のビューを 1 つの OpenGL ウィンドウで表示する必要があります。また、スレッドをまたいで OpenGL 関数にアクセスしないでください。
また、Windows がグラフィックス カード ドライバーを自動的にインストールする場合、OpenGL ハードウェア アクセラレーションはインストールされません。グラフィックス カードの製造元のドライバーを自分でインストールする必要があります。
さらに、無料の全画面表示機能が提供されます:)
関数 FullScreen(win: TWinControl; 幅、高さ、ビット深度: 整数): ブール値;
var 表示モード: DEVMODE;
始める
FillChar(表示モード, サイズオブ(表示モード), 0);
ディスプレイモードで行う
始める
dmSize := sizeof(表示モード);
dmPelsWidth:= 幅;
dmPelsHeight := 高さ;
dmBitsPerPel := ビット深度;
dmFields := DM_BITSPERPEL または DM_PELSWIDTH または DM_PELSHEIGHT;
終わり;
if ChangeDisplaySettings(表示モード、CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
それから始めます
ShowWindow(win.Handle, WS_MAXIMIZE);
結果:= true;
終わり
それ以外の場合は結果 := false;
終わり;
プロシージャ RestoreDisplay(win: TWinControl);
始める
ChangeDisplaySettings(PDEVMODE(0)^, 0);
ShowWindow(win.Handle, SW_RESTORE);
終わり;