小白学opengl 第一课



  • 第一课:创建一个OpenGL窗口

    选择空项目

    0_1526345895281_QQ截图20180515084615.png

    输入项目名称和位置

    0_1526345931933_QQ截图20180515084648.png

    选择编译器

    0_1526345958327_QQ截图20180515084656.png

    创建成功后,首先添加pri文件,pri文件可以管理我们的类文件,类似一个小项目的感觉

    0_1526345984469_QQ截图20180515084928.png

    输入pri名字

    0_1526346029022_QQ截图20180515084949.png

    此时项目结构,只有pro项目文件,和pri文件

    0_1526346106557_QQ截图20180515085040.png

    修改pro代码,改变项目结构

    0_1526346152132_QQ截图20180515085115.png

    右键pri文件,在pri下创建窗口类

    0_1526346188098_QQ截图20180515085147.png

    输入窗口名

    0_1526346216835_QQ截图20180515085222.png

    创建完毕的项目结构

    0_1526346239009_QQ截图20180515085248.png

    为项目添加main.cpp

    0_1526346285326_QQ截图20180515085426.png

    输入main.cpp

    0_1526346314449_QQ截图20180515085436.png

    openglwindow.h代码

    #ifndef OPENGLWINDOW_H
    #define OPENGLWINDOW_H
    
    #include <QtGui/QWindow>
    #include <QtGui/QOpenGLFunctions>
    
    QT_BEGIN_NAMESPACE
    class QPainter;
    class QOpenGLContext;
    class QOpenGLPaintDevice;
    QT_END_NAMESPACE
    
    class Openglwindow : public QWindow, protected QOpenGLFunctions
    {
        Q_OBJECT
    public:
        explicit Openglwindow(QWindow *parent=0);
        ~Openglwindow();
    
        //基于QPainter渲染
        virtual void render(QPainter *parent);
        //基于opengl渲染
        virtual void render();
        //初始化
        virtual void initialize();
        //设置动画
        void setAnimating(bool animating);
    
    public slots:
        //手动刷新一次
        void renderLater();
        //立刻渲染
        void renderNow();
    
    protected:
        //监听事件
        bool event(QEvent *event) override;
        //监听暴露事件
        void exposeEvent(QExposeEvent *event) override;
    
    private:
        //动画状态位
        bool m_animating;
    
        //OpenGL 上下文
        QOpenGLContext *m_context;
        //OpenGL画笔设备,能使用QPainter在上下文里画东西
        QOpenGLPaintDevice *m_device;
    };
    
    #endif // OPENGLWINDOW_H
    

    openglwindow.cpp代码

    #include "openglwindow.h"
    #include <QtGui/QOpenGLContext>
    #include <QtGui/QOpenGLPaintDevice>
    #include <QtGui/QPainter>
    
    Openglwindow::Openglwindow(QWindow *parent)
        :QWindow(parent)
        ,m_animating(false)
        ,m_context(0)
        ,m_device(0)
    {
        //设置使用OpenGL上下文渲染OpenGL
        setSurfaceType(QWindow::OpenGLSurface);
    }
    Openglwindow::~Openglwindow()
    {
        //删除设备
        delete m_device;
    }
    void Openglwindow::render(QPainter *painter)
    {
        Q_UNUSED(painter);
    }
    
    void Openglwindow::initialize()
    {
    }
    void Openglwindow::render()
    {
        //第一次没有画笔设备,需要创建画笔设备
        if (!m_device)
            m_device = new QOpenGLPaintDevice;
    
        //清除屏幕, 颜色缓冲区和深度缓冲区和模板缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        //设置大小
        m_device->setSize(size());
    
        //创建画笔
        QPainter painter(m_device);
        //用QPainter渲染一次
        render(&painter);
    }
    void Openglwindow::renderLater()
    {
        //请求刷新,窗口会收到UpdateRequest事件
        requestUpdate();
    }
    bool Openglwindow::event(QEvent *event)
    {
        switch (event->type()) {
        case QEvent::UpdateRequest:
            renderNow();
            return true;
        default:
            return QWindow::event(event);
        }
    }
    void Openglwindow::exposeEvent(QExposeEvent *event)
    {
        Q_UNUSED(event);
    
        //如果窗口暴露,显示,立刻渲染画面
        if (isExposed())
            renderNow();
    }
    void Openglwindow::renderNow()
    {
        if (!isExposed())
            return;
    
        bool needsInitialize = false;
    
        //没有上下文就创建上下文
        if (!m_context) {
            m_context = new QOpenGLContext(this);
            //设置格式
            m_context->setFormat(requestedFormat());
            //创建
            m_context->create();
    
            needsInitialize = true;
        }
    
        //激活上下文
        m_context->makeCurrent(this);
    
        if (needsInitialize) {
            //初始化当前上下文的OpenGL函数解析
            initializeOpenGLFunctions();
            initialize();
        }
    
        render();
    
        //交换前后缓冲区,完成一帧渲染
        m_context->swapBuffers(this);
    
        if (m_animating)
            renderLater();
    }
    void Openglwindow::setAnimating(bool animating)
    {
        m_animating = animating;
    
        if (animating)
            renderLater();
    }
    

    main.cpp代码

    #include <QtGui/QGuiApplication>
    #include "openglwindow.h"
    
    int main(int argc, char **argv)
    {
        QGuiApplication app(argc, argv);
    
        QSurfaceFormat format;
        //设置采样率
        format.setSamples(16);
    
        Openglwindow window;
        window.setTitle(QStringLiteral("第一个OpenGLFunctions例子"));
        window.setFormat(format);
        window.resize(640, 480);
        window.show();
    
        return app.exec();
    }
    

    运行

    0_1526349599163_QQ截图20180515095818.png

    源代码下载

    https://gitee.com/chen227/opengl_OpenGLFunctions



  • 这是一个最简单,具有黑色的窗体。可以从中学到很基本的OpenGL调用。



  • 我喜欢用deepin、clion和cmake,我来加一些配置在deepin上能用clion跑你的代码



  • 为啥你老是用码云,不用GitHub?



  • 非常简单的配置,代码已经pr

    cmake_minimum_required(VERSION 3.10)
    project(opengl_OpenGLFunctions)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_CXX_STANDARD 11)
    set(QT Core Gui Widgets)
    find_package(Qt5 REQUIRED ${QT})
    add_executable(${PROJECT_NAME} openglwindow.h openglwindow.cpp main.cpp)
    qt5_use_modules(${PROJECT_NAME} ${QT})
    


  • @大黄老鼠 git慢


Log in to reply
 

最近的回复

  • 就在不久前我分享了USD在Windows上的构建方法,其实我也一直没有放弃在开发领域最擅长的Linux中构建USD。不过,在Linux中要成功地构建USD,比Windows的要难不少。尤其是各种麻烦的依赖库,仍然要解决才行。之前一直在CentOS 7构建,没有成功,而且CentOS构建的话,相关的资料更少,坑更多,而Deepin是国产的Linux桌面系统,友好一些,这样可以少一些困难。目前成功地在Deepin Linux上顺利地编译成功了。

    那么,咱们开始在Linux构建USD吧。

    测试并且安装Python

    有些Linux发行版,默认安装了Python,有的则没。如果你安装了Python,可以测试一下,命令是:

    python --version

    如果报错,那么使用apt安装吧。

    sudo apt install python

    为了安装PyOpenGL等库,还是推荐安装pip。有关安装pip的资料还是挺多的,pip类似npm,是一个包管理器,非常方便,推荐安装。这里有一个获取pip的脚本。我发出来。获取pip的命令是:

    python -m get-pip.py

    拿到USD的代码

    毕竟是在github中获取的USD代码,那么最好安装git,并且设置github的账户以及公钥。然后熟练利用git命令进行如下的操作:

    git clone https://github.com/PixarAnimationStudios/USD

    获取USD依赖的库

    由于依然在github上获取相关的库,获取库的速度大家都知道比较慢,于是我将库上传到我创建的USD小组里了,大家感兴趣的话,可以加入这个QQ群(小组),获取相关的库,然后解压之。
    上海USD小组

    获取USD其它的依赖(包括cmake)

    由于Linux开源的特性,很多底层的库都要到包管理器中寻找,如果编译出错了。记得勤用apt来搜索相关的库。命令是:

    apt search cmake
    pip install pyside2

    值得注意的是,USD在19.11的时候,明确说不支持cmake2了,看来大家要在apt中安装cmake3了。

    编译

    USD在Linux的编译和Windows的差不多,差别在于一个是用Shell脚本,另外一个是用bat脚本。这里我将Shell脚本贴出来给大家参考:

    #!/bin/sh # 最后构建USD项目 baseDir=${baseDir:=$(cd `dirname $0`; pwd)} echo $baseDir pushd $baseDir sudo python $baseDir/USD/build_scripts/build_usd.py -j 4 -v --python --build-args=USD,"-DPYSIDE_USE_PYSIDE2=TRUE -DPYSIDE_BIN_DIR=/usr/local/lib/python2.7/dist-packages/PySide2 -DBOOST_LIBRARYDIR=" /usr/local/USD popd 编译可能遇到的问题 权限问题。这个是最常见的了。Windows的权限问题没有那么严重,而Linux是权限everywhere。于是安装USD的时候,它推荐的位置是/usr/local/USD,这个地方是要权限的。所以记得用sudo,没有设置密码的赶紧用passwd root设置密码了。 遇到找不到编译器的问题。很简单,没有安装编译器呗。Linux默认编译器是g++,所以一定要执行

    sudo apt install g++

    这样才能够解决找不到编译器的问题。同样的,如果想要以后对USD进行调试,那么gdb也是必不可少的,推荐一同安装。

    编译完成

    如果你到了这一步,那么非常恭喜,你已经克服了超多的难关,到达了胜利的彼岸。但是不是要测试一下是否成功地运行了USD呢?我们还是要运行一下USDView来测试一下的嘛。于是我们还是要写一段shell脚本来测试USDView的运行情况:

    #!/bin/sh export LD_LIBRARY_PATH=/usr/local/USD/lib64:$LD_LIBRARY_PATH export PYTHONPATH=$PYTHONPATH:/usr/local/USD/lib/python /usr/local/USD/bin/usdview /media/jiangyimin/Data/models/UsdSkelExamples/HumanFemale/HumanFemale.walk.usd

    由于要寻找库的路径,因此记得及时设置LD_LIBRARY_PATH环境变量。如果一切顺利的话,那么会出现这样的效果:Linux运行USDView

    read more
  • 记住了哦,USD不是咱们所说的美元哦,是迪士尼皮克斯工作室推出的一款动画全流程的工具,简单地说,是用来串流程的,USD的使用借鉴了脚本编程的一些思想,让动画的资产变得可配置,也变得可维护。让同时其提出的几个工具,使得它变成一个较为完整的工具链。
    USD的官方网站(开源)在这里。

    https://openusd.org

    接下来我将告诉大家如何在Windows下构建USD。

    安装Python

    首先呢,是安装USD的依赖项。USD的依赖项挺多,最重要的是Python,因为USD的构建脚本就是用Python写的。所以去Python官网下载Python吧,目前测试成功的是Python2.7。当然你也可以安装Python 3.5,只是我没有测试过,不清楚是否可用。Python的下载地址是:

    https://www.python.org/downloads

    一般来说,安装好了Python,它会给你设置环境变量,或者有一些教程让你们设定环境变量,不过呢,这里我不建议设定环境变量,这样让我们的所有软件运行环境都污染了(可能没有什么事),之后我会写一个脚本来教大家如何书写批处理来让简化操作,真正做到“即用即走”。

    下载Visual Studio 2017

    这不用强调了吧。目前VS2017是必备的软件了,而且有免费社区版,再也不用破解了,赶紧下载一个。安装在合适的位置就好了。

    安装Maya 2018

    一般来说,Maya每年都有发布一个版本,但是2018的格外稳定,推荐安装。为什么要安装Maya呢?因为Maya是一款几乎全能的DCC,可以导出很多模型到USD中,所以USD顺便构建了Maya的插件(这个插件名字叫usdMaya,不过核心代码转到了Autodesk里了,详见https://github.com/Autodesk/maya-usd,此插件除了PXR的USD,还有AL的USD),我也将Maya 2018放在了我们讨论小组群中,大家可以下载。
    USD研究小组.jpg
    我将Maya 2018安装到D:\Develop\Autodesk\Maya2018中。

    安装USD的其余依赖项

    由于USD的python脚本会使用curl或者是powershell的下载功能进行下载,但是由于很多依赖项是从github下载的,下载速度实在是太慢了,所以我将其余的依赖项打包好了,放在USD_dependencies文件夹中,供需要的朋友下载。USD的依赖项已经上传到我们讨论小组群群里了,大家可以下载。
    USD研究小组.jpg

    编写构建USD的脚本

    我的USD安装的位置是D:\Develop\USD,打算安装的位置是D:\Develop\USD_build_19_11,根据这两个路径开始编写构建USD的脚本:

    :: 构建USD的脚本 :: 设置编译器的很多环境变量 set Path=D:\Develop\Python27;^ D:\Develop\Python27\Scripts;^ D:\Develop\NASM;^ D:\Develop\Autodesk\Maya2018\bin;^ D:\Develop\cmake\bin;^ %Path% set PYTHONPATH=%PYTHONPATH%;D:\Develop\Autodesk\Maya2018\Python\Lib\site-packages;D:\Develop\Autodesk\Maya2018\Python\Lib\site-packages :: 复制pyside2-uic到pyside-uic.exe 中,使其造成能够找到pyside2-uic.exe的假象 copy D:\Develop\Autodesk\Maya2018\bin\pyside2-uic D:\Develop\Autodesk\Maya2018\bin\pyside2-uic.exe :: 使用pip安装PyOpenGL pip install PyOpenGL :: 复制本地build_usd_local.bat 到 目标的路径上 copy /Y %cd%\build_usd_local.py D:\Develop\USD\build_scripts call D:\Develop\VS2017\VC\Auxiliary\Build\vcvars64.bat :: 最后构建USD项目 python D:\Develop\USD\build_scripts\build_usd_local.py ^ -j4 ^ --build-args "USD,-DPYSIDE_USE_PYSIDE2=TRUE -DPYSIDE_BIN_DIR=D:\Develop\Autodesk\Maya2018\bin" ^ --maya --maya-location "D:\Develop\Autodesk\Maya2018\bin" ^ --materialx ^ D:\Develop\USD_build_19_11 :: 最后删除build_usd_local文件 del D:\Develop\USD\build_scripts\build_usd_local.py pause

    大家成功了吗?肯定有遇到很多问题,包括我遇到的一直卡住的Boost编译问题。大家遇到什么编译问题,可以在此留言,我会尽可能回答大家问题。

    成功编译USD后,可以编写插件来试试USDView,大家可以试试看吧,不过仍然要设置环境变量。USDView运行的脚本如下:

    set Path=^ D:\Develop\Python27;^ D:\Develop\USD_Build\lib;^ D:\Develop\USD_Build\bin;^ D:\Develop\USD_Build\third_party\maya\lib;^ D:\Develop\Autodesk\Maya2018\bin;^ %Path% set MAYA_PLUG_IN_PATH=%MAYA_PLUG_IN_PATH%;^ D:\Develop\USD_Build\third_party\maya\plugin set PYTHONPATH=%PYTHONPATH%;^ D:\Develop\USD_Build\lib\python;^ D:\Develop\Autodesk\Maya2018\Python\Lib\site-packages set MAYA_SCRIPT_PATH=%MAYA_SCRIPT_PATH%;^ D:\Develop\USD_Build\third_party\maya\lib\usd\usdMaya\resources;^ D:\Develop\USD_Build\third_party\maya\plugin\pxrUsdPreviewSurface\resources set XBMLANGPATH=%XBMLANGPATH%;^ D:\Develop\USD_Build\third_party\maya\lib\usd\usdMaya\resources @python "D:\Develop\USD_Build\bin\usdview" %cd%\7_29_1.usda

    USDView运行的截图是这样的:
    USDView运行效果

    看到最终结果,还是很有成就感的。

    read more
  • @天幸健 要么程序一启动就camera.start(),然后再camera.stop(),接着需要的时候再camera.start()。

    read more
  • @jcy 我现在程序一启动就加载了Camera 组件,但是当我要启动摄像头时,调用camera.start() 还是会卡一下

    read more

关注我们

微博
QQ群