当看完这一课之后,我开始感觉我对OpenlGL有了一定基础了.我不知道为什么.我能够很好理解它.
lesson_9当中并没有多大新的知识.全是我们之前所学的.却需要完整的组织起来.希望它产生一个漂亮的图形.
初看小星星的德数据结构,我并为能够得出全部的东西.
typedef struct {
GLint r,g,b;
GLfloat dist;
GLfloat angle;
}stars; 最初看到这个数据结构的时候我以为星星应当是个点.结果我错了.因为我看完之后我忽然明白了不管我们组织任何的图元,我们都可以将它看成"点".而最后在于我们如何来表示这个点罢了.矩阵变换也是基于点.
就像是像素一样.我们始终会认为它仅仅只是个像素点.然其实应该是个具有面积的小方格.
所以星星的表示.这一课我们也需要使用小方格.这不仅用在这里.也将用于许多许多.如粒子.等.
而这一课也给了我一个空间感很强的变换操作,这让我更倾向于使用局部坐标系来考虑整个变化的过程.因为这让我更能明白 我最后所绘制的图形的位置.
对于每个星星我们需要一个小正方形来表示.结果在此贴上星星的纹理,在配合混色操作就能达到非常完美的效果.我们看代码:我希望我的注释能够非常易懂的明白:
/**//** 以下变换的目的在于,我可以使得星星距离中心dist的一圈,因平移x位移时候,x轴已经被旋转至一定方向了*/
glTranslatef(0.0,0.0,zoom); /**//** 深入屏幕里面*/
glRotatef(tilt,1.0,0.0,0.0);/**//** 倾斜角度..x轴 */
glRotatef(star[loop].angle,0.0,1.0,0.0); /**//**当前星星所在的角度*/
glTranslatef(star[loop].dist,0.0,0.0);/**//** x轴平移 */
glRotatef(-star[loop].angle,0.0f,1.0f,0.0f); // 取消当前星星的角度
glRotatef(-tilt,1.0f,0.0f,0.0f); // 取消屏幕倾斜
而对于每个星星若要启动闪烁效果.我们只需要为它绘制两次.以达到一个看起来是在闪烁的效果
总体代码如下:
lesson_9
#include "openglglut.h"
#include "BmpLoader.h"
bool twinkle=false;
bool tp=false;
const int num = 50;
typedef struct {
GLint r,g,b;//颜色
GLfloat dist;//距中心点距离
GLfloat angle;//绕y轴角度
}stars;
stars star[num];
GLfloat zoom = -15.f;
GLfloat tilt=90.0f;
GLfloat spin;
GLuint loop;
GLuint texture[1];
bool LoadBmpTexture(const char* filename,GLuint& texid)
{
BmpLoader bmp;
if(!bmp.loadBitmap((char*)filename))
{
printf("loadBitmap error\n");
return false;
}
glPixelStorei(GL_UNPACK_ALIGNMENT,4); /**//** ? */
glGenTextures(1,&texid); /**//** 创建一个纹理*/
glBindTexture(GL_TEXTURE_2D,texid); /**//** 为它指定一个纹理*/
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); /**//** 线性滤波 */
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); /**//** 线性滤波 */
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,bmp.bitInfo->biWidth,bmp.bitInfo->biHeight
,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.image); /**//** 生成纹理*/
//bmp.Free();
return true;
}
void InitStar()
{
for(loop=0;loop<num;loop++)
{
star[loop].angle=0.0;
star[loop].dist=(loop/num)*5.0f;
star[loop].r=rand()%256;
star[loop].g=rand()%256;
star[loop].b=rand()%256;
}
}
int main(int argc,char** argv)
{
createWindow("opengl lesson_6",&argc,argv); /**//** 初始化并创建窗口*/
glutDisplayFunc(glutDisplay); /**//** 注册重绘函数*/
glutIdleFunc(glutIdle); /**//** 注册空闲回调函数*/
glutReshapeFunc(glutResize); /**//** 注册窗口调整函数*/
glutSpecialFunc(glutSpecial); /**//** 注册特殊按键窗口*/
glutKeyboardFunc(glutKeyboard); /**//** 注册键盘处理函数*/
InitStar(); /**//** 初始化本例中星星数据*/
InitTexture(); /**//** 初始化启用纹理映射并加载纹理*/
InitBlend(); /**//** 初始化混色*/
InitOpenGL(); /**//** 初始化opengl 这节课有必要注释掉这个函数中的深度测试的两句代码*/
glutMainLoop(); /**//** 仿真循环*/
}
void InitBlend()
{
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glEnable(GL_BLEND);
}
void InitTexture(void)
{
/**//** 读入工程目录下data文件中的bmp文件*/
if(!LoadBmpTexture("..\\Data\\Star.bmp",texture[0]))
{
printf("load texture error!\n");
exit(0);
}
/**//** 若载入纹理成功 则启用纹理映射*/
glEnable(GL_TEXTURE_2D);
}
void glutDisplay()
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D,texture[0]);
for(loop=0;loop<num;loop++)
{
glLoadIdentity();
/**//** 以下变换的目的在于,我可以使得星星距离中心dist的一圈,因平移x位移时候,x轴已经被旋转至一定方向了*/
glTranslatef(0.0,0.0,zoom); /**//** 深入屏幕里面*/
glRotatef(tilt,1.0,0.0,0.0);/**//** 倾斜角度..x轴 */
glRotatef(star[loop].angle,0.0,1.0,0.0); /**//**当前星星所在的角度*/
glTranslatef(star[loop].dist,0.0,0.0);/**//** x轴平移 */
glRotatef(-star[loop].angle,0.0f,1.0f,0.0f); // 取消当前星星的角度
glRotatef(-tilt,1.0f,0.0f,0.0f); // 取消屏幕倾斜
if (twinkle) // 启用闪烁效果
{
// 使用byte型数值指定一个颜色
glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
glBegin(GL_QUADS); // 开始绘制纹理映射过的四边形
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd(); // 四边形绘制结束
}
glRotatef(spin,0.0f,0.0f,1.0f); // 绕z轴旋转星星
// 使用byte型数值指定一个颜色
glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
glBegin(GL_QUADS); // 开始绘制纹理映射过的四边形
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd(); // 四边形绘制结束
spin+=0.01f; // 星星的公转
star[loop].angle+=float(loop)/num; // 改变星星的自转角度
star[loop].dist-=0.01f; // 改变星星离中心的距离
spin+=0.01;
if (star[loop].dist<0.0f) // 星星到达中心了么
{
star[loop].dist+=5.0f; // 往外移5个单位
star[loop].r=rand()%256; // 赋一个新红色分量
star[loop].g=rand()%256; // 赋一个新绿色分量
star[loop].b=rand()%256; // 赋一个新蓝色分量
}
}
glutSwapBuffers();
}
void glutIdle()
{
glutPostRedisplay();
}
void glutKeyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 27: /**//** Esc按键按下后退出程序 */
exit(0);
break;
case 't':
case 'T':
twinkle=!twinkle;
default:
break;
}
}
void glutSpecial(int value, int x, int y)
{
switch (value)
{
case GLUT_KEY_F1: // 按F1键时切换窗口/全屏模式
if(isFullScreen)
{
glutReshapeWindow(GL_WIN_WIDTH, GL_WIN_HEIGHT);
glutPositionWindow(GL_WIN_INITIAL_X, GL_WIN_INITIAL_Y);
isFullScreen = false;
}
else
{
glutFullScreen();
isFullScreen = true;
}
return;
default:
return;
}
}
效果图:
posted on 2009-08-08 17:48
米游 阅读(622)
评论(1) 编辑 收藏 引用 所属分类:
OpenGL/OSG