linux使用vscode构建opengl项目

环境

ubuntu20.04
vscode基本使用参考

基本概念

OpenGL是 Open Graphics Library
OpenGL专注在Graphics,3D绘图。

注意区分CV
OpenCV是 Open Source Computer Vision Library
OpenCV主要是提供图像处理和视频处理的基础算法库,还涉及一些机器学习的算法。比如你想实现视频的降噪、运动物体的跟踪、目标(比如人脸)的识别这些都是CV的领域

其实两者的区别就是Computer Graphics和Computer Vision这两个学科之间的区别,前者专注于从采集到的视觉图像中获取信息,是用机器来理解图像;后者是用机器绘制合适的视觉图像给人看。

glew(The OpenGL Extension Wrangler Library)是对底层OpenGL接口的封装,可以让你的代码跨平台。
glad与glew作用相同,可以看作它的升级版。
Freeglut(OpenGL Utility Toolkit)主要用于创建OpenGL上下文、接收一些鼠标键盘事件等等。
glfw(Graphics Library Framework)是Freeglut升级版,作用基本一样

我们现在用glad,glfw。

Linux下的.so是基于Linux下的动态链接,其功能和作用类似与windows下.dll文件。

glfw安装方式(任选其一即可)

apt下载

官网下载源代码后自己编译安装

1.下载GLFW包
glfw官网下载地址
点击source package下载
file

cd  ~/下载  //进入下载的位置,我的是  ~/下载
unzip glfw-3.3.3.zip // 解压GLFW,会在当前目录生成一个同名文件夹。

2.编译

 cd ~/下载/glfw-3.3.3 //进入解压后目录
mkdir glfw-build // 创建build目录,我们之后将会编译到此目录中
 cd glfw-build //进入build目录
cmake  ~/下载/glfw-3.3.3 //生成makefiles
 执行make //编译
 sudo make install //安装,可以看到头文件和动态库分别安装到了/usr/local/下的include和lib目录里

关于/lib /usr/lib /usr/local/lib目录的区别
简单说/lib指向/usr/lib (实际存储在/usr/lib下)是系统级的,/usr/local/lib是用户级的. 仅仅被/usr目录下的程序所使用的共享库不必放到/lib目录下。 只有/bin和/sbin下的程序所需要的库有必要放到/lib目录下
3.Ubuntu下直接运行实例

cd  ~/下载/glfw-3.3.3/glfw-build/examples //进入存放示例程序的目录
./simple //运行

当然我们是为了自己写一个opengl程序,因此还需要继续安装glad

glad下载

lspci | grep 'VGA'  //查看显卡型号
glxinfo | grep -i opengl //查看显卡版本

我的是OpenGL version string: 4.6 (Compatibility Profile) Mesa 20.2.6
即4.6

下载地址,发现不会选就拐回来往下看!
将语言(Language)设置为C/C++,在API选项中,选择3.3以上的OpenGL(gl)版本(我们的教程中将使用3.3版本,但更新的版本也能正常工作)。之后将模式(Profile)设置为Core,并且保证生成加载器(Generate a loader)的选项是选中的。现在可以先(暂时)忽略拓展(Extensions)中的内容。都选择完之后,点击生成(Generate)按钮来生成库文件。

GLAD现在应该提供给你了一个zip压缩文件,包含两个头文件目录,和一个glad.c文件。

cd ~/下载/glad/include  //进入你的下载目录
sudo mv -r glad /usr/local/include //将glad目录移动到/usr/local/include
sudo mv -r KHR /usr/local/include //将KHR目录移动到/usr/local/include
cd ~/下载/glad/src
sudo mv glad.c 你的工程目录 //添加glad.c文件到你的工程中。

在vscode创建工程

main.cpp中头文件
#include <glad/glad.h>
#include <GLFW/glfw3.h> //注意顺序,不可调换
我这里给一个完整的模板,可以在此基础上进行开发
新建一个文件夹test1
里面再新建两个目录source .vscode 分别存放源代码(cpp)与vscode的配置

source /test1.cpp

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h> //注意顺序
int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    GLFWwindow *window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    glViewport(0, 0, 800, 600);
    void framebuffer_size_callback(GLFWwindow * window, int width, int height);
    void processInput(GLFWwindow * window);

    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
};
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
    glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

source /glad.c

内容为下载glad时给的,每个工程都需要用

.vscode/tasks.json

/*
编译设置。不同文件组织形式时需修改部分路径
*/
{
    //Ctrl+Shift+B执行编译(执行此文件),编译器路径也是以此文件为主c_cpp_properties.json为辅
    "version": "2.0.0",
    "tasks": [ // 任务分组,因为是tasks而不是task,意味着可以连着执行很多任务
        {
            "type": "shell", // 任务执行的是shell命令,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(命令解析器)。它类似于DOS下的command.com和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
            "label": "compile", // 任务的名字叫Build,注意是大小写区分的,等会在launch中调用这个名字,从而调用编译
            "command": "g++", //具体命令   
            //"command": ".\\build.bat",//法三 cmake 
            "args": [ //参数
               // "-lGLEW",

                "-g", //只是编译器,在编译的时候,产生调试信息。
                // "-std=c++17",  //使用c++17标准编译
                //"-Wall", // 开启额外警告 
                //"${file}", //当前文件名,注意编译时窗口切换到cpp文件中!
                "${workspaceFolder}/source/*.cpp",  //多文件编  译,法一当前工作空间下文件夹source目录名下的所有cpp文件。 source对应工程目录下的source文件夹名字,可自行修改   
                "${workspaceFolder}/source/*.c", 
                // "${fileDirname}\\此处替换.cpp", //多文件编译,法二每个文件添加一行,也可使用makefile                      
                //"-I","${workspaceFolder}\\include",      // 参数-I 和工程路径 指明了项目中要引用的非标准头文件的位置。 include对应工程目录下的include文件夹名字,可自行修改                   
                // "-finput-charset=UTF-8",           //输入编译器默认文本编码 默认为utf-8 
                //"-fexec-charset=GB18030",          //输出exe文件编码 
                "-o", //制定目标名称,缺省的时候,gcc 编译出来的文件是a.out
                "${fileDirname}/${fileBasenameNoExtension}",
       //         "-lGLEW -lglfw3 -lGL -lX11 -lXxf86vm -lpthread -ldl -lXrandr -lXinerama -lXcursor"
                "-lglfw",
       //         "/lib/x86_64-linux-gnu/libglfw.so.3.3",
                "-lGL",
       //         "/lib/x86_64-linux-gnu/libGL.so.1.7.0",
                "-lX11",
                "-lXxf86vm",
                "-lpthread",
                "-ldl",           
                "-lXrandr", 
                "-lXinerama",
                "-lXcursor",
            ],
            // 所以以上部分,就是在shell中执行(假设文件名为filename.cpp)
            // g++ filename.cpp -o filename.exe
            "problemMatcher": [
                "$gcc" // 使用gcc捕获错误,gcc and g++分别是gnu的c & c++编译器
            ],
            "group": {
                "kind": "build",
                "isDefault": true
                // 在build组的任务们,可以通过在Command Palette(F1) 输入run build task来运行(实际为编译过程)
                // 当然,如果任务分组是test,你就可以用run test task来运行 
            },
            "presentation": {
                "panel": "new", //这里shared表示共享,改成new之后每个进程创建新的端口
            }
        }
    ]
}

.vscode/launch.json

/*
调试设置。不同文件组织形式时需修改部分路径
*/
{
    "version": "0.2.0",
    "configurations": [  
        {
            "name": "C/C++",
            "type": "cppdbg",
            "request": "launch",//为什么选 launch不选attach,是因为attach用来给正在执行的文件用的,比如网页中的组件,而launch是执行新文件
            "program": "${fileDirname}/test1",//需要运行的是当前打开文件的目录中,名字和当前文件相同,但扩展名为exe的程序
            //"program": "${workspaceFolder}/Bin/Compile.exe",//法三,使用cmake时用
            "args": [],
            "stopAtEntry": false,// 选为true则会在打开控制台后停滞,暂时不执行程序
            "cwd": "${workspaceFolder}",// 当前工作路径:当前文件所在的工作空间,
            //"cwd": "${workspaceFolder}\\out", //调试程序时的工作目录 。out对应工程目录下的out文件夹
            "environment": [],
            "externalConsole": false, // 是否使用外部控制台
            "MIMode": "gdb", // VSCode要使用的调试工具or指示VS代码将连接到的调试器
            //"miDebuggerPath": "gdb",// miDebugger的路径,注意这里要与MinGw的路径对应 当未指定时,它将搜索操作系统的PATH变量来寻找调试器
            "preLaunchTask": "compile",//在launch之前运行的任务名,这个名字一定要跟tasks.json中的任务名字大小写一致,有此行,则可直接按F5运行,自动调用编译任务
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing", //为 gdb 启用整齐打印
                    "ignoreFailures": true
                }
            ],
        },
    ]
}

.vscode/c_cpp_properties.json

/*
此文件非必须
*/{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**" 
                //"${workspaceFolder}\\include\\**"  //增加其他包含头文件时用
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "gcc-x64"
        }
    ],
    "version": 4
}

其他问题

/usr/bin/ld: cannot find -lxxx安装xxx时出现(xxx为任意名字)

是因为找不到相应的lib文件,以上面的例子来说就是在系统中找不到libxxx.so文件。

以xxxso为例,我们先在系统中查找下该文件。命令为:
locate libxxx

可以看到,有libxxxso.x文件存在,但是没有libxxx.so文件,因此我们进入/usr/lib/x86_64-linux-gnu/目录中,新建一个libxxx.so的软连接,使其链接到已有的libxxx.so.x文件
命令为:
sudo ln -s libxxx.so.x libxxx.so
到此,该错误已经解决。
Ubuntu Ctrl + Shift + I vscode代码对齐

其他学习资源

https://learnopengl-cn.github.io/01%20Getting%20started/03%20Hello%20Window/