如何在C++ Builder中使用OpenGL
作者:太乙散数
摘要:用一个简单的例子,阐述了bcb中使用opengl的简单方法,包括初始化框架、旋转和平移图形、清除图像、初始化背景色以及在刷新时保持图像。
关键词:bcb6 opengl 旋转 清除 平移
到今天,终于把bcb6中应用Opengl的基本流程等弄清楚了,想想学之费时费力,特总结出来让后来者方便!
网上有很多Opengl应用的书和帖子,我也从中吸取了很多经验,但总感觉这些书和帖子没有把新手最想知道的最基础的东西讲明白。
为了浅显易懂,以一个例子来讲整个流程。首先创建一个新的Form(Form1 在后面的代码中我是这么定义的),然后在上面放置一个panel(Panel1)和 7个Button(具体见图1)。其中,Button1是绘图按钮,button2是清除按钮,button3是平移图像按钮,button4~7分别左旋、右旋、上旋、下旋按钮(担心图片不能上传,故唠叨几句)。这个例子的功能就是:在panel1上用opengl绘图,然后用7个button操作图形。下面是截图:

下面介绍具体的操作流程:
1)设置opengl的绘图环境。在bcb6中,只需在头文件中加入#include <GL/gl.h>、#include <GL/glu.h>两个命令即可。
2)设置hDC,即绘图区的句柄或指针,目的使程序知道你想在那
那个区域绘画。首先需要在头文件中声明HDC hDC,然后在TForm(Owner)函数下面初始化,本文的绘图区为Panel,所以hDC= hDC=GetDC(Form1->Panel1->Handle); 接着要对hDC的像素格式进行设置,SetDCPixelFormat(hDC),其实初学者大可不理会这个函数。
3) 设置RC(Rendering Context),老妖翻译为“图像操作描述表”,很晦涩。我认为就是与Opengl的绘图功能连接的一个通道,建议翻译为“背景通道”。首先要在头文件中声明HGLRC hRC;然后在TForm(Owner)函数下面初始化,要紧跟在hDC初始化之后: hRC=wglCreateContext(hDC);wglMakeCurrent(hDC,hRC)。hRC只在此处有使用,后面就不会应用到。
4)在bcb中还有个比较特别的函数需要提前声明,那就是void __fastcall TForm1::IdleLoop(TObject*, bool& done),这个函数的功能就是控制屏幕刷新时绘图区的的情况。这个函数是个自定义函数在头文件中需要先声明。然后把Application->OnIdle = IdleLoop放入TForm(Owner),要放在第一句。这样就可以调用这个IdleLoop函数,为什么这样能调用,我不是很明白?可参考bcb中自带的opengl例子。
5)在绘图之前,还得对初始化的量hRC、hDC进行关闭设置,在FormDestroy(TObject *Sender)函数中设置。
6)opengl绘图。我把opengl的绘图语句放在button1的单击事件里。首先清除背景色,或者说叫重设背景色:glClearColor(0.5,0.7,0.9,1.0)、 glClear(GL_COLOR_BUFFER_BIT); 然后用glBegin和glEnd之间语句绘图;最后刷新缓存SwapBuffers(hDC)。后面的程序把绘图语句全放入RenderScence()函数里,所以在Button1Click(TObject *Sender)函数中只需调用RenderScence()。
注:要保证绘图后图形一直存在,除非自己清除,那么就必须在IdleLoop函数写入if(Sender==Button1) Button1Click(Sender);
7)很简单吧,图像能够绘制了!然后就需要对图像进行操作设置了。首先清除图像,只需在button2中重新刷新背景色;然后平移图像,只需在button3中写入glTranslatef(0.25,0,0)(这个命令的意思是将图形右移动0.25个单位。有时在0.25后加f,即0.25f,是指0.25是一个float类型的数),注意接着要重新画图形即调用RenderScence()。左右上下旋转与此雷同,就不一一介绍了。旋转的函数为glRotatef(-5, 1.0, 0.0, 0.0)(这个命令的意思是向上旋转5°,也就是说你点击一下,即向上旋转5°)。
8)文中还有一个功能,就是在一开始就把panel1的背景色绘上,但不绘图。要实现这功能,必须FormCreate(TObject *Sender) 、FormPaint(TObject *Sender)配合使用,为什么要这样未搞清楚!
9)很好,可以画图,可以简单操作了。后续还有很多工作要做,比如窗口的设置、光源的设置、图像的大小设置等等,但只要入了门,看相关的书籍就容易多了,祝大家学习轻松、学习快乐!希望本文能对你有一点点帮助。
附件:源程序
头文件程序*.h
//---------------------------------------------------------------------------
#ifndef openglexamH
#define openglexamH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <GL/gl.h>
#include <GL/glu.h>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TPanel *Panel1;
TButton *Button2;
TButton *Button3;
TButton *Button4;
TButton *Button5;
TButton *Button6;
TButton *Button7;
void __fastcall FormPaint(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall FormResize(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift);
void __fastcall Button2Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
HGLRC hRC;
HDC hDC;
void __fastcall IdleLoop(TObject*, bool&);
void __fastcall SetDCPixelFormat(HDC hDC);
void __fastcall RenderScence();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Cpp文件源代码:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "openglexam.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Application->OnIdle = IdleLoop;
hDC=GetDC(Form1->Panel1->Handle);//获取一个DC,
SetDCPixelFormat(hDC); //调整该DC的象素格式
hRC=wglCreateContext(hDC); //用这种DC去创建一个RC
wglMakeCurrent(hDC,hRC); //指定当前DC、当前RC为hDC、hRC
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdleLoop(TObject*, bool& done)
{
done = false;
TObject *Sender;
if(Sender==Button1)
Button1Click(Sender);
}
//----------------------------------------------------
void __fastcall TForm1::SetDCPixelFormat(HDC hDC)
{
//本函数用于调整DC的象素格式,如缓冲区、颜色数等
//先不深究,只要知道它的作用就行
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
, // Version of this structure
PFD_DRAW_TO_WINDOW | // Draw to Window (not to bitmap)
PFD_SUPPORT_OPENGL | // Support OpenGL calls in window
PFD_DOUBLEBUFFER, // Double buffered mode
PFD_TYPE_RGBA, // RGBA Color mode
, // Want 24bit color
,,,,,, // Not used to select mode
,, // Not used to select mode
,,,,, // Not used to select mode
, // Size of depth buffer
, // Not used to select mode
, // Not used to select mode
PFD_MAIN_PLANE, // Draw in main plane
, // Not used to select mode
,, }; // Not used to select mode
// Choose a pixel format that best matches that described in pfd
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
// Set the pixel format for the device context
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
//-----------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
glClearColor(0.5,0.7,0.9,1.0); //指定背景颜色(依次为RGBA)
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(hDC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
wglMakeCurrent(NULL,NULL);//取消当前RC和当前DC
wglDeleteContext(hRC);//删除该RC
DeleteObject(hDC);//删除Windows DC。
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RenderScence()
{
glClearColor(0.5,0.7,0.9,1.0); //指定背景颜色(依次为RGBA)
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0,0.0,0.0);
glVertex3f(-1.0,0.0,0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0,1.0,0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(1.0,0.0,0.0);
glEnd();
SwapBuffers(hDC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
RenderScence();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
glClearColor(0.5,0.7,0.9,1.0); //指定背景颜色(依次为RGBA)
glClear(GL_COLOR_BUFFER_BIT); //用背景色清窗口
SwapBuffers(hDC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
glClearColor(0.5,0.7,0.9,1.0); //指定背景颜色(依次为RGBA)
glClear(GL_COLOR_BUFFER_BIT); //用背景色清窗口
//glFlush();
SwapBuffers(hDC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
glTranslatef(,);
RenderScence();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
glRotatef(-, 1.0, 0.0, 0.0);
RenderScence();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{
glRotatef(, 1.0, 0.0, 0.0);
RenderScence();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
glRotatef(-, 0.0, 1.0, 0.0);
RenderScence();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
glRotatef(, 0.0, 1.0, 0.0);
RenderScence();
}
//---------------------------------------------------------------------------
如何在C++ Builder中使用OpenGL的更多相关文章
- 如何在Report Builder中使用fnd_profile.value
在EBS的Report开发中,需要根据客户化的一个Profile来控制用户可以访问的数据,可是在开发的过程中发现一直取不到该Profile的值,后来百度才找到了原因. 解决方法: 1.添加用户参数p_ ...
- 在MFC框架中使用OpenGL的简单实例
引言 我们知道,在MFC框架中,用于绘图的接口是GDI.但GDI只能绘制简单的2D图形,要想制作精美的3D图形,一个可行的办法是使用OpenGL或者Direct3D等第三方库. 由于最近在给导师的一个 ...
- VS2010中配置OpenGL
下面将对VS2010中配置OpenGL进行简单介绍. 学习OpenGL前的准备工作第一步,选择一个编译环境现在Windows系统的主流编译环境有Visual Studio,Broland C++ Bu ...
- vs2010中配置OpenGL以及针对64位系统所遇问题的解决办法
一.下面将对VS2010中配置OpenGL进行简单介绍. 学习OpenGL前的准备工作 第一步,选择一个编译环境 现在Windows系统的主流编译环境有Visual Studio,Broland C+ ...
- 《MFC dialog中加入OpenGL窗体》
<MFC dialog中加入OpenGL窗体> 最近学习了如何在MFC对话框程序中加入OpenGL窗体的方法,在这里将自己的实现过程归纳一下. 步骤零: 加入PictureControl控 ...
- 如何在 Visual Studio 中使用 Git 同步代码到 CodePlex
开源社区不管在国内还是国外都很火热,微软也曾因为没有开源而倍受指责,但是随着 .Net framework.ASP.Net MVC等框架的逐渐开源,也让大家看到了微软开源的步伐.CodePlex 则是 ...
- VC 6中配置OpenGL开发环境
2010,2012中配置类似 http://hi.baidu.com/yanzi52351/item/f9a600dffa4caa4ddcf9be1d VC 6中配置OpenGL开发环境 这里,我习惯 ...
- 如何在Linux服务器中隐藏PHP版本
通常,大多数默认设置安装的web服务器存在信息泄露,这其中之一就是PHP.PHP 是如今流行的服务端html嵌入式语言(之一?).在如今这个充满挑战的时代,有许多攻击者会尝试发现你服务端的漏洞.因此, ...
- [Laravel-Swagger]如何在 Laravel 项目中使用 Swagger
如何在 Laravel 项目中使用 Swagger http://swagger.io/getting-started/ 安装依赖 swagger-php composer require zirco ...
随机推荐
- Java依据Url下载图片
package com.ronniewang.downloadpicture; import java.io.DataInputStream; import java.io.File; import ...
- C# 线程知识--使用Task执行异步操作
在C#4.0之前需要执行一个复杂的异步操作时,只能使用CLR线程池技术来执行一个任务.线程池执行异步任务时,不知道任务何时完成,以及任务的在任务完成后不能获取到返回值.但是在C#4.0中引人了一个的任 ...
- js:深闭包(范围:上)
/** * 范围封锁 */ fn1(); //fn1 您可以运行,没有报错,对于由function func_name()这样的写法来定义的函数,永远都会被最先初始化. function fn1( ...
- Leetcode dfs Combination SumII
Combination Sum II Total Accepted: 13710 Total Submissions: 55908My Submissions Given a collection o ...
- django csrf_token生成
django模板中生成csrf_token的不同方式 系统环境 CENTOS 6.4 python 2.7.6 django 1.7.1 当post提交表单的的时候,是需要 csrf_token的, ...
- python_基础学习_04_mysql库验证与安装(mysql-python,mysql.connector)
验证python-mysql是否安装 1:python 2: import MySQLdb 安装步骤: 1.sudo apt-get install python-setuptools 2.sudo ...
- 位记录——Windows 7已安装Sublime Text 3、cynwin、SublimeClang
转载请注明出处:http://blog.csdn.net/cywosp/article/details/34429697 1. 到https://www.cygwin.com/下载setup-x86_ ...
- js 正则练习之语法高亮
原文:js 正则练习之语法高亮 学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解.今天就分析下 次碳酸钴 和 Barret Lee 语法高亮实现. 先 ...
- CentOS修改用户密码方法
CentOS修改用户密码方法 CentOS修改用户密码方法 1. 普通用户 a. 获取超级用户root权限 命令:su或者su -或者su - root b. passwd 用户名 2. 超级用户 a ...
- Python的html和xml解析库Beautiful Soup
网站:http://www.crummy.com/software/BeautifulSoup/ 版权声明:本文博主原创文章,博客,未经同意不得转载.