一、相机的核心原理
Open Scene Graph(OSG)中相机的核心原理围绕视图变换和投影变换展开,结合场景图的层次化结构实现三维空间的动态渲染。
1、视图变换(View Transformation)
-
)视图矩阵的作用
视图矩阵将世界坐标系中的物体坐标转换为相机坐标系中的坐标。该矩阵由相机的位置、方向和朝向参数决定,本质上是将场景中的物体变换到以相机为原点的观察空间。- 例如,相机移动时,视图矩阵实时更新,确保场景物体相对于相机的正确空间关系。
-
)实现方式
在OSG中,osg::Camera
类封装了视图矩阵的计算,通过设置相机的LookAt
(视点、目标点、上方向)参数生成视图矩阵。
2、投影变换(Projection Transformation)
-
)投影矩阵的作用
投影矩阵将相机坐标系中的坐标转换到裁剪空间,定义视锥体(Frustum)的形状。视锥体决定了哪些物体可见,并完成透视/正交投影的转换26。- 透视投影:模拟人眼近大远小的效果,适用于自然场景。
- 正交投影:保持物体尺寸不变,常用于CAD等应用。
-
)视锥体裁剪优化
OSG利用场景图的包围体层次(BVH)结构,结合投影矩阵生成的视锥体,快速剔除不可见物体,减少渲染负载。
二、相机系统
OSG的相机系统是3D场景渲染的核心组件,提供了灵活的视图控制和渲染管线配置。
1. 相机基础类型
1.1 透视相机 (Perspective Camera)
// 创建透视相机
osg::Camera* createPerspectiveCamera(double fov, double aspect, double near, double far)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrixAsPerspective(fov, aspect, near, far);camera->setViewMatrixAsLookAt(osg::Vec3(0,0,5), // 相机位置osg::Vec3(0,0,0), // 目标点osg::Vec3(0,1,0)); // 上方向camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);return camera.release();
}
1.2 正交相机 (Orthographic Camera)
// 创建正交相机
osg::Camera* createOrthoCamera(double left, double right, double bottom, double top, double near, double far)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrixAsOrtho(left, right, bottom, top, near, far);camera->setViewMatrixAsLookAt(osg::Vec3(0,0,1), osg::Vec3(0,0,0), osg::Vec3(0,1,0));return camera.release();
}
2. 相机操作器 (Camera Manipulators)
2.1 内置操作器类型
// 设置轨迹球操作器 (默认)
viewer.setCameraManipulator(new osgGA::TrackballManipulator());// 飞行操作器
viewer.setCameraManipulator(new osgGA::FlightManipulator());// 驾驶操作器
viewer.setCameraManipulator(new osgGA::DriveManipulator());// 地形适配操作器
viewer.setCameraManipulator(new osgGA::TerrainManipulator());
2.2 自定义操作器
class CustomManipulator : public osgGA::CameraManipulator {
public:virtual void setByMatrix(const osg::Matrixd& matrix) override {_matrix = matrix;}virtual osg::Matrixd getMatrix() const override {return _matrix;}virtual osg::Matrixd getInverseMatrix() const override {return osg::Matrixd::inverse(_matrix);}virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override {// 处理键盘鼠标事件switch(ea.getEventType()) {case osgGA::GUIEventAdapter::KEYDOWN:if(ea.getKey() == 'w') {_matrix.preMult(osg::Matrixd::translate(0,0,-0.1));return true;}break;// 其他事件处理...}return false;}private:osg::Matrixd _matrix;
};
3. 多相机配置
3.1 分屏视图
// 创建四视图分屏
void setupQuadView(osgViewer::Viewer& viewer)
{osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();unsigned width, height;wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);// 左上视图osg::ref_ptr<osg::Camera> camera1 = new osg::Camera;camera1->setViewport(0, height/2, width/2, height/2);camera1->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera1.get(), false);// 右上视图osg::ref_ptr<osg::Camera> camera2 = new osg::Camera;camera2->setViewport(width/2, height/2, width/2, height/2);camera2->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera2.get(), false);// 左下视图osg::ref_ptr<osg::Camera> camera3 = new osg::Camera;camera3->setViewport(0, 0, width/2, height/2);camera3->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera3.get(), false);// 右下视图 (主相机)viewer.getCamera()->setViewport(width/2, 0, width/2, height/2);
}
3.2 HUD相机 (2D叠加)
osg::Camera* createHUDCamera(int width, int height)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setViewMatrix(osg::Matrix::identity());camera->setClearMask(GL_DEPTH_BUFFER_BIT);camera->setRenderOrder(osg::Camera::POST_RENDER);camera->setAllowEventFocus(false);return camera.release();
}
4. 高级相机技术
4.1 渲染到纹理 (RTT)
osg::Texture2D* createRenderTexture(int width, int height)
{osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;texture->setTextureSize(width, height);texture->setInternalFormat(GL_RGBA);texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);return texture.release();
}osg::Camera* createRTTCamera(osg::Texture2D* texture)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setClearColor(osg::Vec4(0.1,0.1,0.3,1.0));camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);camera->setRenderOrder(osg::Camera::PRE_RENDER);camera->setViewport(0, 0, texture->getTextureWidth(), texture->getTextureHeight());camera->attach(osg::Camera::COLOR_BUFFER, texture);return camera.release();
}
4.2 后处理效果
osg::Camera* createPostProcessingCamera(osg::Texture2D* inputTexture)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setClearMask(GL_DEPTH_BUFFER_BIT);camera->setRenderOrder(osg::Camera::POST_RENDER);// 创建全屏quadosg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1,-1,0), osg::Vec3(2,0,0), osg::Vec3(0,2,0)));// 设置后处理着色器osg::ref_ptr<osg::Program> program = new osg::Program;program->addShader(osgDB::readShaderFile("postprocess.vert"));program->addShader(osgDB::readShaderFile("postprocess.frag"));osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();stateset->setAttributeAndModes(program);stateset->setTextureAttributeAndModes(0, inputTexture);camera->addChild(geode);return camera.release();
}
5. 相机动画
5.1 路径动画
osg::AnimationPath* createCameraPath()
{osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;path->setLoopMode(osg::AnimationPath::LOOP);// 添加关键点path->insert(0.0, osg::AnimationPath::ControlPoint(osg::Vec3(0,0,5), osg::Quat()));path->insert(5.0, osg::AnimationPath::ControlPoint(osg::Vec3(5,0,5), osg::Quat(osg::PI_2, osg::Z_AXIS)));path->insert(10.0, osg::AnimationPath::ControlPoint(osg::Vec3(0,0,5), osg::Quat(osg::PI, osg::Z_AXIS)));return path.release();
}void setupCameraAnimation(osgViewer::Viewer& viewer)
{osg::ref_ptr<osg::AnimationPathCallback> apcb = new osg::AnimationPathCallback(createCameraPath());viewer.getCamera()->setUpdateCallback(apcb);
}
5.2 相机震动效果
class CameraShakeCallback : public osg::NodeCallback {
public:virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {osg::Camera* camera = dynamic_cast<osg::Camera*>(node);if(camera && _shakeTime > 0) {float intensity = _shakeTime / _duration;osg::Vec3 offset((rand()%1000/500.0f-1) * intensity,(rand()%1000/500.0f-1) * intensity,0);osg::Matrix viewMatrix = camera->getViewMatrix();viewMatrix.setTrans(viewMatrix.getTrans() + offset);camera->setViewMatrix(viewMatrix);_shakeTime -= nv->getFrameStamp()->getSimulationTimeDelta();}traverse(node, nv);}void shake(float duration) {_duration = duration;_shakeTime = duration;}private:float _duration = 0;float _shakeTime = 0;
};
6. 相机性能优化
6.1 视锥体剔除
// 启用自动视锥体剔除
viewer.getCamera()->setCullingMode(viewer.getCamera()->getCullingMode() | osg::CullSettings::VIEW_FRUSTUM_CULLING);
6.2 小物体剔除
// 设置小物体剔除阈值 (像素)
viewer.getCamera()->setSmallFeatureCullingPixelSize(2.0f);
6.3 细节层次 (LOD)
// 相机距离相关的LOD设置
osg::LOD* createLODNode()
{osg::ref_ptr<osg::LOD> lod = new osg::LOD;lod->addChild(createHighDetailModel(), 0, 50); // 0-50米高细节lod->addChild(createMediumDetailModel(), 50, 100); // 50-100米中细节lod->addChild(createLowDetailModel(), 100, 1000); // 100-1000米低细节return lod.release();
}