mcpField
O
ohos-dev-graphics3d-combined-postprocess

ohos-dev-graphics3d-combined-postprocess

github.com/openharmonyinsight开发3542 次安装11 周前更新
代码仓库

关于 ohos-dev-graphics3d-combined-postprocess

该技能指导在 OpenHarmony Graphics3D 的 LumeRender、Lume3D 和 LumeScene 中实现单次渲染通道后处理效果,并说明实现顺序及 Combined 流程的适用边界。

主要功能

  1. 01三模块实现流程
  2. 02配置到着色器的数据映射
  3. 03着色器与渲染管线集成
  4. 04ECS 组件和场景 API 注册
  5. 05参数与索引限制说明

适用场景

  1. 01添加色调映射或色彩分级
  2. 02实现单次通道的暗角效果
  3. 03判断效果是否需要多通道管线

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openharmonyinsight/openharmony-skills --skill ohos-dev-graphics3d-combined-postprocess

安装后在 Claude Code 中输入/ohos-dev-graphics3d-combined-postprocess确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
references/
advanced_reference.md
code_templates.md

详细介绍

Combined 后期处理实现指南

按照以下依赖链,在三个模块中实现 Combined 后期处理效果: LumeRender → Lume3D → LumeScene

任务和适用范围

本指南介绍如何在 OpenHarmony Graphics3D 中实现单次处理通道的后期处理效果。

适用范围:

  • 在单个全屏着色器通道中运行的效果(色调映射、色彩分级、暗角)
  • 向 Combined 后期处理系统添加效果

不适用范围:

  • 需要单独渲染通道的效果(需要模糊通道的泛光、景深、运动模糊)

模块依赖关系概览

LumeRender (AGPRender)
    ↓
Lume3D (AGP3D) 
    ↓
LumeScene
  • LumeRender:底层渲染模块,提供着色器/渲染节点基础设施
  • Lume3D:3D 场景模块,提供 ECS 组件,依赖于 LumeRender
  • LumeScene:高层场景模块,提供易用的接口,依赖于 Lume3D

实现前检查清单

实现任何 Combined 后期处理效果之前,请先问自己:

  1. 视觉效果目标:你想实现什么视觉效果?(色调映射、色彩分级、暗角、自定义效果)
  2. 参数复杂度:此效果需要多少个参数?
    • 1-4 个参数:仅使用 factors[] Vec4
    • 5-8 个参数:拆分到 factors[] + userFactors[]
    • 8 个参数:考虑此效果是否适用于 Combined 系统

  3. 渲染通道要求:此效果是否需要中间帧缓冲区?
    • 单个全屏通道:✓ 使用 Combined 后期处理(本指南)
    • 模糊通道、缩小/放大、时域处理:✗ 使用多通道系统(不适用于本指南)
  4. 索引可用性:Combined 系统中的索引 0-7 是否可用?
    • 当前已使用:0(色调)、1(暗角)、2(抖动)、3(色彩转换)、4(色差)、5(升频)、6(白平衡)、7(色彩调整)
    • 需要未使用的索引:必须在着色器和 C++ 中注册新索引

决策树:

Effect needs >4 params? ─────YES──→ Split: factors[] + userFactors[]
                         │
                         NO
                         ↓
Effect needs blur/temporal? ─YES──→ Use multi-pass system (EXIT this skill)
                         │
                         NO
                         ↓
Index 0-7 available? ──────YES──→ Continue with Combined implementation ✓
                         │
                         NO
                         ↓
Need to register new index → Follow LumeRender Step 1-3 first

工作流

LumeRender(8 个步骤):

  1. 定义配置结构
  2. 注册元数据
  3. 定义着色器常量
  4. 实现配置到着色器的转换
  5. 填充后期处理栈
  6. 在 RenderNodeUtil 中添加转换
  7. 实现着色器处理函数
  8. 集成到渲染管线

Lume3D(5 个步骤):

  1. 添加标志位
  2. 定义组件属性
  3. 注册元数据
  4. 集成到渲染系统
  5. 集成到 Lume3D 着色器

LumeScene(9 个步骤):

  1. 定义接口
  2. 添加到 IPostProcess 接口
  3. 实现 API 封装
  4. 实现效果类
  5. 在 PostProcess 中注册
  6. 注册组件类型
  7. 注册插件类型
  8. 注册 Any 类型
  9. 更新构建文件

LumeRender 实现

必须阅读整个文件:开始 LumeRender 步骤之前,必须完整阅读 references/code_templates.md 中的“LumeRender Templates”部分(步骤 1-8,约 300 行)。读取此文件时不得设置任何范围限制。

暂时不要加载 advanced_reference.md —— 留到故障排查阶段再查看。

步骤 1:定义配置结构

文件:api/render/datastore/render/render_data_store_render_pods.h

定义包含属性和默认值的效果配置结构体。添加枚举索引、标志位和属性类型声明。

详情:请参阅 references/code_templates.md#step-1-define-configuration-structure


步骤 2:注册元数据

文件:src/postprocesses/render_post_process_combined_node.cpp

为反射系统注册枚举值、类型元数据和配置结构元数据。

详情:请参阅 references/code_templates.md#step-2-register-metadata


第 3 步:定义着色器常量

文件:api/render/shaders/common/render_post_process_structs_common.h

为效果专用化位和索引定义着色器宏常量。

详情:参见 references/code_templates.md#step-3-define-shader-constants


第 4 步:实现配置到着色器的转换

文件:src/datastore/render_data_store_post_process.h

实现转换函数,将配置打包为适用于着色器的 Vec4 因子。

详情:参见 references/code_templates.md#step-4-implement-config-to-shader-conversion


第 5 步:填充后处理堆栈

文件:src/datastore/render_data_store_post_process.cpp

将效果及内置数据和因子添加到后处理堆栈。

详情:参见 references/code_templates.md#step-5-fill-post-process-stack


第 6 步:在 RenderNodeUtil 中添加转换

文件:src/nodecontext/render_node_util.cpp

在 GetRenderPostProcessConfiguration() 函数中添加因子转换调用。

详情:参见 references/code_templates.md#step-6-add-conversion-in-rendernodeutil


第 7 步:实现着色器处理函数

文件:api/render/shaders/common/render_post_process_blocks.h

实现包含效果逻辑的 GLSL 着色器处理函数。

详情:参见 references/code_templates.md#step-7-implement-shader-processing-function


第 8 步:集成到渲染管线

文件:assets/render/shaders/shader/fullscreen_combined_post_process.frag

在全屏渲染管线中调用着色器处理函数。

详情:参见 references/code_templates.md#step-8-integrate-into-render-pipeline


Lume3D 实现

必须阅读本节:现在请阅读 references/code_templates.md 中的“Lume3D Templates”部分(步骤 1–5,约 100 行),了解 ECS 集成示例。

暂勿加载 advanced_reference.md——继续按照工作流步骤操作。

第 1 步:添加标志位

文件:api/3d/ecs/components/post_process_component.h

向 PostProcessComponent::FlagBits 枚举添加标志位。

详情:参见 references/code_templates.md#lume3d-step-1-add-flag-bit


第 2 步:定义组件属性

文件:api/3d/ecs/components/post_process_component.h

使用 DEFINE_PROPERTY 宏定义组件属性。

详情:参见 references/code_templates.md#lume3d-step-2-define-component-property


第 3 步:注册元数据

文件:src/ecs/components/post_process_component_manager.cpp

注册枚举值和配置元数据。

详情:参见 references/code_templates.md#lume3d-step-3-register-metadata


第 4 步:集成到渲染系统

文件:src/ecs/systems/render_system.cpp

在 ProcessPostProcessComponents() 函数中赋值配置。

详情:参见 references/code_templates.md#lume3d-step-4-integrate-into-render-system


第 5 步:集成到 Lume3D 着色器

文件:api/3d/shaders/common/3d_dm_inplace_post_process.h

在 Lume3D 原位后处理中调用着色器处理函数。

详情:参见 references/code_templates.md#lume3d-step-5-integrate-into-lume3d-shader


LumeScene 实现

必须阅读本节:阅读 references/code_templates.md 中的 “LumeScene Templates” 部分(步骤 1–9,约 400 行),了解 API 包装器和注册示例。

暂勿加载 advanced_reference.md ——仅在遇到错误或需要数据流图时加载。

步骤 1:定义接口

文件:include/scene/interface/postprocess/intf_your_effect.h

使用 META_INTERFACE 和属性声明定义接口类。

详情:请参阅 references/code_templates.md#lumescene-step-1-define-interface


步骤 2:添加到 IPostProcess 接口

文件:include/scene/interface/intf_postprocess.h

为效果接口添加 include 和 META_READONLY_PROPERTY。

详情:请参阅 references/code_templates.md#lumescene-step-2-add-to-ipostprocess-interface


步骤 3:实现 API 包装器

文件:include/scene/api/post_process.h

使用 META_INTERFACE_OBJECT 和属性宏实现包装器类。

详情:请参阅 references/code_templates.md#lumescene-step-3-implement-api-wrapper


步骤 4:实现效果类

文件:

  • 头文件:src/postprocess/your_effect.h
  • 实现文件:src/postprocess/your_effect.cpp

实现继承自 PostProcessEffect 模板、包含 META_OBJECT 宏的效果类。

详情:请参阅 references/code_templates.md#lumescene-step-4-implement-effect-class


步骤 5:在 PostProcess 中注册

文件:

  • 头文件:src/postprocess/postprocess.h
  • 实现文件:src/postprocess/postprocess.cpp

添加静态属性数据和 InitDynamicProperty 处理程序。

详情:请参阅 references/code_templates.md#lumescene-step-5-register-in-postprocess


步骤 6:注册组件类型

文件:src/component/postprocess_component.h

添加 META_TYPE 注册和属性宏。

详情:请参阅 references/code_templates.md#lumescene-step-6-register-component-type


步骤 7:注册插件类型

文件:src/plugin.cpp

添加 RegisterObjectType 和 UnregisterObjectType 调用。

详情:请参阅 references/code_templates.md#lumescene-step-7-register-plugin-type


步骤 8:注册 Any 类型

文件:src/register_anys.cpp

将接口指针类型添加到 ObjectTypes 列表中。

详情:请参阅 references/code_templates.md#lumescene-step-8-register-any-type


步骤 9:更新构建文件

文件:

  • include/CMakeLists.txt
  • src/CMakeLists.txt
  • BUILD.gn

将接口和源文件添加到构建目标中。

详情:请参阅 references/code_templates.md#lumescene-step-9-update-build-files


禁止的做法

切勿用于多通道效果

需要单独渲染通道的效果(带模糊的泛光、景深、运动模糊、FXAA、TAA):

  • 原因:组合式后处理着色器(fullscreen_combined_post_process.frag)仅处理索引 0-7。多通道效果使用索引 8 及以上,并通过单独的着色器和中间帧缓冲区处理。
  • 后果:尝试使用组合式方法会导致组合式着色器忽略 factors[INDEX_BLOOM](索引 9)。效果不会渲染,或者可能会从错误的内存偏移处读取垃圾数据。
  • 验证:检查效果是否需要中间渲染通道(模糊通道、缩小/放大)。如果需要 → 使用多通道系统,而非组合式方法。
  • 正确做法:使用带有单独渲染节点图的专用多通道后处理实现。

切勿让着色器与 C++ 索引不匹配

GLSL 常量与 C++ 枚举之间的索引一致性:

  • 原因:着色器直接访问 uGlobalData.factors[POST_PROCESS_INDEX_TONEMAP]。如果着色器定义 POST_PROCESS_INDEX_TONEMAP 0,而 C++ 定义 INDEX_TONEMAP 1,着色器就会从 factors 数组中读取错误的 Vec4。
  • 后果:产生视觉瑕疵(颜色错误、参数未应用),或者索引超出 POST_PROCESS_GLOBAL_VEC4_FACTOR_COUNT (14) 时出现 GPU 验证错误“array index out of bounds”。
  • 验证:交叉检查以下三个文件:
    1. 着色器:render_post_process_structs_common.h → POST_PROCESS_INDEX_* 值
    2. C++ 配置:render_data_store_render_pods.h → PostProcessConfiguration::INDEX_* 值
    3. DataStore 转换:render_data_store_post_process.cpp → factors[INDEX_*] 赋值
  • 正确做法:确保三个位置使用相同的数值。文件注释明确指出:“需要与 api/core/render/render_data_store_render_pods.h 保持一致”。

参数超过 4 个时,切勿忘记 userFactors

需要超过 4 个浮点参数的效果:

  • 原因:Vec4 只能容纳 4 个浮点数。GlobalPostProcessStruct 有 factors[14](Vec4 数组)和 userFactors[16](Vec4 数组)。如果效果有 5 个或更多参数,则必须将参数拆分到 factors 和 userFactors 中。
  • 后果:着色器尝试读取 uGlobalData.userFactors[USER_INDEX_*],但常量未定义 → 出现“undefined macro”编译错误。或者常量已定义但未填充 → 着色器读取全零 Vec4 → 效果参数错误。
  • 验证:统计效果参数的数量。如果超过 4 个,请确认:
    1. USER_INDEX_* 常量已在 render_data_store_render_pods.h 中定义
    2. render_data_store_post_process.h 中有用于 userFactors 的 GetFactorXXX() 函数
    3. 着色器使用了正确的 userFactors 索引:uGlobalData.userFactors[POST_PROCESS_USER_INDEX_*]
  • 正确做法:对于 5-8 个参数:使用 factors[0-3] + userFactors[0-3]。定义 USER_INDEX_* 常量,实现转换函数,并在 FillDefaultPostProcessData 中调用。

切勿跳过 LumeRender/Lume3D/LumeScene 一致性检查

必须更新全部三个模块:

  • 原因:组合式后处理会经过三个模块:LumeRender 定义着色器常量 → Lume3D 集成到 ECS → LumeScene 封装 API。跳过任何一个模块都会中断整个链路。
  • 后果:
    • 跳过 LumeRender:着色器找不到 PostProcessXXXBlock() 函数 → 编译错误
    • 跳过 Lume3D:PostProcessComponent 缺少属性 → ECS 系统无法传递配置 → 着色器收到的 factors 全为零
    • 跳过 LumeScene:缺少用户 API → 开发者无法配置效果 → 效果无法使用
  • 验证:使用实现检查清单(涵盖 3 个模块的 22 个步骤)。检查每个模块的关键文件是否存在并已修改。
  • 正确做法:完成全部 22 个步骤。依次处理 LumeRender(8 步)→ Lume3D(5 步)→ LumeScene(9 步)。

例外和回退

效果需要多次渲染遍历

症状:效果需要模糊遍历、缩小/放大、时间累积。

  • 回退方案:此技能不适用。请使用专用的多遍后处理系统,并采用独立的渲染节点图。
  • 依据:检查着色器是否需要 uImgSampler + uBloomSampler + 中间帧缓冲区(如泛光效果)。如果需要 → 多遍处理。
着色器编译错误

症状:“undefined macro POST_PROCESS_INDEX_XXX”或“array index out of bounds”。

  • 诊断:索引不匹配或缺少常量定义。
  • 修复:检查着色器常量是否与 C++ 枚举值匹配。确认索引 < 14(POST_PROCESS_GLOBAL_VEC4_FACTOR_COUNT)。
视觉伪影或效果未应用

症状:颜色错误、参数被忽略、效果不可见。

  • 诊断:因子索引错误,或 DataStore 中未调用 GetFactorXXX()。
  • 修复:确认在 render_data_store_post_process.cpp(步骤 5)和 render_node_util.cpp(步骤 6)中都调用了转换函数。

参考资料

主要参考文件
  • references/code_templates.md(785 行):包含全部 22 个步骤的完整代码模板,其中包括通用模板和色调映射示例。实现期间必须加载。
  • references/advanced_reference.md(306 行):高级参考资料,包含数据流图、实现检查清单和故障排查指南。仅在排查问题或需要了解数据流时加载。
加载策略

阶段 1 - 初始实现:

  • ✅ 必须:分三个阶段加载 code_templates.md(LumeRender → Lume3D → LumeScene 部分)
  • ❌ 不要加载:advanced_reference.md(留待之后使用)

阶段 2 - 故障排查:

  • ✅ 按需加载:遇到错误、需要数据流图或实现检查清单时,加载 advanced_reference.md
  • ❌ 不要重新加载:如果已加载 code_templates.md,则无需重新加载

要点

  1. 架构:配置与转换分离

    • 配置结构体用于用户界面
    • 转换函数将数据打包为适合着色器使用的 Vec4
  2. 关键:着色器与 C++ 的索引/位保持一致

    • POST_PROCESS_INDEX_* ↔ PostProcessConfiguration::INDEX_*
    • POST_PROCESS_SPECIALIZATION_*_BIT ↔ FlagBits 枚举
    • 不匹配会导致 GPU 验证错误或视觉伪影
  3. 必须:支持双路径

    • 在 DataStore(步骤 5)和 RenderNodeUtil(步骤 6)中都添加转换
    • 单路径实现会在某些场景中失效
  4. 命名和宏约定

    • 着色器函数:采用 PostProcess<Effect>Block 命名
    • META_TYPE:仅当接口包含枚举类型时才添加
    • META_READONLY_PROPERTY:必须添加到 IPostProcess 接口

评论

支持 Markdown