首页 > 系统相关 >【小沐学OpenGL】Ubuntu环境下OpenGL的安装和使用

【小沐学OpenGL】Ubuntu环境下OpenGL的安装和使用

时间:2024-09-08 22:54:34浏览次数:13  
标签:OpenGL Ubuntu dpy 小沐学 X11 服务器 include display

文章目录

1、简介

1.1 OpenGL简介

OpenGL作为图形界的工业标准,其仅仅定义了一组2D和3D图形接口API,而对于窗口管理、IO消息响应等并没有规定。也就是说,OpenGL依赖各平台提供用于渲染的context以及具体实现方式,而各平台提供的实现不尽相同。这些实现主要有:Windows平台下的WGL、Linux下的Mesa/GLX、Mac OS X下的Cocoa/NSGL,以及跨平台的GLUT、GLFW、SDL等等。
在这里插入图片描述

安装OpenGL库:

# sudo apt-get install build-essential libxmu-dev libxi-dev libgl-dev
sudo apt-get install build-essential
sudo apt-get install libgl1-mesa-dev
sudo apt-get install libglu1-mesa-dev

使用如下的命令来查看对应显卡的OpenGL版本:

glxinfo | grep -i opengl

在这里插入图片描述

1.2 Linux上的窗体系统

Linux上的窗体系统主要有X11和Wayland两种,判断Linux系统的窗体系统可以使用以下方式:

  • 在X11系统上:
echo $XDG_SESSION_TYPE

在这里插入图片描述
Ubuntu 20.04 LTS系统也可以在设置-关于里查看:
在这里插入图片描述

  • 在某些Wayland系统上:
echo $XDG_SESSION_TYPE

在这里插入图片描述
Ubuntu 22.04 LTS系统也可以在设置-关于里查看:
在这里插入图片描述
根据系统与窗体系统进行选择依赖并安装。
如果这里是X11,按照编译指南,这里安装xorg-dev:

sudo apt install xorg-dev

在这里插入图片描述
Xorg(或 X 显示服务器)是传统的显示服务器,而 Wayland 相对较新。 2017 年,Ubuntu 将其设为默认版本 17.10。实验并不顺利,他们又恢复到使用 Ubuntu 18.04 的 Xorg。现在,Wayland 在 21.04 版本中再次成为默认值。

1.3 Linux中的显示服务器

显示服务器是一个程序,其主要任务是协调客户端与其他操作系统,硬件以及彼此之间的输入和输出。显示服务器通过显示服务器协议与其客户端进行通信。

显示服务器是任何图形用户界面(尤其是窗口系统)中的关键组件。它是图形用户界面(GUI)的基本组件,位于图形界面和内核之间。因此,借助显示服务器,您可以将计算机与GUI一起使用。没有它,您将只能使用命令行界面。

不要将显示服务器与桌面环境混淆是非常重要的。桌面环境(Gnome、KDE、Xfce、MATE等)使用了底层的显示服务器。

显示服务器通过显示服务器协议与其客户端进行通信。Linux中提供了三种显示服务器协议。X11和Wayland是其中两个。第三个Mir超出了本文的范围。

  • (1)X Window System, X.Org, X11介绍
    X Window System(通常仅称为X或X11)确实很古老。它最初起源于1984年,最终成为大多数类似UNIX的操作系统(包括Linux)的默认窗口系统。
    在这里插入图片描述

X.Org服务器是X.Org基金会管理的X Window System显示服务器的免费开放源代码实现。它是一个通过X11协议与客户端应用程序进行交互的应用程序,用于在显示器上绘制内容并发送输入事件,例如鼠标移动,单击和击键。通常,将启动一个X服务器,它将等待客户端应用程序连接到它。Xorg基于客户端/服务器模型,因此允许客户端在另一台计算机上本地或远程运行。
在这里插入图片描述

在X11的设计中,应用程序和显示器不必在同一台计算机上,这一点并不明显。在开发X时,X server运行在工作站上,而用户在具有更强处理能力的远程计算机上运行应用程序是很常见的。
在这里插入图片描述

X11 是网络协议。它描述了如何在客户端(应用程序)和显示器(服务器)之间交换消息。这些消息通常带有原始的绘制命令,例如“绘制框”,“在此位置写这些字符”,“已单击鼠标左键”等。
在这里插入图片描述

但是X11已经很古老了,X server协议提供的大部分功能不再使用。X11所做的几乎所有工作都重新分配给了各个应用程序和窗口管理器。然而,所有这些旧特性仍然存在,给所有这些应用程序带来了压力,损害了性能和安全性。

X11(X Window System):X11,也称为 Xorg,几十年来一直是标准显示协议。它使用客户端-服务器架构,其中应用程序(客户端)与中央服务器通信以渲染图形。这种架构允许网络透明,但可能导致效率低下和复杂性。
在这里插入图片描述

  • (2)下一代显示服务器Wayland
    Wayland 由X.Org开发人员Kristian Hogsberg于2008年作为个人项目开始。它是一种通信协议 ,用于指定显示服务器与其客户端之间的通信。Wayland是作为一个免费的开源社区驱动的项目而开发的,目的是用现代,安全和简单的窗口系统代替X Window System(也称为X11或Xorg)。
    在这里插入图片描述
    Wayland:Wayland 采用更现代的方法,采用更简单的架构,旨在消除 X11 的复杂性。在 Wayland 模型中,合成器充当应用程序和显示硬件之间的中介。这种直接沟通使流程更加简化和高效。
    在这里插入图片描述
    Wayland是一套display server(Wayland compositor)与client间的通信协议,而Weston是Wayland compositor的参考实现。其官网为http://wayland.freedesktop.org/。它们定位于在Linux上替换X图形系统。X图形系统经历了30年左右的发展,其设计在今天看来已略显陈旧。在X系统中,X Server作为中心服务,连接clien和硬件以及compositor。但时至今日,原本在X Server中做的事很多已被移到kernel或者单独的库中,因此X Server就显得比较累赘了。Wayland在架构上去掉了这个中间层,将compositor作为display server,使client与compositor直接通信,从而在灵活性和性能等方面上能够比前辈更加出色。
    在这里插入图片描述

1.4 xrandr命令

xrandr是一款官方的扩展配置工具。它可以设置屏幕显示的大小、方向、镜像等,包括对多屏的设置。详细的使用方法可以通过man xrandr查看。

xrandr

在这里插入图片描述

xrandr --verbose

在这里插入图片描述

2、Xlib开发

Xlib 是一个库,它为在 X Window 系统(也称为 X)下运行的应用程序提供函数。 这包括窗口管理和事件处理。X 是一个面向网络的系统:一个应用程序 在计算机 A 上运行的计算机 A 可以将其图形输出发送到计算机 B,该计算机位于网络中的其他位置 (网络可以是 LAN 和 Internet),并且可以从计算机 B 接收键盘或鼠标输入等事件。 这要求在两台计算机上都运行一个名为“X-Server”的程序。在 Linux 中,X-server 是使用 命令 startx.您很可能不必手动启动 X-server,因为大多数 Linux 发行版 将系统设置为在启动后自动启动 X。

https://x.org/releases/current/doc/libX11/libX11/libX11.html

2.1 创建空白窗口

  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8.1)

project(my_project)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)

find_package(X11 COMPONENTS X11 Xft)

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${X11_LIBRARIES})
  • main.cpp
#include <X11/Xlib.h>
#include <stdio.h>
#include <cstdlib>

int main() {
    //程序创建一个基本的窗口,并在按下任意键后退出
    Display *d;
    int s;
    Window w;
    XEvent e;

    d = XOpenDisplay(NULL);
    if (d == NULL) {
        fprintf(stderr, "无法打开显示\n");
        exit(1);
    }

    s = DefaultScreen(d);
    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 600, 400, 1, BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w, ExposureMask | KeyPressMask);
    XMapWindow(d, w);

    const char* title = "yxy x11 window";
    XStoreName( d, w, title );
    XSetIconName( d, w, title );

    while (1) {
        XNextEvent(d, &e);
        if (e.type == KeyPress)
            break;
    }

    XCloseDisplay(d);
    return 0;
}

运行测试程序如下:
在这里插入图片描述

2.2 打印文字

  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8.1)

project(my_project)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)

find_package(X11 REQUIRED)

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${X11_LIBRARIES})
  • main.cpp
/*
  * 下边是编译命令
  * gcc x11.c -o output -I/usr/X11R6/include -L/usr/X11R6/lib -lX11
  */

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    Display *display;
    Window window;
    XEvent event;
    char *msg = "hello, yxy, 2024";
    int s;

    /* 与Xserver建立连接 */
    display = XOpenDisplay(NULL);
    if (display == NULL)
    {
        fprintf(stderr, "Cannot open display\n");
        exit(1);
    }

    s = DefaultScreen(display);

    /* 创建一个窗口 */
    window = XCreateSimpleWindow(display, RootWindow(display, s), 10, 10, 500, 200, 1,
                                 BlackPixel(display, s), WhitePixel(display, s));

    const char* title = "yxy x11 window";
    XStoreName( display, window, title );
    XSetIconName( display, window, title );

    /* 选择一种感兴趣的事件进行监听 */
    XSelectInput(display, window, ExposureMask | KeyPressMask);

    /* 显示窗口 */
    XMapWindow(display, window);

    /* 事件遍历 */
    for (;;)
    {
        XNextEvent(display, &event);

        /* 绘制窗口或者重新绘制 */
        if (event.type == Expose)
        {
            XFillRectangle(display, window, DefaultGC(display, s), 20, 20, 10, 10);
            XDrawString(display, window, DefaultGC(display, s), 50, 50, msg, strlen(msg));
        }
        /* 当检测到键盘按键,退出消息循环 */
        if (event.type == KeyPress)
            break;
    }

    /* 关闭与Xserver服务器的连接 */
    XCloseDisplay(display);

    return 0;
}

在这里插入图片描述

2.3 键盘响应

  • main.cpp
#include <stdio.h>
#include <X11/Xlib.h>

int main ( int argc, char **argv)
{
    Display *display;
    Window window;
    Window root;
    XSetWindowAttributes attributes;
    Pixmap pixmap;
    Visual *visual;
    int screen;
    int depth;
    Atom wmDeleteMessage;
    XEvent event;

    display = XOpenDisplay (NULL);
    screen = DefaultScreen (display);
    visual = DefaultVisual (display, screen);
    root = XRootWindow (display, screen);
    depth = DefaultDepth (display, screen);
    attributes.background_pixel = XWhitePixel (display, screen);
    attributes.override_redirect = 0;

    window = XCreateWindow (display, root,
                           0, 0, 400, 200,
                           0, depth, InputOutput,
                           visual,
                           CWBackPixel | CWBorderPixel |
                               CWOverrideRedirect, &attributes);

    wmDeleteMessage = XInternAtom (display, "WM_DELETE_WINDOW" , False);
    XSetWMProtocols (display, window, &wmDeleteMessage, 1);
    XStoreName (display, window, "yxy x11 window" );
    XMapWindow (display, window);

    do {
        XNextEvent (display, &event);
        if (event.type == Expose) {
        } else if (event.type == ClientMessage
                   && event.xclient.data.l[0] == wmDeleteMessage) {
            break ;
        }
    } while (event.type != KeyPress);

    printf ( "closing display\n" );
    XCloseDisplay (display);
}

在这里插入图片描述

3、OpenGL开发

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等。

它使用 GLX 扩展到 X windows 系统。在 X11 中使用 XLib 与 GLX 绘制 OpenGL 图形的大致过程如下:

  • 1、使用 XOpenDisplay 函数建立窗口(一个 X Client)与 X Server 端的连接。
  • 2、根据指定的 GLX 帧缓存格式,调用 glXChooseVisual 函数选择创建匹配的 X 窗口画面(Visual)格式,使得 GLX 能够将 OpenGL 光栅化产生的图像转换为适当的 X 窗口画面格式。
  • 3、使用 glXCreateContext 函数创建一个 OpenGL 渲染环境。
  • 4、基于步骤 2 中所选择的 X 窗口画面格式,使用 XCreateWindow 构建一个 X 窗口。
  • 5、使用 glXMakeCurrent 函数将 OpenGL 渲染环境设为当前的 X 窗口渲染环境,然后可调用 OpenGL 绘图函数。
  • 6、使用 XMapWindow 函数显示 X 窗口。
  • 7、开始 X 窗口的事件循环。
  • 8、退出 X 窗口事件循环后的资源释放。

3.1 绘制矩形

  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8.1)

project(my_project)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)

find_package(OpenGL REQUIRED)
find_package(X11 REQUIRED)

#INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIRS})
#LINK_DIRECTORIES(${OPENGL_LIBRARY_DIRS})

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${X11_LIBRARIES} ${OPENGL_LIBRARIES})

  • main.cpp
#include<stdio.h>
#include<stdlib.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>

Display                 *dpy;
Window                  root;
GLint                   att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo             *vi;
Colormap                cmap;
XSetWindowAttributes    swa;
Window                  win;
GLXContext              glc;
XWindowAttributes       gwa;
XEvent                  xev;

void DrawAQuad() {
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1., 1., -1., 1., 1., 20.);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);

    glBegin(GL_QUADS);
    glColor3f(1., 0., 0.); glVertex3f(-.75, -.75, 0.);
    glColor3f(0., 1., 0.); glVertex3f( .75, -.75, 0.);
    glColor3f(0., 0., 1.); glVertex3f( .75,  .75, 0.);
    glColor3f(1., 1., 0.); glVertex3f(-.75,  .75, 0.);
    glEnd();
}

int main(int argc, char *argv[]) {

    dpy = XOpenDisplay(NULL);

    if(dpy == NULL) {
        printf("\n\tcannot connect to X server\n\n");
        exit(0);
    }

    root = DefaultRootWindow(dpy);

    vi = glXChooseVisual(dpy, 0, att);

    if(vi == NULL) {
        printf("\n\tno appropriate visual found\n\n");
        exit(0);
    }
    else {
        printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
    }


    cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    win = XCreateWindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);

    XMapWindow(dpy, win);
    XStoreName(dpy, win, "yxy x11 window");

    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    glXMakeCurrent(dpy, win, glc);

    glEnable(GL_DEPTH_TEST);

    while(1) {
        XNextEvent(dpy, &xev);

        if(xev.type == Expose) {
            XGetWindowAttributes(dpy, win, &gwa);
            glViewport(0, 0, gwa.width, gwa.height);
            DrawAQuad();
            glXSwapBuffers(dpy, win);
        }

        else if(xev.type == KeyPress) {
            glXMakeCurrent(dpy, None, NULL);
            glXDestroyContext(dpy, glc);
            XDestroyWindow(dpy, win);
            XCloseDisplay(dpy);
            exit(0);
        }
    } /* this closes while(1) { */
} /* this is the } which closes int main(int argc, char *argv[]) { */

执行程序如下:

gcc -o main main.c -lX11 -lGL -lGLU

在这里插入图片描述

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

标签:OpenGL,Ubuntu,dpy,小沐学,X11,服务器,include,display
From: https://blog.csdn.net/hhy321/article/details/142033148

相关文章

  • ubuntu server 虚拟机通过dhcp server总是获得相同的ip
    参考文档:https://knowledge.broadcom.com/external/article/316620/cloned-vm-acquires-the-same-dhcp-ip-addr.html现象:ubuntuserver22.04,通过vmwareplayer创建了一个虚拟机,然后又复制了多个虚拟机1.复制的虚拟机重新生成了mac地址2.三台虚拟机启动后得到的Ip地址相同......
  • 虚拟机安装Ubuntu16并安装Ros(Kinetic)
    1.虚拟机安装镜像教程参考:https://www.cnblogs.com/su1961117443/p/12419892.html或者https://www.bilibili.com/video/BV1zt411G7Vn?p=2可以安装vmtools,界面显示窗口自适应。2.ROS各个版本注:因为ubuntu是16.04的,所以这里我们安装Kinetic版本的ROS.参考链接:https://blog.csdn.ne......
  • ubuntu 和windows用samba服务器实现数据传输
    1,linux安装samba服务器sudoapt-getinstallsambasamba-common2,linux配置权限,修改目录权限,linux下共享的文件权限设置。sudochmod777/home/lark-R3.添加samba用户 sudosmbpasswd-a lark4,配置共享目录打开/smb.conf在文件末尾添加如下信息: vim/et......
  • 怎么查看ubuntu版本—查看Ubuntu版本方法
    怎么查看ubuntu版本—查看Ubuntu版本方法 城市野鹿 技术教程 2024-05-15 0 3,281怎么查看ubuntu版本—查看Ubuntu版本方法Ubuntu是一种基于Debian的开源操作系统,广泛应用于个人电脑、服务器和云计算平台。对于使用Ubuntu的用户来说,了解自己的系统版本是非常重要的。......
  • Ubuntu 22.04 镜像源
    #aliyundebhttp://mirrors.aliyun.com/ubuntu/lunarmainrestricteduniversemultiversedeb-srchttp://mirrors.aliyun.com/ubuntu/lunarmainrestricteduniversemultiversedebhttp://mirrors.aliyun.com/ubuntu/lunar-securitymainrestricteduniversemultive......
  • Linux命令分享 三 (ubuntu 16.04)
    1、‘>’'>>'输出重定向用法:命令参数>文件ls>a.txt‘>’将一个命令的结果不输出到屏幕上,输出到文件中,如果文件不存在就创建文件,如果存在就覆盖文件。ls>>a.txt‘>>’如果文件不存在就创建文件,如果存在就追加在文件后面。2、echo回显字符你在echo后面输入......
  • ubuntu安装
    一、系统安装1、ubuntu22.04下载地址官方清华源阿里源2、开机启动并设置安装ubuntu3、语言选择4、镜像是否需要更新后才继续安装5、设置键盘6、选择安装类型7、设置网络8、设置系统代理9、设置包的源地址10、硬盘分区11、格式化提示12、设置账号,不能......
  • AWTK 如何用 OpenGL 绘制图形
    在有GPU的情况下,AWTK使用OpenGL绘制图形。但是你会发现,如果自己在paint事件中使用OpenGL绘制图形,图形是无法显示的。原因是,AWTK采用nanovg绘制图形,而nanovg并不是在绘制时立即执行的,而是在整个界面绘制完成(EndFrame中)集中提交给GPU执行的。所以,如果在paint事......
  • 《Ubuntu 下载和安装的详细步骤》
    以下是Ubuntu下载和安装的详细步骤: 下载: 1. 打开Ubuntu的官方网站(https://ubuntu.com/)。2. 在页面中找到“Download”(下载)选项,点击进入下载页面。3. 在下载页面中,您会看到不同的版本可供选择,如最新的长期支持版(LTS)等。根据您的需求选择合适的版本,通常建议选......
  • Ubuntu22 CMake安装使用教程
    1.CMake简介CMake是一个跨平台的自动化构建系统工具,它被用来管理和控制软件构建过程。CMake使用一个称为CMakeLists.txt的文本文件来描述项目的构建过程。这个文件包含了项目所需的各种设置和指令,比如源文件的位置、编译选项、链接器选项等。CMake并不是一个编译器,而是......