﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-漫步者-文章分类-3D图形学</title><link>http://www.cppblog.com/Walker/category/16509.html</link><description>先学会转文章，在仔细读文章，最后自己写点东西........</description><language>zh-cn</language><lastBuildDate>Sat, 16 Apr 2011 20:38:50 GMT</lastBuildDate><pubDate>Sat, 16 Apr 2011 20:38:50 GMT</pubDate><ttl>60</ttl><item><title>MFC下的OpenGL </title><link>http://www.cppblog.com/Walker/articles/144067.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Tue, 12 Apr 2011 12:33:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/144067.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/144067.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/144067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/144067.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/144067.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: MFC下的OpenGL 序：因为要做个2d地图编辑器，决定采用MFC，但是GDI不是很熟，google下终于完成基本MFC下的OpenGL1.首先建个MFC单文档2.加入外部库：opengl32.lib glu32.lib &nbsp; &nbsp;在XXView.cpp加入头文件 gl.h, glu.h3.在XXView.h加入如下代码:　　view ...&nbsp;&nbsp;<a href='http://www.cppblog.com/Walker/articles/144067.html'>阅读全文</a><img src ="http://www.cppblog.com/Walker/aggbug/144067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-12 20:33 <a href="http://www.cppblog.com/Walker/articles/144067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>opengl api介绍</title><link>http://www.cppblog.com/Walker/articles/144066.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Tue, 12 Apr 2011 12:22:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/144066.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/144066.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/144066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/144066.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/144066.html</trackback:ping><description><![CDATA[<font color=#0000ff size=4><strong>
<p><font color=#0000ff size=4><strong>glLoadIdentity()</strong></font></p>
<p><br>将当前的用户坐标系的原点移到了屏幕中心：类似于一个复位操作<br>1.X坐标轴从左至右，Y坐标轴从下至上，Z坐标轴从里至外。<br>2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。<br>3.中心左面的坐标值是负值，右面是正值。<br>&nbsp;&nbsp; 移向屏幕顶端是正值，移向屏幕底端是负值。<br>&nbsp;&nbsp; 移入屏幕深处是负值，移出屏幕则是正值。</p>
<p><font color=#0000ff size=4><strong>glTranslatef(x, y, z)</strong></font></p>
<p>沿着 X, Y 和 Z 轴移动。</p>
<p>注意在glTranslatef(x, y, z)中,当您移动的时候，您并不是相对屏幕中心移动，而是相对与当前所在的屏幕位置。其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。<br><br>画三角形之前调用的glTranslatef(x, y, z) 是为了让你所有的场景在可视区内。<br><br>因为opengl默认的摄像机位置在坐标原点（没有调用gluLookAt改变视图坐标系）， 方向是 Z负向。如果不把物体画在 -z 的区间上， 在此摄像机可视区内是看不到的。<br><br><br></p>
<p>/////////////////////////////////////////////////////////////////////////////////////////////////////////////</p>
<p><font color=#ff0000>glLoadIdentity();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font color=#ff0000>glTranslatef(-1.5f,0.0f,-6.0f);<br></font>glBegin(GL_TRIANGLES);<br>glVertex3f(0.0f,0.0f, 0.0f);<br>glVertex3f(1.0f,0.0f, 0.0f);<br>glVertex3f(0.0f,1.0f, 0.0f);<br>glEnd();</p>
<p><font color=#ff0000>glLoadIdentity();<br>glTranslatef(0.0f,0.0f,-6.0f);<br></font>glBegin(GL_TRIANGLES);<br>glVertex3f(0.0f,0.0f, 0.0f);<br>glVertex3f(1.0f,0.0f, 0.0f);<br>glVertex3f(0.0f,1.0f, 0.0f);<br>glEnd();</p>
<p>/////////////////////////////////////////////////////////////////////////////////////</p>
<p>程序的运行结果如下：</p>
<p>&nbsp;</p>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/zqw19891001/pic/item/eabde411c87b5cefa6ef3f79.jpg" small="0"></div>
<p>左边的三角形是第一步绘制的，可以看到该三角形绘制的坐标系，实际上是以(-1.5f,0.0f,-6.0f)为原点的。</p>
<p>第二个三角形绘制的时候，由于使用glLoadIdentity()使原点重新回到屏幕中心来，因此其原点位于屏幕的中心。</p>
<p><font color=#0000ff><font size=4><strong>glRotatef(<font color=#0000ff>angle, x, y, z</font>)</strong></font></font><br>与glTranslatef(x, y, z)类似，glRotatef(angle, x, y, z)也是对坐标系进行操作。<br>旋转轴经过原点，方向为(x,y,z),旋转角度为angle，方向满足右手定则。<br>////////////////////////////////////////////////////////////////<br>glLoadIdentity();<br>glTranslatef(0.0f,0.0f,-6.0f);<br>glBegin(GL_TRIANGLES);<br>glVertex3f(0.0f,0.0f, 0.0f);<br>glVertex3f(1.0f,0.0f, 0.0f);<br>glVertex3f(0.0f,1.0f, 0.0f);<br>glEnd();<br>////////////////////////////////////////////////////////////////<br>在未旋转的情况下如图所示：</p>
<p>&nbsp;</p>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/zqw19891001/pic/item/3c9a818bd8d683fafc1f1035.jpg" small="0"></div>
<p>////////////////////////////////////////////////////////////////<br>glLoadIdentity();<br><font color=#ff0000>glRotatef(45,0.0f,0.0f,1.0f);<br></font>glTranslatef(0.0f,0.0f,-6.0f);<br>glBegin(GL_TRIANGLES);<br>glVertex3f(0.0f,0.0f, 0.0f);<br>glVertex3f(1.0f,0.0f, 0.0f);<br>glVertex3f(0.0f,1.0f, 0.0f);<br>glEnd();<br>////////////////////////////////////////////////////////////////<br>绕Z轴正向旋转45度角，因为Z轴正方向由屏幕内指向屏幕外，由右手定则可知方向为逆时针转动。<br>由于直角顶点即为原点，因此将围绕直角逆时针旋转。</p>
<p>&nbsp;</p>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/zqw19891001/pic/item/7faf38c711f5d3f5d0006035.jpg" small="0"></div>
<p>////////////////////////////////////////////////////////////////<br>glLoadIdentity();<br><font color=#ff0000>glRotatef(45,0.0f,0.0f,1.0f);<br>glLoadIdentity();<br></font>glTranslatef(0.0f,0.0f,-6.0f);<br>glBegin(GL_TRIANGLES);<br>glVertex3f(0.0f,0.0f, 0.0f);<br>glVertex3f(1.0f,0.0f, 0.0f);<br>glVertex3f(0.0f,1.0f, 0.0f);<br>glEnd();<br>////////////////////////////////////////////////////////////////<br>在旋转之后加了一个复位的指令，图形就不会旋转了。<br><br>终于搞明白gluPerspective和gluLookAt的关系了<br><br>函数原型<br>gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);<br><br>gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)<br><br>一个一个来,首先得设置gluPerspective,来看看它的参数都表示什么意思<br>fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,<br>aspect,这个好理解,就是实际窗口的纵横比,即x/y<br>zNear,这个呢,表示你近处,的裁面,<br>zFar表示远处的裁面,<br><br>如果还没有理解就继续看,<br>我们知道,远处的东西看起来要小一些,近处的东西看起来会大一些,这就是透视原理<br>如下图所示<br></p>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/6d203a299bf5aef799250a2d.jpg" small="0"><br>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/493835fae74b34809e5146aa.jpg" small="0"></div>
<br><br>假设那两条线表示公路,理论上讲,它们的两条边是平行的,<br>但现实情况中,它们在远方(可以无限远)总要相交于一点,<br>实际线段AB的长度=CD的长度,只是在此例中使用了透视角,故会有如上的效果,是不是很接近现实的情况?<br><br>结合我们刚才这两个函数<br>zNear,眼睛距离近处的距离,假设为10米远,请不要设置为负值,OpenGl就傻了,不知道怎么算了,<br>zFar表示远处的裁面,假设为1000米远,<br>就是这两个参数的意义了,<br><br>再解释下那个"眼睛睁开的角度"是什么意思,<br>首先假设我们现在距离物体有50个单位距离远的位置,<br>在眼睛睁开角度设置为45时,请看大屏幕:<br>
<div forimg="1"><a href="http://hiphotos.baidu.com/kkun/pic/item/c68ac9ea62d178dad539c90c.jpg" target=_blank>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/746f352ab97c5e315343c10d.jpg" small="0"></div>
</a><br><br><font color=#000000>我们可以看到,在远处一个球,,很好玩哈,<br>现在我们将眼睛再张开点看,将"眼睛睁开的角度"设置为178<br>(180度表示平角,那时候我们将什么也看不到,眼睛睁太大了,眼大无神)<br></font>
<div forimg="1"><font color=#000000><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/102f01e9a22b6f36b80e2d17.jpg" small="0"></font></div>
<br><br>我们只看到一个点,,,,,,,,,,,,,,,,,,,,,,,,,,,<br>因为我们看的范围太大了,这个球本身大小没有改变,但是它在我们的"视界"内太小了,<br><br><br>反之,我们将眼睛闭小些,改为1度看看会出现什么情况呢?<br>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/ab45dab464dc607a8bd4b21e.jpg" small="0"><br><br>在我们距离该物体3000距离远,"眼睛睁开的角度"为1时,我们似乎走进了这个球内,这个是不是类似于相机的焦距?<br><br>当我们将"透视角"设置为0时,我们相当于闭上双眼,这个世界清静了,<br><br>我们什么也看不到,,,,,,,,,</div>
</div>
<br><br><br>现在来看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);<br><br>它共接受三对坐标,<br>分别为eye,center,up<br>故名思义,eye表示我们眼睛在"世界坐标系"中的位置,<br>center表示眼睛"看"的那个点的坐标,<br>最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可<br>球是画在世界坐标系的原点上的,即O(0,0,0)坐标上,我们的眼睛位于观察点A(0,0,100),Z轴向屏幕里看去的方向为负,屏幕外我们的位置,Z轴为正值,其实很好理解,即我们距离原点的距离,设置100,将观察到如下图所示的影像<br><a href="http://hiphotos.baidu.com/kkun/pic/item/c68ac9ea62d178dad539c90c.jpg" target=_blank>
<div forimg="1"><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/746f352ab97c5e315343c10d.jpg" small="0"></div>
</a><br><font color=#000000>如果我们向前或向后移动,则相应的图像会变大或变小,这里其实就是运用了透视原理,近处的物体大,远处的物体小,实际物体的大小是不变的,<br><br>同理改变center坐标(眼睛看去的那个点,可简单理解为视线的终点)也会影响球的大小,同样可以认为是改变了物体与观察点的距离所致,<br><br>最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可,我们指定0.1f或0.00001f异或1000.0f,效果是一样的,只要能表示方向即可,<br></font><a href="http://hiphotos.baidu.com/kkun/pic/item/c68ac9ea62d178dad539c90c.jpg" target=_blank></a><br><br><br><br><font color=#000000>以上理解了之后,来做一个测试<br>透视图不变,最远处仍为3000,近处为0.1<br><br></font><font color=#000000><em>gluPerspective&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 设置透视图<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (45,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 透视角设置为 45 度,在Y方向上以角度为单位的视野<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (GLfloat)x/(GLfloat)y,&nbsp;&nbsp;&nbsp; // 窗口的宽与高比<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0.1f,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 视野透视深度:近点1.0f<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 3000.0f&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // 视野透视深度:始点0.1f远点1000.0f<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; );</em><br><br>将我们的观察点置于A(0,10,0),<br>将观察位置(视线终点)坐标置于(0,0,0)<br>然后在原点开始绘图,画一个V字形,并将Z轴的值从-1000递增加到+1000,增量为10,<br>代码如下<br></font><em><br><font color=#000000>&nbsp;&nbsp;&nbsp; glColor3f(0.5f, 0.7f, 1.0f);<br><br>&nbsp;&nbsp;&nbsp; glBegin(GL_LINES);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i=-1000;i&lt;=1000;i+=10)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(0,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(10,10,i);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(0,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3f(-10,10,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; glEnd();<br></font></em><br><font color=#000000>F5运行效果如下图<br></font>
<div forimg="1"><font color=#000000><img class=blogimg border=0 src="http://hiphotos.baidu.com/kkun/pic/item/f1be800ad3acf337b1351dd9.jpg" small="0"><br><br></font>上图证实了我们的推测</div>
<br><br><br><br><br><br><br><br><br><br><br>//---------------------------------------------<br>&nbsp;&nbsp;&nbsp; //生成网络<br>&nbsp;&nbsp;&nbsp; glColor3f(0.5f, 0.7f, 1.0f);<br>&nbsp;&nbsp;&nbsp; int x=(int)(40*2);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; glBegin(GL_LINES);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i=-x;i&lt;=x;i+=4)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(-x,0,i);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(x,0,i);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(i,0,x);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; glVertex3i(i,0,-x);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; glEnd();<br><br>//生成球体<br>&nbsp;&nbsp;&nbsp; GLUquadricObj * pObj;<br>&nbsp;&nbsp;&nbsp; pObj = gluNewQuadric();<br>&nbsp;&nbsp;&nbsp; gluQuadricDrawStyle(pObj,GLU_LINE);<br>&nbsp;&nbsp;&nbsp; gluQuadricNormals(pObj,GLU_SMOOTH);<br>&nbsp;&nbsp;&nbsp; gluSphere(pObj,16,16,16);<br><br>glTranslatef(0.0f,-20.0f,-40.0f)表示将当前图形向x轴平移0，向y轴平移-20，向z轴平移-40<br>glScaled(10.0f,10.0f,10.0f)表示将当前图形沿x,y,z轴分别放大为原来的10倍<br>glRotatef(-80.0f,10.0f,1.0f,0.0f)表示将当前图形沿方向向量(-10,1,0)顺时针旋转80<br></div>
</strong></font>
<img src ="http://www.cppblog.com/Walker/aggbug/144066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-12 20:22 <a href="http://www.cppblog.com/Walker/articles/144066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>画旋转的四面体</title><link>http://www.cppblog.com/Walker/articles/144065.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Tue, 12 Apr 2011 12:16:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/144065.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/144065.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/144065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/144065.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/144065.html</trackback:ping><description><![CDATA[&nbsp;四面体由4个三角形组成<br>glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&nbsp;// Clear Screen And Depth Buffer<br>&nbsp;glLoadIdentity();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Reset The Current Modelview Matrix<br>&nbsp;glTranslatef(-1.5f,0.0f,-6.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Move Left 1.5 Units And Into The Screen 6.0<br>&nbsp;glRotatef(rtri,0.0f,1.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Rotate The Triangle On The Y axis ( NEW )<br>&nbsp;glBegin(GL_TRIANGLES);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Start Drawing A Triangle<br>&nbsp;&nbsp;glColor3f(1.0f,0.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Red<br>&nbsp;&nbsp;glVertex3f( 0.0f, 1.0f, 0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Top Of Triangle (Front)<br>&nbsp;&nbsp;glColor3f(0.0f,1.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Green<br>&nbsp;&nbsp;glVertex3f(-1.0f,-1.0f, 1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Left Of Triangle (Front)<br>&nbsp;&nbsp;glColor3f(0.0f,0.0f,1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Blue<br>&nbsp;&nbsp;glVertex3f( 1.0f,-1.0f, 1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Right Of Triangle (Front)<br>&nbsp;&nbsp;glColor3f(1.0f,0.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Red<br>&nbsp;&nbsp;glVertex3f( 0.0f, 1.0f, 0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Top Of Triangle (Right)<br>&nbsp;&nbsp;glColor3f(0.0f,0.0f,1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Blue<br>&nbsp;&nbsp;glVertex3f( 1.0f,-1.0f, 1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Left Of Triangle (Right)<br>&nbsp;&nbsp;glColor3f(0.0f,1.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Green<br>&nbsp;&nbsp;glVertex3f( 1.0f,-1.0f, -1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Right Of Triangle (Right)<br>&nbsp;&nbsp;glColor3f(1.0f,0.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Red<br>&nbsp;&nbsp;glVertex3f( 0.0f, 1.0f, 0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Top Of Triangle (Back)<br>&nbsp;&nbsp;glColor3f(0.0f,1.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Green<br>&nbsp;&nbsp;glVertex3f( 1.0f,-1.0f, -1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Left Of Triangle (Back)<br>&nbsp;&nbsp;glColor3f(0.0f,0.0f,1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Blue<br>&nbsp;&nbsp;glVertex3f(-1.0f,-1.0f, -1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Right Of Triangle (Back)<br>&nbsp;&nbsp;glColor3f(1.0f,0.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Red<br>&nbsp;&nbsp;glVertex3f( 0.0f, 1.0f, 0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Top Of Triangle (Left)<br>&nbsp;&nbsp;glColor3f(0.0f,0.0f,1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Blue<br>&nbsp;&nbsp;glVertex3f(-1.0f,-1.0f,-1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Left Of Triangle (Left)<br>&nbsp;&nbsp;glColor3f(0.0f,1.0f,0.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Green<br>&nbsp;&nbsp;glVertex3f(-1.0f,-1.0f, 1.0f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Right Of Triangle (Left)<br>&nbsp;glEnd();<br>
<img src ="http://www.cppblog.com/Walker/aggbug/144065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-12 20:16 <a href="http://www.cppblog.com/Walker/articles/144065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>opengl学习网站</title><link>http://www.cppblog.com/Walker/articles/144062.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Tue, 12 Apr 2011 11:56:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/144062.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/144062.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/144062.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/144062.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/144062.html</trackback:ping><description><![CDATA[<a href="http://nehe.gamedev.net/lesson.asp?index=01">http://nehe.gamedev.net/lesson.asp?index=01</a><br><br><a href="http://www.videotutorialsrock.com/">http://www.videotutorialsrock.com/</a><br><br>
<img src ="http://www.cppblog.com/Walker/aggbug/144062.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-12 19:56 <a href="http://www.cppblog.com/Walker/articles/144062.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本图元</title><link>http://www.cppblog.com/Walker/articles/144061.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Tue, 12 Apr 2011 11:47:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/144061.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/144061.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/144061.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/144061.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/144061.html</trackback:ping><description><![CDATA[任何复杂的三维模型都是由基本的几何图元：点、线段和多边形组成的，有了这些图元，就可以建立比较复杂的模型。因此这部分内容是学习OpenGL编程的基础。<br><br>　　<strong>一、基本图元的描述及定义</strong><br><br>　　OpenGL图元是抽象的几何概念，不是真实世界中的物体，因此须用相关的数学模型来描述。所有的图元都是由一系列有顺序的顶点集合来描述的。OpenGL中绘制几何图元，必须使用glBegain()和glEnd()这一对函数，传递给glBegain()函数的参数唯一确定了要绘制何种几何图元，同时，在该函数对中给出了几何图元的定义，函数glEnd()标志顶点列表的结束。例如，下面的代码绘制了一个多边形：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>glBegin(GL_POLYGON);<br>glVertex2f(0.0,0.0);<br>glVertex2f(0.0,3.0);<br>glVertex2f(3.0,3.0);<br>glVertex2f(4.0,1.5);<br>glVertex2f(3.0,0.0);<br>glEnd(); </td>
        </tr>
    </tbody>
</table>
<br>　　函数glBegin(GLenum mode)标志描述一个几何图元的顶点列表的开始，其参数mode表示几何图元的描述类型，具体类型见表一：<br><br>
<table border=1 cellSpacing=0 cellPadding=2 width="81%" align=center>
    <tbody>
        <tr>
            <td>类型 </td>
            <td>说明</td>
        </tr>
        <tr>
            <td>GL_POINTS </td>
            <td>单个顶点集</td>
        </tr>
        <tr>
            <td>GL_LINES </td>
            <td>多组双顶点线段</td>
        </tr>
        <tr>
            <td>GL_POLYGON </td>
            <td>单个简单填充凸多边形</td>
        </tr>
        <tr>
            <td>GL_TRAINGLES </td>
            <td>多组独立填充三角形</td>
        </tr>
        <tr>
            <td>GL_QUADS </td>
            <td>多组独立填充四边形</td>
        </tr>
        <tr>
            <td>GL_LINE_STRIP </td>
            <td>不闭合折线</td>
        </tr>
        <tr>
            <td>GL_LINE_LOOP </td>
            <td>闭合折线</td>
        </tr>
        <tr>
            <td>GL_TRAINGLE_STRIP </td>
            <td>线型连续填充三角形串</td>
        </tr>
        <tr>
            <td>GL_TRAINGLE_FAN </td>
            <td>扇形连续填充三角形串</td>
        </tr>
        <tr>
            <td>GL_QUAD_STRIP</td>
            <td>连续填充四边形串</td>
        </tr>
    </tbody>
</table>
　　　　　　　　　　　　　　　　　　表一、几何图元类型说明<br><br>　　部分几何图元的示意图：<br><br>
<table border=0 width="90%" align=center>
    <tbody>
        <tr>
            <td>
            <div align=center><img border=0 src="http://image.tianjimedia.com/imagelist/05/08/ke233v49q29e.jpg"><br>图一、部分几何图元示意图</div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　在glBegin()和glEnd()之间最重要的信息就是由函数glVertex*()定义的顶点，必要时也可为每个顶点指定颜色（只对当前点或后续点有效）、法向、纹理坐标或其他，即调用相关的函数：<br><br>
<table border=1 cellSpacing=0 cellPadding=2 width="90%" align=center>
    <tbody>
        <tr>
            <td>函数</td>
            <td>函数意义</td>
        </tr>
        <tr>
            <td>glColor*()</td>
            <td>设置当前颜色</td>
        </tr>
        <tr>
            <td>glIndex*() </td>
            <td>设置当前颜色表</td>
        </tr>
        <tr>
            <td>glNormal*()</td>
            <td>设置法向坐标</td>
        </tr>
        <tr>
            <td>glEvalCoord*()</td>
            <td>产生坐标</td>
        </tr>
        <tr>
            <td>glCallList(),glCallLists()</td>
            <td>显示列表</td>
        </tr>
        <tr>
            <td>glTexCoord*()</td>
            <td>设置纹理坐标 </td>
        </tr>
        <tr>
            <td>glEdgeFlag*() </td>
            <td>控制边界绘制</td>
        </tr>
        <tr>
            <td>glMaterial*()</td>
            <td>设置材质</td>
        </tr>
    </tbody>
</table>
　　　　　　　　　　　　　　表二、在glBegin()和glEnd()之间可调用的函数<br><br>　　需要指出的是：OpenGL所定义的点、线、多边形等图元与一般数学定义不太一样，存在一定的差别。一种差别源于基于计算机计算的限制。OpenGL中所有浮点计算精度有限，故点、线 、多边形的坐标值存在一定的误差。另一种差别源于位图显示的限制。以这种方式显示图形，最小的显示图元是一个象素，尽管每个象素宽度很小，但它们仍然比数学上所定义的点或线宽要大得多。当用OpenGL进行计算时，虽然是用一系列浮点值定义点串，但每个点仍然是用单个象素显示，只是近似拟合。<br><br>　　<strong>二、点(Point)</strong><br><br>　　用浮点值表示的点称为顶点(Vertex)。所有顶点在OpenGL内部计算时都使用三维坐标（x,y,z）来处理，用二维坐标(x,y)定义的点在OpenGL中默认z值为0。顶点坐标也可以用齐次坐标(x,y,z,w)来表示，如果w不为0.0，这些齐次坐标表示的顶点即为三维空间点(x/w,y/w,z/w),一般来说，w缺省为1.0。<br><br>　　可以用glVertex{234}{sifd}[V](TYPE cords)函数来定义一个顶点。例如：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>glVertex2f(2.0f,3.0f);//二维坐标定义顶点；</td>
        </tr>
    </tbody>
</table>
<br>　　OpenGL中定义的点可以有不同的尺寸，其函数形式为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glPointSize(GLfloat size);</td>
        </tr>
    </tbody>
</table>
<br>　　参数size设置点的宽度（以象素为单位）,必须大于0.0，缺省时为1.0。<br><br>　　<strong>三、线(Line)</strong><br><br>　　在OpenGL中，线代表线段(Line Segment)，它由一系列顶点顺次连结而成。具体的讲，线有独立线段、条带、封闭条带三种，如图二所示： <br><br>
<table border=0 width="90%" align=center>
    <tbody>
        <tr>
            <td>
            <div align=center><img border=0 src="http://image.tianjimedia.com/imagelist/05/08/3lp0m8t6oyqz.jpg"><br>图二、线段的三种连结方式</div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　OpenGL能指定线的宽度并绘制不同的虚点线，如点线、虚线等。相应的函数形式如下：<br><br>　　1、void glLineWidth(GLfloat width);<br><br>　　设置线宽（以象素为单位）。参数width必须大于0.0，缺省时为1.0。<br><br>　　2、void glLineStipple(GLint factor,GLushort pattern);<br><br>　　设置当前线为虚点模式。参数pattern是一系列的16位二进制数（0或1），它重复地赋给所指定的线，从低位开始，每一个二进制位代表一个象素， 1表示用当前颜色绘制一个象素（或比例因子指定的个数），0表示当前不绘制，只移动一个象素位（或比例因子指定的个数）。参数factor是个比例因子，它用来拉伸pattern中的元素，即重复绘制1或移动0，比如，factor为2，则碰到1时就连续绘制2次，碰到0时连续移动2个单元。factor的大小范围限制在1到255之间。<br><br>　　在绘制虚点线之前必须先启动虚点模式，即调用函数glEnable(GL_LINE_STIPPLE);结束时，调用glDisable(GL_LINE_STIPPLE)关闭。下面代码绘制了一个点线： <br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void line2i(GLint x1,GLint y1,GLint x2,GLint y2)<br>{<br>　　glBegin(GL_LINES);<br>　　glVertex2f(x1,y1);<br>　　glVertex2f(x2,y2);<br>　　glEnd();<br>}<br>glLineStipple (1, 0x1C47);　/* 虚点线 */<br>glEnable(GL_LINE_STIPPLE)；<br>glColor3f(0.0,1.0,0.0);<br>line2i (450 , 250 , 600 , 250 );</td>
        </tr>
    </tbody>
</table>
<div class=guanggao><strong>三、多边形(Polygon)<br><br></strong>　　（一）凸、凹多边形。<br><br>　　OpenGL定义的多边形是由一系列线段依次连结而成的封闭区域，多边形可以是平面多边形，即所有顶点在一个平面上，也可以是空间多边形。OpenGL规定多边形中的线段不能交叉，区域内不能有空洞，也即多边形必须是凸多边形（指多边形任意非相邻的两点的连线位于多边形的内部），不能是凹多边形，否则不能被OpenGL函数接受。凸多边形和凹多边形见图三。<br><br>
<table border=0 width="90%" align=center>
    <tbody>
        <tr>
            <td>
            <div align=center><img border=0 src="http://image.tianjimedia.com/imagelist/05/08/5n9v4sx473o6.jpg"><br>图三、凸凹多边形</div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　（二）边界标志问题。<br><br>　　实际应用中，往往需要绘制一些凹多边形，通常解决的办法是对它们进行分割，用多个三角形来替代。显然，绘制这些三角形时，有些边不应该进行绘制，否则，多边形内部就会出现多余的线框。OpenGL提供的解决办法是通过设置边标志命令glEdgeFlag（）来控制某些边产生绘制，而另外一些边不产生绘制，这也称为边界标志线或非边界线。这个命令的定义如下；<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glEdgeFlag(GLboolean flag);<br>void glEdgeFlag(PGLboolean pflag);</td>
        </tr>
    </tbody>
</table>
<br>　　（三）多边形绘制模式。<br><br>　　多边形的绘制模式包含有：全填充式、轮廓点式、轮廓线式、图案填充式及指定正反面等。下面分别介绍相应的OpenGL函数形式。<br><br>　　1）多边形模式设置。其函数为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glPolygonMode(GLenum face,GLenum mode);</td>
        </tr>
    </tbody>
</table>
<br>　　参数face为GL_FRONT、GL_BACK或GL_FRONT_AND_BACK；参数mode为GL_POINT、GL_LINE或GL_FILL，分别表示绘制轮廓点式多边形、轮廓线式多边形或全填充式多边形。在OpenGL中，多边形分为正面和反面，对这两个面都可以进行操作，在缺省状况下，OpenGL对多边形正反面是以相同的方式绘制的，要改变绘制状态，必须调用PolygonMode（）函数，<br><br>　　2）设置图案填充式多边形。其函数为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glPolygonStipple(const GLubyte *mask);</td>
        </tr>
    </tbody>
</table>
<br>　　参数mask是一个指向32x32位图的指针。与虚点线绘制的道理一样，某位为1时绘制，为0时什么也不绘。注意，在调用这个函数前，必须先启动glEnable(GL_POLYGON_STIPPLE)；不用时用glDisable(GL_POLYGON_STIPPLE)关闭。下面举出一个多边形扩展绘制实例：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void CALLBACK display(void)<br>{<br>　　/* 填充模式定义 （32x32） */<br>　　GLubyte pattern[]= {<br>　　　　0x00, 0x01, 0x80, 0x00,<br>　　　　0x00, 0x03, 0xc0, 0x00,<br>　　　　　　0x00, 0x07, 0xe0, 0x00,<br>　　　　　　0x00, 0x0f, 0xf0, 0x00,<br>　　　　　　0x00, 0x1f, 0xf8, 0x00,<br>　　　　　　0x00, 0x3f, 0xfc, 0x00,<br>　　　　　　0x00, 0x7f, 0xfe, 0x00,<br>　　　　　　0x00, 0xff, 0xff, 0x00,<br>　　　　　　0x01, 0xff, 0xff, 0x80,<br>　　　　　　0x03, 0xff, 0xff, 0xc0,<br>　　　　　　0x07, 0xff, 0xff, 0xe0,<br>　　　　　　0x0f, 0xff, 0xff, 0xf0,<br>　　　　　　0x1f, 0xff, 0xff, 0xf8,<br>　　　　　　0x3f, 0xff, 0xff, 0xfc,<br>　　　　　　0x7f, 0xff, 0xff, 0xfe,<br>　　　　　　0xff, 0xff, 0xff, 0xff,<br>　　　　　　0xff, 0xff, 0xff, 0xff,<br>　　　　　　0x7f, 0xff, 0xff, 0xfe,<br>　　　　　　0x3f, 0xff, 0xff, 0xfc,<br>　　　　　　0x1f, 0xff, 0xff, 0xf8,<br>　　　　　　0x0f, 0xff, 0xff, 0xf0,<br>　　　　　　0x07, 0xff, 0xff, 0xe0,<br>　　　　　　0x03, 0xff, 0xff, 0xc0,<br>　　　　　　0x01, 0xff, 0xff, 0x80,<br>　　　　　　0x00, 0xff, 0xff, 0x00,<br>　　　　　　0x00, 0x7f, 0xfe, 0x00,<br>　　　　　　0x00, 0x3f, 0xfc, 0x00,<br>　　　　　　0x00, 0x1f, 0xf8, 0x00,<br>　　　　　　0x00, 0x0f, 0xf0, 0x00,<br>　　　　　　0x00, 0x07, 0xe0, 0x00,<br>　　　　　　0x00, 0x03, 0xc0, 0x00,<br>　　　　　　0x00, 0x01, 0x80, 0x00<br>　　　　};<br>　　　　glClear (GL_COLOR_BUFFER_BIT);<br>　　　/* 绘制一个指定图案填充的三角形 */<br>　　　　glColor3f(0.9,0.86,0.4);<br>　　　　glPolygonStipple (pattern);<br>　　　　glBegin(GL_TRIANGLES);<br>　　　　　　glVertex2i(310,310);<br>　　　　　　glVertex2i(220,80);<br>　　　　　　glVertex2i(405,80);<br>　　　　glEnd();<br>　　　　glDisable (GL_POLYGON_STIPPLE);<br>　　　　glFlush ();<br>　　} </td>
        </tr>
    </tbody>
</table>
<br>　　（三）指定多边形的正反面。 <br><br>　　其函数为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glFrontFace(GLenum mode);</td>
        </tr>
    </tbody>
</table>
<br>　　在正常情况下，OpenGL中的多边形的正面和反面是由绘制的多边形的顶点顺序决定的，逆时针绘制的面是多边形的正面，但是，在OpenGL中使用该函数可以自定义多边形的正面。该函数的参数mode指定了正面的方向。它可以是CL_CCW和CL_CW，分别指定逆时针和顺时针方向为多边形的正方向。<br><strong>四、法向量的计算及指定<br><br></strong>　　法向量是几何图元的重要属性之一。几何对象的法向量是垂直与曲面切面的单位向量，它定义了几何对象的空间方向，特别定义了它相对于光源的方向，决定了在该点上可接受多少光照。<br><br>　　OpenGL本身没有提供计算法向量的函数（计算法向量的任务由程序员自己去完成），但它提供了赋予当前顶点法向的函数。<br><br>　　（一）平面法向的计算方法。<br><br>　　在一个平面内，有两条相交的线段，假设其中一条为矢量W，另一条为矢量V，平面法向为N，则平面法向就等于两个矢量的叉积（遵循右手定则），即N＝WxV。例如：一个三角形平面三个顶点分别为P0、P1、P2，相应两个向量为W、V，则三角平面法向的计算方式如下列代码所示：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void getNormal(GLfloat gx[3],GLfloat gy[3],<br>GLfloat gz[3],GLfloat *ddnv)<br>{<br>　GLfloat w0,w1,w2,v0,v1,v2,nr,nx,ny,nz;<br>　w0=gx[0]-gx[1]; w1=gy[0]-gy[1];w2=gz[0]-gz[1];<br>　v0=gx[2]-gx[1]; v1=gy[2]-gy[1];v2=gz[2]-gz[1];<br>　nx=(w1*v2-w2*v1);ny=(w2*v0-w0*v2);nz=(w0*v1-w1*v0);<br>　nr=sqrt(nx*nx+ny*ny+nz*nz); //向量单位化。<br>　ddnv[0]=nx/nr; ddnv[1]=ny/nr;ddnv[2]=nz/nr; <br>}</td>
        </tr>
    </tbody>
</table>
<br>　　以上函数的输出参数为指针ddnv，它指向法向的三个分量，并且程序中已经将法向单位化（或归一化）了。<br><br>　　（二）曲面法向量的计算。<br><br>　　对于曲面各顶点的法向计算有很多种，如根据函数表达式求偏导的方法等。但是，在大多数情况，OpenGL中的多边形并不是由曲面方程建立起来的，而是由模型数组构成，这时候求取法向量的办法是将曲面细分成多个小多边形，然后选取小多边形上相邻的三个点v1、v2、v3（当然三个点不能在同一直线上），按照平面法向量的求取方法就可以了。<br><br>　　（三）法向量的定义。<br><br>　　OpenGL法向量定义函数为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glNormal3{bsifd}(TYPE nx,TYPE ny,TYPE nz);<br>void glNormal3{bsifd}v(const TYPE *v);</td>
        </tr>
    </tbody>
</table>
<br>　　非向量形式定义法向采用第一种方式，即在函数中分别给出法向三个分量值nx、ny和nz；向量形式定义采用第二种，即将v设置为一个指向拥有三个元素的指针，例如v[3]={nx,ny,nz}。<br><br>　　<strong>五、显示列表</strong><br><br>　　（一）定义显示列表。<br><br>　　前面所举出的例子都是瞬时给出函数命令，OpenGL瞬时执行相应的命令，这种绘图方式叫做立即或瞬时方式（immediate mode）。OpenGL显示列表（Display List）是由一组预先存储起来的留待以后调用的OpenGL函数语句组成的，当调用显示列表时就依次执行表中所列出的函数语句。显示列表可以用在以下场合：<br><br>　　1）矩阵操作<br><br>　　大部分矩阵操作需要OpenGL计算逆矩阵，矩阵及其逆矩阵都可以保存在显示列表中。<br><br>　　2）光栅位图和图像<br><br>　　程序定义的光栅数据不一定是适合硬件处理的理想格式。当编译组织一个显示列表时，OpenGL可能把数据转换成硬件能够接受的数据，这可以有效地提高画位图的速度。<br><br>　　3）光、材质和光照模型<br><br>　　当用一个比较复杂的光照环境绘制场景时，因为材质计算可能比较慢。若把材质定义放在显示列表中，则每次改换材质时就不必重新计算了，因此能更快地绘制光照场景。<br><br>　　4）纹理<br><br>　　因为硬件的纹理格式可能与OpenGL格式不一致，若把纹理定义放在显示列表中，则在编译显示列表时就能对格式进行转换，而不是在执行中进行，这样就能大大提高效率。<br><br>　　5）多边形的图案填充模式，即可将定义的图案放在显示列表中。 <br><br>　　OpenGL提供类似于绘制图元的结构即类似于glBegin()与glEnd()的形式创建显示列表，其相应的函数为：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>void glNewList(GLuint list,GLenum mode);<br>void glEndList(void);</td>
        </tr>
    </tbody>
</table>
<br>　　glNewList（）函数说明一个显示列表的开始，其后的OpenGL函数存入显示列表中，直至调用结束表的函数glEndList(void)。glNewList（）函数中的参数list是一个正整数，它标志唯一的显示列表；参数mode的可能值有GL_COMPILE和GL_COMPILE_AND_EXECUTE；若要使列表中函数语句只存入而不执行，则用GL_COMPILE；若要使列表中的函数语句存入表中且按瞬时方式执行一次，则用GL_COMPILE_AND_EXECUTE。<br><br>　　注意：并不是所有的OpenGL函数都可以在显示列表中存储且通过显示列表执行。一般来说，用于传递参数或返回数值的函数语句不能存入显示列表，因为这张表有可能在参数的作用域之外被调用；如果在定义显示列表时调用了这样的函数，则它们将按瞬时方式执行并且不保存在显示列表中，有时在调用执行显示列表函数时会产生错误。以下列出的是不能存入显示列表的OpenGL函数：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>　　glDeleteLists()　　　　glIsEnable()<br>　　glFeedbackBuffer()　　 glIsList()<br>　　glFinish()　　　　　　 glPixelStore()<br>　　glGenLists()　　　　　 glRenderMode()<br>　　glGet*()　　　　　　　 glSelectBuffer()</td>
        </tr>
    </tbody>
</table>
<br>　　在建立显示列表以后就可以调用执行显示列表的函数来执行它，并且允许在程序中多次执行同一显示列表，同时也可以与其它函数的瞬时方式混合使用。显示列表执行的函数形式如下：<br><br>　　void glCallList(GLuint list);<br><br>　　参数list指定被执行的显示列表。显示列表中的函数语句按它们被存放的顺序依次执行；若list没有定义，则不会产生任何事情。<br><br>　　（二）管理显示列表<br><br>　　在实际应用中，一般调用函数glGenList()来创建多个显示列表，这样可以避免意外删除，产生一个没有用过的显示列表。此外，在管理显示列表的过程中，还可调用函数glDeleteLists()来删除一个或一个范围内的显示列表。<br><br>　　1）GLuint glGenList(GLsizei range)<br><br>　　该函数分配range个相邻的未被占用的显示列表索引。这个函数返回的是一个正整数索引值，它是一组连续空索引的第一个值。返回的索引都标志为空且已被占用，以后再调用这个函数时不再返回这些索引。若申请索引的指定数目不能满足或range为0则函数返回0。<br><br>　　2）GLboolean glIsList(GLuint list)<br><br>　　该函数询问显示列表是否已被占用的情况，若索引list已被占用，则函数返回TURE；反之，返回FAULSE。<br><br>　　3）void glDeleteLists(GLuint list,GLsizei range)<br><br>　　该函数删除一组连续的显示列表，即从参数list所指示的显示列表开始，删除range个显示列表，并且删除后的这些索引重新有效。<br><br>　　（三）多级显示列表<br><br>　　多级显示列表的建立就是在一个显示列表中调用另一个显示列表，也就是说，在函数glNewList()与glEndList()之间调用glCallList()。多级显示列表对于构造由多个元件组成的物体十分有用，尤其是某些元件需要重复使用的情况。但为了避免无穷递归，显示列表的嵌套深度最大为64（也许更高些，这依赖于不同的OpenGL实现），当然也可调用函数glGetIntegerv()来获得这个最大嵌套深度值。OpenGL也允许用一个显示列表包含几个低级的显示列表来模拟建立一个可编辑的显示列表。<br><br>　　下面的一段代码使用了列表嵌套来显示一个三角形：<br><br>
<table border=1 borderColor=#cccccc width="90%" bgColor=#e3e3e3 align=center>
    <tbody>
        <tr>
            <td>　　glNewList(1,GL_COMPILE);<br>　　glVertex3fv(v1);<br>　　glEndList(); <br>　　glNewList(2,GL_COMPILE);<br>　　glVertex3fv(v2);<br>　　glEndList();<br><br>　　glNewList(3,GL_COMPILE);<br>　　glVertex3fv(v3);<br>　　glEndList();<br><br>　　glNewList(4,GL_COMPILE);<br>　　glBegin(GL_POLYGON);<br>　　glCallList(1);<br>　　glCallList(2);<br>　　glCallList(3);<br>　　glEnd();<br>　　glEndList();</td>
        </tr>
    </tbody>
</table>
<br></div>
<img src ="http://www.cppblog.com/Walker/aggbug/144061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-12 19:47 <a href="http://www.cppblog.com/Walker/articles/144061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenGL的函数库介绍</title><link>http://www.cppblog.com/Walker/articles/143978.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Mon, 11 Apr 2011 14:08:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/143978.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/143978.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/143978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/143978.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/143978.html</trackback:ping><description><![CDATA[<p>在此简单介绍一下<strong>OpenGL的函数库</strong>及<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold"><font color=#000000>OpenGL实用工具包(GLUT)</font></span>:<br>1、<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">核心库 115个库函数，每个函数都以gl开头，这些函数是最基本的，它们可以在任何OpenGL的工作平台上应用。</span>这些函数用于建立各种各样的形体，产生光照效果,进行反走样以及进行纹理映射，进行投影变换等等。由于这些核心函数有许多种形式并能够接受不同类型的参数，实际上这些函数可以派生出300多个函数。<br>2<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">、实用库：43个函数，每个函数以glu开头；是比OpenGL核心函数更高一层的函数，这些函数是通过调用核心函数来起作用的。它们可以在任何OpenGL的工作平台上应用。</span>这些函数提供了十分简单的用法，从而减轻了开发者的编程负担。OpenGL的实用函数包括纹理映射、坐标变换、多边形分化、绘制一些如椭球、圆柱、茶壶等简单多边形实体等。这部分函数象核心函数一样在任何OpenGL平台都可以应用。<br>3、<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">辅助库：31个函数，每个函数以aux开头；这些函数本来是用于初学者做简单的练习之用，因此这些函数不能在所有的OpenGL平台上使用，</span>在Windows NT环境下可以使用这些函数。这些函数使用简单，它们可以用于窗口管理、输入输出处理以及绘制一些简单的三维形体。为了使OpenGL的应用程序具有良好的移植性，在使用OpenGL辅助库的时候应谨慎。<br>4、<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">专用库函数，</span>每种窗口都有一个用于扩展窗口系统功能，以支持OpenGL渲染的函数库。在使用X窗口系统的计算机中，提供了X窗口系统的OpenGL扩展（GLX），作为OpenGL的附加。GLX库函数的名称中包含前缀"glX"。在windows系统上，6个以wgl开头的函数提供了额windows和OpenGL之间的接口。<br>5、<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">OpenGL实用工具包（GLUT,OpenGL Utility Toolkit）</span>是Mark Kilgard开发的一个独立于窗口系统的工具包，用于绕开窗口系统API的复杂性。GLUT函数名中包含前缀"glut"。<br>6、<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">Win32 API函数</span>：5个函数，函数前面没有专用前缀；用于处理象素存储格式和双缓冲区，显然这些函数仅仅能够用于Win32系统而不能用于其他OpenGL平台。</p>
<p><span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">OpenGL实用工具包(GLUT)介绍：</span><br>OpenGL包含渲染函数，但被涉及成独立于任何窗口系统和操作系统。因此，<span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">OpenGL并没用用于打开窗口以及检测键盘或鼠标事件的函数。GLUT库被用来简化这些相关任务，此外还提供了一些用于创建复杂三位物体（如球体、圆环和茶壶等）的函数。</span><br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">窗口管理函数</span><br>&nbsp;&nbsp; glutInit(int *argc, char **argv)，初始化GLUT并处理命令行参数，应在调用其他GLUT函数前调用glutInit()。<br>&nbsp;&nbsp; glutInitDisplayMode(unsigned int mode),指定使用RGBA模式还是颜色索引模式。还可以指定使用单缓存还是双缓存等。<br>&nbsp;&nbsp; glutInitWindowPosition(int x, int y),指定窗口左上角在屏幕上的位置。<br>&nbsp;&nbsp; glutInitWindowSize(int width, int size),指定窗口的大小，单位为象素。<br>&nbsp;&nbsp; int glutCreateWindow(char *string)，使用一个OpenGL场景创建一个窗口，该函数返回一个标识符，唯一的标识新建的窗口，注意，在调用glutMainLoop()之前，窗口不会被显示出来。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">显示回调函数</span><br>&nbsp;&nbsp; glutDisplayFunc(void(*func)(void))是最重要的时间回调函数。每当GLUT认为需要重新显示窗口的内容时，都将执行函数glutDisplayFunc()函数注册的回调函数，因此，应将为重新绘制场景需要调用的函数都放到显示回调函数中。如果程序修改了窗口的内容，可能需要调用函数glutPostRedisplay(void)，它提醒函数glutMainLoop调用注册的显示回调函数。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">运行程序</span><br>&nbsp;&nbsp; glutMainLoop(void)，显示创建的所有窗口，被渲染到这些窗口中的内容也将显示出来。程序开始事件处理，这册的显示回调函数被触发，进入该循环，便不会退出。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">处理输入事件</span><br>&nbsp;&nbsp; glutReshapeFunc(void(*func)(int w, int h))，指定窗口大小发生改变时应采取的措施；<br>&nbsp;&nbsp; glutKeyboardFunc(void(*func)(unsigned char key, int x, int y))和glutMouseFunc(void(*func)(int button,int state,int x,int y))，指定当特定的键和鼠标按钮被按下或者松开时应调用的回调函数。<br>&nbsp;&nbsp; glutMotionFunc(void(*func)(int x, int y))，这册了当用户按下鼠标按钮并移动鼠标时应调用的回调函数。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">管理后台处理</span><br>&nbsp;&nbsp; glutIdleFunc(void(*func)(void))指定一个在没有其他事件需要处理时（如事件循环空闲）执行的函数。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: rgb(255,0,0); FONT-WEIGHT: bold">绘制三维物体</span><br>&nbsp;&nbsp; glutWireCube(GLdouble size)、glutSolidCube(GLdouble size)、glutWireSphere(GLdouble radius, GLint slices,GLint statcks)、glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)等</p>
<img src ="http://www.cppblog.com/Walker/aggbug/143978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-11 22:08 <a href="http://www.cppblog.com/Walker/articles/143978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>glViewport和glOrtho</title><link>http://www.cppblog.com/Walker/articles/143976.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Mon, 11 Apr 2011 14:05:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/143976.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/143976.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/143976.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/143976.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/143976.html</trackback:ping><description><![CDATA[<p>在OpenGL中有两个比较重要的投影变换函数，glViewport和glOrtho.<br>glOrtho是创建一个正交平行的视景体。 一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。比如，常用的工程中的制图等。需要比较精确的显示。 而作为它的对立情况, glFrustum则产生一个透视投影。这是一种模拟真是生活中，人们视野观测物体的真实情况。例如：观察两条平行的火车到，在过了很远之后，这两条铁轨是会相交于一处的。还有，离眼睛近的物体看起来大一些，远的物体看起来小一些。<br>glOrtho(left, right, bottom, top, near, far)， left表示视景体左面的坐标，right表示右面的坐标，bottom表示下面的，top表示上面的。这个函数简单理解起来，就是一个物体摆在那里，你怎么去截取他。这里，我们先抛开glViewport函数不看。先单独理解glOrtho的功能。 假设有一个球体，半径为1，圆心在(0, 0, 0)，那么，我们设定glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽高都是3的框框把这个球体整个都装了进来。&nbsp; 如果设定glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽是1.5， 高是3的框框把整个球体的右面装进来;如果设定glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10)；就表示用一个宽和高都是1.5的框框把球体的右上角装了进来。上述三种情况可以见图：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>从上述三种情况，我们可以大致了解glOrtho函数的用法。</p>
<p>---glViewport():<br>glOrtho函数只是负责使用什么样的视景体来截取图像，并不负责使用某种规则把图像呈现在屏幕上。<br>glViewport主要完成这样的功能。它负责把视景体截取的图像按照怎样的高和宽显示到屏幕上。<br>比如：如果我们使用glut库建立一个窗体:glutInitWindowSize(500, 500); 然后使用glutReshapeFunc(reshape); reshape代码如下：</p>
<p>void reshape(int width, int height)<br>{<br>&nbsp;&nbsp;&nbsp; glViewport(0, 0, (GLsizei)width, (GLsizei)height);<br>&nbsp;&nbsp;&nbsp; glMatrixModel(GL_PROJECTION);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp;&nbsp; glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);</p>
<p>&nbsp;&nbsp;&nbsp; ....<br>}<br>这样是可以看到一个正常的球体的。但是，如果我们创建窗体时glutInitWindowSize(800, 500),那么看到的图像就是变形的。上述情况见图。</p>
<p>&nbsp;<br>因为我们是用一个正方形截面的视景体截取的图像，但是拉伸到屏幕上显示的时候，就变成了glViewport(0, 0, 800, 500);也就是显示屏变宽了， 倒是显示的时候把一个正方形的图像&#8220;活生生的给拉宽了&#8221;。就会产生变形。这样，就需要我们调整我们的OpenGL显示屏了。我们可以不用800那么宽，因为我们是用的正方形的视景体，所以虽然窗体是800宽，但是我们只用其中的500就够了。修改一下程序。<br>void reshape(int width, int height)<br>{<br>&nbsp;&nbsp;&nbsp; int dis = width &lt; height ? width : height;<br>&nbsp;&nbsp;&nbsp; glViewport(0, 0, dis, dis);&nbsp;&nbsp; /*这里dis应该是500*/</p>
<p>&nbsp;&nbsp;&nbsp; glMatrixModel(GL_PROJECTION);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp;&nbsp; glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);<br>&nbsp;&nbsp;&nbsp; .....<br>}</p>
<p>&nbsp;</p>
<p>OK. 如果你能看明白我写的内容。你可能对glViewport函数有个大致的了解。</p>
<p>不过，我们采用上面的办法，就是只使用了原来屏幕的一部分（宽度从501到800 我们没有用来显示图像）。如果我们想用整个OpenGL屏幕显示图像，但是又不使图像变形怎么办？<br>那就只能修改glOrtho函数了。也就是说，我们使用一个和窗体一样比例的视景体（而不再是正方形的视景体）来截取图像。例如，对于(800, 500)的窗体，我们使用glOrtho(-1.5 * 800/500, 1.5 * 800/500, -1.5, 1.5, -10, 10)，就是截取的时候，我们就使用一个&#8220;扁扁&#8221;的视景体截取，那么，显示的到OpenGL屏幕时(800, 500)，我们只要正常把这个扁扁的截取图像显示（扁扁的截取图像是指整个截取的图像，包括球形四周的黑色部分。 球形还是正常圆形的），就可以了。如：<br>void reshape(int width , int height)<br>{<br>&nbsp;&nbsp;&nbsp; glViewport(width, height); //按照窗体大小制作OpenGL屏幕<br>&nbsp;&nbsp;&nbsp; glMatrixMode(GL_PROJECTION);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp;&nbsp; if (width &lt;= height)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(-1.5, 1.5, -1.5 * (GLfloat)height/(GLfloat)width, 1.5 * (GLfloat)height/(GLfloat)width, -10.0, 10.0);<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(-1.5*(GLfloat)width/(GLfloat)height, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);</p>
<p>&nbsp;&nbsp;&nbsp; ....<br>}</p>
<p>&nbsp;</p>
<p>另外，关于glViewport()函数，我们还可以用来调整图像的分辨率。例如，保持目前的窗体大小不变，我们如果用这个size来只显示整个物体的一部分，那么图像的分辨率就必然会增大。例如：<br>void reshape(int w, int h)<br>{<br>&nbsp;&nbsp;&nbsp; glViewport(0, 0, (GLsizei)w, (GLsizei)h);<br>&nbsp;&nbsp;&nbsp; glMatrixMode(GL_PROJECTION);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp;&nbsp; if (w &lt;= h)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(0, 1.5, 0, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(0, 1.5*(GLfloat)w/(GLfloat)h, 0, 1.5, -10.0, 10.0);<br>}<br>可以把分辨率扩大4倍。</p>
<p>&nbsp;</p>
<p>而如果再修改一下glViewport(0, 0, 2 * (GLsizei)w, 2 * (GLsizei)h); 则可以把分辨率扩大16倍。</p>
<p>&nbsp; </p>
<p>完整的测试程序：</p>
<p>/*Build on ubuntu 9.04*/</p>
<p>#include &lt;GL/gl.h&gt;<br>#include &lt;GL/glu.h&gt;<br>#include &lt;GL/glut.h&gt;</p>
<p>void init(void)<br>{<br>&nbsp;&nbsp;&nbsp; GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};<br>&nbsp;&nbsp;&nbsp; GLfloat mat_shininess[] = {50.0};<br>&nbsp;&nbsp;&nbsp; GLfloat light_position[] = {1.0, 1.0f, 1.0, 0.0};<br>&nbsp;&nbsp;&nbsp; GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};<br>&nbsp;&nbsp;&nbsp; GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};<br>&nbsp;&nbsp;&nbsp; glClearColor(0.0, 0.0, 0.0, 0.0);<br>&nbsp;&nbsp;&nbsp; glShadeModel(GL_SMOOTH);<br>&nbsp;&nbsp;&nbsp; glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);<br>&nbsp;&nbsp;&nbsp; glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);<br>&nbsp;&nbsp;&nbsp; glLightfv(GL_LIGHT0, GL_POSITION, light_position);<br>&nbsp;&nbsp;&nbsp; glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);<br>&nbsp;&nbsp;&nbsp; glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);<br>&nbsp;&nbsp;&nbsp; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);</p>
<p>&nbsp;&nbsp;&nbsp; glEnable(GL_LIGHTING);<br>&nbsp;&nbsp;&nbsp; glEnable(GL_LIGHT0);<br>&nbsp;&nbsp;&nbsp; glEnable(GL_DEPTH_TEST);<br>&nbsp;&nbsp;&nbsp; <br>}</p>
<p>void display(void)<br>{<br>&nbsp;&nbsp;&nbsp; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br>&nbsp;&nbsp;&nbsp; glutSolidSphere(1.0, 20, 16);<br>&nbsp;&nbsp;&nbsp; glFlush();<br>}</p>
<p>void reshape(int w, int h)<br>{<br>&nbsp;&nbsp;&nbsp; glViewport(0, 0, (GLsizei)w, (GLsizei)h);<br>&nbsp;&nbsp;&nbsp; glMatrixMode(GL_PROJECTION);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>&nbsp;&nbsp;&nbsp; if (w &lt;= h)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(-1.5, 1.5, -1.5 * (GLfloat)h/(GLfloat)w, 1.5 * (GLfloat)h/(GLfloat)w, -10.0, 10.0);<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glOrtho(-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);</p>
<p>&nbsp;&nbsp;&nbsp; glMatrixMode(GL_MODELVIEW);<br>&nbsp;&nbsp;&nbsp; glLoadIdentity();<br>}</p>
<p>int main(int argc, char **argv)<br>{<br>&nbsp;&nbsp;&nbsp; glutInit(&amp;argc, argv);<br>&nbsp;&nbsp;&nbsp; glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);<br>&nbsp;&nbsp;&nbsp; glutInitWindowSize(500, 500);<br>&nbsp;&nbsp;&nbsp; glutInitWindowPosition(100, 100);<br>&nbsp;&nbsp;&nbsp; glutCreateWindow(argv[0]);<br>&nbsp;&nbsp;&nbsp; init();<br>&nbsp;&nbsp;&nbsp; glutDisplayFunc(display);<br>&nbsp;&nbsp;&nbsp; glutReshapeFunc(reshape);<br>&nbsp;&nbsp;&nbsp; glutMainLoop();<br>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p>/*CMakeLists.txt*/</p>
<p>PROJECT(s5)<br>CMAKE_MINIMUM_REQUIRED(VERSION 2.6)<br>ADD_EXECUTABLE(s5 main.cpp)</p>
<p><br>FIND_PACKAGE(OpenGL)<br>FIND_PACKAGE(GLUT)</p>
<p>IF(OPENGL_FOUND)<br>&nbsp; INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})<br>&nbsp; TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OPENGL_LIBRARIES})<br>ELSE(OPENGL_FOUND)<br>&nbsp; MESSAGE(FATAL_ERROR "OpenGL not found")<br>ENDIF(OPENGL_FOUND)</p>
<p>IF(GLUT_FOUND)<br>&nbsp; INCLUDE_DIRECTORIES(${GLUT_INCLUDE_DIR})<br>&nbsp; TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${GLUT_LIBRARIES})<br>ELSE(GLUT_FOUND)<br>ENDIF(GLUT_FOUND)</p>
<p>参考: OpenGL编程指南(原书第6版)</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/shizhipeng/archive/2009/12/13/4939529.aspx">http://blog.csdn.net/shizhipeng/archive/2009/12/13/4939529.aspx</a></p>
<img src ="http://www.cppblog.com/Walker/aggbug/143976.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-11 22:05 <a href="http://www.cppblog.com/Walker/articles/143976.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>opengl环境配置</title><link>http://www.cppblog.com/Walker/articles/143975.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Mon, 11 Apr 2011 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/143975.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/143975.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/143975.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/143975.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/143975.html</trackback:ping><description><![CDATA[<p><strong>学习OpenGL前的准备工作</strong> </p>
<p>第一步，选择一个编译环境<br>　　现在Windows系统的主流编译环境有Visual Studio，Broland C++ Builder，Dev-C++等，它们都是支持OpenGL的。但这里我们选择Visual Studio 2005作为学习OpenGL的环境。 </p>
<p>第二步，安装GLUT工具包<br>　　GLUT不是OpenGL所必须的，但它会给我们的学习带来一定的方便，推荐安装。<br>Windows环境下的GLUT下载地址：（大小约为150k）<br>http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip<br>无法从以上地址下载的话请使用下面的连接:<br>http://upload.programfan.com/upfile/200607311626279.zip<br>Windows环境下安装GLUT的步骤：<br>1、将下载的压缩包解开，将得到5个文件<br>2、在&#8220;我的电脑&#8221;中搜索&#8220;gl.h&#8221;，并找到其所在文件夹（如果是VisualStudio2005，则应该是其安装目录下面的&#8220;VC\PlatformSDK\include\gl文件夹&#8221;）。把解压得到的glut.h放到这个文件夹。<br>3、把解压得到的glut.lib和glut32.lib放到静态函数库所在文件夹（如果是VisualStudio2005，则应该是其安装目录下面的&#8220;VC\lib&#8221;文件夹）。<br>4、把解压得到的glut.dll和glut32.dll放到操作系统目录下面的system32文件夹内。（典型的位置为：C:\Windows\System32）<br>第三步，建立一个OpenGL工程<br>这里以VisualStudio2005为例。<br>选择File-&gt;New-&gt;Project，然后选择Win32 Console Application，选择一个名字，然后按OK。<br>在谈出的对话框左边点Application Settings，找到Empty project并勾上，选择Finish。<br>然后向该工程添加一个代码文件，取名为&#8220;OpenGL.c&#8221;，注意用.c来作为文件结尾。<br>搞定了，就跟平时的工程没什么两样的。 </p>
<p><strong>第一个OpenGL程序</strong><br><br>一个简单的OpenGL程序如下：（注意，如果需要编译并运行，需要正确安装GLUT，安装方法如上所述）<br><br>#include &lt;GL/glut.h&gt;<br><br>void myDisplay(void)<br>{<br>glClear(GL_COLOR_BUFFER_BIT);<br>glRectf(-0.5f, -0.5f, 0.5f, 0.5f);<br>glFlush();<br>}<br><br>int main(int argc, char *argv[])<br>{<br>glutInit(&amp;argc, argv);<br>glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);<br>glutInitWindowPosition(100, 100);<br>glutInitWindowSize(400, 400);<br>glutCreateWindow("第一个OpenGL程序");<br>glutDisplayFunc(&amp;myDisplay);<br>glutMainLoop();<br>return 0;<br>}<br><br>该程序的作用是在一个黑色的窗口中央画一个白色的矩形。下面对各行语句进行说明。 </p>
<p>怎么样？代码还不算长吧？<br><br>首先，需要包含头文件#include&lt;GL/glut.h&gt;，这是GLUT的头文件。<br>本来OpenGL程序一般还要包含&lt;GL/gl.h&gt;和&lt;GL/glu.h&gt;，但GLUT的头文件中已经自动将这两个文件包含了，不必再次包含。<br><br>然后看main函数。<br>int main(int argc, char *argv[])，这个是带命令行参数的main函数，各位应该见过吧？没见过的同志们请多翻翻书，等弄明白了再往下看。<br>注意main函数中的各语句，除了最后的return之外，其余全部以glut开头。这种以glut开头的函数都是GLUT工具包所提供的函数，下面对用到的几个函数进行介绍。<br>1、glutInit，对GLUT进行初始化，这个函数必须在其它的GLUT使用之前调用一次。其格式比较死板，一般照抄这句glutInit(&amp;argc, argv)就可以了。<br>2、glutInitDisplayMode，设置显示方式，其中GLUT_RGB表示使用RGB颜色，与之对应的还有GLUT_INDEX（表示使用索引颜色）。GLUT_SINGLE表示使用单缓冲，与之对应的还有GLUT_DOUBLE（使用双缓冲）。更多信息，请自己Google。当然以后的教程也会有一些讲解。<br>3、glutInitWindowPosition，这个简单，设置窗口在屏幕中的位置。<br>4、glutInitWindowSize，这个也简单，设置窗口的大小。<br>5、glutCreateWindow，根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意：窗口被创建后，并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。<br>6、glutDisplayFunc，设置一个函数，当需要进行画图时，这个函数就会被调用。（这个说法不够准确，但准确的说法可能初学者不太好理解，暂时这样说吧）。<br>7、glutMainLoop，进行一个消息循环。（这个可能初学者也不太明白，现在只需要知道这个函数可以显示窗口，并且等待窗口关闭后才会返回，这就足够了。）<br><br>在glutDisplayFunc函数中，我们设置了&#8220;当需要画图时，请调用myDisplay函数&#8221;。于是myDisplay函数就用来画图。观察myDisplay中的三个函数调用，发现它们都以gl开头。这种以gl开头的函数都是OpenGL的标准函数，下面对用到的函数进行介绍。<br>1、glClear，清除。GL_COLOR_BUFFER_BIT表示清除颜色，glClear函数还可以清除其它的东西，但这里不作介绍。<br>2、glRectf，画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标。<br>3、glFlush，保证前面的OpenGL命令立即执行（而不是让它们在缓冲区中等待）。其作用跟fflush(stdout)类似。 </p>
<p>大家可以按照上面的叙述，自己设置编译器，下载GLUT，并亲手编译示例代码。<br>祝大家成功~<br></p>
<img src ="http://www.cppblog.com/Walker/aggbug/143975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-11 22:04 <a href="http://www.cppblog.com/Walker/articles/143975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenGL &amp;DirectX （转）</title><link>http://www.cppblog.com/Walker/articles/143894.html</link><dc:creator>漫步者×&amp;……%￥</dc:creator><author>漫步者×&amp;……%￥</author><pubDate>Sun, 10 Apr 2011 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/Walker/articles/143894.html</guid><wfw:comment>http://www.cppblog.com/Walker/comments/143894.html</wfw:comment><comments>http://www.cppblog.com/Walker/articles/143894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Walker/comments/commentRss/143894.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Walker/services/trackbacks/143894.html</trackback:ping><description><![CDATA[<p>3D编程的第一个问题就是用何种API：OpenGL还是Direct3D？以下是它们的一些比较：&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 操作系统平台：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你的操作系统是Windows，你可以选择。如果是Unix、Linux等，那么就只能用OpenGL。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 易学易用性：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OpenGL相对来说比DirectX易学，能够很快入门（这是公认的）。即使你将来可能要用到Direct3D，OpenGL仍然不失为一种好的3D编程的入门途径，OpenGL中原汁原味的3D函数简直和大多数计算机图形学教材中的伪代码一模一样。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp; 文档支持：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在网上你可以找到很多很好的OpenGL的文档、教程、例程等，特别是&#8220;红宝书&#8221;（相关链接和文档可以在本站OpenGL栏目找到）。但是，DirectX&nbsp;&nbsp; SDK所提供的文档难嚼多了（公认），在网上你也难以找到好的教程（本站的DirectX栏目所提供的几乎是全部能找到的不重复的中文资料）。另外，书店里有不少OpenGL的中文书，而DirectX只有&#8220;希望&#8221;出的一种，并且不是讲Direct3D的。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp; 关于COM：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DirectX是基于COM的，而OpenGL不是。如果你对COM不是那么感冒的话，最好先选择OpenGL。但是，如果你将一直在Windows平台上做3D编程的话，总应该熟悉Direct3D，因为Microsoft/SGI/HP共同开发中的一种新的3D接口是基于COM的，它将和Direct3D比较接近。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp; 移植性：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DirectX与Windows紧密相连，难以移植。而OpenGL是一种非常&#8220;干净的&#8221;API，无论从VB语言到VC语言、还是从Windows平台到Linux平台（几乎一样的C代码）的移植都非常容易（并且在GLUT里提供了平台无关的窗口管理库）。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp; 多媒体性能：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于DirectX包括了DirectSound、DirectInput等，如果Direct3D和它们一起使用，将比较容易控制声音、操纵杆等，这是DirectX的整体优势。当然，没有人反对你同时使用OpenGL和DirectSound，Quake就是这样做的。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp; 速度：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很难说哪个更快，QUAKE用的是OpenGL的引擎，而Unreal用的是Direct3D，它们都非常著名。其实，程序的速度并不在于你选择了OpenGL或DirectX，它还至少和两个因素有关：你写的代码的质量（依赖于你对你使用的接口的熟悉程度），硬件的支持（包括硬件的驱动程序的支持）。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp; 强壮性：&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样说吧，OpenGL调用发生了错误，它什么都不做；而DirectX出了错，它什么都做得出&#8230;&#8230;</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/didibabawu055/archive/2009/02/21/3919401.aspx">http://blog.csdn.net/didibabawu055/archive/2009/02/21/3919401.aspx</a></p>
<img src ="http://www.cppblog.com/Walker/aggbug/143894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Walker/" target="_blank">漫步者×&……%￥</a> 2011-04-10 22:10 <a href="http://www.cppblog.com/Walker/articles/143894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>