在这里插入图片描述

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

层级类作用解析

  1. osg::Object:OSG 所有对象的基类,提供智能指针(ref_ptr)、引用计数、对象销毁等基础能力,保证内存安全。
  2. osg::StateAttribute渲染状态属性基类,光照、纹理、材质、裁剪平面/屏幕裁剪都继承于此,统一通过节点的 StateSet 管理。
  3. 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 专注屏幕二维裁剪,适用场景明确且高效:

  1. 多视口/分屏渲染
    把窗口划分为多个区域,分别渲染不同场景(如三维软件的四视图)。
  2. UI 界面裁剪
    限制 2D 界面、文本、图标在指定面板内显示,防止内容溢出。
  3. 局部渲染优化
    仅渲染窗口部分区域,减少 GPU 绘制像素量,提升性能。
  4. 截图/局部预览
    只渲染指定区域,用于生成局部预览图、小窗口监控画面。
  5. 特效遮罩
    实现屏幕圆形、矩形视野框,用于游戏、仿真的视觉特效。

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 界面还是多视口渲染,都能轻松应对。

在这里插入图片描述

Logo

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

更多推荐