OpenGL第十一课.docx

上传人:b****3 文档编号:12641408 上传时间:2023-04-21 格式:DOCX 页数:39 大小:35.99KB
下载 相关 举报
OpenGL第十一课.docx_第1页
第1页 / 共39页
OpenGL第十一课.docx_第2页
第2页 / 共39页
OpenGL第十一课.docx_第3页
第3页 / 共39页
OpenGL第十一课.docx_第4页
第4页 / 共39页
OpenGL第十一课.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

OpenGL第十一课.docx

《OpenGL第十一课.docx》由会员分享,可在线阅读,更多相关《OpenGL第十一课.docx(39页珍藏版)》请在冰豆网上搜索。

OpenGL第十一课.docx

OpenGL第十一课

第十一课

飘动的旗帜:

这一课从第六课的代码开始,创建一个飘动的旗帜。

我相信在这课结束的时候,你可以掌握纹理映射和混合操作。

大家好!

对那些想知道我在这里作了些什么的朋友,您可以先按文章的末尾所列出的链接,下载我那毫无意义的演示(Demo)看看先!

我是bosco,我将尽我所能教您来实现一个以正弦波方式运动的图象。

这一课基于NeHe的教程第六课,当然您至少也应该学会了一至六课的知识。

您需要下载源码压缩包,并将压缩包内带的data目录连其下的位图一起释放至您的代码目录下。

或者使用您自己的位图,当然它的尺寸必须适合OpenGL纹理的要求。

  在我们开始之前,先打开VisualC++(译者:

我可是用的C++Builder…)并在其他的#inlude之后,添加如下的代码。

这将引入我们在程序中将要用到的复杂(译者:

复杂吗?

)数学函数sine和cosine。

#include//引入数学函数库中的Sin

我们将使用points数组来存放网格各顶点独立的x,y,z坐标。

这里网格由45×45点形成,换句话说也就是由44格×44格的小方格子依次组成了。

wiggle_count用来指定纹理波浪的运动速度。

每3帧一次看起来很不错,变量hold将存放一个用来对旗形波浪进行光滑的浮点数。

这几行添加在程序头部,位于最后一行#include之后、GLuinttexture[1]之前的位置。

floatpoints[45][45][3];//Points网格顶点数组

intwiggle_count=0;//指定旗形波浪的运动速度

GLfloathold;//临时变量

然后下移至LoadGLTextures()子过程。

本课中使用的纹理文件名是Tim.bmp。

找到LoadBMP("Data/NeHe.bmp")这一句,并用LoadBMP("Data/Tim.bmp")替换它。

if(TextureImage[0]=LoadBMP("Data/Tim.bmp"))//载入位图

接着在InitGL()函数的尾部returnTRUE之前,添加如下的代码。

glPolygonMode(GL_BACK,GL_FILL);//后表面完全填充

glPolygonMode(GL_FRONT,GL_LINE);//前表面使用线条绘制

上面的代码指定使用完全填充模式来填充多边形区域的背面(译者:

或者叫做后表面吧)。

相反,多边形的正面(译者:

前表面)则使用轮廓线填充了。

这些方式完全取决于您的个人喜好。

并且与多边形的方位或者顶点的方向有关。

详情请参考红宝书(RedBook)。

这里我顺便推销一本推动我学习OpenGL的好书—Addison-Wesley出版的《Programmer'sGuidetoOpenGL》。

个人以为这是学习OpenGL的无价之宝。

接着上面的代码并在returnTRUE这一句之前,添加如下的几行。

//沿X平面循环

for(intx=0;x<45;x++)

{

//沿Y平面循环

for(inty=0;y<45;y++)

{

//向表面添加波浪效果

points[x][y][0]=float((x/5.0f)-4.5f);

points[x][y][1]=float((y/5.0f)-4.5f);

points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));

}

}

这里感谢GrahamGibbons关于使用整数循环变量消除波浪间的脉冲锯齿的建议。

  

上面的两个循环初始化网格上的点。

使用整数循环可以消除由于浮点运算取整造成的脉冲锯齿的出现。

我们将x和y变量都除以5,再减去4.5。

这样使得我们的波浪可以“居中”(译者:

这样计算所得结果将落在区间[-4.5,4.5]之间)。

  

点[x][y][2]最后的值就是一个sine函数计算的结果。

Sin()函数需要一个弧度参变量。

将float_x乘以40.0f,得到角度值。

然后除以360.0f再乘以PI,乘以2,就转换为弧度了。

接着我将彻底重写DrawGLScene函数。

intDrawGLScene(GLvoid)//绘制我们的GL场景

{

intx,y;//循环变量

floatfloat_x,float_y,float_xb,float_yb;//用来将旗形的波浪分割成很小的四边形

我们使用不同的变量来控制循环。

下面的代码中大多数变量除了用来控制循环和存储临时变量之外并没有什么别的用处。

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓冲

glLoadIdentity();//重置当前的模型观察矩阵

glTranslatef(0.0f,0.0f,-12.0f);//移入屏幕12个单位

glRotatef(xrot,1.0f,0.0f,0.0f);//绕X轴旋转

glRotatef(yrot,0.0f,1.0f,0.0f);//绕Y轴旋转

glRotatef(zrot,0.0f,0.0f,1.0f);//绕Z轴旋转

glBindTexture(GL_TEXTURE_2D,texture[0]);//选择纹理

正如您所见,上面的代码和第六课的很类似,唯一的区别就是我将场景挪的离镜头更远了一些。

glBegin(GL_QUADS);//四边形绘制开始

for(x=0;x<44;x++)//沿X平面0-44循环(45点)

{

for(y=0;y<44;y++)//沿Y平面0-44循环(45点)

{

接着开始使用循环进行多边形绘制。

这里使用整型可以避免我以前所用的int()强制类型转换。

float_x=float(x)/44.0f;//生成X浮点值

float_y=float(y)/44.0f;//生成Y浮点值

float_xb=float(x+1)/44.0f;//X浮点值+0.0227f

float_yb=float(y+1)/44.0f;//Y浮点值+0.0227f

上面我们使用4个变量来存放纹理坐标。

每个多边形(网格之间的四边形)分别映射了纹理的1/44×1/44部分。

循环首先确定左下顶点的值,然后我们据此得到其他三点的值。

glTexCoord2f(float_x,float_y);//第一个纹理坐标(左下角)

glVertex3f(points[x][y][0],points[x][y][1],points[x][y][2]);

glTexCoord2f(float_x,float_yb);//第二个纹理坐标(左上角)

glVertex3f(points[x][y+1][0],points[x][y+1][1],points[x][y+1][2]);

glTexCoord2f(float_xb,float_yb);//第三个纹理坐标(右上角)

glVertex3f(points[x+1][y+1][0],points[x+1][y+1][1],points[x+1][y+1][2]);

glTexCoord2f(float_xb,float_y);//第四个纹理坐标(右下角)

glVertex3f(points[x+1][y][0],points[x+1][y][1],points[x+1][y][2]);

}

}

glEnd();//四边形绘制结束

上面几行使用glTexCoord2f()和glVertex3f()载入数据。

提醒一点:

四边形是逆时针绘制的。

这就是说,您开始所见到的表面是背面。

后表面完全填充了,前表面由线条组成。

  

如果您按顺时针顺序绘制的话,您初始时见到的可能是前表面。

也就是说您将看到网格型的纹理效果而不是完全填充的。

if(wiggle_count==2)//用来降低波浪速度(每隔2帧一次)

{

每绘制两次场景,循环一次sine值,以产生运动效果。

for(y=0;y<45;y++)//沿Y平面循环

{

hold=points[0][y][2];//存储当前左侧波浪值

for(x=0;x<44;x++)//沿X平面循环

{

//当前波浪值等于其右侧的波浪值

points[x][y][2]=points[x+1][y][2];

}

points[44][y][2]=hold;//刚才的值成为最左侧的波浪值

}

wiggle_count=0;//计数器清零

}

wiggle_count++;//计数器加一

上面所作的事情是先存储每一行的第一个值,然后将波浪左移一下,是图象产生波浪。

存储的数值挪到末端以产生一个永无尽头的波浪纹理效果。

然后重置计数器wiggle_count以保持动画的进行。

  

上面的代码由NeHe(2000年2月)修改过,以消除波浪间出现的细小锯齿。

xrot+=0.3f;//X轴旋转

yrot+=0.2f;//Y轴旋转

zrot+=0.4f;//Z轴旋转

returnTRUE;//返回

}

标准的NeHe旋转增量。

现在编译并运行程序,您将看到一个漂亮的位图波浪。

除了嘘声一片之外,我不敢确信大家的反应。

但我希望大家能从这一课中学到点什么。

如果您有任何问题或者需要澄清的地方,请随便联络我。

感谢大家。

Lesson11

Wellgreetingsall.Forthoseofyouthatwanttoseewhatwearedoinghere,youcancheckitoutattheendofmydemo/hackWorthless!

IamboscoandIwilldomybesttoteachyouguyshowtodotheanimated,sine-wavepicture.ThistutorialisbasedonNeHe'stutorial#6andyoushouldhaveatleastthatmuchknowledge.YoushoulddownloadthesourcepackageandplacethebitmapI'veincludedinadirectorycalleddatawhereyoursourcecodeis.Oruseyourowntextureifit'sanappropriatesizetobeusedasatexturewithOpenGL.

Firstthingsfirst.OpenTutorial#6inVisualC++andaddthefollowingincludestatementrightaftertheother#includestatements.The#includebelowallowsustoworkwithcomplexmathsuchassineandcosine.

#include//ForTheSin()Function

We'llusethearraypointstostoretheindividualx,y&zcoordinatesofourgrid.Thegridis45pointsby45points,whichinturnmakes44quadsx44quads.wiggle_countwillbeusedtokeeptrackofhowfastthetexturewaves.Everythreeframeslooksprettygood,andthevariableholdwillstoreafloatingpointvaluetosmoothoutthewavingoftheflag.Theselinescanbeaddedatthetopoftheprogram,somewhereunderthelast#includeline,andbeforetheGLuinttexture[1]line.

floatpoints[45][45][3];//TheArrayForThePointsOnTheGridOfOur"Wave"

intwiggle_count=0;//CounterUsedToControlHowFastFlagWaves

GLfloathold;//TemporarilyHoldsAFloatingPointValue

MovedownthetheLoadGLTextures()procedure.WewanttousethetexturecalledTim.bmp.FindLoadBMP("Data/NeHe.bmp")andreplaceitwithLoadBMP("Data/Tim.bmp").

if(TextureImage[0]=LoadBMP("Data/Tim.bmp"))//LoadTheBitmap

NowaddthefollowingcodetothebottomoftheInitGL()functionbeforereturnTRUE.

glPolygonMode(GL_BACK,GL_FILL);//BackFaceIsFilledIn

glPolygonMode(GL_FRONT,GL_LINE);//FrontFaceIsDrawnWithLines

Thesesimplyspecifythatwewantbackfacingpolygonstobefilledcompletelyandthatwewantfrontfacingpolygonstobeoutlinedonly.Mostlypersonalpreferenceatthispoint.Hastodowiththeorientationofthepolygonorthedirectionofthevertices.SeetheRedBookformoreinformationonthis.Incidentally,whileI'matit,letmeplugthebookbysayingit'soneofthedrivingforcesbehindmelearningOpenGL,nottomentionNeHe'ssite!

ThanksNeHe.BuyTheProgrammer'sGuidetoOpenGLfromAddison-Wesley.It'saninvaluableresourceasfarasI'mconcerned.Ok,backtothetutorial.Rightbelowthecodeabove,andabovereturnTRUE,addthefollowinglines.

//LoopThroughTheXPlane

for(intx=0;x<45;x++)

{

//LoopThroughTheYPlane

for(inty=0;y<45;y++)

{

//ApplyTheWaveToOurMesh

points[x][y][0]=float((x/5.0f)-4.5f);

points[x][y][1]=float((y/5.0f)-4.5f);

points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));

}

}

ThankstoGrahamGibbonsforsuggestinganintegerlooptogetridofthespikeintheripple.

Thetwoloopsaboveinitializethepointsonourgrid.Iinitializevariablesinmylooptolocalizetheminmymindasmerelyloopvariables.Notsureit'skosher.Weuseintegerloopstopreventoddgraphicalglitchesthatappearwhenfloatingpointcalculationsareused.Wedividethexandyvariablesby5(i.e.45/9=5)andsubtract4.5fromeachofthemtocenterthe"wave".Thesameeffectcouldbeaccomplishedwithatranslate,butIpreferthismethod.

Thefinalvaluepoints[x][y][2]statementisoursinevalue.Thesin()functionrequiresradians.Wetakeourdegreevalue,whichisourfloat_xmultipliedby40.0f.Oncewehavethat,toconverttoradianswetakethedegree,divideby360.0f,multiplybypi,oranapproximationandthenmultiplyby2.0f.

I'mgoingtore-writetheDrawGLScenefunctionfromscratchsocleanitoutanditreplacewiththefollowingcode.

intDrawGLScene(GLvoid)//DrawOurGLScene

{

intx,y;//LoopVariables

floatfloat_x,float_y,float_xb,float_yb;//UsedToBreakTheFlagIntoTinyQuads

Differentvariablesusedforcontrollingtheloops.Seethecodebelowbutmostoftheseserveno"specific"purposeotherthancontrollingloopsandstoringtemporaryvalues.

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//ClearTheScreenAndDepthBuffer

glLoadIdentity();//ResetTheCurrentMatrix

glTranslatef(0.0f,0.0f,-12.0f);//Translate17UnitsIntoTheScreen

glRotatef(xrot,1.0f,0.0f,0.0f);//RotateOnTheXAxis

glRotatef(yrot,0.0f,1.0f,0.0f);//RotateOnTheYAxis

glRotatef(zrot,0.0f,0.0f,1.0f);//RotateOnTheZAxis

glBindTexture(GL_TEXTURE_2D,texture[0]);//SelectOurTexture

You'veseenallofthisbeforeaswell.Sameasintutorial#6exceptImerelypushmyscenebackawayfromthecameraabitmore.

glBegin(GL_QUADS);//StartDrawingOurQuads

for(x=0;x<44;x++)//LoopThroughTheXPlane0-44(45Points)

{

for(y=0;y<44;y++)//LoopThroughTheYPlane0-44(45Points)

{

Merelystartsthelooptodrawourpolygons.Iuseintegersheretokeepfromhavingtousetheint()functionasIdidearliertogetthearrayreferencereturnedasaninteger.

float_x=float(x)/44.0f;//CreateAFloatingPointXValue

float_y=float(y)/44.0f;//CreateAFloatingPointYValue

float_xb=float(x+1)/44.0f;//CreateAFloatingPointYValue+0.0227f

float_yb=float(y+1)/44.0f;//CreateAFloatingPointYValue+0.0227f

Weusethefourvariablesaboveforthetexturecoordinates.Eachofourpolygons(s

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

当前位置:首页 > 初中教育 > 理化生

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

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