Linux中opengl库叫什么名字,Linux下的OpenGL——Mesa和GLX简介
一.什么是Mesa和GLX
众所周知,OpenGL作为图形界的工业标准,其仅仅定义了一组2D和3D图形接口API,而对于窗口管理、IO消息响应等并没有规定。也就是说,OpenGL依赖各平台提供用于渲染的context以及具体实现方式,而各平台提供的实现不尽相同。这些实现主要有:Windows平台下的WGL、Linux下的Mesa/GLX、Mac OS X下的Cocoa/NSGL,以及跨平台的GLUT、GLFW、SDL等等。
Mesa是Linux下的OpenGL实现。它提供了对AMD Radeon系列、Nvidia GPU、Intel i965, i945, i915以及VMWare虚拟GPU等多种硬件驱动的支持,同时也提供了对softpipe等多种软件驱动的支持。Mesa项目由Brian Paul于1993年8月创建,于1995年2月发布了第一个发行版,此后便受到越来越多的关注,如今Mesa已经是任何一个Linux版本首选的OpenGL实现。
GLX则是在Linux上用于提供GL与窗口交互、窗口管理等等的一组API。它的作用与Windows的WGL、Mac OS X的AGL以及针对OpenGL ES的EGL相似。在Linux上,窗口创建、管理等API遵循X Window接口,而GLX提供了OpenGL与X Window交互的办法。因此GLX也可以运用于其他使用X Window的平台,例如FreeBSD等。
二. Mesa和GLX的安装
在Debian/Ubuntu系统上,我们可以使用以下命令来安装Mesa和GLX:
Shell
sudo apt-get install libgl1-mesa-dev
1
sudoapt-getinstalllibgl1-mesa-dev
如果希望安装OpenGL ES版本的Mesa,那么就是如下命令:
Shell
sudo apt-get install libgles2-mesa-dev
1
sudoapt-getinstalllibgles2-mesa-dev
对于OpenGL ES,EGL的安装如下:
Shell
sudo apt-get install libegl1-mesa-dev
1
sudoapt-getinstalllibegl1-mesa-dev
安装完毕以后,可以使用以下命令查看安装的Mesa版本以及安装是否成功:
Shell
glxinfo | grep "OpenGL version"
1
glxinfo|grep"OpenGL version"
这里我安装完毕后显示的结果是:
Shell
szsilence06@ubuntu:~$ glxinfo | grep "OpenGL version"
OpenGL version string: 3.0 Mesa 11.2.0
1
2
szsilence06@ubuntu:~$glxinfo|grep"OpenGL version"
OpenGLversionstring:3.0Mesa11.2.0
三. 第一个Mesa程序
3.1 CMake构建
这里我们采用CMake来构建项目。在CMakeLists.txt内加入如下代码来包含mesa:
find_package(OpenGL REQUIRED)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIRS})
LINK_DIRECTORIES(${OPENGL_LIBRARY_DIRS})
1
2
3
4
find_package(OpenGLREQUIRED)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIRS})
LINK_DIRECTORIES(${OPENGL_LIBRARY_DIRS})
如下代码负责包含X Window:
find_package(X11 REQUIRED)
1
find_package(X11REQUIRED)
最后链接库文件:
target_link_libraries(mesa_test
${OPENGL_LIBRARIES}
${X11_LIBRARIES}
)
1
2
3
4
target_link_libraries(mesa_test
${OPENGL_LIBRARIES}
${X11_LIBRARIES}
)
这里mesa_test是我创建的可执行文件名称,读者应当换成自己设定的名称。
3.2 创建窗口
Mesa依赖GLX来为其提供渲染的context。而在继续讨论GLX前,我们需要简单了解一下X Window。X Window支持客户端-服务器模型,也就是说,X Server和X Window可以分别运行于不同的机器上,从而允许我们远程运行桌面系统。因此,在渲染之前,我们必须了解程序将在哪个显示器上进行渲染。
我们可以使用如下函数来获取显示器:
C
Display* display = XOpenDisplay(getenv("DISPLAY"));
1
Display*display=XOpenDisplay(getenv("DISPLAY"));
当然,在此之前,我们需要包含相应的头文件:
#include
#include
#include
1
2
3
#include
#include
#include
在程序退出前,我们需要关闭到显示器的连接:
C
XCloseDisplay(display);
1
XCloseDisplay(display);
在获取显示器以后,我们就可以创建窗口了。创建窗口使用XCreateWindow函数,这个函数的原型如下:
C
Window XCreateWindow(
Display*/* display */,
Window/* parent */,
int/* x */,
int/* y */,
unsigned int/* width */,
unsigned int/* height */,
unsigned int/* border_width */,
int/* depth */,
unsigned int/* class */,
Visual*/* visual */,
unsigned long/* valuemask */,
XSetWindowAttributes*/* attributes */
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WindowXCreateWindow(
Display*/* display */,
Window/* parent */,
int/* x */,
int/* y */,
unsignedint/* width */,
unsignedint/* height */,
unsignedint/* border_width */,
int/* depth */,
unsignedint/* class */,
Visual*/* visual */,
unsignedlong/* valuemask */,
XSetWindowAttributes*/* attributes */
);
各参数的意义我不列出了,请自行google,这里我给一个简单的调用示例:
C
int screen = DefaultScreen(display);
int width = 640;
int height = 480;
int screen_width = DisplayWidth(display, screen);
int screen_height = DisplayHeight(display, screen);
window = XCreateWindow(display, XRootWindow(display, screen), (screen_width - width) / 2,
(screen_height - height) / 2, width, height, 0, CopyFromParent,
InputOutput, DefaultVisual(display, screen), 0, nullptr);
1
2
3
4
5
6
7
8
9
intscreen=DefaultScreen(display);
intwidth=640;
intheight=480;
intscreen_width=DisplayWidth(display,screen);
intscreen_height=DisplayHeight(display,screen);
window=XCreateWindow(display,XRootWindow(display,screen),(screen_width-width)/2,
(screen_height-height)/2,width,height,0,CopyFromParent,
InputOutput,DefaultVisual(display,screen),0,nullptr);
创建好窗口之后,还要调用以下函数将窗口显示出来:
C
XMapWindow(display,window);
1
XMapWindow(display,window);
3.3 创建OpenGL环境
有了窗口以后,下一步就是创建context。在创建Context之前,我们需要先对帧缓存进行配置。以下函数可以得到当前屏幕的帧缓存配置信息:
C
int configNum;
GLXFBConfig* config = glXGetFBConfigs(display, screen, &configNum);
1
2
intconfigNum;
GLXFBConfig*config=glXGetFBConfigs(display,screen,&configNum);
GLXFBConfig是一个包含大量配置项的结构体,configNum即为函数返回的GLXFBConfig中的配置项数目。为简单起见,我这里就不去修改这个config里面的配置项了。然后我们需要从这个配置项建立一个XVisualInfo,这是X Window用来描述显示参数的数据结构:
C
XVisualInfo* visualInfo = glXGetVisualFromFBConfig(display, *config);
1
XVisualInfo*visualInfo=glXGetVisualFromFBConfig(display,*config);
然后,我们终于可以创建OpenGL环境了:
C++
GLXContext context = glXCreateContext(display, visualInfo, nullptr, true);
1
GLXContextcontext=glXCreateContext(display,visualInfo,nullptr,true);
最后将该环境设为当前绘制环境:
C
glXMakeCurrent(display, window, context);
1
glXMakeCurrent(display,window,context);
3.4 消息循环
熟悉Windows编程的同学应该对消息循环都不陌生。以上我们写好的程序如果运行一下,会发现窗口一闪而过然后程序就退出了。显然这是因为我们还没有为窗口添加消息循环的缘故。
X Window的消息与Windows有一些不同。由于X Window是基于客户端-服务器模型的,因此我们可以自由选择想要处理的消息,这样可以节省网络带宽。以下函数就是负责选择窗口想要处理的消息的:
C
int XSelectInput(
Display*/* display */,
Window/* w */,
long/* event_mask */
);
1
2
3
4
5
intXSelectInput(
Display*/* display */,
Window/* w */,
long/* event_mask */
);
event_mask有很多种,具体我不列出了。以下代码可以侦听所有的消息:
C
int event_mask = (1 << 25) - 1;
XSelectInput(display, window, event_mask); //listen to all types of events
1
2
intevent_mask=(1<<25)-1;
XSelectInput(display,window,event_mask);//listen to all types of events
设置好要侦听的消息以后,我们可以调用以下函数来获取消息:
C
XEvent e;
XNextEvent(display, &e);
1
2
XEvente;
XNextEvent(display,&e);
XNextEvent是一个阻塞式函数,它可以获取XEvent消息。我们可以根据XEvent的type字段判断消息的类型:
C
switch (e.type) {
//...
}
1
2
3
switch(e.type){
//...
}
各种XEvent中,我们这里需要侦听Expose消息,这个消息在窗口绘制的时候触发,我们应当在这里处理我们的渲染。此外,我们还需要侦听窗口退出消息,好让我们可以进行程序退出前的一些处理操作。然而,X Window标准并没有为窗口退出定义一个消息类型。想要侦听到窗口退出消息的话,一种方法如下所示:
C
Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(display, window, &wmDelete, 1);
1
2
AtomwmDelete=XInternAtom(display,"WM_DELETE_WINDOW",True);
XSetWMProtocols(display,window,&wmDelete,1);
这样,当窗口退出时,程序就会发送ClientMessage消息。于是,一个基本的消息循环就如下所示:
C
bool needQuit = false;
while(needQuit == false) {
XEvent e;
XNextEvent(display, &e);
switch (e.type) {
case Expose:
Render();
break;
case ClientMessage:
needQuit = true;
break;
default:
break;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
boolneedQuit=false;
while(needQuit==false){
XEvente;
XNextEvent(display,&e);
switch(e.type){
caseExpose:
Render();
break;
caseClientMessage:
needQuit=true;
break;
default:
break;
}
}
3.5 绘制
在以上工作都做好之后,我们就可以按通常的OpenGL编程方式编写绘制代码了。例如,创建好环境以后进行如下初始化设置:
C
glViewport(0, 0, width, height);
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glOrtho(0, width, 0, height, 0, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
1
2
3
4
5
6
glViewport(0,0,width,height);
glClearColor(0,0,0,1);
glMatrixMode(GL_PROJECTION);
glOrtho(0,width,0,height,0,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
绘制一个三角形:
C
void Render()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(400,400);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(400,200);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(200,200);
glEnd();
glFlush();
glXSwapBuffers(display, window);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
voidRender()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex2f(400,400);
glColor3f(0.0f,1.0f,0.0f);
glVertex2f(400,200);
glColor3f(0.0f,0.0f,1.0f);
glVertex2f(200,200);
glEnd();
glFlush();
glXSwapBuffers(display,window);
}
程序运行结果如图。
3.6 收尾工作
程序退出前要记得以下收尾工作:
C
glXDestroyWindow(display, glxWindow);
XDestroyWindow(display, window);
XCloseDisplay(display);
1
2
3
glXDestroyWindow(display,glxWindow);
XDestroyWindow(display,window);
XCloseDisplay(display);
四.总结
本文简要介绍了简要介绍了Linux下OpenGL程序的写法。可以看到这种基于X Window的写法还是很繁琐的,因此如果要做Linux上的图形程序开发的话,还是尽量选用GLUT、GLFW、SDL和Qt这样的封装好的环境比较好。
Linux中opengl库叫什么名字,Linux下的OpenGL——Mesa和GLX简介相关推荐
- Linux中动态库(共享库)的制作与使用
0. 库的基本概念 见博客:Linux中静态库的制作与使用 0.1 动态库的工作原理 首先回忆一下静态库,使用静态库,在GCC进行链接时,会把静态库中代码打包到可执行程序中. 但是使用动态库,在GCC ...
- Linux中静态库和动态库(共享库)的区别
1. 静态库和动态库的制作过程区别 1.1 静态库的制作过程 详见博客:Linux中静态库的制作与使用 1.2 动态库的制作过程 详见博客:Linux中动态库(共享库)的制作与使用 2. 静态库和动态 ...
- Unix网络编程unp.h问题以及Linux中的库
Stevens的<UNIX网络编程 卷1:套接字连网API>是一本很著名的UNIX网络编程书籍.其中使用了一个unp.h的引用,如果没有设置相应的库的话,即使引入了头文件也是没用的.所以首 ...
- linux查看动态库导出的符号,Linux下控制动态库导出
在Linux中动态库的确给程序带来了良好的扩充性,并减少了内存的使用量,但这是有代价的.例如: #include Int main(int argc, char *argv[]) { Printf(& ...
- Linux下dislocate命令用法,在 Linux 中遨游手册页的海洋 | Linux 中国
原标题:在 Linux 中遨游手册页的海洋 | Linux 中国 Linux 系统上的手册页可以做的不仅仅是提供特定命令的信息.它们可以帮助你发现你没有意识到的命令. https://linux.cn ...
- linux vi 移动光标,linux中vi命令的光标移动操作linux网页制作 -电脑资料
分享一篇关于linux中vi命令的光标移动操作的文章,有需要的朋友可以参考一下, 全屏幕文本编辑器中, 光标的移动操作无疑是最经常使用的操作了.用户只有熟练地使用移动光标的这些命令,才能迅速准确地到达 ...
- linux中打开pdf文件_在Linux中减少PDF文件大小
linux中打开pdf文件 In our Linux system, If we have a large PDF file, we may want to reduce it's size. We ...
- Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Win3 ...
- linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...
一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...
最新文章
- hp惠普笔记本电脑黑屏大小写锁定键闪烁报错无法开机怎么办?
- 同一份数据,Redis为什么要存两次?
- php 做的网页 排版错误,discuz 帖子排版显示出错
- MFC消息处理学习总结
- Linux内核开发函数详解
- python问题化教学设计_基于IPO的Python教学设计
- OpenShift 4 - 用内置的Prometheus监控应用
- C#AutoResetEvent和ManualResetEvent的区别
- Appium下载遇到的问题
- ipad浏览器安装java_360浏览器苹果平板下载
- 投影仪是计算机的基本配置吗,投影仪如何设置
- 路径规划算法:Dijkstra
- 南京计算机类事业单位,南京市属事业单位公开招聘579人 3月25日起报名
- 挖掘:如何用迅雷下载4399小游戏站内的所有游戏
- JavaScript案例之抽奖机
- 如何估算一个项目的成本:CAPEX与OPEX的区别
- 一个屌丝程序猿的人生(八)
- Lambda表达式到底是什么?——简单了解Lambda表达式
- Python 深度学习 Class 2:神经网络的数学基础
- matlab多元变量最优解,模拟退火算法确定多个变量的最优解
热门文章
- u8系统清理异常咋进服务器,用友u8怎么清除异常
- 关于C/C++读写64位内存的实例笔记
- 【万兴PDF专家】OCR引擎的离线安装方法,让你不受网速的折磨,PDF给OCR成可搜索的高级PDF,牛逼了我的万兴
- Python+Flask
- 计算机ps cs2考试,Adobe Photoshop CS2考试大纲
- c语言点餐系统测试总结报告,数据结构实训报告c语言点餐系统net
- xsy1436-括号游戏
- jquery延时执行
- WebSecurityConfigurerAdapter简单分析
- G1D17-研究方向rce45-49不快乐就去敲敲代码