opengl(七)

今天讲一下如何做动画,动画本质上就是一张一张的图片在很短的时间内放过去,以至于人们认为这是动起来的不是由一张一张图片放过去。

(一)双缓冲技术

其实在Java做游戏的时候已经遇到过这个问题了,提到这个概念讲一下什么叫单缓冲,单缓冲就是在显示物体的时候,是在屏幕上开始绘画的。

双缓冲:先把画,花在缓冲区然后在把缓冲放到屏幕上。

为什么要这么做:

因为在绘画简单的图的时候并不是很需要双缓冲,单缓冲来得及,但是绘画过于复杂那么就会来不及画出来,屏幕上显示的就是不完整的图画。这样的效果很不好。所以要使用双缓冲技术。

这个是怎么使用双缓冲方法:

在main函数里面写:

glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

其中GLUT_SINGLE表示单缓冲,如果改成GLUT_DOUBLE就是双缓冲了。

当然还有需要更改的地方——每次绘制完成时,我们需要交换两个缓冲区,把绘制好的信息用于屏幕显示(否则无论怎么绘制,还是什么都看不到)。如果使用GLUT工具包,也可以很轻松的完成这一工作,只要在绘制完成时简单的调用glutSwapBuffers函数就可以了。

而且我们在绘制图画的时候应该是在cpu空闲的时候,不能因为我们要画图就让歌不放了,视频不看了,这个明显是不合理的。

所以使用glut中的glutIdleFunc()函数来在cpu空的时候绘画。使用方法我下面代码写了。

#include <GL/glut.h>
#include <stdio.h>
#include<stdlib.h>
static float n = -1.0;
void display()
{

	glClear(GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);//使用模型矩阵

	glLoadIdentity();//消除之前矩阵的影响

	glTranslatef(0.0f,  n, 0.0f);

	glutSolidSphere(1, 80, 16);

	glutSwapBuffers();
}

void ne()//图像变化的函数
{
	n += 0.1;
	if (n >= 0.0f)
	{
		n = -1.0;
	}
	display();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition(150, 150);
	glutInitWindowSize(400, 400);
	glutCreateWindow("透视投影变换");
	//init();
	glutDisplayFunc(display);
	glutIdleFunc(ne);
	glutMainLoop();
	return 0;
}

这个程序就是很简单的把一个圆移动特定的位置。

还有一点就是gflush函数和glutSwapBuffers两个函数的问题,因为glutSwapBuffers函数会自动刷新一次缓存区,如果在使用一次glflush那么效率就会很低。

->

这个就是效果的变化。

(二)垂直同步

这个是一种可以控制帧数的方法。

引用一下别人的话(自己说起来解释不清):

大家知道显示器的刷新率是比较有限的,一般为60~120Hz,也就是一秒钟刷新60~120次。但如果叫计算机绘制一个简单的画面,例如只有一个三角形,则一秒钟可以绘制成千上万次。因此,如果最大限度的利用计算机的处理能力,绘制很多幅画面,但显示器的刷新速度却跟不上,这不仅造成性能的浪费,还可能带来一些负面影响(例如,显示器只刷新到一半时,需要绘制的内容却变化了,由于显示器是逐行刷新的,于是显示器上半部分和下半部分实际上是来自两幅画面)。采用垂直同步技术可以解决这一问题。即,只有在显示器刷新时,才把绘制好的图象传输出去供显示。这样一来,计算机就不必去绘制大量的根本就用不到的图象了。如果显示器的刷新率为85Hz,则计算机一秒钟只需要绘制85幅图象就足够,如果场景足够简单,就会造成比较多的CPU空闲。

几乎所有的显卡都支持“垂直同步”这一功能。

垂直同步也有它的问题。如果刷新频率为60Hz,则在绘制比较简单的场景时,绘制一幅图画需要的时间很段,帧速可以恒定在60FPS(即60帧/秒)。如果场景变得复杂,绘制一幅图画的时间超过了1/60秒,则帧速将急剧下降。

如果绘制一幅图画的时间为1/50,则在第一个1/60秒时,显示器需要刷新了,但由于新的图画没有画好,所以只能显示原来的图画,等到下一个1/60秒时才显示新的图画。于是显示一幅图画实际上用了1/30秒,帧速为30FPS。(如果不采用垂直同步,则帧速应该是50FPS)

如果绘制一幅图画的时间更长,则下降的趋势就是阶梯状的:60FPS,30FPS,20FPS,……(60/1,60/2,60/3,……)

如果每一幅图画的复杂程度是不一致的,且绘制它们需要的时间都在1/60上下。则在1/60时间内画完时,帧速为60FPS,在1/60时间未完成时,帧速为30FPS,这就造成了帧速的跳动。这是很麻烦的事情,需要避免它——要么想办法简化每一画面的绘制时间,要么都延迟一小段时间,以作到统一。

但是一般的英伟达的显卡这个功能是自带启动的,其他的不一定。

(三)

这个是我没事干看到的。+第一次我在学opengl的时候我看到main函数里面有个显示时才进行绘画的函数,我在想为什么要用这个直接调用绘画的函数不就好了,但是有一个问题,就是你的窗口被覆盖或者被移动了那么什么时候进行重新画呢?你的main函数里面不可能定义这么多的信息。所以只能通过glut那些函数来交给系统,让系统决定什么时候进行重画。

时间: 2024-10-13 01:07:00

opengl(七)的相关文章

OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-while) 跳跃(discard, return, break, continue) 6.1函数定义   着色器是由一系列全局声明和函数定义组成的.函数声明规范如下: // prototype returnType functionName (type0 arg0, type1 arg1, ...,

NeHe OpenGL教程 第七课:光照和键盘

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第七课:光照和键盘 光照和键盘控制: 在这一课里,我们将添加光照和键盘控制,它让程序看起来更美观. 这一课我会教您如何使用三种不同的纹理滤波方式.教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照.这一课

OpenGL学习进程(10)第七课:四边形绘制与动画基础

    本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意:在使用四边形时必需记住四边形的四个角必须位于同一个平面中(不存在弯曲的四边形). 2)四边形带(GL_QUAD_STRIP) 该图元指定一个连接的四边形带.它们都保持相同方向的环绕. 3)通用多边形GL_POLYGON 我们可以用它绘制任意数

Lane-学习OpenGL(1)-七个简单例子

在看了许多实例之后, 准备沿着OpenGL编程指南(第七版)学习OpenGL. 运行环境: (1)Windows 7 (2)CodeBlocks (3)GLUT (4)Author:Lane 2014-12-02 1.黑色背景加白色矩形 #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <cstdlib> #inclu

【OpenGL】Shader实例分析(七)- 雪花飘落效果

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40624603 研究了一个雪花飘落效果.感觉挺不错的.分享给大家,效果例如以下: 代码例如以下: Shader "shadertoy/Flakes" { // https://www.shadertoy.com/view/4d2Xzc Properties{ iMouse ("Mouse Pos", Vector) = (100,100,0,0) iChan

Android OpenGL ES(七)----理解纹理与纹理过滤

1.理解纹理 OpenGL中的纹理可以用来表示图像,照片,甚至由一个数学算法生成的分形数据.每个二维的纹理都由许多小的纹理元素组成,它们是小块的数据,类似于我们前面讨论过的片段和像素.要使用纹理,最常用的方式是直接从一个图像文件加载数据. 每个二维纹理都有其自己的坐标空间,其范围是从一个拐角的(0,0)到另一个拐角的(1,1).按照惯例,一个维度叫做S,而另一个称为T.当我们想要把一个纹理应用于一个三角形或一组三角形的时候,我们要为每个顶点指定一组ST纹理坐标,以便OpenGL知道需要用那个纹理

SharpGL学习笔记(七) OpenGL的变换总结

笔者接触OpenGL最大的困难是: 经常调试一份代码时, 屏幕漆黑一片, 也不知道结果对不对,不知道如何是好! 这其实就是关于OpenGL"变换"的基础概念没有掌握好, 以至于对"将三维体正确的显示在屏幕上指定位置"这样的操作都无法完成. OpenGL变换包括计算机图形学中最基本的三维变换,即几何变换.投影变换.裁剪变换.视口变换,以及针对OpenGL的特殊变换概念理解和用法,如相机模拟.矩阵堆栈等,这些基础是开始真正走进三维世界无法绕过的基础. 所以笔者在前面花了

OpenGL学习(七)纹理映射

纹理映射     一m*n的像素数组,我们并不将其看做有离散元素构成的数组,而是将其视作一个连续数组.该数组中的任意一点通过变量s和t来定义.则每个坐标(s,t)都对应一个像素值.现在考虑一个三维空间中的一个几何对象.其表面上的每一点都对应于三维世界坐标系中的一个坐标(x,y,z),如果能通过一对函数映射将对象坐标系的每一点(x,y,z)与纹理坐标中的一点(s,t)建立关联,则可用纹理图像中的颜色或灰度值来确定对象表面上可见点的颜色. OpenGL对此问题的解决方法是强制应用程序为每个顶点都定义

OpenGL之路(七)为立方体加入丰富色彩

在立方体的六个面贴上不同的颜色,假设想达到混合颜色的效果,能够參照立方体的前面代码在每一行前都加上颜色 代码例如以下 #include <gl/glut.h> #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glut32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "glut.l

OpenGL之路(七)为立方体添加丰富色彩

在立方体的六个面贴上不同的颜色,如果想达到混合颜色的效果,可以参照立方体的前面代码在每一行前都加上颜色 代码如下 #include <gl/glut.h> #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glut32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "glut.lib