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] 斯坦福兔子与显示列表的更多相关文章

  1. OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别

    OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...

  2. OpenGL(八) 显示列表

    OpenGL在即时模式(Immediate Mode)下绘图时,程序中每条语句产生的图形对象被直接送进绘图流水线,在显示终端立即绘制出来.当需要在程序中多次绘制同一个复杂的图像对象时,这种即时模式会消 ...

  3. NeHe OpenGL教程 第十二课:显示列表

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. 第12课 OpenGL 显示列表

    显示列表: 想知道如何加速你的OpenGL程序么?这一课将告诉你如何使用OpenGL的显示列表,它通过预编译OpenGL命令来加速你的程序,并可以为你省去很多重复的代码. 这次我将教你如何使用显示列表 ...

  5. 字符图元 & 显示列表

    [字符图元] 1.typeface(字样),即设计风格,如Courier等. 2.font(字体),如10磅Courier斜体. 3.monspace即为等宽字体,proportional为非等宽字体 ...

  6. 尝试使用Osg共享渲染描述表(HGLRC)实现多线程编译显示列表--总结

    在realize()前打开预编译选项指令: osg::DisplaySettings::instance()->setCompileContextsHint(true);    mpr_osgv ...

  7. SharePoint 2013 自定义翻页显示列表项

    项目需求:自定义开发一个能分页显示列表项的小部件,允许左右翻页,能根据用户权限来显示管理链接等. 效果如下: 技术要求:使用sharepoint rest API 来获取列表项,这样性能高,能够快速响 ...

  8. 小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果

    0x00 前言 发现最近没有了写长篇大论的激情,可能是到了冬天了吧.所以这篇小文只是简单介绍下如何在Unity中利用shader很简单的实现雪地效果以及毛皮效果,当然虽然标题写在了一起,但其实这是俩事 ...

  9. Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表

    Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...

随机推荐

  1. python测试开发django-11.模型models详解

    前言 Django 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库 只需要在settings ...

  2. Work Management Service application in SharePoint 2016

    最近开始弄SharePoint 2016的Workflow,遇到问题发现没有了Work Management Service application,然后用PowerShell命令创建也不行,bing ...

  3. 用SDWebImage加载FLAnimatedImage

    用SDWebImage加载FLAnimatedImage 效果 源码 https://github.com/YouXianMing/Animations // // GifPictureControl ...

  4. .Net Excel操作之NPOI(二)常用操作封装

    一.Excel数据导出常用操作 1.指定表头和描述 2.指定数据库中读出的数据集合 二.ExcelExport封装 /// <summary> /// Excel常用的表格导出逻辑封装 / ...

  5. SVG.js 文本绘制整理

    1.SVG.Text var draw = SVG('svg1').size(300, 300); //画文字内容展示 //var text = draw.text('中文内容测试\n换行处理'); ...

  6. delete method not allowed 405错误

    造成该问题的原因:iis版本问题 解决办法如下: 修改配置文件web.config <system.webServer><modules><remove name=&qu ...

  7. cull/clip distance example

      http://www.gamedev.net/topic/578866-d3d10-how-to-increase-maxcount-of-sv_clipdistance/ The D3D#_CL ...

  8. Asp.net WebAPi gzip压缩和json格式化

    现在webapi越来越流行了,很多时候它都用来做接口返回json格式的数据,webapi原本是根据客户端的类型动态序列化为json和xml的,但实际很多时候我们都是序列化为json的,所以webapi ...

  9. 如何得知当前机器上安装的PowerShell是什么版本的?

    $PSVersionTable.PSVersion   参考资料 ================ http://stackoverflow.com/questions/1825585/determi ...

  10. Android传感器应用——重力传感器实现滚动的弹球

    一. 问题描述 Android中有多达11种传感器,不同的手机设备支持的传感器类型也不尽相同 1. 重力传感器 GV-sensor 2. 加速度传感器 G-sensor 3.  磁力传感器  M-se ...