[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基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...
随机推荐
- Kali Linux 与 BackTrack Linux
(一)BackTrack BackTrack是基于Ubuntu的自启动运行光盘,它包含了一套安全及计算机取证工具.它其实是依靠融合Auditor Security Linux和WHAX(先前的Who ...
- 寂静之地百度云在线观看迅雷下载A Quiet Place高清BT下载
原名:A Quiet Place 地区:美国 语言:英语 / 美国手语 首播:2018-05-18(中国大陆) / 2018-03-09(西南偏南电影节) / 2018-04-06(美国) 电视台 ...
- 行尸走肉第八季/全集The Walking Dead迅雷下载
<行尸走肉第八季>将在10月22号回归播出, 将于5月1日起正式开始拍摄!目前剧组已开始招募客串演员和丧尸群演,第八季拍摄时长初步预计会持续到11月16日.而这三位已确认为<行尸走肉 ...
- 详细解读Volley(三)—— ImageLoader & NetworkImageView
ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码中没有提供磁盘缓存的设置,所以咱们还需要去源码中进行修改,让我们可以更加自如的设定是否进行磁盘 ...
- 代码实现Android5.0的下拉刷新效果
如图所示,实现类似与gmail的下拉刷新. 项目地址:https://github.com/stormzhang/SwipeRefreshLayoutDemo 一.在xml文件中定义 这个控件在sup ...
- Android安装和设置的方法
问题:gradle project sync failed 1.进入C:\Users\自己的用户名\.gradle\wrapper\dists\gradle-1.12-all\2apkk7d25mia ...
- mongodb分布式集群搭建手记
一.架构简介 目标单机搭建mongodb分布式集群(副本集 + 分片集群),演示mongodb分布式集群的安装部署.简单操作. 说明在同一个vm启动由两个分片组成的分布式集群,每个分片都是一个PSS( ...
- jquery fullPage
FROM : http://www.dowebok.com/77.html 应用: http://txhd.163.com/
- intellij idea 如何一键清除所有断点
原文地址: https://blog.csdn.net/yanziit/article/details/73459795 我之前写了一个百度经验,但是搜不到,现在复制一遍,自己留个记录. 注:此方法适 ...
- org.codehaus.jackson.map.JsonMappingException: Can not construct instance of java.util.Date from String value '20Spring Jackson 反序列化Date时遇到的问题
Jackson对于date的反序列化只支持几种,如果不符合默认格式则会报一下错误 org.codehaus.jackson.map.JsonMappingException: Can not cons ...