在这里插入图片描述

卡通渲染特效 osgFX::Cartoon

在三维图形渲染领域,除了追求逼真的真实感渲染外,非真实感渲染(NPR) 也有着广泛的应用场景,卡通渲染(Cel-Shading)就是其中最具代表性的技术之一。

OpenSceneGraph(OSG)作为成熟的三维图形引擎,通过内置的 osgFX::Cartoon 类封装了完整的卡通渲染功能,无需手动编写复杂的着色器代码,即可快速为三维模型实现卡通风格的渲染效果。

本文将全面介绍 osgFX::Cartoon 类的核心特性、继承关系、关键接口,并提供完整可运行的实战代码,带你从零掌握 OSG 卡通渲染的实现。

osgFX::Cartoon 核心特性

osgFX::Cartoon 是 OSG 特效库中专门用于实现卡通渲染的核心类,它具备以下关键特性:

  1. 双通道渲染:采用两个渲染通道完成效果,第一个通道绘制模型实体表面,实现块状化的卡通光照效果;第二个通道绘制模型轮廓线,勾勒出卡通画特有的边缘线条。
  2. GPU 着色器支持:依赖 OpenGL 顶点着色器处理纹理坐标与光照计算,需要硬件支持 ARB_vertex_program 扩展或 GLSL 着色语言,保证渲染效率。
  3. 高度可定制:支持自定义轮廓线颜色、线宽,可配置光照数量,灵活调整卡通渲染的视觉效果。
  4. 节点式集成:作为 OSG 场景树节点使用,可直接挂载任意模型节点,无缝接入 OSG 渲染流程。

类继承关系

osgFX::Cartoon 并非独立存在,而是遵循 OSG 严谨的类继承体系,其完整继承关系如下:

osg::Object
  └── osg::BaseNode
       └── osg::Node         <--- 这里!它最终继承自 Node!
            └── osg::Group
                 └── osgFX::Effect
                      └── osgFX::Cartoon

osgFX::Cartoon 核心接口

在使用该类前,我们先了解最常用的几个成员函数,这是实现自定义卡通效果的关键:

函数接口 功能说明
setOutlineColor(const osg::Vec4& color) 设置轮廓线颜色,参数为 RGBA 四维向量(取值 0.0~1.0)
getOutlineColor() const 获取当前轮廓线颜色
setOutlineLineWidth(float width) 设置轮廓线宽度(单位:像素)
getOutlineLineWidth() const 获取当前轮廓线宽度
setLightNumber(int num) 设置参与渲染的光源数量,0 表示关闭光照,纯卡通平涂效果

完整实战代码

以下代码实现加载 cessna 飞机模型 + 卡通渲染,包含完整的注释,可直接编译运行:

1. 主程序代码(main.cpp)

// 包含OSG核心头文件
#include <osgDB/ReadFile>       // 模型文件读取
#include <osgViewer/Viewer>    // OSG视图器,负责窗口管理与渲染
#include <osgFX/Cartoon>       // 卡通渲染特效头文件
#include <osgUtil/Optimizer>   // 场景优化工具
#include <osg/Group>           // 场景组节点,用于管理子节点
#include <iostream>            // 控制台输出

// 主函数
int main()
{
    // ===================== 1. 初始化渲染窗口 =====================
    // 创建OSG视图器对象,自动管理窗口、相机、渲染循环
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;

    // ===================== 2. 创建场景根节点 =====================
    // 创建组节点,作为整个场景的根节点,统一管理所有子对象
    osg::ref_ptr<osg::Group> root = new osg::Group;

    // ===================== 3. 加载三维模型 =====================
    // 读取cessna.osg模型(OSG官方示例模型,需放在程序运行目录)
    osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
    // 判断模型是否加载成功
    if (!model)
    {
        std::cerr << "错误:无法加载模型文件 cessna.osg,请检查文件路径!" << std::endl;
        return -1;
    }

    // ===================== 4. 创建并配置卡通特效 =====================
    // 实例化卡通渲染特效节点
    osg::ref_ptr<osgFX::Cartoon> cartoonEffect = new osgFX::Cartoon;

    // 设置轮廓线颜色:黑色 (R=0, G=0, B=0, A=1)
    cartoonEffect->setOutlineColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));

    // 设置轮廓线宽度:2像素
    cartoonEffect->setOutlineLineWidth(2.0f);

    // 设置光源数量:0,关闭光照,实现纯卡通平涂效果
    cartoonEffect->setLightNumber(0);

    // ===================== 5. 构建场景树 =====================
    // 将模型添加到卡通特效节点中(特效作用于该模型)
    cartoonEffect->addChild(model);
    // 将卡通特效节点添加到场景根节点
    root->addChild(cartoonEffect);

    // ===================== 6. 优化场景(提升渲染效率) =====================
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root);

    // ===================== 7. 启动渲染循环 =====================
    // 为视图器设置场景数据
    viewer->setSceneData(root);
    // 初始化窗口、相机等渲染资源
    viewer->realize();
    // 启动渲染循环,直到关闭窗口
    return viewer->run();
}

在这里插入图片描述

代码解析

我们将代码分为初始化、模型加载、特效配置、场景构建、渲染启动五大模块,逐行解析:

模块1:渲染窗口初始化

osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
  • osg::ref_ptr:OSG 智能指针,自动管理内存,防止内存泄漏。
  • osgViewer::Viewer:OSG 核心视图类,封装了窗口创建、相机控制、渲染循环、交互事件等所有基础功能。

模块2:场景根节点创建

osg::ref_ptr<osg::Group> root = new osg::Group;
  • osg::Group:组节点,是 OSG 场景树的核心容器,可挂载模型、特效、相机等所有子节点,统一管理场景结构。

模块3:模型加载

osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
  • osgDB::readNodeFile:OSG 文件读取工具,支持 .osg.obj.fbx 等主流三维模型格式。
  • 异常判断:如果文件路径错误或文件损坏,会输出错误信息并退出程序,保证程序健壮性。

模块4:卡通特效核心配置

osg::ref_ptr<osgFX::Cartoon> cartoonEffect = new osgFX::Cartoon;
  • 实例化卡通特效节点,这是实现卡通渲染的核心对象。
cartoonEffect->setOutlineColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
  • 设置轮廓线为黑色,如果设置为白色(1,1,1,1),在默认白色背景下会无法显示轮廓,这是新手最容易踩的坑。
cartoonEffect->setOutlineLineWidth(2.0f);
  • 轮廓线宽度设为 2 像素,粗细适中,视觉效果最佳。
cartoonEffect->setLightNumber(0);
  • 关闭光照,让模型呈现纯平面卡通效果;如果设置为 1,会保留基础光照,增加立体感。

模块5:场景树构建

cartoonEffect->addChild(model);
root->addChild(cartoonEffect);
  • OSG 场景树遵循父子节点结构:模型 → 卡通特效节点 → 根节点。
  • 渲染时,特效节点会自动作用于其子节点(模型),实现卡通渲染。

模块6:场景优化

osgUtil::Optimizer optimizer;
optimizer.optimize(root);
  • OSG 内置优化工具,对场景进行几何体合并、状态优化等操作,大幅提升渲染效率。

模块7:渲染启动

viewer->setSceneData(root);
viewer->realize();
return viewer->run();
  • setSceneData:为视图器绑定场景根节点,告诉引擎需要渲染的内容。
  • realize:初始化 OpenGL 上下文、窗口、相机等底层渲染资源。
  • run:启动无限渲染循环,直到用户关闭窗口,程序退出。

总结

osgFX::Cartoon 是 OSG 中实现卡通渲染的极简方案,它依托 OSG 成熟的继承体系和渲染架构,将复杂的双通道渲染、GPU 着色器逻辑完全封装,开发者只需几行代码即可实现专业的卡通效果。

在这里插入图片描述

Logo

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

更多推荐