【OSG学习笔记】Day 44: Scissor( 屏幕裁剪)

OSG 屏幕裁剪利器 osg::Scissor
在 OpenSceneGraph 三维渲染开发中,除了基于三维空间的裁剪平面 ClipPlane,还有一个专门用于屏幕二维区域裁剪的高效工具——osg::Scissor(裁剪测试)。
它基于 OpenGL 原生的 Scissor Test 机制,能够精准限定屏幕上的渲染区域,是实现分屏、UI 裁剪、局部渲染优化的核心手段。
本文结合完整可运行代码,系统讲解 osg::Scissor 的继承关系、核心原理、使用方法,并与 osg::ClipPlane 做全方位对比,帮你快速区分两者的使用场景,在开发中精准选型。
osg::Scissor 类继承关系
osg::Scissor 是 OSG 渲染状态体系的标准组件,严格遵循 OSG 面向对象设计,其完整继承链如下:
osg::Object
└── osg::StateAttribute
└── osg::Scissor
层级类作用解析
- osg::Object:OSG 所有对象的基类,提供智能指针(ref_ptr)、引用计数、对象销毁等基础能力,保证内存安全。
- osg::StateAttribute:渲染状态属性基类,光照、纹理、材质、裁剪平面/屏幕裁剪都继承于此,统一通过节点的
StateSet管理。 - osg::Scissor:屏幕裁剪测试的具体实现类,封装了 OpenGL 裁剪测试的全部功能,提供矩形区域设置、参数修改接口。
✅ 核心特性:Scissor 属于渲染状态,必须绑定到节点的 StateSet 并启用才能生效,这是 OSG 所有渲染属性的标准使用方式。
osg::Scissor 核心原理
osg::Scissor 实现的是 OpenGL 裁剪测试(Scissor Test),核心作用:
在屏幕上定义一个矩形区域,仅该区域内的像素会被渲染,区域外的像素直接被丢弃。
1. 坐标系规则
OSG/OpenGL 屏幕坐标系:
- 原点 (0,0):窗口左下角
- X 轴:向右递增
- Y 轴:向上递增
2. 核心接口
// 设置裁剪矩形:x(左下x), y(左下y), width(宽), height(高)
void setScissor(int x, int y, int width, int height);
所有参数单位均为屏幕像素,简单直观。
3. 启用方式
// 将裁剪状态绑定到节点,开启裁剪
node->getOrCreateStateSet()->setAttributeAndModes(
scissor, osg::StateAttribute::ON
);
完整实战代码解析
以下代码实现屏幕固定区域裁剪,模型仅在指定矩形内显示,可直接编译运行:
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Scissor> // 核心:屏幕裁剪头文件
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
int main()
{
// 1. 创建渲染窗口
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
// 2. 创建屏幕裁剪对象
osg::ref_ptr<osg::Scissor> scissor = new osg::Scissor();
// 定义裁剪区域:左下角(150,150),宽800,高600
scissor->setScissor(150, 150, 800, 600);
// 3. 创建场景根节点
osg::ref_ptr<osg::Group> root = new osg::Group();
// 4. 加载模型
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
if (!node)
{
OSG_WARN << "模型加载失败!" << std::endl;
return 1;
}
root->addChild(node.get());
// 5. 启用屏幕裁剪(核心步骤)
root->getOrCreateStateSet()->setAttributeAndModes(
scissor.get(), osg::StateAttribute::ON
);
// 6. 优化场景
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
// 7. 启动渲染
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
运行效果

osg::Scissor 使用场景
Scissor 专注屏幕二维裁剪,适用场景明确且高效:
- 多视口/分屏渲染
把窗口划分为多个区域,分别渲染不同场景(如三维软件的四视图)。 - UI 界面裁剪
限制 2D 界面、文本、图标在指定面板内显示,防止内容溢出。 - 局部渲染优化
仅渲染窗口部分区域,减少 GPU 绘制像素量,提升性能。 - 截图/局部预览
只渲染指定区域,用于生成局部预览图、小窗口监控画面。 - 特效遮罩
实现屏幕圆形、矩形视野框,用于游戏、仿真的视觉特效。
osg::Scissor 与 osg::ClipPlane 全方位对比
这是 OSG 开发中最容易混淆的两个概念,下表清晰区分两者核心差异:
| 对比维度 | osg::Scissor(屏幕裁剪) | osg::ClipPlane(空间裁剪) |
|---|---|---|
| 裁剪维度 | 二维屏幕像素空间 | 三维模型/世界空间 |
| 裁剪对象 | 最终渲染的屏幕像素 | 三维模型的几何体本身 |
| 坐标系 | 屏幕像素坐标(原点左下) | 三维空间坐标 |
| 裁剪形状 | 只能是矩形 | 无限大平面(可组合任意形状) |
| 核心用途 | 分屏、UI 裁剪、区域渲染 | 模型剖切、截面显示、内部查看 |
| 硬件限制 | 无数量限制,全局一个生效 | OpenGL 最多支持 6 个 |
| 性能 | 极低开销,GPU 原生支持 | 极低开销,硬件加速 |
| 典型效果 | 屏幕局部显示模型 | 模型被“切开”,显示内部结构 |
一句话区分
- 想切屏幕 → 用
Scissor - 想切模型 → 用
ClipPlane
总结
osg::Scissor 是 OSG 中极简、高效、专用的屏幕裁剪工具,继承自标准渲染状态 StateAttribute,使用方式简单、性能优异。
它与 osg::ClipPlane 互为补充:
- Scissor 管屏幕,做分屏、UI、区域渲染;
- ClipPlane 管空间,做剖切、截面、模型裁剪。
掌握两者的原理与区别,就能在三维开发中灵活实现各类裁剪需求,无论是工业仿真、UI 界面还是多视口渲染,都能轻松应对。

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)