惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Troy Hunt's Blog
Schneier on Security
Schneier on Security
N
News | PayPal Newsroom
Hacker News: Ask HN
Hacker News: Ask HN
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
N
News and Events Feed by Topic
V
Vulnerabilities – Threatpost
Cyberwarzone
Cyberwarzone
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
WordPress大学
WordPress大学
U
Unit 42
PCI Perspectives
PCI Perspectives
S
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
The Cloudflare Blog
I
Intezer
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
Martin Fowler
Martin Fowler
B
Blog
美团技术团队
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
酷 壳 – CoolShell
酷 壳 – CoolShell
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
博客园_首页
A
About on SuperTechFans
Vercel News
Vercel News
Attack and Defense Labs
Attack and Defense Labs
H
Heimdal Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
小众软件
小众软件
H
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
The Exploit Database - CXSecurity.com
Y
Y Combinator Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Webroot Blog
Webroot Blog
T
Tenable Blog

博客园 - 京山游侠

使用 Alacritty 替代 Gnome-Terminal 解决 Ubuntu 中终端的行间距问题 Linux 下的 OpenGL 之路(九):天空盒、反射和折射 Linux 下的 OpenGL 之路(八):贴图和材质 Linux 下的 OpenGL 之路(七):光照 新版 Ubuntu 中 gnome-terminal 可恶的行间距问题逼我退回了 Ubuntu 20.04 Linux 下的 OpenGL 之路(六):使用 GLFW 在 OpenGL 的场景中漫游 Linux 下的 OpenGL 之路(五):使用 Assimp 库加载 3D 模型 Linux 下的 OpenGL 之路(四):展示红宝书中自带的 3D 模型 Linux 下的 OpenGL 之路(三):向 3D 世界迈出一小步 Linux 下的 OpenGL 之路(一):安装 Ubuntu 20.10,高性能计算和 3D 视觉呈现第一步 测试一下我的电脑有多快 在4K屏下以超过VMWare默认的最高分辨率运行Linux系统 Linux 桌面玩家指南:20. 把 Linux 系统装入移动硬盘打包带走 Linux 桌面玩家指南:19. 深入理解 JavaScript,及其开发调试工具 Linux 桌面玩家指南:18. 使用 Docker 隔离自己的开发环境和部署环境 Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解决一些依赖 Windows 的痛点问题 Linux 桌面玩家指南:16. 使用 CUDA 发挥显卡的计算性能 Linux 桌面玩家指南:15. 深度学习可以这样玩 Linux 桌面玩家指南:14. 数值计算和符号计算
Linux 下的 OpenGL 之路(二):为什么说使用 Linux 系统学习 OpenGL 更方便
京山游侠 · 2021-01-27 · via 博客园 - 京山游侠

前言

上一篇随笔介绍了我的电脑,同时也介绍了 Ubuntu 20.10 系统的安装和美化。这一篇,我将正式开始 OpenGL 之旅。使用 Ubuntu 来进行开发,不仅仅只是因为我对 Linux 桌面比较熟悉,其实我对 Windows 也很熟悉,主要还是因为在 Linux 系统下搭建 OpenGL 的开发环境确实是太方便了。在 Windows 下开发 OpenGL,每用到一个库,我们都要单独去搜索和下载,然后在 Visual Studio 中进行设置,很繁琐。在 Ubuntu 中,安装这些库,就是一条命令的事,下面详细论述。

搭建 OpenGL 的开发环境

学 OpenGL,C/C++ 应该是首选,所以先安装 C/C++ 的开发环境,无论是选择 GCC,还是选择 CLang,在 Ubuntu 中就是一条命令的事,我这里选 GCC。在 Ubuntu 中,可以直接安装 build-essential,更省事。命令如下:

sudo apt install build-essential

OpenGL 不提供和 GUI 相关的 API,所以 OpenGL 不能处理诸如创建窗口、处理用户的键盘鼠标输入这样的任务。这时,我们需要 GLFW。使用 GLFW 库,我们可以简化搭建 OpenGL 程序框架的任务,同时还可以轻松获得跨平台的功能。安装 GLFW 也是一条命令的事:

sudo apt install libglfw3 libglfw3-dev

除此之外,我们还需要 GLEW。有了GLEW 扩展库,就再也不用为找不到函数的接口而烦恼了,因为GLEW能自动识别平台所支持的全部 OpenGL 高级扩展涵数。安装命令如下:

sudo apt install libglew2.1 libglew-dev

另外,在写 OpenGL 程序的过程中,会经常需要进行向量、矩阵的计算,所以有一个顺手的数学库是很重要的,我这里选择 GLM。安装命令如下:

sudo apt install libglm-dev

学会了 OpenGL 的基本概念后,当然会忍不住想加载个 3D 模型看看效果,这时候,就可以考虑使用 Assimp 库了。安装命令如下:

sudo apt install assimp-utils libassimp5 libassimp-dev

assimp-utils 包提供了一个assimp命令,使用该命令可以显示 Assimp 库支持哪些格式的 3D 模型文件,也可以使用该命令显示 3D 模型文件的详细信息,如下图:

当然,3D 的东西,还是应该用可视化的方式看起来更直观一些。好在,Linux 中可用的 3D 建模动画软件有 Blender。安装起来也只是一条命令的事:

sudo apt install blender

下面,让大家看一下我的老婆,用的就是 Blender:

最简单的 OpenGL 程序框架

下面,开始写我们的第一个 OpenGL 程序,如下:

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

const int SCR_WIDTH = 1920;
const int SCR_HEIGHT = 1080;

int main(int argc, char** argv){
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "StudyOpenGL", nullptr, nullptr);
    if (window == NULL)
    {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK){
        std::cerr << "Failed to initalize GLEW" << std::endl;
        return -1;
    }

    while (!glfwWindowShouldClose(window))
    {
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

这段程序比较短,使用任何编辑器如 vim、gedit 等等都可以。当后面程序变长之后,我选择使用 Visual Studio Code。我们将这个文件保存为 FirstStep.cpp。编译执行的命令也很简单:

g++ FirstStep.cpp -o FirstStep -lGL -lGLEW -lglfw
./FirstStep

就可以看到我们的第一个 OpenGL 窗口了,目前,它还只是空洞洞的漆黑一片,如下图:

因为我是 4K 屏,所以即使定义了SCR_WIDTH = 1920SCR_HEIGHT = 1080,窗口看起来也不是特别大。上面那个程序是纯 C 版的,等程序变大之后,会在 main() 函数之外遗留很多全局的变量和函数,不是那么清爽,所以常规会使用 C++ 封装一下,建立一个 App 类,以后要添加鼠标键盘输入的功能也在这个类里面加,建立新程序时,只需要继承这个类就可以了。App 类的内容如下:

#ifndef __APP_HPP__
#define __APP_HPP__

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

class App{
    private:
        const int SCR_WIDTH = 1920;
        const int SCR_HEIGHT = 1080;
        
    public:  
    	static App* the_app;
    	
        App(){

        }

        virtual void init(){
            
        }
        
        virtual void display(){
            
        }


        virtual void run(App* app){
            if(the_app != NULL){ //同一时刻,只能有一个App运行
                std::cerr << "The the_app is already run." << std::endl;
                return;
            }            
            the_app = app;
            
            glfwInit();
            GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "StudyOpenGL", NULL, NULL);
            if (window == NULL)
            {
                std::cerr << "Failed to create GLFW window" << std::endl;
                glfwTerminate();
                return;
            }
            glfwMakeContextCurrent(window);
            if(glewInit() != GLEW_OK){
                std::cerr << "Failed to initalize GLEW" << std::endl;
                return;
            }

            init(); //用来准备各种数据

            while (!glfwWindowShouldClose(window))
            {

                display(); //这里才是渲染图形的主战场 
                               
                glfwSwapBuffers(window);
                glfwPollEvents();
            }
            glfwDestroyWindow(window);

            glfwTerminate();
            return;
        }

};

App* App::the_app = NULL;

#define DECLARE_MAIN(a)                             \
int main(int argc, const char ** argv)              \
{                                                   \
    a *app = new a;                                 \
    app->run(app);                                  \
    delete app;                                     \
    return 0;                                       \
}

#endif

把这个文件保存在 include 目录下,命名为 app.hpp,然后,把之前的 FirstStep.cpp 改成如下内容:

#include "../include/app.hpp"

class MyApp : public App {
    private:
        
    public:
        void init(){

        }

        void display(){

        }

        ~MyApp(){

        }

};


DECLARE_MAIN(MyApp)

编译运行,结果是一样的。以后,只需要把初始化数据的代码放到 init() 方法中,把渲染图形的代码放到 display() 方法中即可。程序运行时,init() 方法只调用一次,而 display() 方法每渲染一帧图像就调用一次。

OK,到这里,我们的环境就搭建好了。在下一篇随笔中,我们争取使用 OpenGL 渲染一点有用的东西。

版权申明

该随笔由京山游侠在2021年01月27日发布于博客园,引用请注明出处,转载或出版请联系博主。QQ邮箱:1841079@qq.com