OpenGL中的缓冲区
颜色缓冲区
OpenGL在绘制图元时,先是在一个缓冲区中完成渲染,然后再把渲染结果交换到屏幕上。我们把这两个缓冲区称为前颜色缓冲区(屏幕)和后颜色缓冲区。在默认情况下,OpenGL命令是在后颜色缓冲区进行渲染的。当然,也可以直接在前颜色缓冲区中进行渲染。
若要在前颜色缓冲区中进行渲染,第一种方法是直接告诉OpenGL希望在前颜色缓冲区中进行绘图,可以调用下面这个函数来实现这个目的:
void glDrawBuffer(Glenum mode);
如果参数mode指定为GL_FRONT,OpenGL就会在前颜色缓冲区中进行渲染;
如果参数mode指定为GL_BACK,那么渲染将在后颜色缓冲区中进行。
在前颜色缓冲区进行渲染的第二种方法是在OpenGL被初始化时简单地不要求进行双缓冲区渲染。进行单缓冲区渲染时,如果希望把渲染结果实际绘制到屏幕上,需要调用glFlush()或glFinsh(),这点非常重要。
OpenGL实现除了支持单纯的前颜色缓冲区和后颜色缓冲区之外,还支持其他模式,如用于立体渲染的左和右缓冲区以及辅助缓冲区。
深度缓冲区
与颜色缓冲区不同的是,深度缓冲区中所填充的是深度值而不是颜色值。
为了启用深度缓冲区进行深度测试,只需要调用:
glEnable(GL_DEPTH_TEST);
另外,即使深度缓冲区未被启用,如果深度缓冲区被创建,OpenGL也会把所有写入到颜色缓冲区的颜色片段对应的深度值写入到深度缓冲区中。但是,如果我们希望在进行深度测试时临时禁止把值写入到深度缓冲区,我们可以使用函数:
void glDepthMask(GLboolean mask);
把GL_FALSE作为参数,经禁止写入深度值,但并不禁止用已经写入到深度缓冲区的值进行深度测试。
把GL_TRUE作为参数,可以重新启用深度缓冲区的写入。同时,这也是默认的设置。
裁剪测试
OpenGL允许在窗口中指定一个裁剪矩形,让渲染只在这个区域内进行。在默认情况下,裁剪矩形就是窗口的大小,不会进行裁剪测试。我们可以打开裁剪测试:
glEnable(GL_SCISSOR_TEST);
在窗口内部执行渲染的那个区域称为裁剪框(scissor box),它使用下面这个函数以窗口坐标的形式指定:
void glScissor(Glint x, Glint y, GLsizei width, GLsizei height);
下面的程序清除了3次颜色缓冲区,每次在清除之前都指定一个更小的裁剪框,形成一组重叠的着色矩形,如图所示:
/* 程序清单 3-12
* 2014/5/7
*/
#include <glut.h>
#include <math.h>
// 设置渲染状态
void SetupRC()
{
// 设置清除窗口的颜色(黑色背景)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 设置绘图颜色为绿色
glColor3f(0.0f, 1.0f, 0.0f);
}
// 绘制场景(显示回调函数)
void RenderScene()
{
// 设置清除窗口的颜色(蓝色背景)
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 把裁剪框设置为一个更小的红色子区域
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glScissor(100, 100, 600, 400);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
// 把裁剪框设置为一个更小的绿色子区域
glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
glScissor(200, 200, 400, 200);
glClear(GL_COLOR_BUFFER_BIT);
// 关闭裁剪测试,以便进行下一次渲染
glDisable(GL_SCISSOR_TEST);
glutSwapBuffers();
}
// 当窗口大小改变时由GLUT函数库调用
void ChangeSize(GLsizei w, GLsizei h)
{
// 范围
GLfloat nRange = 100.0f;
// 纵横比
GLfloat aspectRatio;
// 防止被0所除
if (0== h){
h = 1;
}
// 根据窗口大小设置视口
glViewport(0, 0, w, h);
// 选择投影矩阵,并重置坐标系统
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 计算窗口的纵横比(像素比)
aspectRatio = (GLfloat) w / (GLfloat)h;
// 定义裁剪区域(根据窗口的纵横比,并使用正投影)
if (w<=h) {//宽 <高
glOrtho(-nRange, nRange,-nRange /aspectRatio, nRange / aspectRatio, -nRange, nRange);
} else{//宽 >高
glOrtho(-nRange * aspectRatio,nRange *aspectRatio, -nRange, nRange,-nRange, nRange);
}
// 选择模型视图矩阵,并重置坐标系统
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char *argv[])
{
// 传递命令行参数,并对GLUT函数库进行初始化
glutInit(&argc, argv);
// 设置创建窗口时的显示模式(双缓冲区、RGB颜色模式)
glutInitDisplayMode(GLUT_DOUBLE |GLUT_RGB);
// 设置窗口的初始大小
glutInitWindowSize(800, 600);
// 创建窗口
glutCreateWindow("Bounce");
// 设置显示回调函数
glutDisplayFunc(RenderScene);
// 设置当窗口的大小发生变化时的回调函数
glutReshapeFunc(ChangeSize);
// 设置渲染状态
SetupRC();
// 启动GLUT框架的运行,一经调用便不再返回,直到程序终止
glutMainLoop();
return0;
}