![b7f9c3031e9d2c393f5fe0280296ec7d.png](https://i-blog.csdnimg.cn/blog_migrate/7744086e7be8cff643fa06179101c066.png)
本文为学习OpenGL的学习笔记,如有书写和理解错误还请大佬扶正;
文章为OpenGL配置UI界面,使用的是GLUI;使用GLUI必须先配置GLUT;
一,配置GLUT与GLUI
参考文章:
从零开始OpenGL-- 一、 环境配置www.cnblogs.com![d2b328600ec317a93f487b99e4cfe2b1.png](https://i-blog.csdnimg.cn/blog_migrate/ae4b77e1c099e713cf469313db85fe11.png)
参考文章内为VS2017配置GLUT写的很清楚,网上配置基本都是一样,这里不再进行记录;
参考文章内关于GLUI部分配置,会有一些报错(参考文章下有大佬给出解决方案),但依然(太菜)在配置过程中造成一定麻烦,所以在这里记录一下;
1,下载GLUI,并解压
https://github.com/libglui/gluigithub.com![399521522d8b866506bdd7529dce5638.png](https://i-blog.csdnimg.cn/blog_migrate/5337202dc5ed6975c4aa4f62a8773b56.jpeg)
2,打开glui.sln文件(路径:glui-2.37msvc),弹出解决方案,无需更改,点击确定
![3526e39a44ec34f8bc6b696531e86fb0.png](https://i-blog.csdnimg.cn/blog_migrate/5db5136eeb1f88c4255682366285b17a.jpeg)
3,重新定位解决方案,点击确定
![859bf489cd2b694070d0f1fb8be0c2de.png](https://i-blog.csdnimg.cn/blog_migrate/8738d8356937e14c4bca6b1bfb3d8ea9.jpeg)
4,右键点击解决方案,点击批生成,选择前四个,点击生成
![2363feee840870b31f6c4615c2b6b7fd.png](https://i-blog.csdnimg.cn/blog_migrate/bce4274c2ab699af7dcdcce4a377f5d8.jpeg)
生成失败(-..-)(文章使用的GLUI为2.37版本,参考文章为2.36所以会多一种报错)
![5af3f1e0f94aa8bd0900ce920c24bd07.png](https://i-blog.csdnimg.cn/blog_migrate/7eac864ab65386e0e6a92a2eb9d1e537.jpeg)
5,解决错误
打开_gluidll library项目的"属性页"对话框,更改左上角配置为所有配置
单击"链接器"文件夹,单击"高级"属性页,将映像具有安全异常处理程序 改为 /SAFESEH:NO ,然后点击应用。
![bd57ff94dc2ffd737ea240f3ee0a6fec.png](https://i-blog.csdnimg.cn/blog_migrate/40b896b40db8cfef367eb8952b6cd4df.jpeg)
继续点击批生成->重新生成
![f4f1ab81d9a31cdf8ff52520ed183260.png](https://i-blog.csdnimg.cn/blog_migrate/2e4c85fd51459a59e1bb87e6d4d1e108.png)
同样对于案例项目也进行相应的更改(example1-6)
![cefef179ba7a3fcc3212ef2670433c61.png](https://i-blog.csdnimg.cn/blog_migrate/4b997c37153356bc2395aa4d2f2a2e28.jpeg)
手动为Release配置和ReleaseGLUDIDL配置L附加依赖库
其中Release配置库为glui32.lib
![31872c6394041bca8ec8d7c92366a127.png](https://i-blog.csdnimg.cn/blog_migrate/ec1b80046c8115dd1835fa7e3bdd81f3.jpeg)
ReleaseGLUDIDLL配置库为glui32dll.lib
![2092c2752186b910dbc46ccae98d4c82.png](https://i-blog.csdnimg.cn/blog_migrate/8d89e627d13684aeacc35caa3bed19ec.jpeg)
点击批生成,生成剩余的项目
![254fdeb9708ce75ddcd0fa185ed2318c.png](https://i-blog.csdnimg.cn/blog_migrate/6b1c2bf0e1f4a0630833170ddeb6f0fd.jpeg)
生成成功
![2d12913b6d24ae1d5abd93c820b9774e.png](https://i-blog.csdnimg.cn/blog_migrate/520621a14781c8690da0f60846fbd7e3.png)
剩下的配置与参考文章一致,就不在记录了(可以把相关的库和.h文件放到自己定义的文件夹内,方便移植一些);
生成的6个Demo原文件(glui-2.37msvc)与执行文件(glui-2.37msvcbin)很有参考价值;
二,实践GLUT与GLUI
1,GLUT
官方文档:
GLUT API, version 3www.opengl.org前文记录一直使用GLFW库进行相应窗口创建与管理,GLUT也能实现同样的功能,方法很相似;
![4507eee24695c7b7a55bfb0ed5c59f83.png](https://i-blog.csdnimg.cn/blog_migrate/0a1e0a7fb915725894e3b3df670849fd.png)
实现代码
#include <gl/glut.h>
#include<gl/gl.h>
#include<gl/GLU.h>
void SceneRendering()
{
//清除颜色缓冲区,并将颜色设置为ClearColor
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//渲染四边形
glBegin(GL_POLYGON);
//顶点颜色/顶点位置
glColor3f(1.0, 0.0, 0.0);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
//强制刷新缓冲,保证绘图命令被执行
glFlush();
}
int main(int argc, char ** argv)
{
//初始化glut
glutInit(&argc, argv);
//设置显示模式
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
//设定窗口位置与大小
glutInitWindowPosition(100, 100);
glutInitWindowSize(1080, 720);
//创建窗口
glutCreateWindow("Renderer");
//回调渲染函数
glutDisplayFunc(SceneRendering);
//循环执行
glutMainLoop();
}
相关函数的解释(文档里都有)
函数 glutInit(&argc, argv);
这个函数传了主函数的两个参数,它除了初始化GLUT库以外还会与窗口系统沟通。同时可以包含其他有用的选项比如 '-sync' 和 '-gldebug',这样可以自动的检查GL的错误并独立的显示它们,如果操作系统没有合适的OpenGL或者非法命令行选项就会抛出错误,初始化失败。
函数glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
设置一些 GLUT 的参数
Mode参数是一个GLUT库里预定义的可能的布尔组合。你使用mode去指定颜色模式,数量和缓冲区类型。
指定颜色模式的预定义常量有:
- 1:GLUT_RGBA或者GLUT_RGB。指定一个RGBA窗口,这是一个默认的颜色模式。
- 2:GLUT_INDEX。指定颜色索引模式。
这个显示模式还允许你选择单缓冲区或双缓冲区窗口。
- 1:GLUT_SINGLE.单缓冲区窗口。
- 2:GLUT_DOUBLE.双缓冲区窗口,这是产生流畅动画必须选的。
还可以指定更多,如果你想指定一组特殊的缓冲的话,用下面的变量:
- 1:GLUT_ACCUM.累积缓冲区。
- 2:GLUT_STENCIL.模板缓冲区。
- 3:GLUT_DEPTH.深度缓冲区
函数glutInitWindowPosition(100, 100);
函数设置了窗口的参数(包括窗口大小、窗口位置以及窗口标题)并创建窗口。
- X: 距离屏幕左边的像素数。-1是默认值,意思就是由窗口管理程序决定窗口出现在哪里。如果不使用默认值,那你就自己设置一个值。
- Y:距离屏幕上边的像素数。和X一样。
函数glutInitWindowSize(1080, 720);
- Width:窗口的宽度。
- Height:窗口的高度。
函数glutCreateWindow("Windowname");
这个函数被用来创建一个显示图像的窗口。它有一个字符指针类型的参数,用来初始化窗口显示的名称,还有一个整数类型的返回值,用来标识该创建的窗口。需要注意的是,所有新建的窗口都是有单独的OpenGL上下文,也就是说有各自的 状态机,因此窗口标识符可以用来区别这些窗口。
函数glutDisplayFunc(SceneRendering);
- 因为我们工作在一个窗口系统中,可以通过事件回调函数与运行中的项目进行交互。GLUT 可以和基本的窗口系统进行交互,并且提供给我们一些回调函数。
- 在这里我们仅仅使用了一个主回调函数,这个主回调函数完成了一帧中的所有渲染工作。
- 这个函数被 GLUT 内部循环不断的调用。
函数glutMainLoop();
这个函数既没有参数,也没有返回值。只是单纯的进入事件处理循环使得GLUT不断的调用渲染图形回调函数。通过这种办法我们就可以在显示器看到图形了。
2,GLUT弹出式菜单
参考文章:
OpenGL---GLUT教程(十) GLUT菜单blog.csdn.net![9401b4778bae8828056dd8a3e71ed696.png](https://i-blog.csdnimg.cn/blog_migrate/1a0d95573b29346ea0cab14da9d5821c.jpeg)
效果参考:
![086fdcec8cd5f57889abe6cb42772649.gif](https://i-blog.csdnimg.cn/blog_migrate/1dfad3c3a46fc71103860df68750a899.gif)
代码参考:
#include <glui/glut.h>
#include<gl/gl.h>
#include<gl/GLU.h>
#include <string.h>
#include <glui/glui.h>
#define RED 1
#define GREEN 2
#define BLUE 3
#define WHITE 4
float red = 0.0;
float green = 0.0;
float blue = 0.0;
//绘制函数
void myDisplay()
{
//设置背景色
glClearColor(.2f, .2f, .2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//绘制三角形
glBegin(GL_TRIANGLES);
glColor3f(red, blue, green);
glVertex3f(-0.5, -0.5, 0.0);
glVertex3f(0.5, 0.0, 0.0);
glVertex3f(0.0, 0.5, 0.0);
glEnd();
//双缓冲
glutSwapBuffers();
}
void processMenuEvents(int option) {
//option 就是传递过来的value的值。
switch (option) {
case RED:
red = 1.0;
green = 0.0;
blue = 0.0; break;
case GREEN:
red = 0.0;
green = 1.0;
blue = 0.0; break;
case BLUE:
red = 0.0;
green = 0.0;
blue = 1.0; break;
case WHITE:
red = 1.0;
green = 1.0;
blue = 1.0; break;
}
glutPostRedisplay();
}
void createGLUTMenus() {
int menu;
// 创建菜单并告诉GLUT,processMenuEvents处理菜单事件。
menu = glutCreateMenu(processMenuEvents);
//给菜单增加条目
glutAddMenuEntry("Red", RED);
glutAddMenuEntry("Blue", BLUE);
glutAddMenuEntry("Green", GREEN);
glutAddMenuEntry("White", WHITE);
// 把菜单和鼠标右键关联起来。
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
int main(int argc, char *argv[])
{
//初始化glut
glutInit(&argc, argv);
//设置显示模式
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
//设定窗口位置与大小
glutInitWindowPosition(100, 100);
glutInitWindowSize(1080, 720);
//创建窗口
glutCreateWindow("OpenGL");
//回调渲染函数
glutDisplayFunc(&myDisplay);
//调用菜单
createGLUTMenus();
//循环
glutMainLoop();
return 0;
}
3,glui
参考资料:
开源项目之C++界面库 GLUIblog.csdn.net![d7afc88788146ba314cbef1a95d6f07c.png](https://i-blog.csdnimg.cn/blog_migrate/6047700284112cda6e235515950a4224.png)
修改配置:
添加预处理器定义 GLUI_NO_LIB_PRAGMA,GLUIDLL
![1266136c0b0122bfa77ae373fbe646f3.png](https://i-blog.csdnimg.cn/blog_migrate/2b3bfae5432c16a287dadf1fb683f870.jpeg)
添加附加依赖库 glui32dll.lib
![67f868697ed251b0a811ad3e773300e8.png](https://i-blog.csdnimg.cn/blog_migrate/eb42d3ffe7e54569d7ca7f99ebc69110.jpeg)
实现效果:
![e19859c2e551164e7952de05c909077a.gif](https://i-blog.csdnimg.cn/blog_migrate/a23170fe03920bc67b04c6b39f8e2f24.gif)
代码参考:
#include <gl/glut.h>
#include<gl/gl.h>
#include<gl/GLU.h>
#include <string.h>
#include <glui/glui.h>
/**************************ID*******************************/
float red = 1.0;
float green = 1.0;
float blue = 1.0;
int changeRed;
int changeGreeen;
int changeBlue;
float redChannelValue;
float greenChannelValue;
float blueChannelValue;
int main_window;
/****************************渲染函数***********************************/
void SceneRendering(void)
{
//清除颜色缓冲区,并将颜色设置为ClearColor
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//改变颜色值
if (changeRed)
{
red = redChannelValue;
}
if (changeGreeen)
{
green = greenChannelValue;
}
if (changeBlue)
{
blue = blueChannelValue;
}
//渲染四边形
glBegin(GL_POLYGON);
//顶点颜色/顶点位置
glColor3f(red, green, blue);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
//强制刷新缓冲,保证绘图命令被执行
//glFlush();
//双缓冲
glutSwapBuffers();
}
/****************************保持窗口比例函数***********************************/
void myGlutReshape(int w, int h)
{
// 防止除数即高度为0
// (你可以设置窗口宽度为0).
if (h == 0)
h = 1;
float ratio = 1.0* w / h;
// 单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//导入单位矩阵
// 设置视口大小为增个窗口大小
glViewport(0, 0, w, h);
// 设置正确的投影矩阵
gluPerspective(45, ratio, 1, 1000);//宽高比例改为当前值,视线区域与屏幕大小一致
//设置模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f); //观察者位置
}
/****************************GLUI回调函数***********************************/
void myGlutIdle(void)
{
//判断是否为当前窗口
if (glutGetWindow() != main_window)
glutSetWindow(main_window);
//glutPostRedisplay 标记当前窗口需要重新绘制
glutPostRedisplay();
}
//主函数
int main(int argc, char ** argv)
{
//初始化glut
glutInit(&argc, argv);
//设置显示模式
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
//设定窗口位置与大小
glutInitWindowPosition(100, 100);
glutInitWindowSize(1080, 720);
//创建窗口
main_window = glutCreateWindow("Renderer");
//回调渲染函数
glutDisplayFunc(SceneRendering);
//改变窗口大小时,保留窗口比例
glutReshapeFunc(myGlutReshape);
/***************************GLUI CODE*******************************/
//GLUI版本号
float version = GLUI_Master.get_version();
//创建新的UI窗口
GLUI *glui_window = GLUI_Master.create_glui("GLUI");
//glui_window->add_statictext("Hello World!"); //输入一行字符串
//创建Checkbox/Spinner
new GLUI_Checkbox(glui_window, "ChangeRed", &changeRed);
(new GLUI_Spinner(glui_window, "RedChannelValue:", &redChannelValue))
->set_int_limits(0, 1);
new GLUI_Checkbox(glui_window, "ChangeGreen", &changeGreeen);
(new GLUI_Spinner(glui_window, "GreenChannelValue:", &greenChannelValue))
->set_int_limits(0, 1);
new GLUI_Checkbox(glui_window, "ChangeBlue", &changeBlue);
(new GLUI_Spinner(glui_window, "BlueChannelValue:", &blueChannelValue))
->set_int_limits(0, 1);
//GLUI回调函数
GLUI_Master.set_glutIdleFunc(myGlutIdle);
//循环执行
glutMainLoop();
}