计算机图形学报告太阳系.docx
《计算机图形学报告太阳系.docx》由会员分享,可在线阅读,更多相关《计算机图形学报告太阳系.docx(17页珍藏版)》请在冰豆网上搜索。
计算机图形学报告太阳系
SolarSystem
计算机图形学
课程报告
文档编号:
报告名称:
算法设计
编写:
谢天添05
编写日期:
2009-12
指导老师:
李征
审核日期:
1图形学基本原理
1.1几何变换相关原理
几何变换所涉及坐标系和变换如下:
Objectcoordinates---modelviewMatrix
eyecoordinates—projectionmatrix
clipcoordinate----perspectiveMatrix
normalizeddevicecoordinates---viewportTransformation
windowcoordinates.
1.2几何图形像素化相关原理
几何图形像素化就是几何图形经过一系列的变换后储存在帧缓存中的图形,经过其他的一些操作后,将输出到屏幕坐标。
由于光栅化前这些坐标是浮点连续的。
而屏幕坐标系是离散的像素点。
几何图形像素画就是将这些连续的图形变为离散的像素点集并且确保正确的渲染。
如果没有该步骤,几何图形是不能渲染到使用像素的屏幕坐标。
1.3光照模型相关原理
点光源:
向四面八方发射光线的单点。
聚光灯光源:
从特定地点射向特定方向的光源。
平行光源:
从无限远处射来的点光源。
面光源:
从一个平面发出平行光的光源。
最终的每个像素color输出为几何点在光珊化中环境光,漫反射和镜面光的叠加。
2系统界面与操作说明(阐述如何操作你的软件)
2.1系统界面与图形显示示例
左下角:
camera的数据,当前帧率。
2.2操作说明(配合图示进行说明)
在该太阳系中,提供以下几个键:
F:
摄像机到目标物体的距离增加5。
R:
摄像机到目标物体的距离减少5。
[:
开启或关闭反锯齿。
鼠标左键按住不放时,左右上下移动改变摄像机相对目标物体的位置,
但是不改变距离
选取一个星球,摄像机自动飞向该星球:
未操作前截图:
按F后
按R:
鼠标左键不放左上拖动
过程图片:
到达图片:
目前在反据此模式下,点击“[”关闭反锯齿:
这里只有通过帧数的改变显示出改变
3源程序:
3.1太阳系概述:
太阳系(SolarSystem)就是我们现在所在的恒星系统。
它是以太阳为中心,和所有受到太阳引力约束的天体的集合体:
8颗行星冥王星已被开除、至少165颗已知的卫星,和数以亿计的太阳系小天体。
这些小天体包括小行星、柯伊伯带的天体、彗星和星际尘埃。
广义上,太阳系的领域包括太阳、4颗像地球的内行星、由许多小岩石组成的小行星带、4颗充满气体的巨大外行星、充满冰冻小岩石、被称为柯伊伯带的第二个小天体区。
在柯伊伯带之外还有黄道离散盘面、太阳圈和依然属于假设的奥尔特云。
模拟太阳系不仅仅是完成作业,也能让我们更近一步的了解太阳系,拓广知识面,对行星的运行有基本的感性和理性感知。
增加我们对宇宙探索的渴望,可能培养出又一批天文学家。
3.2数据收集:
要模拟太阳系的运行首先需要他们的数据,这里我收集了“9”大行星,太阳,月球数据如下:
行星
a(AU)
轨道
周期(yr)
i(deg)
e
自转周期
自转轴
倾斜(度)
质量(地球)
半径(地球)
水星
0
金星
244d
-2
地球
火星
木星
318
土星
天王星
海王星
冥王星
248
122
10^3km
d
10^20kg
km
月球
385
730
1738
a=轨道半长轴
i=轨道倾角
e=轨道偏心率
1AU=0km
质量和半径是对于地球的相应值的相对值
地球质量=*10^27次方
地球赤道半径=6378km
以上每列数据是每个星球必有的。
通过这些属性,以地球为标准,获取行星的运动方程就可以模拟出行星的运动轨迹和位置等数据。
现在还需要的外部数据就是:
每个行星的纹理。
在纹理选择上。
我使用的是分辨率为256*256RBGA的tga格式文件。
使用自己编写的一个类
resourceImage派生于C4_Image.读取该纹理。
以在渲染时使用。
在这个程序中,假设所有星球的运动轨迹是圆。
而非椭圆。
这样就简化了程序在编写时的复杂度。
并且假设程序不考虑万有引力。
3.3类设计:
在该太阳系中类图关系如下:
3.3.1MainClass
baseGameEntity:
提供的最主要功能为:
为每一个实体提供一个独特的ID.以便为绑定纹理,选择,提供方便,以免冲突。
MovingEntity:
提供实体的up,front,speed等参数。
Galaxy:
是星系的抽象体,他具有个天空球(CSkySphere)和他所包含的星球(star)的集合。
Star:
是一个星球的抽象实体。
他具有表中的属性,除此还有一个CSkySphere。
这里CSkySphere作为该星球的球体渲染时的纹理和顶点信息。
由于每个星球可能也有他的卫星,他的卫星也可能还有卫星。
所以每个star中都有一个star的集合.
ChaseCamera:
提供围绕一个星球旋转的功能;
提供调整到星球距离的功能;
C4_Image:
从文件加载32位,24位或8位tga格式的纹理。
保存到一个unsignedchar数组中。
ResourceImage:
对C4_Image进行扩展。
可以加载DDS_DX1_decals_compressed,DDS_DX1_CUBMAP两类文件。
但是由于DDS_DX1_CUBMAP显示分辨率太低,所以就没有用cubmap.这使得没有使用cubmap而是使用自己写的天空球来模拟环境纹理。
3.3.2辅助类:
类图如下:
这6个类为辅助类,每一个需要渲染的物体都有一个C4_Material.
matrix3Dmatrix4D,vector3D,vector4D提供基本的几何运算,不用多说。
C4_Light提供创建8个光源实例。
在程序中使用了1个光源。
3.3.3模块增强类:
所谓模块增强类,就是提供更好的图形显示或更多的功能。
该太阳系提供3个增强模块,3个功能:
1),C4_Selector:
对派生于baseGameEntity的物体提供鼠标选择功能。
2),C4_Antialiasing:
提供全局的antialiasing,反锯齿(反走样),使用的是glaccum.
3),C4_CgEffect:
提供高级顶点,片段编程。
基于NVADIA的.(openglversion:
>=)
以上为对程序的一些类的简介。
不过大体就这15个类。
(2,3运行截图请参看附录)
3.4功能设计:
3.4.1反锯齿:
在太阳系中使用了2组jitter系数,让projectionmatrix产生微小位移,然后渲染物体。
将两次渲染的结果累计到缓存区,然后渲染出来。
使用前后对比:
前后
使用的样本数据:
doublej2[][2]={{,},{,}};(参考theredbook累积缓冲区)
在使用glCalllist调用一个非常冗余的圆的渲染时在开启反锯齿后在同样的情况下,每秒的帧数只有6帧/秒,而改进之后帧数达到了9帧/秒左右。
在原来情况下每个顶点要被渲染4次。
改进后每个点被渲染2次。
如果要进一步的该进,就要使用索引。
由于时间关系就不再优化。
以下为改进前和改进后的性能对比。
改进前:
改进后
对比。
由该表可以看出glAccum所使用的时间之巨大,也可以让我们了解到渲染时顶点越少越好。
3.4.2帧率
但是如果不开启反锯齿,改进前和改进后的区别基本上没有。
都是20帧左右。
但是,不过为什么无论我怎么调,该帧数都不变。
例如将太阳系中的行星删除掉80,禁用光源,但是帧数依然不变。
最终发现是glutTimerFunction中设置问题。
开始设置的1/。
而后当我设置成1/时。
帧数变为32帧左右。
当我继续减少该值的时候。
无反锯齿下,最多可以达到66帧,反锯齿下反而有所降低到8~9帧。
但是此时又有一个问题。
当帧数载66帧左右的时候。
有某个瞬间尤其不稳定可能突然渲染时间降低到以下或突然上升到。
此时.就需要一个采样的队列对时间进行采样使得物体和镜头的移动更加平滑。
在程序中我使用了一个最简单的方法,求最近n次的平均帧长。
这里应该设置一个比率。
越早的数据权重应该越低。
以下为部分代码。
#defineFRAMESAMPLESIZE100
intcurframeSample=0;
floatframe[FRAMESAMPLESIZE]={0};
curframeSample=(curframeSample+1)%FRAMESAMPLESIZE;
frame[curframeSample]=time_eclipse;
updateTime=0;
for(inti=0;i{updateTime+=frame[i];}updateTime/=FRAMESAMPLESIZE;这样问题也很多,例如每次runtime更改程序引起的帧改变要过一段时间才能反应真实的帧率。这里就不多说了。现在要解决的问题是如何让反锯齿状态下帧速率更高。如果将全局的glAccum换为对每个物体进行积累的话:也就是将glAccum换到每一个物体上去的话会不会有更好的效果结果是不会,帧数降低到1帧。除了将glAccum换到局部去渲染每个行星外,没有任何变化情况下的函数调用时间比例。对比值可以看出。glAccum在一次渲染中不能过多的调用,很消耗资源。目前使用glaccum还没找到好的方法。3.4.3大气云层地球大气有云层。所以可以在地球上添加一个有云纹理的球,然后混合,混合代码如下。boolbEnable=glIsEnabled(GL_BLEND);boolbCullEnable=glIsEnabled(GL_CULL_FACE);if(!bEnable)glEnable(GL_BLEND);if(bCullEnable)glDisable(GL_CULL_FACE);glDepthMask(false);glEnable(GL_ALPHA_TEST);glAlphaFunc(GL_GREATER,0);glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_DST_ALPHA);glScalef,,;this->m_pAtmosphere->Render();glDisable(GL_ALPHA_TEST);if(!bEnable)glDisable(GL_BLEND);if(bCullEnable)glEnable(GL_CULL_FACE);glDepthMask(true);截图如下:从左到右分别为:太阳,月球,金星,地球。由于没找到好的云图片,效果就只有这样了。不过这依然还需要改进。3.4.4太阳特效太阳应该看起来有一点流动效果,并且太阳的周围应该还有飞出的火焰,也就是类似于光晕的光圈。这就有2个问题。1,流动,2,光圈(glow)。3.4.4.1流动流动如果在常规的管道流程中来生成,对太阳的每个顶点进行变换或纹理。是比较耗费时间的。所以这里在程序中使用了NVIDIA的cg(支持及其以上)。我的电脑最多支持,所以就只有用cg所支持的fragmentshader和vertexshader.这里只是对顶点进行放缩。floatdisplacement=scaleFactor**sin*frequency*time)+1;float4displacementDirection=float4,,,0);float4newPosition=position+displacement*displacementDirection;oPosition=mul(modelViewProj,newPosition);这里,对于每个顶点,都会在其法向量方向进行震动。具有相同y值的顶点会有相同的幅度,在法线方向的长度相同。这样又y值的不一样,在视觉上就有起伏感觉。而在modelviewproj构造时会有一个根据时间增加的旋转值。这样看起来每个顶点都在起伏并且移动。在贴了纹理后就有点流体的感觉。这是在使用cg时的太阳这是在没有使用时的图片但是太阳的反锯齿由于cg的特性(在渲染cg前的所有其他非cg的函数操作都对其没有作用)而变没了。3.4.4.2Glow:目前我在opengl下还没弄出来………不过班上有同学在dx下已经弄出来了。3.4.5光属性如果你查看附录的图像时,你会发现及时是很远的行星向光面都很亮,因为光的衰减函数如下:F(x)=1/(1+;Yx01000AU3.5代码实现:只将关键代码罗列如下:3.5.1Star类:/**/#pragmaonce#include""#include""#include""#include/*astarhasaskyspheretoshowitsoutsidepattern*/classStar:publicMovingEntity{private:CSkySphere*m_sSphere;C4_Materialm_c4Mat;std::vector*m_pvSatellite;charm_szStarName[10];CSkySphere*m_pAtmosphere;public:Star(intid,floatinMass,floatinRadiu,floatinAU,floatinYr,floatinDeg,floatinE,constchar*texFileName,floatinRPeriod=0,floatinRotInc=0,constchar*starName="NONE");~Star(void);public:floatm_fDeg;,CameraMgr->getPos().y,CameraMgr->getPos().z};cgSetParameter3fv(m_pCgEffect->getVsParam("eyePosition"),eyePosition);Vector4Dv=ProjectM*viewM*Vector4D(1,0,0,1);cgSetParameter3dv(m_pCgEffect->getVsParam("lightPosition"),());cgSetParameter1d(m_pCgEffect->getVsParam("time"),time);m_pCgEffect->UpdateFsParam();m_pCgEffect->UpdateVsParam();if(this->isSelectEnable()){glLoadName(this->getID());}::C4_checkForCgError("beforerenderingscene");this->m_sSphere->Render();m_pCgEffect->DisableTexture("sun");m_pCgEffect->EndVsEffect();m_pCgEffect->EndFgEffect();return;}#endifErrorCheck1("beforerenderstar");glPushMatrix();ga/(GLfloat)iStacks;GLfloatdtheta=*(GLfloat)(3.)/(GLfloat)iSlices;GLfloatds=/(GLfloat)iSlices;GLfloatdt=/(GLfloat)iStacks;GLfloatt=;GLfloats=;GLinti,j;Thishoweverintroducestexturing.);voidAxis();voidErrorCheck(char*string);voidInit();:changeTarget=!changeTarget;break;case'[':if(g_pAntil)g_pAntil=NULL;elseg_pAntil=ComPonentAntiAnliase;break;case27:exit(0);break;default:break;}glutPostRedisplay();}\n";.){va_listargs;charbuffer[255],*s;va_start(args,format);vsprintf(buffer,format,args);va_end(args);glRasterPos2i(x,y);for(s=buffer;*s;s++)glutBitmapCharacter(font_style,*s);}floatlastFrame=0;voidPrintHelp(){intstep=16;intuper=200;f%.3f%.3f)",(float)g_pCamera->getPos().x,(float)g_pCamera->getPos().y,(float)g_pCamera->getPos().z);drawstr(10+3*12,uper-=step,"Up:(%.3f%.3f%.3f)",(float)g_pCamera->getUp().x,(float)g_pCamera->getUp().y,(float)g_pCamera->getUp().z);drawstr(10,uper-=step,"Cameratheta=%.3f",(float)g_pCamera->getTheta());drawstr(10,uper-=step,"Cameragama=%.3f",(float)g_pCamera->getGama());drawstr(10,uper-=step,"TargetPos:(%.3f%.3f%.3f)",(float)g_pCamera->getTargetPos().x,(float)g_pCamera->getTargetPos().y,(float)g_pCamera->getTargetPos().z);f",updateTime>01/updateTime:0); //drawstr(}voidInitFog(){//setfogparametersglEnable(GL_FOG);GLfloatfogColor[4]={,,,};glFogi(GL_FOG_MODE,GL_EXP);glFogfv(GL_FOG_COLOR,fogColor);glFogf(GL_FOG_DENSITY,;glHint(GL_FOG_HINT,GL_DONT_CARE);glFogf(GL_FOG_START,10);glFogf(GL_FOG_END,200);}voidInitGlowTexture(){glBindTexture(GL_TEXTURE_2D,2000);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);//filter::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);::C4_Imagem;("image/glow/");//getanddrawgluBuild2DMipmaps(GL_TEXTURE_2D,(),(),()(),GL_UNSIGNED_BYTE,());}4小结4.1总结在原理理解、程序设计中所遇到的困难是如何解决的,可以举出1至2个例子。困难有一个:如何在opengl下实现glow(光晕)。找到了相关文章,但是是dx下面的,只有理论描述,没有代码参考。但是还没有解决该问题。4.2总结本门课程所学到的知识。本门课所学到的最重要的知识是将各个变换矩阵的行列完全弄清楚。5参考文献(1)参考文献列表OpenGL编程指南(原书第6版)GPUgems6运行截图无反锯齿,启用cg使太阳流动启用反据此,未启用cg
{
updateTime+=frame[i];
}
updateTime/=FRAMESAMPLESIZE;
这样问题也很多,例如每次runtime更改程序引起的帧改变要过一段时间才能反应真实的帧率。
这里就不多说了。
现在要解决的问题是如何让反锯齿状态下帧速率更高。
如果将全局的glAccum换为对每个物体进行积累的话:
也就是将glAccum换到每一个物体上去的话会不会有更好的效果结果是不会,帧数降低到1帧。
除了将glAccum换到局部去渲染每个行星外,没有任何变化情况下的函数调用时间比例。
对比值
可以看出。
glAccum在一次渲染中不能过多的调用,很消耗资源。
目前使用glaccum还没找到好的方法。
3.4.3大气云层
地球大气有云层。
所以可以在地球上添加一个有云纹理的球,然后混合,混合代码如下。
boolbEnable=glIsEnabled(GL_BLEND);
boolbCullEnable=glIsEnabled(GL_CULL_FACE);
if(!
bEnable)
glEnable(GL_BLEND);
if(bCullEnable)
glDisable(GL_CULL_FACE);
glDepthMask(false);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0);
glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_DST_ALPHA);
glScalef,,;
this->m_pAtmosphere->Render();
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDepthMask(true);
截图如下:
从左到右分别为:
太阳,月球,金星,地球。
由于没找到好的云图片,效果就只有这样了。
不过这依然还需要改进。
3.4.4太阳特效
太阳应该看起来有一点流动效果,并且太阳的周围应该还有飞出的火焰,也就是类似于光晕的光圈。
这就有2个问题。
1,流动,2,光圈(glow)。
3.4.4.1流动
流动如果在常规的管道流程中来生成,对太阳的每个顶点进行变换或纹理。
是比较耗费时间的。
所以这里在程序中使用了NVIDIA的cg(支持及其以上)。
我的电脑最多支持,所以就只有用cg所支持的fragmentshader和vertexshader.这里只是对顶点进行放缩。
floatdisplacement=scaleFactor**sin*frequency*time)+1;
float4displacementDirection=float4,,,0);
float4newPosition=position+displacement*displacementDirection;
oPosition=mul(modelViewProj,newPosition);
这里,对于每个顶点,都会在其法向量方向进行震动。
具有相同y值的顶点会有相同的幅度,在法线方向的长度相同。
这样又y值的不一样,在视觉上就有起伏感觉。
而在modelviewproj构造时会有一个根据时间增加的旋转值。
这样看起来每个顶点都在起伏并且移动。
在贴了纹理后就有点流体的感觉。
这是在使用cg时的太阳这是在没有使用时的图片
但是太阳的反锯齿由于cg的特性(在渲染cg前的所有其他非cg的函数操作都对其没有作用)而变没了。
3.4.4.2Glow:
目前我在opengl下还没弄出来………不过班上有同学在dx下已经弄出来了。
3.4.5光属性
如果你查看附录的图像时,你会发现及时是很远的行星向光面都很亮,因为光的衰减函数如下:
F(x)=1/(1+;
Y
x
01000AU
3.5代码实现:
只将关键代码罗列如下:
3.5.1Star类:
/*
*/
#pragmaonce
#include""
#include
astarhasaskyspheretoshowitsoutsidepattern
classStar:
publicMovingEntity
private:
CSkySphere*m_sSphere;
C4_Materialm_c4Mat;
std:
:
vector*m_pvSatellite;
charm_szStarName[10];
CSkySphere*m_pAtmosphere;
public:
Star(intid,
floatinMass,floatinRadiu,
floatinAU,floatinYr,floatinDeg,floatinE,
constchar*texFileName,
floatinRPeriod=0,floatinRotInc=0,
constchar*starName="NONE");
~Star(void);
floatm_fDeg;,CameraMgr->getPos().y,CameraMgr->getPos().z};
cgSetParameter3fv(m_pCgEffect->getVsParam("eyePosition"),eyePosition);
Vector4Dv=ProjectM*viewM*Vector4D(1,0,0,1);
cgSetParameter3dv(m_pCgEffect->getVsParam("lightPosition"),());
cgSetParameter1d(m_pCgEffect->getVsParam("time"),time);
m_pCgEffect->UpdateFsParam();
m_pCgEffect->UpdateVsParam();
if(this->isSelectEnable())
glLoadName(this->getID());
C4_checkForCgError("beforerenderingscene");
this->m_sSphere->Render();
m_pCgEffect->DisableTexture("sun");
m_pCgEffect->EndVsEffect();
m_pCgEffect->EndFgEffect();
return;
#endif
ErrorCheck1("beforerenderstar");
glPushMatrix();
ga
/(GLfloat)iStacks;
GLfloatdtheta=*(GLfloat)(3.)/(GLfloat)iSlices;
GLfloatds=/(GLfloat)iSlices;
GLfloatdt=/(GLfloat)iStacks;
GLfloatt=;
GLfloats=;
GLinti,j;Thishoweverintroducestexturing
.);
voidAxis();
voidErrorCheck(char*string);
voidInit();
changeTarget=!
changeTarget;
break;
case'[':
if(g_pAntil)
g_pAntil=NULL;
else
g_pAntil=ComPonentAntiAnliase;
case27:
exit(0);
default:
glutPostRedisplay();
\n";
.)
va_listargs;
charbuffer[255],*s;
va_start(args,format);
vsprintf(buffer,format,args);
va_end(args);
glRasterPos2i(x,y);
for(s=buffer;*s;s++)
glutBitmapCharacter(font_style,*s);
floatlastFrame=0;
voidPrintHelp()
intstep=16;
intuper=200;
f%.3f%.3f)",(float)g_pCamera->getPos().x,(float)g_pCamera->getPos().y,(float)g_pCamera->getPos().z);
drawstr(10+3*12,uper-=step,"Up:
(%.3f%.3f%.3f)",(float)g_pCamera->getUp().x,(float)g_pCamera->getUp().y,(float)g_pCamera->getUp().z);
drawstr(10,uper-=step,"Cameratheta=%.3f",(float)g_pCamera->getTheta());
drawstr(10,uper-=step,"Cameragama=%.3f",(float)g_pCamera->getGama());
drawstr(10,uper-=step,"TargetPos:
(%.3f%.3f%.3f)",(float)g_pCamera->getTargetPos().x,(float)g_pCamera->getTargetPos().y,(float)g_pCamera->getTargetPos().z);
f",updateTime>01/updateTime:
0);
//drawstr(
voidInitFog()
//setfogparameters
glEnable(GL_FOG);
GLfloatfogColor[4]={,,,};
glFogi(GL_FOG_MODE,GL_EXP);
glFogfv(GL_FOG_COLOR,fogColor);
glFogf(GL_FOG_DENSITY,;
glHint(GL_FOG_HINT,GL_DONT_CARE);
glFogf(GL_FOG_START,10);
glFogf(GL_FOG_END,200);
voidInitGlowTexture()
glBindTexture(GL_TEXTURE_2D,2000);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
//filter
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
C4_Imagem;("image/glow/");
//getanddraw
gluBuild2DMipmaps(GL_TEXTURE_2D,(),(),()
(),GL_UNSIGNED_BYTE,());
4小结
4.1总结在原理理解、程序设计中所遇到的困难是如何解决的,可以举出1至2个例子。
困难有一个:
如何在opengl下实现glow(光晕)。
找到了相关文章,但是是dx下面的,只有理论描述,没有代码参考。
但是还没有解决该问题。
4.2总结本门课程所学到的知识。
本门课所学到的最重要的知识是将各个变换矩阵的行列完全弄清楚。
5参考文献
(1)参考文献列表
OpenGL编程指南(原书第6版)
GPUgems
6运行截图
无反锯齿,启用cg使太阳流动
启用反据此,未启用cg
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1