OpenGL学习记录6
2014-04-20 17:29
357 查看
Exercise 6:放大镜功能
要求:
1. 在练习5的基础上,实现放大镜功能,放大场景中的任意部分;
2. 放大镜可以通过鼠标键盘进行控制;
考察目的:
1. 对OpenGL坐标系变换的理解;
by/scu xx
运行结果:
要求:
1. 在练习5的基础上,实现放大镜功能,放大场景中的任意部分;
2. 放大镜可以通过鼠标键盘进行控制;
考察目的:
1. 对OpenGL坐标系变换的理解;
by/scu xx
#include <iostream> #include <gl\glew.h> #include <glut.h> #include <windows.h> #pragma comment( lib, "glew32.lib") using namespace std; bool isRotatef; // 控制要旋转整个视图 GLfloat LightPosition[] = {4.0f, 4.0f, 6.0f, 1.0f}; //点光源的位置 static int mousePosX = 0, mousePosY = 0, tempX, tempY; bool isMosDownMove = false;//鼠标按下时是否移动的判断变量 ///放大镜所需变量 GLuint framebuffer, renderbuffer;//声明FBO缓冲区名称 float MagnifierSize = 80; float MagnifierRation = 20; int mouseCurPosX = 0; int mouseCurPosY = 0; const int WIN_WIDTH = 800; const int WIN_HEIGHT = 600; bool isOpenMagnifier = false; bool initFBO() { glEnable(GL_DEPTH_TEST); //分配1个帧缓冲区对象名字,并且在framebuffer中返回这个名字,即创建FBO,生成FBO缓冲区名称 glGenFramebuffersEXT(1, &framebuffer); //指定一个帧缓冲区对象用于读取或写入 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); //判定一个特定的无符号整数是否是应用程序分配的一个帧缓冲区对象 //如果framebuffer是glGenFramebuffersEXT()返回的一个缓冲区的名字,将返回GL_TRUE if (glIsFramebufferEXT(framebuffer) != GL_TRUE) { return false; } //分配一个未使用的渲染缓冲区的对象名,并把名字返回到renderbuffer中,即创建一个渲染缓冲区对象 glGenRenderbuffersEXT(1, &renderbuffer); //影响一个渲染缓冲区的创建与修改它相关的状态 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer); if (glIsRenderbufferEXT(renderbuffer) != GL_TRUE) { return false; } //分配存储空间存储图像数据,这里是把渲染缓冲区用做深度缓冲区 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, MagnifierSize, MagnifierSize); //检查帧缓冲区是否完整 if (!glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_COMPLETE_EXT)) { return false; } //一旦为渲染缓冲区创建了存储空间,需要将其附加到一个帧缓冲区对象,然后才能像其中渲染 //把渲染缓冲区绑定到帧缓冲区对象,即把renderbuffer和当前绑定的帧缓冲区(framebuffer)对象附加联系起来 glFramebufferRenderbufferEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffer); return true; } void createLight() { glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat LightAmbient[]= { 0.0f, 0.5f, 0.5f, 1.0f }; //环境光参数 GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; //漫射光参数(由参数可知识最亮的漫射光) GLfloat LightSpecular[]= { 0.5f, 0.5f, 0.0f, 1.0f }; //镜面光参数 //指定光源属性,3个参数决定了它所指定的哪个光源的属性、具体的属性以及该属性的预想值 glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular); } void init(void) { glClearColor(0.7f, 0.7f, 0.7f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); if (GLEW_OK != glewInit()) { cout << "Fail to initialize GLEW!\n"; exit(1); } createLight(); isRotatef = true; //默认移动鼠标旋转整个视图 } void display(void) { GLfloat mat_emission1[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat mat_diffuse1[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_emission2[] = { 0.0, 0.8, 0.8, 0.6 }; GLfloat mat_diffuse2[] = { 0.0, 0.3, 0.3, 0.6 }; GLfloat mat_emission3[] = { 0.4, 0.4, 0.0, 0.4 }; GLfloat mat_diffuse3[] = { 0.6, 0.6, 0.0, 0.4 }; GLfloat mat_emission4[] = { 0.75, 0.75, 0.0, 0.5 }; GLfloat mat_diffuse4[] = { 0.4, 0.0, 0.4, 0.5 }; GLfloat mat_emission5[] = { 0.9, 0.9, 0.0, 0.6 }; GLfloat mat_diffuse5[] = { 0.0, 0.0, 0.0, 0.6 }; GLfloat mat_emission6[] = { 0.0, 0.6, 0.6, 1.0 }; GLfloat mat_diffuse6[] = { 0.0, 0.0, 0.0, 1.0 }; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //进行视图变换前调用下面两个函数,接下来的变换函数将影响模型变换矩阵 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //3组参数:指定了观察点的位置,定义照相机瞄准的参考点,提示哪个方向是朝上的(3个为一组) //设置照相机的位置 b gluLookAt(0.0f, 0.0f, 20.0f, 0.0f, 0.0f, 0.0f, 0, 1, 0); //通过平移与旋转按照预想的方式移动观察点 //glTranslatef(0.0f, 0.0f, 0.0f); /*************************************点光源的处理***********************************************/ //复制一份当前矩阵,并把这份复制添加到堆栈的顶部(记住自己的位置) glPushMatrix(); glTranslatef(LightPosition[0], LightPosition[1], LightPosition[2]); //用于渲染一个球体 函数原型void glutSolidSphere(GLdouble radius , GLint slices , GLint stacks); //radius球体的半径 //slices以Z轴上线段为直径分布的圆周线的条数(将Z轴看成地球的地轴,类似于经线) //stacks围绕在Z轴周围的线的条数(类似于地球上纬线) //一般而言, 后两个参数赋予较大的值, 渲染花费的时间要长, 效果更逼真 glutSolidSphere(0.1, 10.0, 10.0); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); glPopMatrix(); //丢弃堆栈顶部的那个矩阵(回到原来的位置) if (isRotatef) //判断是否需要旋转视图 { glRotatef((GLfloat) mousePosX, -1.0, 0.0, 0.0); glRotatef((GLfloat) mousePosY, 0.0, -1.0, 0.0); } /****************************************茶壶1************************************************/ glPushMatrix(); glTranslatef(-4.0f, 0.0f, 0.0f);//设定茶壶的初始位置 glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission1); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse1); glEnable(GL_BLEND); glDepthMask(GL_FALSE);//控制深度缓冲区是否可写 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//选择源混合因子与目标混合因子 glutSolidTeapot(0.8);//显示一个茶壶,参数为茶壶的大小 glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); /****************************************茶壶2************************************************/ glPushMatrix(); glTranslatef(0.0f, 3.0f, -2.0f); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission2); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse2); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutSolidTeapot(0.8); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); /****************************************茶壶3************************************************/ glPushMatrix(); glTranslatef(4.0f, 0.0f, 0.0f); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission3); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse3); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutSolidTeapot(0.8); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); /****************************************茶壶4************************************************/ glPushMatrix(); glTranslatef(0.0f, -3.0f, 2.0f); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission4); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse4); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutSolidTeapot(0.8); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); /****************************************茶壶5************************************************/ glPushMatrix(); glTranslatef(-8.0f, -3.0f, 2.0f); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission5); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse5); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutSolidTeapot(0.8); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); /****************************************茶壶6************************************************/ glPushMatrix(); glTranslatef(8.0f, -3.0f, 2.0f); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission6); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse6); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutSolidTeapot(0.8); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glPopMatrix(); if (isOpenMagnifier) { float mouseY = WIN_HEIGHT - mouseCurPosY; //指定了读取操作的源(0表示窗口系统默认缓冲区) glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); //指定帧缓冲区要渲染的目标framebuffer glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer); //前4个参数表示复制的区域,即复制的源 //中间四个参数表示复制到的区域,即复制的目标 //后2个参数分别是蒙板参数和过滤器 glBlitFramebufferEXT(mouseCurPosX - MagnifierRation, mouseY - MagnifierRation, mouseCurPosX + MagnifierRation, mouseY + MagnifierRation, WIN_WIDTH - MagnifierSize, WIN_HEIGHT - MagnifierSize, WIN_WIDTH, WIN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer); glBlitFramebufferEXT(WIN_WIDTH - MagnifierSize, WIN_HEIGHT - MagnifierSize, WIN_WIDTH, WIN_HEIGHT, mouseCurPosX-MagnifierSize/2.0, mouseY-MagnifierSize/2.0, mouseCurPosX+MagnifierSize/2.0, mouseY+MagnifierSize/2.0, GL_COLOR_BUFFER_BIT, GL_LINEAR); } glutSwapBuffers(); } void reshape(int w, int h) { float aspect = (float) w/((h)?h:1); //平截头体的纵横比,也就是宽度除以高度,(h)?h:1意思是若h=0,则h=1 glViewport(0,0, w, h); //进行投影变换前调用下面两个函数,接下来的变换函数将影响投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, aspect, 1.0f, 100.0f); glViewport(0,0,w,h); glMatrixMode(GL_MODELVIEW); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'o': isOpenMagnifier = !isOpenMagnifier; break; case 'x': MagnifierRation += 4.0f; break; case 'd': MagnifierRation -= 4.0f; if (MagnifierRation < 1) { MagnifierRation = 1.0; } break; case 27: //退出程序 exit(0); break; } } void mouse(int button, int state, int x, int z) { switch(button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { tempX = x; tempY = z; isMosDownMove = true; //鼠标移动时需要用到的判断变量 } else { isMosDownMove = false; } break; } } void motion(int x, int y) { if(isMosDownMove) { mousePosY = (mousePosY + (x - tempX))%360; mousePosX = (mousePosX + (y - tempY))%360; tempX = x; tempY = y; glutPostRedisplay(); } } void animate(void) { //刷新屏幕 glutPostRedisplay(); } void move(int x, int y) { if (isOpenMagnifier) { mouseCurPosX = x; mouseCurPosY = y; } } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB); glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); glutInitWindowPosition(100,100); glutCreateWindow("Teaports"); GLenum err = glewInit(); //如果使用FBO的话,此句不能缺少 init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutPassiveMotionFunc(move); //鼠标移动的回调函 glutMouseFunc(mouse); glutMotionFunc(motion); glutIdleFunc(animate); glutMainLoop(); return 0; }
运行结果:
相关文章推荐
- Qt+openGL学习记录(5)`加入定时器开启自动旋转,绘制三维简单对象`
- OpenGL入门学习记录
- OpenGL学习记录5
- Qt+openGL学习记录(1)`Qt中openGL的三个重要事件处理函数的调用规则`
- OpenGL学习记录——旋转立方体+文件贴图
- Qt+openGL学习记录(4)`如何实现物体在三维坐标系中的旋转`
- 学习opengl (es, glsl) 记录搜索项,链接
- Qt+openGL学习记录(2)`相机坐标移动的研究·
- OpenGL学习记录4
- OpenGL学习问题记录
- OpenGL学习记录1
- 学习OpenGL遇到的一些问题,记录下以备用。
- OpenGL学习记录——旋转矩形
- 记录几个 OpenGL 学习 的靠谱网站
- 2015年4月20日晚12点,发博开始记录我的OpenGL学习之旅
- OpenGL学习记录2
- OpenGL学习记录3
- 记录一些学习opengl矩阵转换相关文章
- OpenGL学习记录(三)--函数库分类
- 我的OpenGL学习记录1