第一章 初始化OpenGL

无论是什么东西,要使用它,就必须对它进行初始化。如果你之前使用过GDI,你应该也多多少少了解到GDI在绘制图形之前要为之创建渲染环境。OpenGL也一样。本章给出的代码,大家可以不必理解其中的具体意义,反正以后每次初始化是使用这个代码即可。

首先,在一个新的应用程序中,我们需要添加对OpenGL库的引用。Delphi已经为我们写好了OpenGL的头文件,因此我们只须直接在单元的uses中添加OpenGL即可:

...

uses Windows, Graphics, OpenGL, ...

...

在创建窗口时,应添加如下代码:

procedure Form1.Create(Sender:TObject);
var DC: HDC;
HRC :HGLRC ;
    pfd:TPIXELFORMATDESCRIPTOR; pixelFormat:integer;
begin
DC := GetDC(Handle); With pfd do
begin nSize:=sizeof(TPIXELFORMATDESCRIPTOR); // size
nVersion:=; // version
dwFlags:=PFD_SUPPORT_OPENGL or PFD_DRAW_to_WINDOW or
PFD_DOUBLEBUFFER; // support double-buffering
iPixelType:=PFD_TYPE_RGBA; // color type
cColorBits:=; // preferred color depth
cRedBits:=;
cRedShift:=; // color bits (ignored)
cGreenBits:=;
cGreenShift:=;
cBlueBits:=;
cBlueShift:=;
cAlphaBits:=;
cAlphaShift:=; // no alpha buffer
cAccumBits:=;
cAccumRedBits:=; // no accumulation buffer,
cAccumGreenBits:=; // accum bits (ignored)
cAccumBlueBits:=;
cAccumAlphaBits:=;
cDepthBits:=; // depth buffer
cStencilBits:=; // no stencil buffer
cAuxBuffers:=; // no auxiliary buffers
iLayerType:=PFD_MAIN_PLANE; // main layer
bReserved:=;
dwLayerMask:=;
dwVisibleMask:=;
dwDamageMask:=; end; pixelFormat := ChoosePixelFormat(DC, @pfd);
if (pixelFormat = ) then
exit;
if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) then
exit;
hRc := wglCreateContext(DC);
wglMakeCurrent(DC,HRC); end;

上面的代码是Windows下初始化OpenGL的固定代码。因为本教程不使用任何第三方库,所以在初始化上显得麻烦些。但这些代码是固定的,每次初始化OpenGL时,照抄代码即可。下面对上述代码作简单的说明。

首先,我们用GetDC(Handle)获取当前窗口的设备目录。然后初始化一个TPIXELFORMATDESCRIPTOR类型的字段,用于描述将要使用的像素格式。在此字段中,dwFlags表示渲染方式,一般情况下使用PFD_SUPPORT_OPENGL or PFD_DRAW_to_WINDOW or PFD_DOUBLEBUFFER。其中,PFD_DOUBLEBUFFER表示支持双缓冲。这将会在今后的章节中讲到。cColorBits表示使用的色深,一般情况下使用24位色深。在今后的教程中,会根据不同的需求而改变TPIXELFORMATDESCRIPTOR字段中的值,而其他代码一般都是不变的。

初始化完OpenGL之后,就可以调用OpenGL的绘制函数来绘制图形了。一般情况下,我们把所有绘制图形的函数调用写在一个名为RenderScene的过程中:

第一章 初始化OpenGL

无论是什么东西,要使用它,就必须对它进行初始化。如果你之前使用过GDI,你应该也多多少少了解到GDI在绘制图形之前要为之创建渲染环境。OpenGL也一样。本章给出的代码,大家可以不必理解其中的具体意义,反正以后每次初始化是使用这个代码即可。

首先,在一个新的应用程序中,我们需要添加对OpenGL库的引用。Delphi已经为我们写好了OpenGL的头文件,因此我们只须直接在单元的uses中添加OpenGL即可:

...

uses Windows, Graphics, OpenGL, ...

...

在创建窗口时,应添加如下代码:

procedure Form1.Create(Sender:TObject);
    var DC: HDC;
        HRC :HGLRC ;
    pfd:TPIXELFORMATDESCRIPTOR; pixelFormat:integer;
    begin
      DC := GetDC(Handle);

With pfd do
begin

nSize:=sizeof(TPIXELFORMATDESCRIPTOR); // size
nVersion:=1; // version
dwFlags:=PFD_SUPPORT_OPENGL or PFD_DRAW_to_WINDOW or
         PFD_DOUBLEBUFFER; // support double-buffering
iPixelType:=PFD_TYPE_RGBA; // color type
cColorBits:=24; // preferred color depth
cRedBits:=0;
cRedShift:=0; // color bits (ignored)
cGreenBits:=0;
cGreenShift:=0;
cBlueBits:=0;
cBlueShift:=0;
cAlphaBits:=0;
cAlphaShift:=0; // no alpha buffer
cAccumBits:=0;
cAccumRedBits:=0; // no accumulation buffer,
cAccumGreenBits:=0; // accum bits (ignored)
cAccumBlueBits:=0;
cAccumAlphaBits:=0;
cDepthBits:=16; // depth buffer
cStencilBits:=0; // no stencil buffer
cAuxBuffers:=0; // no auxiliary buffers
iLayerType:=PFD_MAIN_PLANE; // main layer
bReserved:=0;
dwLayerMask:=0;
dwVisibleMask:=0;
dwDamageMask:=0;

end;

pixelFormat := ChoosePixelFormat(DC, @pfd);
if (pixelFormat = 0) then
exit;
if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) then
exit;
hRc := wglCreateContext(DC);
wglMakeCurrent(DC,HRC);

end;

上面的代码是Windows下初始化OpenGL的固定代码。因为本教程不使用任何第三方库,所以在初始化上显得麻烦些。但这些代码是固定的,每次初始化OpenGL时,照抄代码即可。下面对上述代码作简单的说明。

首先,我们用GetDC(Handle)获取当前窗口的设备目录。然后初始化一个TPIXELFORMATDESCRIPTOR类型的字段,用于描述将要使用的像素格式。在此字段中,dwFlags表示渲染方式,一般情况下使用PFD_SUPPORT_OPENGL or PFD_DRAW_to_WINDOW or PFD_DOUBLEBUFFER。其中,PFD_DOUBLEBUFFER表示支持双缓冲。这将会在今后的章节中讲到。cColorBits表示使用的色深,一般情况下使用24位色深。在今后的教程中,会根据不同的需求而改变TPIXELFORMATDESCRIPTOR字段中的值,而其他代码一般都是不变的。

初始化完OpenGL之后,就可以调用OpenGL的绘制函数来绘制图形了。一般情况下,我们把所有绘制图形的函数调用写在一个名为RenderScene的过程中:

procedure TForm1.RenderScene;

begin

...

end;

然后,我们使用一个Timer,其Interval属性设为1,然后在OnTimer事件中调用RenderScene即可。

在窗体关闭时,我们还必须关闭渲染环境以释放内存。方法如下:

procedure TForm1.Form1Close(Sender:TObject;....);

begin

wglMakeCurrent(DC,HRC);
      wglDeleteContext(hRc);
      ReleaseDC(Handle,DC);

end;

其实,关于OpenGL初始化,我已经写好了一个类。用这个类初始化,可以让窗体的代码简洁一些。首先,下载glInit.pas,并引用它。然后向单元中加入如下代码初始化OpenGL。

...

uses ...,GLInit;

var

glInitor:TOpenGLInit;

implementation

procedure TForm1.Create(....);

begin

glInitor:=TOpenGLInit.Create(Handle,24,stdDoubleBuffer);

end;

procedure TForm1.Close(...);

begin

glInitor.Free;

end;

在本章的示例程序中,我们将初始化OpenGL,并用OpenGL绘制一个三角形。在此程序中,我们还对OpenGL作了其他一些设置,现在你无须理解其中的意义。此程序中,InitOpenGL过程用于初始化OpenGL,FreeOpenGL过程用于销毁OpenGL,SetView过程用于设置视图投影(将在今后的章节中讲到),在RenderScene过程中,我们使用了一个OpenGL的函数绘制了一个三角形。

以下就是本章示例程序的代码。

unit untMainForm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ExtCtrls, OpenGL;

type

TfrmMain = class(TForm)

tmrRender: TTimer;

procedure FormCreate(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

procedure tmrRenderTimer(Sender: TObject);

private

procedure InitOpenGL;

procedure FreeOpenGL;

procedure SetView;

procedure RenderScene;

public

end;

var

frmMain: TfrmMain;

DC: HDC;

HRC :HGLRC ;

implementation

{$R *.dfm}

procedure TfrmMain.FreeOpenGL;

begin

wglMakeCurrent(DC,HRC);

wglDeleteContext(hRc);

ReleaseDC(Handle,DC);

end;

procedure TfrmMain.InitOpenGL;

var pfd:TPIXELFORMATDESCRIPTOR; pixelFormat:integer;

begin

DC := GetDC(Handle);

with pfd do

begin

nSize:=sizeof(TPIXELFORMATDESCRIPTOR); // 此结构尺寸

nVersion:=1;

dwFlags:=PFD_SUPPORT_OPENGL or PFD_DRAW_to_WINDOW or

PFD_DOUBLEBUFFER; // 使用双缓冲区

iPixelType:=PFD_TYPE_RGBA; //使用RGBA颜色空间

cColorBits:=24;     //24位真彩色

cRedBits:=0;

cRedShift:=0;

cGreenBits:=0;

cGreenShift:=0;

cBlueBits:=0;

cBlueShift:=0;

cAlphaBits:=0;

cAlphaShift:=0;

cAccumBits:=0;

cAccumRedBits:=0;

cAccumGreenBits:=0;

cAccumBlueBits:=0;

cAccumAlphaBits:=0;

cDepthBits:=16;

cStencilBits:=0;

cAuxBuffers:=0;

iLayerType:=PFD_MAIN_PLANE;

bReserved:=0;

dwLayerMask:=0;

dwVisibleMask:=0;

dwDamageMask:=0;

end;

pixelFormat := ChoosePixelFormat(DC, @pfd);

if (pixelFormat = 0) then

exit;

if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) then

exit;

hRc := wglCreateContext(DC);

wglMakeCurrent(DC,HRC);

end;

procedure TfrmMain.FormCreate(Sender: TObject);

begin

InitOpenGL;

SetView;

end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);

begin

FreeOpenGL;

end;

procedure TfrmMain.tmrRenderTimer(Sender: TObject);

begin

RenderScene;

end;

procedure TfrmMain.RenderScene;

begin

glLoadIdentity;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);//清空缓冲区

glColor3ub(0,255,0); //将颜色设置为绿色。

glBegin(GL_TRIANGLES);//告诉OpenGL将要绘制三角形

glVertex2f(200,300);  //传输三角形的三个顶点坐标给OpenGL

glVertex2f(400,300);

glVertex2f(300,150);

glEnd; //结束图元的绘制。

SwapBuffers(DC);//交换双缓冲区内容,这将把刚绘制的图形翻印到屏幕上。

end;

procedure TfrmMain.SetView;

begin

glClearColor(0,0,0,0);//设置背景颜色为黑色

glViewPort(0,0,ClientWidth,ClientHeight);//指定OpenGL在此区域内绘图。

glMatrixMode(GL_PROJECTION);//设置视图投影变换矩阵

glLoadIdentity;//加载单位矩阵。

glOrtho(0,ClientWidth,ClientHeight,0,1,-1);//创建平行投影空间。

//在平行投影空间中,远处的物体和近处的物体大小是一致的。

glMatrixMode(GL_MODELVIEW);//将矩阵变换对象切换为模型视图变换。

end;

end.

OpenGL完全教程 第一章 初始化OpenGL的更多相关文章

  1. [ABP教程]第一章 创建服务端

    Web应用程序开发教程 - 第一章: 创建服务端 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发 ...

  2. 村田噪声抑制基础教程-第一章 需要EMI静噪滤波器的原因

    1-1. 简介 EMI静噪滤波器 (EMIFIL®) 是为电子设备提供电磁噪声抑制的电子元件,配合屏蔽罩和其他保护装置一起使用.这种滤波器仅从通过连线传导的电流中提取并移除引起电磁噪声的元件.第1章说 ...

  3. [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍

    注:为了看上去比较清晰这里只转载了中文 原地址:  [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍 本章将引导您完成安装和设置开发环境,然后你就可 ...

  4. javascript进阶教程第一章案例实战

    javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...

  5. 《进击吧!Blazor!》系列入门教程 第一章 8.部署

    <进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门教程视频,此教程能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...

  6. NeHe OpenGL教程 第一课:OpenGL窗口

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. python 教程 第一章、 简介

    第一章. 简介 官方介绍: Python是一种简单易学,功能强大的编程语言,它有高效率的高层数据结构,简单而有效地实现面向对象编程.Python简洁的语法和对动态输入的支持,再加上解释性语言的本质,使 ...

  8. Flask 教程 第一章:Hello, World!

    本文翻译自The Flask Mega-Tutorial Part I: Hello, World! 一趟愉快的学习之旅即将开始,跟随它你将学会用Python和Flask来创建Web应用.上面的视频包 ...

  9. storm入门教程 第一章 前言[转]

    1.1   实时流计算 互联网从诞生的第一时间起,对世界的最大的改变就是让信息能够实时交互,从而大大加速了各个环节的效率.正因为大家对信息实时响应.实时交互的需求,软件行业除了个人操作系统之外,数据库 ...

随机推荐

  1. Ubuntu小点汇总,更新中...

    转自:http://blog.csdn.net/zxz_tsgx/article/details/39713627 昨天重装了Ubuntu14.04 64位版,又被一些基础操作/设置给搞怕了,以前安装 ...

  2. Struts2文件上传和下载(原理)

    转自:http://zhou568xiao.iteye.com/blog/220732 1.    文件上传的原理:表单元素的enctype属性指定的是表单数据的编码方式,该属性有3个值:1)     ...

  3. 解决:Google代码achartengine曲线代码报错问题(转)

    原文地址链接 官网:http://code.google.com/p/achartengine/ 下载代码部署项目会报下面的错误: java.lang.NoClassDefFoundError: or ...

  4. JAVA中分为基本数据类型及引用数据类型

    一.基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768 ...

  5. jq查找父类元素三个函数的区别

    parent是找当前元素的第一个父节点,parents是找当前元素的所有父节点 parent().parents()与closest()方法两两之间有类似又有不同,本篇简短的区分一下这三个方法.通过本 ...

  6. 解析Cloudera Manager内部结构、功能包括配置文件、目录位置等

    转载自 http://www.aboutyun.com/thread-9189-1-1.html 问题导读1.CM的安装目录在什么位置? 2.hadoop配置文件在什么位置? 3.Cloudera m ...

  7. servlet中cookie的使用

    ---恢复内容开始--- Cookie是存储在客户端计算机上的文本文件,并保留了它们的各种信息跟踪的目的. Java Servlet透明支持HTTP Cookie. 涉及标识返回用户有三个步骤: 服务 ...

  8. 8.Smack类库

    1.登陆IM Connection.DEBUG_ENABLED = true;//首先激活调试模式 1.1建立连接 首先,在启动DSM Message时,客户端通过XMPPConnection与服务器 ...

  9. 数据采集器移动手持打印POS终端(PDA)商超抄单方案-PDA抄单无线开单+进销存软件

    PDA主要应用在业务员外出在超市能及时抄单发送回总公司,总公司办公人员及时在软件里面调出业务员的抄单数量进行配货,大大提供工作效率. 移动数据终端和无线基础架构相结合,面向零售与批发门店店员的解决方案 ...

  10. jQuery回调、递延对象总结(一)jQuery.Callbacks详解

    前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...