OpenGL编程(三)让矩形动起来
上次实现了在窗口中添加一个了一个矩形。这次的任务是在上次代码的基础上,让那个矩形动起来。
1、思路
要看到动态的效果,首先添加一个定时器,规定的时间刷新一次窗口;不断修改矩形的位置,使其在时间轴上达到动态的效果。
2、注册定时器
glutTimerFunc(33, timerFunction, 1); 33表示33毫秒后调用,timerFunction为回调函数,1为区别值(用以区分不同的定时器)。然后我们在timerFunction函数里修改矩形的坐标。因为注册一次定时器(glutTimerFunc)才会回调一次,所以要达到持续的效果,在timerFunction函数体内的末尾再是注册定时器回调自己glutTimerFunc(33, timerFunction, 1);
3、在定时器回调函数体内修改矩形的位置
假设矩形的左下角的位置为(x1, y1),每次回调我们修改x1,y1的值,让x1,y1加上或减去一个步长(向左运动是加,向右运动是减;向上运动是加,向下运动是减)。当x1的值大于等于窗口的宽度减去矩形的长(x1 > windowWidth - size)时x1开始改方向为减去步长x1 -= xstep;;当x1的值小于0时x1再次改为反方向为加步长(x1 += xstep;);同理y1也使用同样的方法处理。
4、重绘窗口
glutPostRedisplay();每次修改矩形的位置时要调用该函数重绘窗口。该函数的调用不是马上让GULT马上重绘窗口,而是先告诉GULT窗口已经改变,需要重新绘画,等GULT再次调用glutMainLoop()函数时会重回窗口,以达到窗口改变的效果。
完整代码如下:
#include <windows.h>
#include <gl/glut.h>
//animation.cpp
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei size = 50;
GLfloat xstep = 5.0f;
GLfloat ystep = 5.0f;
GLfloat windowWidth = 300.0f;
GLfloat windowHeight = 300.0f;
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT); //清空颜色缓冲池
glColor3f(1.0f, 0.0f, 0.0f); //设置绘图颜色
glRectf(x1, y1, x1 + size, y1 + size); //绘制矩形
glFlush(); //执行OpenGL指令列表中的指令
}
void timerFunction(int value)
{
if(x1 > windowWidth - size || x1 < 0)
xstep = -xstep;
if(y1 > windowWidth - size || y1 < 0)
ystep = -ystep;
if(x1 > windowWidth - size)
x1 = windowWidth - size - 1;
if(y1 > windowHeight - size)
y1 = windowHeight - size - 1;
x1 += xstep;
y1 += ystep;
glutPostRedisplay();
glutTimerFunc(33, timerFunction, 1);
}
void main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //设置显示模式
glutInitWindowSize(windowWidth, windowHeight); //设置窗口大小
glutInitWindowPosition(200, 200); //设置窗口在屏幕上的位置
glutCreateWindow("动画"); //创建窗口并给出标题
glutDisplayFunc(renderScene); //注册显示窗口时回调函数renderScene
glOrtho(0.0f, windowWidth, 0.0f, windowHeight, 1.0, -1.0); //修改修剪空间的范围
glutTimerFunc(33, timerFunction, 1); //注册定时器
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //使用蓝色清空背景底
glutMainLoop(); //消息循环(处理操作系统等的消息,例如键盘、鼠标事件等)
}
5、让动画看起来更顺畅
上面能看到了动画的效果,但是有时候看起来不是很顺畅,主要原因是上面使用的是单缓冲的技术(前面文章提到过),即在显示窗口执行绘图过程。应该把单缓冲改为双缓冲,即现在显示窗口外完成了绘图,然后再把已经渲染完成的绘图切换到显示窗口。要修改的地方有:glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 把GLUT_SINGLE改成GLUT_DOUBLE。同时把glFlush();改成glutSwapBuffers();
完整代码如下:
#include <windows.h>
#include <gl/glut.h>
//animation.cpp
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei size = 50;
GLfloat xstep = 5.0f;
GLfloat ystep = 5.0f;
GLfloat windowWidth = 300.0f;
GLfloat windowHeight = 300.0f;
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT); //清空颜色缓冲池
glColor3f(1.0f, 0.0f, 0.0f); //设置绘图颜色
glRectf(x1, y1, x1 + size, y1 + size); //绘制矩形
glutSwapBuffers();
}
void timerFunction(int value)
{
if(x1 > windowWidth - size || x1 < 0)
xstep = -xstep;
if(y1 > windowWidth - size || y1 < 0)
ystep = -ystep;
if(x1 > windowWidth - size)
x1 = windowWidth - size - 1;
if(y1 > windowHeight - size)
y1 = windowHeight - size - 1;
x1 += xstep;
y1 += ystep;
glutPostRedisplay();
glutTimerFunc(33, timerFunction, 1);
}
void main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //设置显示模式
glutInitWindowSize(windowWidth, windowHeight); //设置窗口大小
glutInitWindowPosition(200, 200); //设置窗口在屏幕上的位置
glutCreateWindow("动画"); //创建窗口并给出标题
glutDisplayFunc(renderScene); //注册显示窗口时回调函数renderScene
glOrtho(0.0f, windowWidth, 0.0f, windowHeight, 1.0, -1.0); //修改修剪空间的范围
glutTimerFunc(33, timerFunction, 1); //注册定时器
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //使用蓝色清空背景底
glutMainLoop(); //消息循环(处理操作系统等的消息,例如键盘、鼠标事件等)
}
6、效果
OpenGL编程(三)让矩形动起来的更多相关文章
- 用MFC实现OpenGL编程
一.OpenGL简介 众所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他们的图形工作站上开发高质量图像的接口.但最近几年它成为一个非常优秀的开放式 ...
- Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤
http://blog.csdn.net/vagrxie/article/details/4602961 Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤 wri ...
- OpenGL编程指南(第七版)
OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...
- OpenGL编程(一)渲染一个指定颜色的背景窗口
上次已经搭好了OpenGL编程的环境.已经成功运行了第一个程序.可只是照搬书上的代码,并没弄懂其中的原理.这次通过一个小程序来解释使用GLUT库编写OpenGL程序的过程. 程序的入口 与其他程序一样 ...
- [转]OpenGL编程指南(第9版)环境搭建--使用VS2017
1.使用CMake Configure中选择VS2017 Win64 , Finish: 点击Generate. 2.进入build目录 打开GLFW.sln , 生成解决方案. 打开vermilio ...
- 编译opengl编程指南第八版示例代码通过
最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...
- 在 Mac OS X Yosemite 10.10.5 上配置 OpenGL 编程环境
这个教程主要参考了youtube上的视频 Getting Started in OpenGL with GLFW/GLEW in Xcode 6 ,这个视频有点问题,不能照搬.本人通过自己摸(瞎)索( ...
- 用AE如何制作如下三个loading动效,
在本期象牙绘UED团队分享当中,我们将详细演示用AE如何制作如下三个loading动效, 其中涉及到AE表达式的应用.值曲线调整.速度曲线编辑等知识. 对于初学者来说可能信息量略大,希望通过是视频教程 ...
- Linux网络编程(三)
Linux网络编程(三) wait()还是waitpid() Linux网络编程(二)存在客户端断开连接后,服务器端存在大量僵尸进程.这是由于服务器子进程终止后,发送SIGCHLD信号给父进程,而父进 ...
随机推荐
- shareSDK的初步使用(shareSDK中微信、qq等兼容问题,以及cocoapods支持架构冲突问题的解决)
第一次使用shareSDK来做第三方分享,可是.昨天一天都是在调试bug,一直错误不断! 先说下我的开发环境: xcode:5.1 真机调试:iPhone5s 我们都知道xcode5.1以后開始是支持 ...
- Java知识点解析
JAVA 1:简述Java的基本历史 java起源于SUN公司的一个GREEN的项目,其原先目的是为家用消费电子产品 发送一个信息的分布式代码系统,通过发送信息控制电视机.冰箱等. 2:简单写出Jav ...
- c# 获取文件夹下面所有文件夹列表
方法一: string dirPath = @"D:\App1"; List<string> dirs = new List<string>(Directo ...
- doT中嵌套for循环的使用
1.数据结构 var goods = [ { "id": "1", "name": "衣服", "goods& ...
- C#语言基础之第一个C#程序
1.在记事本中编写如下代码,保存为Simple.cs文件. using System; class Hello World{ public static void Main(){ Console.Wr ...
- Codeforces 988E. Divisibility by 25
解题思路: 只有尾数为25,50,75,00的数才可能是25的倍数. 对字符串做4次处理,以25为例. a. 将字符串中的最后一个5移到最后一位.计算交换次数.(如果没有找到5,则不可能凑出25,考虑 ...
- Matplotlib 画廊
https://matplotlib.org/gallery.html
- js+css实现全局loading加载
js var Mask = function() { //定义一个Mask对象 this.btn = ["取消", "确定"], this.init = fun ...
- [LOJ2607]【NOIP2012】疫情控制
题意: 题目描述 H 国有n个城市,这n个城市用n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边 ...
- WPF内嵌WCF服务对外提供接口
要测试本帖子代码请记得管理员权限运行vs. 我写这个帖子的初衷是在我做surface小车的时候有类似的需求,感觉这个功能还挺有意思的,所以就分享给大家,网上有很多关于wcf的文章 我就不一一列举了.公 ...