opengl详解.docx

上传人:b****6 文档编号:8848306 上传时间:2023-02-02 格式:DOCX 页数:64 大小:38.38KB
下载 相关 举报
opengl详解.docx_第1页
第1页 / 共64页
opengl详解.docx_第2页
第2页 / 共64页
opengl详解.docx_第3页
第3页 / 共64页
opengl详解.docx_第4页
第4页 / 共64页
opengl详解.docx_第5页
第5页 / 共64页
点击查看更多>>
下载资源
资源描述

opengl详解.docx

《opengl详解.docx》由会员分享,可在线阅读,更多相关《opengl详解.docx(64页珍藏版)》请在冰豆网上搜索。

opengl详解.docx

opengl详解

[OPENGL怎么用]

OPENGL编程类似C编程,实际接口就是C,所以熟悉C是必要的

一般编程可用到的函数库包括:

OPENGL实用库:

函数以glu开头

OPENGL辅助库:

函数以aux开头

Windows专用函数库:

函数以wgl开头

Win32API:

无专用前缀

OPENGL中有115个核心函数,可以在任何OPENGL平台上使用

OPENGL实用库比上面这115个函数高一级,提供高级调用

OPENGL辅助库本来是提供初学者入门的函数,不保证在任何平台的使用

但恰好可以在WIN32下使用,所以本讲座将大量引用

WIN32下OPENGL编程有两个方便途径:

1使用辅助库

2使用C++基于消息驱动的编程

显然1要简单一些,入门从这里开始吧。

[用之前的准备]

1

首先你需要下列*.lib包含在你的工程中:

opengl32.libglu32.libglaux.lib

本讲座所有例子“将”在VC5下调试通过,所以从

project->setting->link->general->object/libarymodules

中加入上面三个*.lib

(这些LIB,VC4以上版本已经自带,加入即可,不用在四处搜寻文件)

2

另外在你的运行程序路径下或\win95\system\下你需要一些*.dll动态连接库

opengl32.dllglu32.dllrxddi.dllmga.drv

第一讲

[编程入门]

这里我将给出一个小例子让大家熟悉用辅助库的编程结构:

 

//GLOS.H

//////////////////////////////////////////////////////////

//ThisisanOSspecificheaderfile

//判别操作系统的基本头文件

 

#include

 

//disabledataconversionwarnings

 

#pragmawarning(disable:

4244)//MIPS

#pragmawarning(disable:

4136)//X86

#pragmawarning(disable:

4051)//ALPHA

//////////////////////////////////////////////////////////

//opengl.cpp

//主程序

#include"glos.h"

#include

#include

#include"windows.h"

 

voidmain(void)

{

/*初始化:

*/

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);

//窗口显示单缓存和RGB(彩色)模式

auxInitPosition(0,0,500,500);

//大小x=500y=500(0,0)是屏幕左上点

auxInitWindow("sample1");

//窗口初始化,参数是标题

glClearColor(0.0,0.0,0.0,0.0);

//将窗口清为黑色

glClear(GL_COLOR_BUFFER_BIT);

//将颜色缓存清为glClearColor命令所设置的颜色

//即背景色

 

/*绘图*/

glColor3f(1.0,0.0,0.0);

//选颜色(R,G,B),参数0

glRectf(-0.5,-0.5,0.5,0.5);

//画个方块

 

glFlush();

//强制绘图,不驻留缓存

_sleep(1000);

//windows函数,显示1秒(单位是毫秒)

}

//endofsample

根据注释,应该看出程序功能:

显示红色方块(2D)一秒钟。

主程序结构不外乎:

初始化+绘图+其它功能调用,现在不用过分追究函数细节,知道是干什么的就可以乐,好吗?

我想结束本节前让大家实现第一个3D的例子,很简单而且好看的,但是我们必须被迫不得不多学些东东:

第二讲

1.OPENGL函数、变量命名准则

 

变量:

前缀类型对应C变量

b8-bitintsignedchar

s16-bitintshort

i32-bitintlong

f32-bitfloatfloat

d64-bitfloatdouble

ub8-bitunsignedintunsignedchar

us16-bitunsignedintunsignedshort

ui32-bitunsignedintunsignedlong

例如1.0f实际就是1.0,一般写成1.0f看上去好辨认一些。

 

函数:

函数参数类型作为函数后缀

例如:

glVertex2i(2,4)表明是opengl基本函数(gl-)

是绘点的函数(-Vertex-)

是两个整型参数(-2i)

将来对一个函数掐头去尾就知道它是干什么的乐。

 

2.CALLBACK函数

是一些用来让系统调用的函数,系统要调用它们,例如显示、接受键盘输入...

你就好比擂积木一样把它们列在主程序初始化后(顺序一般无关紧要),

系统会自动执行它们,例如:

voidCALLBACKdisplay(void)中你写好乐想画什么东东,然后主程序中使用auxMainLoop(display);就可以让这个东东一直显示乐,很类似VC中的OnPaint()

 

3.OPENGL基本库的绘图方法

 

glBegin(类型);

glColor3f(...);

glVertex(...)

glColor3f(...);

glVertex(...);

...

glEnd();

 

先由“类型”指定画什么平面:

GL_POINTS单个顶点集

GL_LINES多组线,2个点一条线

GL_GL_POLYGON单个简单填充凸多边形

GL_TRAINGLES多组三角型,3个点一个三角

..用到在说吧(自己可以在VCHELPINDEX中查找)

//////////////////////////////////////////////////////

//sample.cpp

 

#include"glos.h"

#include

#include

#include"windows.h"

 

voidmyinit(void);

voidCALLBACKdisplay(void);

voidCALLBACKreshape(GLsizeiw,GLsizeih);

//这里不用管reshape(),只是一个用于窗口改变大小时的处理

//与绘图无关,后面会讲到

//这里的重点是display(),请注意绘图的方法

voidmyinit(void)

{

/*初始化:

*/

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);

//窗口显示单缓存和RGB(彩色)模式

auxInitPosition(0,0,500,500);

//大小x=500y=500(0,0)是屏幕左上点

auxInitWindow("sample1");

//窗口初始化,参数是标题

glClearColor(0.0,0.0,0.0,0.0);

//将窗口清为黑色

glClear(GL_COLOR_BUFFER_BIT);

//将颜色缓存清为glClearColor命令所设置的颜色

//即背景色

}

 

voidCALLBACKreshape(GLsizeiw,GLsizeih)

{

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if(w<=h)

glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,

20.0*(GLfloat)h/(GLfloat)w,-50.0,50.0);

else

glOrtho(-20.0*(GLfloat)h/(GLfloat)w,

20.0*(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

voidCALLBACKdisplay(void)

{

glBegin(GL_TRIANGLE_STRIP);//画连续填充的多个三角

glColor3f(1.0,0.0,0.0);

glVertex3f(15.0,0.0,0.0);

glColor3f(0.0,1.0,0.0);

glVertex3f(-15.0,0.0,0.0);

glColor3f(0.0,0.0,1.0);

glVertex3f(0.0,15.0,15.0);

//第一个三角

glColor3f(0.0,1.0,1.0);

glVertex3f(10.0,15.0,-15.0);

//第二个三角

glColor3f(1.0,1.0,0.0);

glVertex3f(15.0,0.0,0.0);

//第三个三角

glEnd();

glFlush();

}

 

voidmain(void)

{

myinit();

auxReshapeFunc(reshape);

auxMainLoop(display);

}

//endofsample

所谓连续填充就是1、2、3点组成三角1

2、3、4点组成三角2...

这里一共画乐3个向连接的彩色三角,组成乐一个由三个彩色平面围成的空心三角椎...enjoyit

第三讲

上回书说道有个reshape需要进一步讲解这个函数功能是对用户改变窗口大小的操作进行一些重绘的动作(类似VC中的OnResize)。

其中用到了一些变换的概念我希望大家已经具备初步的计算机图形学的知识,这将有利于这部分的理解。

如果还没有,也没关系,我尽量讲解的通俗一些对于3D绘图,把其中3D坐标写成齐次坐标系后,是4*4的矩阵形式(详细…………………………………………………………

可以参阅相关文献,后面也会讲到。

)任何投影、旋转...操作都可以看成是矩阵相乘的操作。

矩阵操作----这个概念一定要形成!

例如在2D中普通的旋转变换,可以写成:

|cosθsinθ0|

[x'y'1]=[xy1]|-sinθcosθ0|

|001|

3D中道理完全一样,一个3D图形的显示包括下面步骤:

1.视点变换(将相机放在合适的地方对准3D景物)

2.模型变换(将3D物体放在合适的地方)

3.投影变换(将相机镜头调整,使3D景物投影在2D胶片上)

4.视口变换(决定胶片大小)

其中1、2并没有本质区别。

里面有几个关键性函数:

 

一几何变换

1.

voidglTranslated(

GLdoublex,

GLdoubley,

GLdoublez

);

voidglTranslatef(

GLfloatx,

GLfloaty,

GLfloatz

);

目标沿XYZ轴平移xyz

 

2.

voidglRotated(

GLdoubleangle,

GLdoublex,

GLdoubley,

GLdoublez

);

voidglRotatef(

GLfloatangle,

GLfloatx,

GLfloaty,

GLfloatz

);

目标分别以XYZ轴为轴逆时针旋转xyz

 

3.

voidglScaled(

GLdoublex,

GLdoubley,

GLdoublez

);

voidglScalef(

GLfloatx,

GLfloaty,

GLfloatz

);

目标在XYZ方向缩放,缩放因子为xyz

二投影变换

 

1.正射投影(即没有“近大远小”)

voidglOrtho(GLdoubleleft,GLdoubleright,GLdoublebottom,GLdoubletop,

GLdoublenear,GLdoublefar)

创建一个平行视景体(的矩阵),即投射线是平行线,把第一个矩形

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

视景投影到第二个矩形视景上。

并用这个矩阵乘以当前矩阵,以完成变换。

近景第一个矩形的左上角三维空间坐标(left,bottom,-near),右下角的三维空间坐标(right,top,-near);

远景第二个矩形左上角三维空间坐标(left,bottom,-far),右下角的三维空间坐标(right,top,-far);

 

2.透射投影(“近大远小”)

voidglFrustum(

GLdoubleleft,

GLdoubleright,

GLdoublebottom,

GLdoubletop,

GLdoubleznear,

GLdoublezfar

);

创建一个型如棱台的视景体,其近截取面由leftrightbottomtopznear

确定,远截取面由从视点投影近截取面到Z轴zfar位置决定

 

三视口变换

voidglViewport(GLintx,GLinty,GLsizewidth,GLsizeheight);

这个函数定义一个视口,x和y是视口在屏幕窗口坐标系中左上坐标

缺省是(0,0)。

widthheight是宽和高。

注意使用中视口长宽比例的调整会导致图象变形。

因此reshape()中

要检测窗口尺寸,修正视口大小,保证图象不变形。

 

附:

voidglMatrixMode(GLenummode);

把当前矩阵转换为指定的矩阵类型

 

这三个函数的利用见例子中的中文说明:

////////////////////////////////////////////////////////////

//sample.cpp

#include"glos.h"

#include

#include

#include"windows.h"

voidmyinit(void);

voidCALLBACKdisplay(void);

voidCALLBACKreshape(GLsizeiw,GLsizeih);

/////////////////////////////////////////////////////////////

voidmyinit(void)

{

/*初始化:

*/

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);

//窗口显示单缓存和RGB(彩色)模式

auxInitPosition(0,0,500,500);

//大小x=500y=500(0,0)是屏幕左上点

auxInitWindow("sample1");

//窗口初始化,参数是标题

glClearColor(0.0,0.0,0.0,0.0);

//将窗口清为黑色

glClear(GL_COLOR_BUFFER_BIT);

//将颜色缓存清为glClearColor命令所设置的颜色

//即背景色

}

//////////////////////////////////////////////////

voidCALLBACKreshape(GLsizeiw,GLsizeih)

{

//设定视口XY方向不要大于500单位

if(w<=500&&h<=500)

glViewport(0,0,w,h);

if(w>500&&h<=500)

glViewport(0,0,500,h);

if(w<=500&&h>500)

glViewport(0,0,w,500);

if(w>500&&h>500)

glViewport(0,0,500,500);

 

//进入世界坐标系,准备变换

//必要的步骤,初始化变换矩阵步骤:

1确定类型2清成单位阵

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

 

//定义一个合适的视景体

if(w<=h)

glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,

20.0*(GLfloat)h/(GLfloat)w,-50.0,50.0);

else

glOrtho(-20.0*(GLfloat)h/(GLfloat)w,

20.0*(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);

 

//把变换结果返回视点坐标系

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

//////////////////////////////////////

//画三棱锥,功能同上一讲

voiddraw(void)

{

glBegin(GL_TRIANGLE_STRIP);

glColor3f(1.0,0.0,0.0);

glVertex3f(15.0,0.0,0.0);

glColor3f(0.0,1.0,0.0);

glVertex3f(-15.0,0.0,0.0);

glColor3f(0.0,0.0,1.0);

glVertex3f(0.0,15.0,15.0);

//

glColor3f(0.0,1.0,1.0);

glVertex3f(10.0,15.0,-15.0);

//

glColor3f(1.0,1.0,0.0);

glVertex3f(15.0,0.0,0.0);

//

glEnd();

}

////////////////////////////////////////

voidCALLBACKdisplay(void)

{

//按上个例子中方法画第一个三棱锥

glClearColor(0.0,0.0,0.0,1.0);

glClear(GL_COLOR_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0.0,0.0,-25.0);

draw();

 

//开始画第二个三棱锥

//变换开始,清变换矩阵为单位阵

glLoadIdentity();

//先沿XYZ平移-5-10-4,屏幕上看就是向左下移动

//Z方向由于是平行投影,没有“近大远小”所以看不出效果

glTranslatef(-5.0,-10.0,-4.0);

//再沿Z轴转90度

glRotatef(90,0.0,0.0,1.0);

draw();

 

//绘图工作完成,强制绘图结束

glFlush();

}

 

voidmain(void)

{

myinit();

auxReshapeFunc(reshape);

auxMainLoop(display);

}

 

//sampleendshere

/////////////////////

如果大家运行一下就知道上述函数的作用,无非是把物体移动、转动、变形缩放、透视...

我想有了前3讲,OPENGL的基本原理已经如此了它就是提供了一个标准的计算机图形学所使用的数学模型到显示的接口,只要具备图形学知识,掌握OPENGLAPI函数使用,绘图很EASY啦基础部分已经完毕,慢慢再来谈高级一些的绘图功能如:

纹理、光源、动画...

真诚希望大家提提意见和高论

第四讲

前面三篇文章已经把OPENGL的编程基本结构描述完毕。

以后会在这个基础上逐渐深化,不断增添新内容。

这一篇是讲述键盘操作和动画基础(实际还差的远哪)。

只是个简单的能由用户控制的动画,让物体前后移动,左右旋转。

是我们自己的第一个QUAKE!

当然这个版本谁买谁上当,呵呵。

这篇的另一个目的就是加深前面对于CALLBACK函数的认识以及对于变换的直观解释,任何变换你都可以从屏幕上通过自己的操作看出来:

我只把和以前变化的部分标记中文解释

 

////////////////////////////////////////////////////

//sample.cpp

#include"glos.h"

#include

#include

#include"windows.h"

 

voidmyinit(void);

voidCALLBACKdisplay(void);

voidCALLBACKreshape(GLsizeiw,GLsizeih);

 

//注意到乐吗?

这里新加乐4个CALLBACK函数

//类似display()reshape(),也由主函数调用它们

//实现对键盘输入的响应

voidCALLBACKleft(void);//按LEFT

voidCALLBACKright(void);//按RIGHT

voidCALLBACKup(void);//按UP

voidCALLBACKdown(void);//按DOWN

 

//两个全局变量,z_motion用来控制物体远近

//rotate用来控制物体旋转

staticintz_motion=0,rotate=0;

 

voidmyinit(void)

{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);

auxInitPosition(0,0,500,500);

auxInitWindow("sample1");

glClearColor(0.0,0.0,0.0,0.0);

glClear(GL_COLOR_BUFFER_BIT);

}

 

voidCALLBACKr

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1