OpenGL之变换
这一次用到的有双缓冲、双缓存技术,空闲调用函数,激活函数(启用功能),平移和旋转等
Code:
#include<GL/glut.h>
#include<stdlib.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
GLfloat rtri; //金字塔旋转角度,==这个东西叫金字塔貌似不怎么样。。。只是因为底面没有填充。。
void init()
{
glClearColor(0.0f,0.0f,0.0f,0.0f);
glShadeModel(GL_SMOOTH); //GL_FLAT和GL_SMOOTH在这里的区别很明显哟
glEnable(GL_DEPTH_TEST);
/*激活深度测试,也就是,如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作。
启动它,OpenGL就可以跟踪Z轴上的像素,这样,它只会在那个像素前方没有东西时,才会绘画这个像素。
通俗的说,就是根据坐标的远近自动隐藏被遮住的图形(材料)*/
}
void mydisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.2f,-4.0f); //平移,三个方向的偏移量,缩小一下
glRotatef(rtri,0.0f,1.0f,0.0f); //旋转,沿各个不同方向
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(1.0f,-1.0f,1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f(1.0f,-1.0f,1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,1.0f);
glEnd();
rtri += 0.1f; //这家伙可以控制旋转角度,也就是速度,单位时间内转过的角度,当然越大越快了
glutSwapBuffers();
}
void reshape(int width,int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char * argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(300,100);
glutInitWindowSize(650,500);
glutCreateWindow("change");
init();
glutDisplayFunc(mydisplay);
glutReshapeFunc(reshape);
glutIdleFunc(mydisplay); //设置空闲时调用的函数,idle就是空闲的、闲置的意思
glutMainLoop();
return 0;
}
下面来说说以前没见过的函数的用法~
(各处总结来的,讲的都特别好~)
双缓冲技术
在计算机上的动画与实际的动画有些不同:实际的动画都是先画好了,播放的时候直接拿出来显示就行。
计算机动画则是画一张,就拿出来一张,再画下一张,再拿出来。
如果所需要绘制的图形很简单,那么这样也没什么问题。
但一旦图形比较复杂,绘制需要的时间较长,问题就会变得突出。
让我们把计算机想象成一个画图比较快的人,
假如他直接在屏幕上画图,而图形比较复杂,则有可能在他只画了某幅图的一半的时候就被观众看到。
而后面虽然他把画补全了,但观众的眼睛却又没有反应过来,还停留在原来那个残缺的画面上。
也就是说,有时候观众看到完整的图象,有时却又只看到残缺的图象,这样就造成了屏幕的闪烁。
如何解决这一问题呢?
我们设想有两块画板,画图的人在旁边画,画好以后把他手里的画板与挂在屏幕上的画板相交换。
这样以来,观众就不会看到残缺的画了。这一技术被应用到计算机图形中,称为双缓冲技术。
即:在存储器(很有可能是显存)中开辟两块区域,一块作为发送到显示器的数据,一块作为绘画的区域,
在适当的时候交换它们。由于交换两块内存区域实际上只需要交换两个指针,
这一方法效率非常高,所以被广泛的采用。
注意:虽然绝大多数平台都支持双缓冲技术,但这一技术并不是 OpenGL 标准中的内容。
OpenGL 为了保证更好的可移植性,允许在实现时不使用双缓冲技术。当然,我们常用
的 PC 都是支持双缓冲技术的。
要启动双缓冲功能,最简单的办法就是使用 GLUT 工具包。我们以前在 main 函数里面
写:glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
其中 GLUT_SINGLE 表示单缓冲,如果改成 GLUT_DOUBLE就是双缓冲了。
当然还有需要更改的地方——每次绘制完成时,我们需要交换两个缓冲区,把绘制好的
信息用于屏幕显示(否则无论怎么绘制,还是什么都看不到)。如果使用 GLUT 工具包,
也可以很轻松的完成这一工作,只要在绘制完成时简单的调用 glutSwapBuffers函数就可
以了。-- 交换双缓存函数
总之一句话,使用双缓存,以避免把计算机作图的过程都表现出来,或者为了平滑地实现动画。
GLUT_DEPTH 和 GL_DEPTH_TEST
在glutInitDisplayMode()参数说明GLUT_DEPTH,表明窗口使用深度缓存
在glEnable里激活GL_DEPTH_TEST,说明启用深度测试,也就是,如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作。启动它,OpenGL就可以跟踪Z轴上的像素,这样,它只会在那个像素前方没有东西时,才会绘画这个像素。通俗的说,就是根据坐标的远近自动隐藏被遮住的图形(材料)
在glutInitDisplayMode()里还有很多别的参数如下:
值
|
对应宏定义
|
意义
|
GLUT_RGB
|
0x0000
|
指定 RGB 颜色模式的窗口
|
GLUT_RGBA
|
0x0000
|
指定 RGBA 颜色模式的窗口
|
GLUT_INDEX
|
0x0001
|
指定颜色索引模式的窗口
|
GLUT_SINGLE
|
0x0000
|
指定单缓存窗口
|
GLUT_DOUBLE
|
0x0002
|
指定双缓存窗口
|
GLUT_ACCUM
|
0x0004
|
窗口使用累加缓存
|
GLUT_ALPHA
|
0x0008
|
窗口的颜色分量包含 alpha 值
|
GLUT_DEPTH
|
0x0010
|
窗口使用深度缓存
|