OpenGL
FAQ
(
2002/04/03
)
http://www.chinagamedev.net
http://bbs.chinagamedev.net
参与者:
NewCyber3D.com
、
LangFox
、
mays
、
xnp
、
Qian Jingping
问:我想看英文常见问题解答,有没有?
答:
http://www.opengl.org/developers/fa...aq.webvena.com/
问:
OpenGL
中的
Stencil Buffer
是什么东西?
答:模板缓存(
Stencil Buffer
)。它可以保持屏幕上某些部位的图形不变,而其它部位仍然可以进行图形绘制。比方说,可以通过模板缓存来绘制透过汽车挡风玻璃观看车外景物的画面。首先,将挡风玻璃的形状存贮到模板缓存中去,然后再绘制整个场景。这样,模板缓存挡住了通过挡风玻璃看不见的任何东西,而车内的仪表及其它物品只需绘制一次。因此,随着汽车的移动,只有外面的场景在不断地更改。
问:我如何将
3D
文件转换成
OpenGL C
程序?
答:
3DWin/3D to 3D
,它能将多种
3D
格式互相转换,还可以转存成
Opengl C
程序。网站:
http://www.stmuc.com/thbaier/tools.html
问:
glos.h
是什么文件?
答:判别操作系统的头文件。
问:
OpenGL
的左右缓冲区如何使用?即:
gldrawbuffer()
中的,
GL_RIGHT
、
GL_LEFT
参数的使用。我想做一副立体图,(两副图像交替在屏幕上不停刷新)。
图形加速卡选用的是华硕的
3800
带立体镜的那一种。
答:这需要看驱动程序是否支持
OpenGL
的左右缓冲区。据我们所知,华硕显卡不带这样的驱动。而象
Diamond Fire GL
系列、
ELSA
的
Glorial
系列等显卡支持这种功能。在购买显卡时,应认清驱动程序的支持性能。
问:请问用在
OpenGL
编程中有哪些方法可以得到两个曲面的交线?
答:
OpenGL
用于绘制图形,没有交线计算,需要自行开发算法。
问:关于
OpenGL
中雾的问题。
答:首先我想说一下
OpenGL
中雾的定义,
OpenGL
中雾的模式有三种:
GL_LINEAR
,
GL_EXP
,
GL_EXP2
。以
GL_LINEA
为例:雾的混合因子
f(0=<=1)
的计算公式为
f=(end-z)/(end-start)
。其中
start
和
end
为程序设置的雾的起点和终点(即
glFogf(GL_FOG_START,start); glFogf(GL_FOG_END,end);
)。最值得关注的是
z
的定义。我手头上有好几本
OpenGL
的参考书,但介绍了雾的定义的却只有两本。在《
OpenGL
编程实例与技巧》(吴斌
毕丽蕴
编著)中,他们认为
“z
表示视点与图元中心的观察坐标之间的距离
”
。在《
OpenGL
深入编程与实例揭秘》(彭晓明
王坚
编著)中,他们认为
“z
是像素或顶点在眼坐标系中的
z
坐标分量值(总为负值)
”
。在
VC++
的联机帮助中说的是
“Let z be the distance in eye coordinates from the origin to the fragment being fogged. ”
。如果所绘制的物体不大(比如长和宽都为
1
个单位的矩形),那么上面所说的都可以近似为:
z
就是视点与物体在观察坐标之间的距离(负值)。当绘制的物体很大时(比如长和宽都为
200
个单位的矩形),我认为上面的说法都值得探讨。我认为
z
可能是
“
视点与绘制物体边缘在观察坐标之间的最近距离(负值)
”
,上次我绘制图形时绘制了几个很大的物体,所以当我移动物体时,雾的效果并不是近处清晰,远处模糊。我想如果把大的物体划分为很小的物体进行绘制,就可以解决问题。
问:请问画树时如何将树设置为透明格式?
答:可以使用融合的方法。
问:我在做一个虚拟场景时是用
Bezier
曲面拟合环境中的曲面,然后再贴以纹理,但我发现这样极其占用系统资源,而且我用了显示列表来处理。我想请教一下有没有什么别的方法来拟合曲面而不是那么占用系统资源,或者是我的用法不对。
答:当然不能用
Bezier
曲面拟合环境中的曲面,
Bezier
曲面需要大量的计算。最好的办法是直接获得曲面的顶点,采用
TRANGLES
或四边形来绘制。
问:我已经做好了一个视景,现在要做它的后视景,但是有个问题就是后视景并不能由前视景简单的经过旋转
180
度得到(因为后视的原理是以镜平面对称),例如现在将视景绕
Y
轴(视景坐标系)旋转
180
度,出来的效果是左边的物体到右边而右边的物体到左边了,所以也不符合,现在想请教一下有没有比较简便些的算法来实现这个后视景问题。
答:这个问题不只是旋转坐标轴,而是镜面反射编程,你可网上有关编程示例。
问:我用
OpenGL
画曲面,原始数据通过打开数据文件获取,但为什么打开一个数据文件画好后,紧接着打开另一个文件再画时,其形状和颜色都受第一次的曲面影响?为什么我的曲面重画(刷新视区)后变成了坐标系中的平面?即各点
Z
坐标的值表面上看似乎变的相等了?
答:显然你没有重新设置颜色。至于形状,检查坐标数组。检查
Z
轴坐标值。另外,注意几何变换
PushMatrix
和
PopMatrix
。
问:如何通过屏幕坐标获取物体三维坐标?
答:使用
gluUnProject
函数。
问:如何在
OpenGL
中将显示列表的文本用字体对话框控制?
答:在显示列表中就不能进行中间变化!用字体对话框控制字体,只能在显示列表之前。
问:导入
3D
模型文件为什么总是不能很好的倒入纹理贴图,有什么办法可以很好的导入一个完整的
3D
模型文件?
答:这种情况一般都是由于纹理坐标错误。读带纹理
3DS
格式模型一般比较复杂,需要时间理解透彻才行,暂时可以用材质(不含纹理)代替。借鉴网上一些免费纹理模型贴图的示例也行呀。
问:我的工程将视区分为两个后(加了一个
FormView
窗体,用于放一些控制图形缩放的控件,这样它于绘图窗口共享原来的视区)为什么用
OpenGL
画的图不见了?我需要注意什么?错在那里?
答:注意设置好象素格式。
问:
我自己绘的四边形片怎么原来有边框和界限即一个个的小方格,现在运行程序后突然变成了一条没有任何界限的色带?程序片段如下:
glPolygonMode(GL_FRONT,GL_FILL); 111
glBegin(GL_QUAD_STRIP);
for(i=0;i<=HEIGHTNUMBER;i++)
{
glVertex3f(base,Ybase- i*Yalphe,0.0);
glColor3f(m_getMinR+i*Redalphe,
m_getMinG+i*Greenalphe,m_getMinB+i*Bluealphe);
}
glEnd();
答:调用了
glPolygonMode
的填充方式,当然变成色带。
问:用
OpenGL
做人体动画合适吗?
答:做动画可用
3DSMAX
这样的动画软件。而实时开发则需要
OpenGL
。
OpenGL
是很好的三维图形库,当然做人体动画需要比较复杂的编程。
问:
OpenGL Extension
是什么?
答:
Extension
是
OpenGL
的扩展库,各硬件厂家为了更好地发挥自己的芯片的图形性能,驱动程序支持许多特别有用的扩展库。当然,
SGI
和微软力求统一标准,无奈象
TNT2
这样的芯片产量太大,所以厂家完全可以自行其是。为此,扩展库的支持种类、支持程度与计算机中的图形卡及其驱动程序有关。象
SGI NT
工作站完全支持
SGI
发布的所有扩展库,
nVIDIA TNT2
图形芯片一般都支持
nVIDIA
的扩展库。所支持的扩展库名称可在驱动程序显示高级设置中看到。目前
ELSA
这样的图形卡的性能较为优越,其
nVIDIA GeForce2
为芯片的图形卡所支持的扩展库相对比较完整。
问:在
OpenGL
中,房间漫游时总是要
“
穿墙而过
”
,下楼梯时总是悬浮在半空中。请教解决办法。
答:这需要图形学中的
“
碰撞检测
”
方法,具体过程比较复杂并很有技巧性。自己到网上看看吧。
问:请问在
OpenGL
的辅助库函数中是否有可以将所绘图形存为位图的函数?我想把所绘图形存为位图格式,有哪些方法?
答:没有现成的函数,自己写吧。
问:在标准
C
语言下,可用
glBingTexture
来贴纹理(以便硬件加速),不知道在
Visual C++ 6.0
下为什么不行,还是我没考虑到某些什么?
答:检查函数的使用方法;正确安装
OpenGL1.1
,甚至
OpenGL1.2
。
问:
Delphi
和
Visual C++
都支持
OpenGL
,如果要编类似模拟飞行的程序,
哪个更容易一些,或者说
Delphi
和
Visual C++
哪个处理图形动画更快一些?
答:
Delphi
做界面比
VC
较容易,做算法较麻烦。但
VC
做算法和图形程序都会更好一些。
问:在进行编程时,我想把自己的三维模型或人体骨骼运动输出到
3DS
中,不知我可找到相应答案吗?
答:
3DS MAX
好象还不能直接接受外部运动数据,但它可以生成运动数据(使用一些插入件,网站里有),或者先有运动数据后,再设法输入到
3DSMAX
中。
问:我们知道通过一个点的三维坐标可很方便地计算出在二维屏幕上该点的二维坐标(用
OpenGL
编程更容易)。但反过来,在知道二维显示坐标的前提下怎样计算出三维坐标解集(应为一直线)?
答:这个问题可用
OpenGL
的
gluUnproject()
函数。
问:在
OpenGL
编程中,我遇到一个问题:在知道三自由度转角与臂长的前提下如何计算臂长端点的空间坐标
(x,y,z)
。我用
C
语言进行了编程,不知
OpenGL
中是否有相应的函数?
答:这个问题属计算问题,需要自行编程解决,
OpenGL
主要解决三维图形及效果的绘制问题。
问:请问如何解决大数据量的三维可视化的速度问题?除此之外还有没有别的办法?
答:
OpenGL
只是一个很好绘图渲染的库,大数据量的算法则需要自行编程实现。
问:我想做一个有关人体模型的三维重建的东西,该如何做呢?
答:关于三维重建的问题,由于国内还处于学术研讨层次上,我建议首先看一些有关论文,再考虑程序实现。
1
)医学图象三维重建及可视化技术研究
http://www.cad.zju.edu.cn/chinagrap...ot_QinXuJia.ppt
2
)科学计算视化及虚拟现实医学应用
http://www.cad.zju.edu.cn/chinagrap.../VisualHOT3.ppt
3
)应用数学研究室
研究室的主要研究方向有:工业
CT
图像重建的数学理论与算法。
http://www.biti.edu.cn/t_r/yy.htm
问:网上一些程序中用到的纹理图像并不是位图格式,而是以
bw
或
rgb
为扩展名的文件,不知用什么软件才能打开这些图形文件,并且我想问一下这些图形文件能否转换成位图格式?我用
Acdsee
和
Photoshop
都打不开。
答:可以用
Acdsee2.4
版打开
rgb
格式图象文件,你也可直接在
OpenGL
程序中使用
bmp
文件,可查
glu.h
中的
image
宏。
问:请问在
OpenGL
下如何画凹多边形,若分解为三角形,则不能使用
glPolygonMode
功能,有什么办法解决。
答:一般都要预处理,保证不出现凹多边形,但
OpenGL
也提供了一种处理方法,即
Tesselation
分化方法,但占内存大,影响速度性能,不宜使用。
问:如何解决由于
Win
系统不支持
spong
平滑模式
导致曲面镜面光不平滑的问题?
答:需要材质、网格密度与
SMOOTH
绘制模式结合。
问:如何锁定图形中部分图形对象
,
而只对某些对象进行操作?
答:对每个对象命名(可用
OpenGL
中的显示列表方法),然后分别控制就可。
问:有关
OpenGL
的颜色操作与纹理,材质和光照之间的关系。
答:说来话长,需好好看书。
问:在拾取操作过程中,整个显示列表是否不起作用?如果要对单个地物进行操作时,是否必须单个进行建立显示列表?
答:显示列表与内存含义类似,一旦确定显示列表,其中的内容就不要改变;但可加速。
问:请问如何在不修改其他图形对象时,删除某些对象?
答:仍然用显示列表方法。
问:我要将一个人的照片用贴纹理的方法贴到一视景中,要使除人以外的部分要是透明的,而位图往往是矩形的,那么在编程如何才能让除人以外的部分透明呢?
答:可考虑使用
stencil
纹理贴图方法。
问:如何锁定图形中部分图形对象
,
而只对某些对象进行操作?
答:对每个对象命名(可用
OpenGL
中的显示列表方法),然后分别控制就可。
问:我在
OpenGL
中用一维求值器绘制
Bezier
曲线:
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();
该
Bezier
曲线是由
30
段
line
构成,我需要在场景中设置一个物体沿该曲线路径移动,
我怎么获得各个顶点的坐标值呢?反馈信息好象只包含窗口可见的顶点信息,有更好的办法吗?请赐教。
答:最直接的办法是你自己来计算(只是简单的
Matrix
变换)当然也是比较麻烦的;另外可以让
OpenGL
帮你算,方法是定出物体的坐标系沿着
Bezier
曲线移动后的新位置,这种移动可能不唯一(比如简单的平移或利用曲线的切平面和法平面来定义),所以你必须定出移动的规则,有了新的坐标系数据,可以
gl
相应的
Matrix,
就可以直接显示了,如果要求出实际的坐标(如果只是想显示是没有必要计算的),用
Matrix
去乘吧。
问:我现在遇到一个问题,就是用
OpenGL
来画出一个动态的海洋,波浪涌动。因为还要有船贴图似乎不行,而计算海平面的三维坐标值简直太麻烦了,巨量的点,复杂的法线
...
。最后一招,用
3DS MAX
画出来在加载进去,但格式转换也不容易。我该怎么做呢?
答:这个问题其实可以用很简单的方法解决。可用一个简单的四边形或格网构成海面框架,然后进行海面纹理贴图,让纹理动起来,不就有动态波浪海洋的场景了吗。在海面上的船可以继续加,各种变换照常进行。
问:在用
C++Builder
编写
OpenGL
程序时,在
Scene
窗口中,用鼠标移动物体,能否有办法知道移动后物体所在的坐标位置?用鼠标任意旋转物体,怎样知道该物体的旋转角度和方向等数值。即:物体初始位于原点,怎样把鼠标移动物体的视觉效应转化为精确的坐标变换?
答:需要建立一个新的三维坐标系,将视点、图像投影面(
Scene
窗口)以及物体等,一起定位与这个坐标系里。当鼠标移动时,延长视点与鼠标屏幕点的连线,使其相交与物体移动的面(假定使用二维鼠标,物体在
XY
或
YZ
或
ZX
或球面上移动),其交点就是物体移动后的坐标点。旋转角度则根据前后两次位置不同,计算出相对于某个旋转中心(如视点、物体中心点或坐标原点等)的旋转角度。
问:
MiniGL
与
OpenGL
的内容有什么不同?
答:
MiniGL
只是
OpenGL
的一个外包装,在它的内部是根据当前的显卡来决定实际的
OpenGL
驱动(如
PowerVR
、
3dfx
、
etc..
),
MiniGL
实际并不实现任何
OpenGL
功能。
问:在编写
OpenGL
的纹理程序时,函数
auxDIBImageLoad()
打开文件时返回
“
文件打开错误
”
,我希望了解调入位图的详细方法。
答:
1
)在调用该函数之前必须确认调入的图象是
BMP
格式,而且宽和高是
2
的
n
次幂。
2
)
OpenGL
中调入位图方法。
OpenGL
中调入位图作为纹理,关键是清楚位图文件的结构,对于
Windows
下的位图,一般从第
54
个字节处开始才是图形数据,下面是个例子:
int MakeTexture128(char *name,GLubyte Image[128][128][3] )
{
GLint index;
FILE *fp;
int i, j, r,g,b;
fp=fopen(name,"rb");
if(fp==NULL)
{
fprintf(stderr, "Cannot open input file./n");
}
fseek(fp,54L,0);
for (i = 0; i <128; i++)
{
for (j = 0; j < 128; j++)
{
r=fgetc(fp);
g=fgetc(fp);
b=fgetc(fp);
Image[i][j][0] = (GLubyte) b;
Image[i][j][1] = (GLubyte) g;
Image[i][j][2] = (GLubyte) r;
}
}
fclose(fp);
index =glGenLists(1);
glNewList(index,GL_COMPILE);
glTexImage2D(GL_TEXTURE_2D,0,3,128,128,0,GL_RGB,GL_UNSIGNED_BYTE,&Image[0][0][0]);
glEndList();
return index;
}
问:在
VC
中创建
OpenGL
应用程序时,需要连接
LIB
目录中的
opengl32.lib
、
glu32.lib
、
glaux.lib
这三个函数库。但我不知道该如何将这三个文件同我的程序连接起来,特请教。
答:可用二种方法:
1
)在
VC
的
Project->Setting->Link->Object/Library modules
中加入这三个库;
2
)在
VC
的
Project->Add to Project->Files
中加入这三个库。
3
)在你的源文件任何一个地方加入
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
同时,
glaux.lib
不推荐使用,推荐使用
glut
。包含
glut32.lib
的库。同时请下载
glut 3.7
的运行库和头文件。
问:在
OpenGL
的一个完整的变换过程中,要经过一系统的矩阵变换,其中第一步是取景变换,或者叫视点变换。请问一个完整变换过程是否只能有一个视点?而这个视点的任何变换(取景变换)是否对于场景中所有模型均产生作用?
答:对于一个视口(
Viewport
)而言只能有一个视点。视点的变换是否对场景中的模型起作用,还要看投影变换。