OSG 之学习八:OSG 视口 & LOD & 多通道

时间:2024-03-15 08:40:43

说明


  • OSG 入门看的,大佬绕道
  • 示例来源于《OSG程序设计教程》
  • 没有此电子书的小伙伴们,我已上传至CSDN

1. 多视口


OSG 之学习八:OSG 视口 & LOD & 多通道

OSG 之学习八:OSG 视口 & LOD & 多通道

  • 程序功能:创建前后左右视图
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <iostream>

// 创建前后左右视图
void CreateCamera(osgViewer::Viewer &viewer) {
    // 系统接口。用来得到分辩率
    osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
    // 窗口宽高
    unsigned int width, height;
    wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);

    // 上下文关键参数
    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
    traits->x = 0;
    traits->y = 0;
    traits->width = width;
    traits->height = height;
    traits->windowDecoration = true;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;
    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
    gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
    gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 主视口
    osg::ref_ptr<osg::Camera> cameraMaster = new osg::Camera;
    cameraMaster->setGraphicsContext(gc.get());
    // 相机视口设置
    cameraMaster->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
    // 添加相机到VIEWER
    viewer.addSlave(cameraMaster.get());

    // 后视图
    double aspectRatioScale = 1.0;
    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
    // 设置上下文
    camera->setGraphicsContext(gc.get());
    // 设置后视图的窗口位置
    camera->setViewport(new osg::Viewport(0, 0, width / 4, height / 4));
    GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
    camera->setDrawBuffer(buffer);
    camera->setReadBuffer(buffer);
    // 添加相机到视口
    viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::DegreesToRadians(180.0), 0.0, 1.0, 0.0));

    // 初始化右视图
    osg::ref_ptr<osg::Camera> rightViewer = new osg::Camera;

    // 设置上下文
    rightViewer->setGraphicsContext(gc.get());
    // 设置视口位置
    rightViewer->setViewport(new osg::Viewport(traits->width / 4, 0, traits->width / 4, traits->height / 4));
    GLenum bufferright = traits->doubleBuffer ? GL_BACK : GL_FRONT;
    rightViewer->setDrawBuffer(bufferright);
    rightViewer->setReadBuffer(bufferright);
    // 添加相机到视口当中
    viewer.addSlave(rightViewer.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::DegreesToRadians(213.0), 0.0, 1.0, 0.0));

    // 初始化前视图
    osg::ref_ptr<osg::Camera> frontViewer = new osg::Camera;
    // 设置上下文
    frontViewer->setGraphicsContext(gc.get());
    frontViewer->setViewport(new osg::Viewport((traits->width / 4) * 2 - 1, 0, traits->width / 4, traits->height / 4));
    GLenum bufferfront = traits->doubleBuffer ? GL_BACK : GL_FRONT;
    frontViewer->setDrawBuffer(bufferfront);
    frontViewer->setReadBuffer(bufferfront);
    // 添加相机到视口当中
    viewer.addSlave(frontViewer.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::DegreesToRadians(246.0), 0.0, 1.0, 0.0));

    //初始化左视图
    osg::ref_ptr<osg::Camera> leftViewer = new osg::Camera;
    // 上下文
    leftViewer->setGraphicsContext(gc.get());
    leftViewer->setViewport(new osg::Viewport((traits->width / 4) * 3 - 2, 0, traits->width / 4, traits->height / 4));
    GLenum bufferleft = traits->doubleBuffer ? GL_BACK : GL_FRONT;
    leftViewer->setDrawBuffer(bufferleft);
    leftViewer->setReadBuffer(bufferleft);
    // 添加相机到视口当中
    viewer.addSlave(leftViewer.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::DegreesToRadians(279.0), 0.0, 1.0, 0.0));
}

int main(int argc, char **argv) {
    osgViewer::Viewer viewer;
    CreateCamera(viewer);
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    viewer.setSceneData(osgDB::readNodeFile("ceep.ive"));
    viewer.realize();
    viewer.run();
    return 0;
}

书上说运行效果是图的上方是主视口,下方是主视口的后面前后左右四个面,说实在的,我没有看出来这是什么鬼,但是代码还是好理解的

OSG 之学习八:OSG 视口 & LOD & 多通道

2. 多窗口渲染


  • 意思不大

3. LOD


  • 这里有一个简单的例子来说明该功能

  • 一共在场景中添加了三个球,随着鼠标滚轮的滚动,显示不同级别的数据

示例来自于返回主页 准前端工程师的博客:osg的点云lod技术预研

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/StateSetManipulator>
#include <osgUtil/Optimizer>
#include <osgUtil/DelaunayTriangulator>

// 创建视图所需头
#include <osgDB/Registry>
#include <osg/Node>
#include <osg/ShapeDrawable>
#include <osgGA/StateSetManipulator>

int main() {
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    // 这里还是给显示进行一下初始化来看看
    {
        viewer->getCamera()->setClearColor(osg::Vec4(1, 1, 0.3, 0));
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->x = 40;
        traits->y = 40;
        traits->width = 600;
        traits->height = 480;
        traits->windowDecoration = true;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;

        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());

        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setGraphicsContext(gc.get());
        camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
        camera->setDrawBuffer(buffer);
        camera->setReadBuffer(buffer);

        // add this slave camera to the viewer, with a shift left of the projection matrix
        viewer->addSlave(camera.get());
    }

    osg::ref_ptr<osg::Group> root = new osg::Group();
    osg::ref_ptr<osg::Geode> geode = new osg::Geode();
    osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
    hints->setDetailRatio(0.05);// 设置精细度
    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), 100.0), hints.get()));

    osg::ref_ptr<osg::Geode> geode2 = new osg::Geode();
    osg::ref_ptr<osg::TessellationHints> hints2 = new osg::TessellationHints;
    hints2->setDetailRatio(0.5);
    geode2->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), 100.0), hints2.get()));

    osg::ref_ptr<osg::Geode> geode3 = new osg::Geode();
    osg::ref_ptr<osg::TessellationHints> hint3 = new osg::TessellationHints;
    hint3->setDetailRatio(10);
    geode3->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), 100.0), hint3.get()));

    osg::ref_ptr<osg::LOD> lod = new osg::LOD;

    lod->addChild(geode, 300, 400);
    lod->addChild(geode2, 400, 600);
    lod->addChild(geode3, 600, 5000);

    lod->setCenter(osg::Vec3(0.0, 0.0, 0.0));
    root->addChild(lod);
    viewer->setSceneData(root.get());
    viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
    return viewer->run();
}

OSG 之学习八:OSG 视口 & LOD & 多通道

4. 多通道

  • 用到时再补充吧

5. Imposter


  • 用到时再补充吧

6. 又是一些类,自己看吧