COVER王锐大大——最长的一帧(第四日)

当前位置:osgViewer/Viewer.cpp 第514行 osgViewer::Viewer::realize()

setUpViewOnSingleScreen();setUpViewAcrossAllScreens()和之前的setUpViewInWindow是一样的流程。基本一致。都是通过apply()方法来执行了相应config的类型所对应的configure()方法。

这里注意一下setUpViewAcrossAllScreens对应的configure()方法。

当前位置:osgViewer/AcrossAllScreens.cpp 第24行 AcrossAllScreens::configure(osgViewer::View& view) 

类似之前的setUpViewInWindow,获取WindowingSystemInterface的指针wsi。如果wsi为空,则无法创建窗口。尝试获取osg::DisplaySettings的指针。也就是获取一些viewer所需的display settings.

接着就设置了主相机的透视投影矩阵的内容。

这里通过了WindowingSystemInterface来获取了屏幕的数量

unsigned int numScreens = wsi->getNumScreens(si);
如果我们需要在自己的程序中获取屏幕分辨率,或者设置屏幕刷新率的话,也可以使用同样的方法,调用 getScreenResolution, setScreenResolution 和 setScreenRefreshRate等相关函数即可。具体的实现方法可以参见 GraphicsWindowWin32.cpp 的源代码。
setUpViewAcrossAllScreens 函数可以自行判断屏幕的数量,如果显示屏数目为1,则执行SingleView里的configure方法。对于多个屏幕也进行了相应的处理,这里就忽略了。

后面的内容就和之前的SingleView里的configure函数一致了。

新建显示设备特性实例等等一系列的操作。这里有一点增加的内容。

 view.assignSceneDataToCameras();字面上理解就是将场景数据分配给了视景器的相机。让我们去看看这个方法具体做了什么吧。

当前位置:osgViewer/View.cpp 第778行 osgViewer::View::assignSceneDataToCameras()

这其中包括以下几项工作:
1、对于场景漫游器_cameraManipulator,执行其 setNode 函数和 home 函数,也就是设置漫游器对应于场景图形根节点, 并回到其原点位置。不过在我们使用 setCameraManipulator函数时也会自动执行同样的操作。
2、将场景图形赋予主摄像机_camera,同时设置它对应的渲染器(Renderer)的相关函数。这里的渲染器起到了什么作用?还是先放到悬疑列表中吧,不过依照我们的解读速度,这个问题可能会悬疑很久。
3、同样将场景图形赋予所有的从摄像机_slaves,并设置每个从摄像机的渲染器。

以上是复制《最长的一帧》原文,这里大概看了一下这个函数。反正也看不懂。但知道了一点就是,场景漫游器是被设置来对应于场景图形根节点的。

再次回到realize()函数吧。

当前位置:osgViewer/Viewer.cpp 第525行 osgViewer::Viewer::realize()

判断缺省的GraphicsContext是否成功,判断是否建好了窗口,如果这个时候还是没有窗口,那就别继续玩了。你走吧,妈妈不让我和傻子玩。

接着根据代码注释,

// get the display settings that will be active for this viewer获取视景器需要的显示设置

// pass on the display settings to the WindowSystemInterface.将这些显示设置传给WSI

(摔,这个realize()函数读到这里真的是爆炸了,根本看不懂。挖的太深了,坚持坚持!!看不懂就背吧!!)

接着获取了maxTexturePoolSize,maxBufferPoolSize,没有注释,大神也没写,字面上感觉就是最大能保存的Texture和Buffer的数量吧。

然后就开始遍历GraphicsContext设备(通常只有一个)

for(Contexts::iterator citr = contexts.begin(); citr != contexts.end();
对于每个 GraphicsContext 指针 gc  

osg::GraphicsContext* gc = *citr;,依次执行:

if (ds->getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback);

        // set the pool sizes, 0 the default will result in no GL object pools.
        gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize);
        gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);

        gc->realize();

        if (_realizeOperation.valid() && gc->valid())
        {
            gc->makeCurrent();

            (*_realizeOperation)(gc);

            gc->releaseContext();
        }

首先就是设置pool sizes,然后又对gc进行realize()操作。这里进去看看GraphicsContext的realize()方法吧。

当前位置:osg/GraphicsContext.cpp 第509行 GraphicsContext::realize()

非常短的代码,返回bool类型,判断了realizeImplementation(),其实实质就是这个函数。查看这个函数的定义,发现有三处,有两处都是纯虚函数。

virtual bool osgViewer::GraphicsWindow::realizeImplementation()

virtual bool osgViewer::GraphicsWindowEmbedded::realizeImplementation()

bool osgViewer::GraphicsWindowWin32::realizeImplementation()

之前尝试创建缺省的图形上下文设备时,我们使用下面一句代码来创建的。

osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get());
现在来看看这个createGraphicsContext()的内容。

当前位置:osg/GraphicsContext.cpp 第509行 GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits)

  ref_ptr &wsref = windowingSystemInterfaceRef();
    if ( wsref.valid())
    {
        // catch any undefined values.
        if (traits) traits->setUndefinedScreenDetailsToDefaultScreen();

        return wsref->createGraphicsContext(traits);
    }

wsref 所指向的是平台相关的 API 接口类,也就是 Win32 API 的接口,也就是 GraphicsWindowWin32.cpp 中对应类的实例。换句话说,此时 WindowingSystemInterface:: createGraphicsContext 函数返回的值,也应当是派生自 GraphicsContext 的具体类的实例!
对于
Windows 用户来说,这个函数返回的恰恰是 GraphicsWindowWin32 的实例,而前文的 realizeImplementation 函数,正是 GraphicsWindowWin32::realizeImplementation  这里我真的晕了,看一下一个类图

COVER王锐大大——最长的一帧(第四日)_第1张图片

1、视景器 Viewer 的主/从摄像机均需要使用 setGraphicsContext 设置对应的图形设备上下文,实际上也就是对应的显示窗口;
2、 GraphicsContext 的创建由平台相关的抽象接口类 WindowingSystemInterface 负责,对于 Win32 平台而言, 这个类是由 GraphicsWindowWin32.cpp 的 Win32WindowingSystem 类具体实现的,它创建的显示窗口设备osgViewer::GraphicsWindowWin32 的实例。

上面的内容还能理解,下面的就不知道在说什么了。就这样吧。

3、进一步深究的话,如果窗口特性(Traits)中开启了 pbuffer 选项,则 OSG 将尝试创建 osgViewer::PixelBufferWin32 设备,以实现离屏渲染(Offscreen Render),纹理烘焙(Render-To-Texture)等工作;否则只建立通常的 OpenGL 窗口。
真是令人兴奋!没错, GraphicsContext::makeCurrent 和 GraphicsContext:: releaseContext函数也是用相同的方法来实现多态性的,而它们的工作也就是 OpenGL 开发者使用函数wglMakeCurrent 完成的工作,将渲染上下文 RC 对应到正确的窗口绘制句柄上。



你可能感兴趣的:(COVER最长的一帧)