[OpenGL] 斯坦福兔子与显示列表
1.调整桌子的大小。
在OpenGL绘制长方体,能够通过函数:
glutSolidCube(Size)
绘制得到的是一个正方体,再利用缩放矩阵使其变成长方体。使得桌子的大小刚好能够放下16仅仅兔子。
2.兔子的增多降低
使用一个全局变量rabbitNum来记录兔子的数量。
在键盘回调函数中,在按下I,K后令rabbitNum添加或降低,并维护兔子的数量在1~16,等于16或1不再进行对应操作。
绘制兔子时。通过循环控制,每画完一仅仅兔子,平移一段距离,画到第4i+1仅仅兔子时。平移到下一行。
在普通绘制模式下,直接调用绘制桌子、兔子函数。
在显示列表绘制模式下。调用事先准备好的桌子显示列表和兔子显示列表来绘制。
3.FPS
fps的含义是每秒传输帧数,它的大小反映了绘制的流畅性。在这里我们须要计算普通以及显示列表模式下fps大小的差别。
计算fps。我们能够调用该函数:
glutGet(GLUT_ELAPSED_TIME);
该函数返回两次调用glutGet(GLUT_ELAPSED_TIME)的时间间隔,单位为毫秒。
通过得到两次调用的间隔时间,我们能够计算绘制图像的刷新帧率。
我们用frame变量存储帧数,两次间隔调用时间差大于1000ms时我们更新fps的值。依照定义fps = 帧数/时间。
调用例如以下函数:
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *c);
能够把字符变成位图显示在窗体中。
4.显示列表
通过调用:
glGenLists(int num)
我们得到了num个连续的显示列表,返回第一个显示列表。
glNewList(name,mode);
……
glEndList();
在这两者之间,写要增加显示列表的详细语句。
类似于数组。下一个显示列表仅仅需移动偏移值1就能够了得到名称了。
glCallList(name);
调用显示列表。
实验数据记录和处理
通过实验,我们发如今使用了显示列表的情况下,每秒刷新的帧率更高。它是一种快速的缓存,当我们须要重复地绘制同一物体时,能够将其存入显示列表,并在绘制时调用显示列表,这样就避免了由于重复调用而导致的重复计算。
缺点是不能动态绘制,也就是说我们后来在外面改动了一些变量的值,是不会影响到显示列表的。详细到此次实验来说,我们不能把绘制多次兔子的循环放入显示列表,由于循环的次数会随着兔子次数的变化而变化,而一旦载入入了显示列表,这样的动态是无法体现出来的,显示列表仅仅会存储最初始增加时的状态。所以我们仅仅能把绘制兔子的函数放入显示列表,而在普通的函数中进行循环控制。
// glutEx1.cpp : 定义控制台应用程序的入口点。
//
//注意FPS函数的应用 #include <stdlib.h>
#include "glut.h"
#include <stdio.h>
#include <string.h> #include "stanford_bunny.h" float eye[] = {0, 4, 6}; //眼睛位置
float center[] = {0, 0, 0}; //视点位置
float fDistance = 0.2f; //距离因子
float fRotate = 0; //旋转因子
bool bAnim = false; //是否旋转 bool bDrawList = false; //是否使用显示列表
GLint tableList=0; //桌子列表
GLint rabbitList = 0; //兔子列表
int rabbitNum = 1; //兔子数量 //绘制桌子
void DrawTable()
{
glPushMatrix();
glTranslatef(0, 3.5, 0);
glScalef(5, 1, 4); glPushMatrix();
glScalef(1.3, 0.4, 1.3);
glutSolidCube(1.0);
glPopMatrix(); glPopMatrix(); glPushMatrix();
glTranslatef(2.0, 0.5, 1.5);
glScalef(0.6, 5, 0.6);
glutSolidCube(1.0);
glPopMatrix(); glPushMatrix();
glTranslatef(-2.0, 0.5, 1.5);
glScalef(0.6, 5, 0.6);
glutSolidCube(1.0);
glPopMatrix(); glPushMatrix();
glTranslatef(2.0, 0.5, -1.5);
glScalef(0.6, 5, 0.6);
glutSolidCube(1.0);
glPopMatrix(); glPushMatrix();
glTranslatef(-2.0, 0.5, -1.5);
glScalef(0.6, 5, 0.6);
glutSolidCube(1.0);
glPopMatrix();
} GLint GenTableList()
{
GLint lid=glGenLists(2); //生成两个空的显示列表
glNewList(lid, GL_COMPILE); // 用于创建和替换一个显示列表函数原型
// 指定显示列表的名称,编译模式:仅仅编译 //第一个显示列表:画桌子
DrawTable();
glEndList(); //第二个显示列表:画兔子
glNewList(lid + 1, GL_COMPILE);
DrawBunny();
glEndList(); return lid; //返回显示列表编号
} void Draw_Table_List()
{
glPushMatrix();
glTranslatef(2.2, 4.5, 1.5); //平移与缩放
glScalef(2, 2, 2); for (int i = 1; i <= rabbitNum; i++) {
glCallList(rabbitList); //调用显示列表画兔子
if (i == 4 || i == 8 || i == 12) {
glTranslatef(2.1f, 0, -0.5f); //兔子换行
}
else glTranslatef(-0.7f, 0.0f, 0.0f); //兔子平移
}
glPopMatrix(); glCallList(tableList); //调用显示列表画桌子
} void DrawScene()
{
glPushMatrix();
glTranslatef(2.2, 4.5, 1.5);
glScalef(2, 2, 2); for (int i = 1; i <= rabbitNum; i++) {
DrawBunny(); //直接绘制兔子
if (i==4||i==8||i==12) {
glTranslatef(2.1f, 0, -0.5f); //兔子换行
}
else glTranslatef(-0.7f, 0.0f, 0.0f); //兔子平移
}
glPopMatrix(); DrawTable(); //直接绘制桌子
} void reshape(int width, int height)
{
if (height == 0)
{
height = 1; //高度为0时,让高度为1
} glViewport(0, 0, width, height); //设置视窗大小 glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影
glLoadIdentity(); //初始化矩阵为单位矩阵 float whRatio = (GLfloat)width / (GLfloat)height;
gluPerspective(45, whRatio, 1, 1000); //设置投影方位 glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型
} void idle()
{
glutPostRedisplay(); //调用当前绘制函数
} void key(unsigned char k, int x, int y)
{
switch(k)
{
case 27:
case 'q': {exit(0); break; } case 'a': //物体左移
{
eye[0] += fDistance;
center[0] += fDistance;
break;
}
case 'd': //物体右移
{
eye[0] -= fDistance;
center[0] -= fDistance;
break;
}
case 'w': //物体上移
{
eye[1] -= fDistance;
center[1] -= fDistance;
break;
}
case 's': //物体下移
{
eye[1] += fDistance;
center[1] += fDistance;
break;
}
case 'z': //靠近
{
eye[2] *= 0.95;
break;
}
case 'c': //远离
{
eye[2] *= 1.05;
break;
}
case 'l': // 切换显示列表和非显示列表绘制方式
{
bDrawList = !bDrawList;
break;
}
case ' ': //旋转
{
bAnim = !bAnim;
break;
}
case 'i': //兔子增多
{
if(rabbitNum<=15)rabbitNum++;
break;
}
case 'k': //兔子降低
{
if (rabbitNum>=2)rabbitNum--;
break;
}
default: break;
}
} void getFPS()
{
static int frame = 0, time, timebase = 0;
static char buffer[256]; //字符串缓冲区 char mode[64]; //模式
if (bDrawList) //是否用显示列表绘制
strcpy(mode, "display list");
else
strcpy(mode, "naive"); frame++;
time=glutGet(GLUT_ELAPSED_TIME);
//返回两次调用glutGet(GLUT_ELAPSED_TIME)的时间间隔,单位为毫秒
if (time - timebase > 1000) { //时间间隔差大于1000ms时
sprintf(buffer,"FPS:%4.2f %s",
frame*1000.0/(time-timebase), mode); //写入buffer中
timebase = time; //上一次的时间间隔
frame = 0;
} char *c;
glDisable(GL_DEPTH_TEST); // 禁止深度測试
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glPushMatrix(); // 保存原矩阵
glLoadIdentity(); // 装入单位矩阵
glOrtho(0,480,0,480,-1,1); // 位置正投影
glMatrixMode(GL_MODELVIEW); // 选择Modelview矩阵
glPushMatrix(); // 保存原矩阵
glLoadIdentity(); // 装入单位矩阵
glRasterPos2f(10,10);
for (c=buffer; *c != '\0'; c++) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *c); //绘制字符
}
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glPopMatrix(); // 重置为原保存矩阵
glMatrixMode(GL_MODELVIEW); // 选择Modelview矩阵
glPopMatrix(); // 重置为原保存矩阵
glEnable(GL_DEPTH_TEST); // 开启深度測试
} /*画图函数*/
void redraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//清除颜色和深度缓存
glClearColor(0, 0.5, 0, 1); //设置清除颜色
glLoadIdentity(); //初始化矩阵为单位矩阵 gluLookAt(eye[0], eye[1], eye[2],
center[0], center[1], center[2],
0, 1, 0);
// 场景(0,0,0)的视点中心 (0, 5, 50)。Y轴向上
// 视点位置。望向位置,头顶方向 glEnable(GL_DEPTH_TEST); //开启深度測试
glEnable(GL_LIGHTING); //开启光照
GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 }; //设置灰色
GLfloat light_pos[] = {10, 10, 10, 1}; //设置光源位置
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,gray); //指定整个场景的环境光强度
glLightfv(GL_LIGHT0, GL_POSITION, light_pos); //设置第0号光源的光照位置
glLightfv(GL_LIGHT0, GL_AMBIENT, gray); //设置第0号光源多次反射后的光照颜色(环境光颜色)
glEnable(GL_LIGHT0); //开启第0号光源 if (bAnim)
fRotate += 0.5f; //改变旋转因子
glRotatef(fRotate, 0, 1.0f, 0); //绕y轴旋转 glScalef(0.4, 0.4, 0.4); //缩放
if(!bDrawList)
DrawScene(); // 普通绘制
else
Draw_Table_List(); // 显示列表绘制 getFPS(); //得到每秒传输帧数(Frames Per Second)
glutSwapBuffers(); //交换缓冲区
} int main (int argc, char *argv[])
{
glutInit(&argc, argv);//初始化glut
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
//初始化显示模式:RGB颜色模型,双缓冲,深度測试
glutInitWindowSize(480,480);//设置窗体大小
int windowHandle = glutCreateWindow("Exercise 4");
//取得新建窗体的句柄
glutDisplayFunc(redraw);//注冊显示函数
glutReshapeFunc(reshape); //注冊重绘函数
glutKeyboardFunc(key); //注冊键盘回调事件
glutIdleFunc(idle); //注冊空暇回调事件 tableList = GenTableList(); //初始化显示列表
rabbitList = tableList + 1; glutMainLoop(); //开启时间循环
return 0;
}
[OpenGL] 斯坦福兔子与显示列表的更多相关文章
- OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别
OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...
- OpenGL(八) 显示列表
OpenGL在即时模式(Immediate Mode)下绘图时,程序中每条语句产生的图形对象被直接送进绘图流水线,在显示终端立即绘制出来.当需要在程序中多次绘制同一个复杂的图像对象时,这种即时模式会消 ...
- NeHe OpenGL教程 第十二课:显示列表
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 第12课 OpenGL 显示列表
显示列表: 想知道如何加速你的OpenGL程序么?这一课将告诉你如何使用OpenGL的显示列表,它通过预编译OpenGL命令来加速你的程序,并可以为你省去很多重复的代码. 这次我将教你如何使用显示列表 ...
- 字符图元 & 显示列表
[字符图元] 1.typeface(字样),即设计风格,如Courier等. 2.font(字体),如10磅Courier斜体. 3.monspace即为等宽字体,proportional为非等宽字体 ...
- 尝试使用Osg共享渲染描述表(HGLRC)实现多线程编译显示列表--总结
在realize()前打开预编译选项指令: osg::DisplaySettings::instance()->setCompileContextsHint(true); mpr_osgv ...
- SharePoint 2013 自定义翻页显示列表项
项目需求:自定义开发一个能分页显示列表项的小部件,允许左右翻页,能根据用户权限来显示管理链接等. 效果如下: 技术要求:使用sharepoint rest API 来获取列表项,这样性能高,能够快速响 ...
- 小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果
0x00 前言 发现最近没有了写长篇大论的激情,可能是到了冬天了吧.所以这篇小文只是简单介绍下如何在Unity中利用shader很简单的实现雪地效果以及毛皮效果,当然虽然标题写在了一起,但其实这是俩事 ...
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...
随机推荐
- WordPress基础:wp_list_pages显示页面信息列表
函数:wp_list_pages($args) 作用:列出某个分类下的分类项目 常见参数说明: 参数 用途 值 sort_column 排序方式 post_title 按标题排序 [默认] m ...
- SharePoint Designer 配置工作流后需要重启的问题
前言 最近,很多朋友配置SharePoint工作流以后,用SharePoint Designer打开站点,创建SharePoint 2013 工作流的时候,都会报一个错误. 查了很多帖子,发现是个De ...
- Linux下怎么确定Nginx安装目录
linux环境下,怎么确定nginx是以那个config文件启动的? 输入命令行: ps -ef | grep nginx 摁回车,将出现如下图片: master process 后面的就是 ngi ...
- jquery入门 改动网页背景颜色
我们在浏览一些站点,尤其是一些小说站点的时候,都会有改动页面背景颜色的地方,这个功能使用jquery非常easy实现. 效果图: show you code: <!doctype html> ...
- [转]PHP: 深入pack/unpack
From : http://my.oschina.net/goal/blog/195749 http://www.w3school.com.cn/php/func_misc_pack.asp PHP作 ...
- [转]Windows 下 Apache Virtual hosts 简单配置
From : http://blog.csdn.net/wuerping/article/details/4164362 /* Author : Andrew.Wu [ Created on : 20 ...
- swift:简单使用翻页控制器UIPageViewController
一.小叙 UIPageViewController是一个实现图书阅读的控制器,使用它可以设置书脊位置.单双页.过渡效果等,它是通过代理的方式来实现翻页,也即上一页.下一页.最终这个UIPageView ...
- 样条之拉格朗日Lagrange(一元全区间)插值函数
这是使用拉格朗日插值函数生成的样条曲线.在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法.许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过 ...
- @Autowired用法详解
@Autowired 注释,它可以对类成员变量.方法及构造函数进行标注,完成自动装配的工作. 通过 @Autowired的使用来消除 set ,get方法.在使用@Autowired之前,我们对一个b ...
- iOS 开发的一些网址
http://www.cnblogs.com/iCocos/p/4553291.html ios学习路线图,值得看一下你的哪些技术还没掌握到位还有就是往高级发展还差哪些知识(这个人的博客特别值得看,虽 ...