裁剪平面(osg::Scissor)示例(二)的代码如程序清单8-2所示
// 裁剪平面测试(2)
void scissor_8_2(const string strDataFolder)
{
osg::ref_ptr
osg::ref_ptr
traits->x = 50;
traits->y = 50;
traits->width = 1000;
traits->height = 800;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr
osg::ref_ptr
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);
viewer->addSlave(camera.get());
// 创建一个裁剪面
osg::ref_ptr
// 设置裁剪面矩形(左下角坐标,长和宽)
scissor->setScissor(150, 150, 800, 600);
osg::ref_ptr
string strDataPath = strDataFolder + "cow.osg";
osg::ref_ptr
if (node == nullptr)
{
cout << "读取cow.osg失败!" << endl;
return;
}
root->addChild(node.get());
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
}
运行程序,截图如图 8-9 所示。
图8-9裁剪平面示例(二)截图
在OSG中,单视图的管理是通过osgViewer.:Viewer来实现的。osgViewer.:Viewer 继承自多个类,负责OSG中单视图的管理,继承关系图如图8-10所示
图8-10 osgViewer::Viewer 的继承关系图
从继承关系图中可以看出osgViewer:Viewer继承自osgVicwer:View类和osg:Viewer:ViewerBase,同样它也间接继承自osg::Referenced 类。因此,可以使用智能指针来管理
在osgViewer:Viewer中,只允许单视图,单视图可以同时包含多个相机渲染,也可以在多窗口中渲染。为了能够进行正常的渲染,还需要创建一个图形环境(默认的情况下已经创建了一个)。有时为了方便控制场景渲染,需要设置一个合适的图形环境窗口。
创建图形环境的主要步骤如下:
x;y,width,height;// 窗口的坐标、高度及宽度,默认值都为0;windowDecration(false); // 是否支持窗口扩展的功能,Wi32中style
supportsResize(truc),// 是否支持窗口编放
red(8). //红色位数,默认8位
blue(8)//蓝色位数,默认8位
green(8)//绿色位数,默认8位
alpha(0)//alpha值位数,透明度,默认没有alpha通道,为RGB格式
depth(24)//颜色的深度(16,24,32),默认使用24位
stencil(0)//模板默认无
sampleBuffers(0)//采样缓存,默认无
samples(0).//采样倍数(抗锯齿的倍数),默认无
pbuffer(false)//pbuffer,默认不支持
quadBufferStereo(false)//立体四缓存,主要在高端显卡上有,如QUDRO显卡上
doubleBuffer(false) //是否支持双缓存,默认不支持
target(0),//目标
format(0)//格式
level(0)//嵌套的层数,默认无
face(0)./
mipMapGeneration(false),//是否支持生成Mipmap,默认不支持
vsync(true)//是否支持同步,默认同步模式
useMultiThreadedOpenGLEngine(false)/是否采用多线程,默认不支持
useCursor(true)//是否使用鼠标的指针,默认使用
sharedContext(0),//共享上下文
setInheritedWindowPixelFormat(false)//是否继承Window 中的位格式
osg::GraphicsContext:createGraphics(trait.get());
<4> 通过图形环境建窗口(hwnd)
有时仅用上面的方法创建一个图形环境是远远不够的,在OSG2.x系列以后,窗口的控制方式发生了变换,主要由宽度来控制场景的缩放。当窗口的宽度和高度不是 4:3 时,会出现一系列的问题,如变形等。这时调整宽度和高度肯定是可以的,还有一种方法就是设置投影矩阵。可以通过得到默认的对称透视投影,然后根据当前窗口的比例来确定一个合适的投影矩阵,代码可参看第 8.1.5节的示例。
宽屏变形示例的代码如程序清单8-3所示
// 单视图+单相机 宽屏变形示例(3)
void wideScreen_8_3(const string strDataFolder)
{
// 创建Viewer对象,场景浏览器
osg::ref_ptr
// 创建场景组节点
osg::ref_ptr
// 读取模型
string strDataPath = strDataFolder + "cow.osg";
osg::ref_ptr
root->addChild(node.get());
// 设置图像环境特性
osg::ref_ptr
traits->x = 0;
traits->y = 0;
traits->width = 1000;
traits->height = 800;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
// 创建图像环境特性
osg::ref_ptr
if (gc.valid())
{
osg::notify(osg::INFO) << " GraphicsWindow has been created successfully." << endl;
// 清除窗口颜色及清除颜色和深度缓冲
gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
osg::notify(osg::NOTICE) << " GraphicsWindow has not been created successfully" << endl;
}
// 根据分辨率确定合适的投影来保证显示的图形不变形
double fovy, aspectRatio, zNear, zFar;
viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
double newAspectRatio = double(traits->width) / double(traits->height);
double aspectRatioChange = newAspectRatio / aspectRatio;
if (aspectRatioChange != 1.0)
{
// 设置投影矩阵
viewer->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRatioChange, 1.0, 1.0);
}
// 设置视口
viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
// 设置图形环境
viewer->getCamera()->setGraphicsContext(gc.get());
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
}
运行程序,截图如图8-11所示
图8-11宽屏变形示例截图
单视图多相机渲染示例的代码如程序清单8-4所示
// 单视图多相机示例(4)
void singleWindowMultipleCameras(osg::ref_ptr
{
// 创建窗口系统接口
osg::ref_ptr
if (!wsi)
{
osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available cannot create windows." << endl;
return;
}
// 得到窗口分辨率
unsigned int width, height;
wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
// 设置图形环境特性
osg::ref_ptr
traits->x = 0;
traits->y = 0;
traits->width = width;
traits->height = height;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
// 创建图形环境
osg::ref_ptr
if (gc->valid())
{
osg::notify(osg::INFO) << " GraphicsWindow has been created successfully." << endl;
// 确保窗口清除干净
gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
osg::notify(osg::NOTICE) << " GraphicsWindow has not been created successfully." << endl;
}
// 得到cameraMaster(主相机)
osg::ref_ptr
// 设置图形环境
cameraMaster->setGraphicsContext(gc.get());
// 根据分辨率确定合适的投影来保证显示的图形不变形
double fovy, aspectRatio, zNear, zFar;
cameraMaster->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
double newAspectRatio = double(traits->width) / double(traits->height);
double aspectRatioChange = newAspectRatio / aspectRatio;
if (aspectRatioChange != 1.0)
{
cameraMaster->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRatioChange, 1.0, 1.0);
}
// 设置视口
cameraMaster->setViewport(new osg::Viewport(0, 0, width, height));
GLenum bufferMaster = traits->doubleBuffer ? GL_BACK : GL_FRONT;
// 设置缓冲区
cameraMaster->setDrawBuffer(bufferMaster);
cameraMaster->setReadBuffer(bufferMaster);
// 创建从属相机
osg::ref_ptr
cameraClient->setGraphicsContext(gc.get());
cameraClient->setViewport(new osg::Viewport(9, 0, 400, 400));
GLenum bufferClient = traits->doubleBuffer ? GL_BACK : GL_FRONT;
cameraClient->setDrawBuffer(bufferClient);
cameraClient->setReadBuffer(bufferClient);
// 添加从属相机
viewer->addSlave(cameraClient, osg::Matrix::scale(aspectRatio, 1.0, 1.0), osg::Matrix());
}
void sinGraphMulCam_8_4(const string strDataFolder)
{
osg::ref_ptr
// 读取牛的模型
string strDataPath = strDataFolder + "cow.osg";
osg::ref_ptr
// 启用单视图多相机渲染
singleWindowMultipleCameras(viewer.get());
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(node.get());
viewer->setSceneData(node.get());
viewer->realize();
viewer->run();
}
运行程序,截图如图8-12所示
图8-12单视图多相机染示例截图