Delphi版OpenGL样例代码导游

原创 2002年05月31日 09:13:00

由于Delphi自带OpenGL.pas是1.0版的,而现在实际使用的至少是1.1版,Windows纯软件模拟方式也是1.1版的,所以要自己导入一些必要的函数。也可用一些开源的免费单元,如Mike Lischke的OpenGL12.pas。当然,自己写可以设计得更简洁,而且不必在过于超前完备的庞大代码中找错误。

首先引入必要的单元Windows, Messages, OpenGL

要增加一些必要的扩展。

const
  // GL_EXT_bgra
  GL_BGR_EXT                                 = $80E0;
  GL_BGRA_EXT                                = $80E1;

  // polygon offset
  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;


procedure glBindTexture(target: GLEnum; texture: GLuint); stdcall; external opengl32;
procedure glDeleteTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32;
procedure glGenTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32;
function glIsTexture(texture: GLuint): GLboolean; stdcall; external opengl32;
procedure glPolygonOffset(factor, units: GLfloat); stdcall; external opengl32;

// 此声明用于纠正OpenGL.pas的一个bug
function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; Data: Pointer): GLint; stdcall; external opengl32;

现在接口已经基本升级到1.1版。如果还需要其他扩展,可类似增加。

接下来,要创建OpenGL的绘图上下文RC,为此需要GDI窗口的设备上下文DC。TForm.Handle属性或其他TWinControl的Handle属性都是DC。可使用如下函数由DC创建RC,返回值为RC的句柄。之后即可使用OpenGL绘图。一般可在Form的OnCreate事件内使用。此函数的选项含义分别为深度缓冲区,模版缓冲区,积累缓冲区,生成Alpha通道的值。

type
  TRCOptions = set of (roDepth, roStencil, roAccum, roAlpha);

function CreateRC(dc: HDC; opt: TRCOptions): HGLRC;
var
  PFDescriptor: TPixelFormatDescriptor;
  PixelFormat: Integer;
begin
  FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
  with PFDescriptor do
  begin
    nSize := SizeOf(PFDescriptor);
    nVersion := 1;
    dwFlags := PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER;
    iPixelType := PFD_TYPE_RGBA;
    cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
    if roDepth in opt then cDepthBits := 24;
    if roStencil in opt then cStencilBits := 8;
    if roAccum in opt then cAccumBits := 64;
    iLayerType := PFD_MAIN_PLANE;
  end;

  PixelFormat := ChoosePixelFormat(DC, @PFDescriptor);
  Assert(PixelFormat <> 0);
  Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
  Result := wglCreateContext(DC);
  Assert(Result <> 0);
  wglMakeCurrent(dc, Result);
end;

在Form的OnPaint事件里绘图。记住,绘图完成后要用SwapBuffers(dc: HDC)交换绘图缓冲和显示缓冲,这样图象才会显示出来。还要记得在Form的OnResize事件里调用 glViewport(0, 0, ClientWidth, ClientHeight); 好让RC和DC同步。

在Form的OnDestroy事件里销毁RC。

procedure DestroyRC(rc: HGLRC);
begin
  if rc = 0 then Exit;
  wglMakeCurrent(0, 0);
  wglDeleteContext(rc);
end;

至此,一个OpenGL程序的框架就大致成型。但还有问题要解决。

第一,要防止Windows擦除背景而影响速度。在Form中加入成员函数

  private
    procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;

procedure TGLWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
  Message.Result := 1;
end;

第二,为了更保险些。再增加以下成员函数。

  protected
    procedure CreateParams(var Params: TCreateParams); override;

procedure TGLWindow.CreateParams(var Params: TCreateParams);
begin
  inherited;
  with Params do
  begin
    Style := Style or WS_CLIPCHILDREN or WS_CLIPSIBLINGS;
    WindowClass.Style := CS_VREDRAW or CS_HREDRAW or CS_OWNDC;
  end;
end;

好,现在就可以忘掉这些麻烦的东西了,写你的精彩3D显示吧:)

还得唠叨几句,在一个线程里不要创建多个RC,这样会严重影响性能。有些个人的OpenGL窗口控件演示有在一个Form上放多个控件,其实并非好主义。应该用一个OpenGL窗口显示多个视图。另外,不要跨线程访问OpenGL函数。

还有Windows自动安装显卡驱动时不会安装OpenGL的硬件加速,一定要自己安装显卡厂商的驱动!

另外,副赠全屏显示的函数:)

function FullScreen(win: TWinControl; width, height, bitdepth: integer): boolean;
var displaymode: DEVMODE;
begin
  FillChar(displaymode, sizeof(displaymode), 0);
  with displaymode do
  begin
    dmSize := sizeof(displaymode);
    dmPelsWidth := width;
    dmPelsHeight := height;
    dmBitsPerPel := bitdepth;
    dmFields := DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
  end;
  if ChangeDisplaySettings(displaymode, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
  then begin
    ShowWindow(win.Handle, WS_MAXIMIZE);
    result := true;
  end
  else result := false;
end;

procedure RestoreDisplay(win: TWinControl);
begin
  ChangeDisplaySettings(PDEVMODE(0)^, 0);
  ShowWindow(win.Handle, SW_RESTORE);
end;

========================================

LI Qingrui
http://wrighteagle.org/appdev

数据结构-校园导游咨询系统

#include "string.h"#include "stdio.h"#include "malloc.h"#include "stdlib.h"#define Max 20000#define ...
  • raywwen
  • raywwen
  • 2011年06月16日 09:43
  • 1894

OpenGL: glEdgeFlag示例程序:

glEdgeFlag (GLboolean flag)表示一个顶点是否应该被认为是多边形的一条边界边的起点。flag为GL_TRUE后面的点都被认为是边界上的点,flag为GL_FALSE则之后的点不...
  • Augusdi
  • Augusdi
  • 2014年03月04日 17:05
  • 3391

校园导游系统

校园导游系统 问题描述:设计一个校园导游程序,完成校园信息的维护以及为来访的客人 提供信息查询等服务功能。 基本要求: 设计学校的校园平面图,所含景点不少于10个,以图中顶点表示校内各景点, ...
  • HappyNewStart
  • HappyNewStart
  • 2014年07月24日 18:56
  • 3047

校园交通导游系统

1.1  需求分析 随着社会的发展,越来越多的大学生选择去找同学,游历一些名校,然而到了一个陌生的学校又该怎么样去选择利用更少的时间,走最少的路去游历校园的所有景点呢。此时就需要这块校园交通导游系统...
  • u013930856
  • u013930856
  • 2015年06月14日 14:36
  • 1151

C语言简单校园导游程序的设计与实现

这个是用最短路写的,具体给忘了。好久以前做过的,最近在整理就把代码贴上吧。其实很简单的。算法最重要就是思想。其它都是浮云。 # include # include # include int ...
  • ALL_Dash
  • ALL_Dash
  • 2013年07月12日 22:35
  • 2497

校园导游系统 数据结构课程设计

校园导游系统   数据结构课程设计 郑州师范学院老校区校园导游系统 尴尬的最短路算法 Floyd and Dijkstra 尴尬的数据结构...... 记录一下代码: 多有参考.....
  • qq_33406883
  • qq_33406883
  • 2016年12月11日 22:20
  • 4343

数据结构项目-校园导游系统

#include #include #include #include #include #include #define INF 32767 int visited[100],passw...
  • zw159357
  • zw159357
  • 2017年08月07日 19:43
  • 621

数据结构-校园导游咨询系统…

原文地址:数据结构-校园导游咨询系统(c语言版)作者:陶陶//本程序最好在VC++中运行,但这是C程序,在TC中,显示结果会出现乱码,TC不支持汉字 #include "string.h" #incl...
  • S04103037
  • S04103037
  • 2013年04月25日 17:36
  • 2085

用Delphi写的一个完整OpenGL框架

用Delphi写的一个完整OpenGL框架 program OpenGLFramework; {     OpenGL DelphiXE     出处:根据NeHe代码翻译而来(http://...
  • shuaihj
  • shuaihj
  • 2012年02月03日 14:55
  • 4250

DELPHI中OPENGL图形程序设计

OPENGL图形程序设计OPENGL是一个三维图形和模型库,由于它在三维图形方面的杰出性能,目前许多高级语言都提供了与OPENGL的接口,如:VC、DELPHI、C++Builder等。使用OPENG...
  • jaguarcts
  • jaguarcts
  • 2003年01月02日 09:22
  • 9677
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Delphi版OpenGL样例代码导游
举报原因:
原因补充:

(最多只允许输入30个字)