下载 App

HDR 模式下所有 PBR 模型颜色严重失真

修改于05/17127 浏览BUG反馈
使用模型都出现颜色严重失真情况,都是14号突然出现,13号之前都是没有问题的。经过2天排查发现是系统问题,个人无法修复。
使用两次对话确认问题,花费2W以上积分
第二次对话连接:TapTap 制造
第一次对话连接:TapTap 制造
问题描述
我在开发一款 DND 风格的回合制策略 RPG。项目中有 4 个 3D 场景:角色创建界面(展示 3D 角色模型,背后有 CustomGeometry 做的渐变天空穹顶和地板)、酒馆招募界面(结构与角色创建相同)、六边形网格战斗场景(3D 角色站在六边形地块上,有方向光和 Zone 雾)、以及大地图场景(六边形地形瓦片、POI 标记、迷雾系统)。
这些场景的灯光配置分两种方式:角色创建和酒馆场景通过加载 LightGroup/Daytime.xml 获取灯光(其中方向光 brightness=3.0, temperature=6500, castShadows=true);战斗和大地图场景则手动创建 DirectionalLight,brightness 同样为 3.0。
角色模型共 6 个(战士男/女、法师男/女、盗贼男/女),全部通过 GLB 导入工具转换为引擎 MDL 格式。材质统一使用 PBRMetallicRoughDiffNormalSpec.xml Technique,三张贴图(法线/漫反射/金属度粗糙度),MatDiffColor=(1,1,1,1),Metallic=1.0,Roughness=1.0,颜色完全由 Albedo 贴图提供。
遇到的问题是:所有 6 个角色模型在所有 4 个 3D 场景中颜色都显示异常。整体像蒙了一层白雾,饱和度严重降低。原本深紫色的法师袍变成了亮紫/蓝紫色,棕色的皮肤变成了粉白色,模型表面的暗部和亮部之间的过渡几乎消失了,变成平坦的亮色块。这个问题不是个别模型的现象——6 个不同来源、不同颜色的模型全部表现一致。
关键发现:把 renderer.hdrRendering 设为 false 之后,同样的模型、同样的材质、同样的灯光,颜色就基本正常了。这直接说明问题不在模型、材质或灯光上,而是出在 HDR 开启后引擎自动注入的后处理管线里。
排查过程
为了确认不是自己代码或资产的问题,我花了 10 多轮对话逐一排除了所有可能性。
首先检查了材质参数,所有材质 XML 的 MatDiffColor、Metallic、Roughness 都符合标准 PBR 工作流,没有异常值。然后确认了贴图本身没有问题——关闭 HDR 后同样的贴图显示颜色正常。GLB 导入流程也严格按照导入手册操作,没有遗漏步骤。
接着检查了代码,确认全部场景中没有任何 rp:Append() 调用——也就是说我没有手动添加任何后处理效果,所有后处理都是引擎默认注入的。又尝试了降低灯光亮度,从 brightness=3.0 降到 1.0,发现颜色失真的特征不变,只是画面整体变暗了,排除了"灯光太亮"的可能。
还检查了 PBR Technique XML 的 shader define 参数,没有发现异常配置。也检查了贴图的 sRGB 标志,但由于关闭 HDR 后颜色就正常,sRGB 不太可能是主因。
所有自身原因排除后,我编写了一个叫 RenderDiag v2.1 的诊断脚本。这个脚本在运行时直接 dump 引擎的 Graphics 和 Renderer 全局状态、RenderPath 的完整命令列表和参数值。通过这个诊断工具,我终于拿到了引擎实际运行时的管线数据,发现了问题的根源。
诊断数据与发现
运行时环境状态
诊断脚本采集到的引擎状态:apiName = GL3,graphics.sRGB = false(但 sRGBSupport = true 且 sRGBWriteSupport = true,说明硬件支持但引擎没有开启),renderer.hdrRendering = true,multiSample = 2。
RenderPath 完整命令列表
诊断脚本 dump 出了当前 RenderPath 的全部 49 条渲染命令。其中前 20 条是场景渲染(CLEAR、depth pass、SSAO、base pass、前向光照等),从第 21 条开始是后处理。我没有手动添加任何后处理,以下全部是引擎在 HDR 模式下自动注入的:
命令 [21] DOF(景深)
命令 [22] FXAA2(抗锯齿)
命令 [23] BloomHDR     tag=BRIGHT2
命令 [24] BloomHDR     tag=BRIGHT4
命令 [25] BloomHDR     tag=BRIGHT8
命令 [26] BloomHDR     tag=BRIGHT16
命令 [27] BloomHDR     tag=BRIGHT32
命令 [28] BloomHDR     tag=COMBINE32
命令 [29] BloomHDR     tag=COMBINE16
命令 [30] BloomHDR     tag=COMBINE8
命令 [31] BloomHDR     tag=COMBINE2
命令 [32] BloomHDRPlus tag=BRIGHT
命令 [33] BloomHDRPlus tag=DUALBLUR_DOWN4
命令 [34] BloomHDRPlus tag=DUALBLUR_DOWN8
命令 [35] BloomHDRPlus tag=DUALBLUR_DOWN16
命令 [36] BloomHDRPlus tag=DUALBLUR_DOWN32
命令 [37] BloomHDRPlus tag=DUALBLUR_UP16
命令 [38] BloomHDRPlus tag=DUALBLUR_UP8
命令 [39] BloomHDRPlus tag=DUALBLUR_UP4
命令 [40] BloomHDRPlus tag=DUALBLUR_COMBINE
命令 [41] ColorGrading
命令 [42] GaussianBlur tag=BLURH
命令 [43] GaussianBlur tag=BLURV
命令 [44] GaussianBlur tag=BLURH
命令 [45] GaussianBlur tag=BLURV
命令 [46] GaussianBlur tag=BLURH
命令 [47] GaussianBlur tag=BLURV
命令 [48] GaussianBlur tag=COMBINE
一共 28 个后处理 pass,其中 19 个是泛光(Bloom)相关的。
发现 1:两套 Bloom 系统同时激活
从命令列表可以看到,引擎同时运行了 BloomHDR(命令 [23] 到 [31],共 10 个 pass)和 BloomHDRPlus(命令 [32] 到 [40],共 9 个 pass)两套完全独立的泛光系统。BloomHDR 用的是传统 5 级降采样 + 4 级升采样的金字塔方式,BloomHDRPlus 用的是 DualBlur(双重模糊)方式。两套系统是串联执行的,意味着场景画面先被 BloomHDR 做了一轮泛光处理,然后结果又被 BloomHDRPlus 做了第二轮泛光。图像被泛光了两遍。
发现 2:BloomHDR 的默认合成参数非常极端
诊断脚本采集到的 BloomHDR 默认参数是:
BloomHDRThreshold = 0.4
BloomHDRMix = 1 0.2(即 Vector2(1.0, 0.2))
Threshold=0.4 意味着画面中亮度超过 40% 的像素全部参与泛光计算。在正常场景中,大部分像素的亮度都会超过 0.4,所以几乎整个画面都会被泛光覆盖。
BloomHDRMix=(1.0, 0.2) 的含义是合成时的权重——泛光结果乘以 1.0,原始画面乘以 0.2,然后相加。换算一下:最终画面中泛光贡献占 1.0/(1.0+0.2)=83%,原始画面仅占 0.2/(1.0+0.2)=17%。也就是说,PBR 着色器精心计算出来的固有色、金属质感、粗糙度表现等,在最终画面中只剩下 17% 的权重,剩下 83% 都是模糊化的泛光。这就是为什么所有模型看起来都是"白蒙蒙"的——不是模型颜色有问题,而是原始颜色被泛光淹没了。
发现 3:管线中没有找到显式的 Tonemapping 通道
49 条命令中没有找到名为 Tonemap 或 ToneMapping 的独立通道。方向光 brightness=3.0 配合 PBR 着色器会产生大量 HDR 值(亮度 > 1.0),这些值在没有 tonemapping 压缩的情况下,高光区域可能直接被 clamp 到 1.0(纯白),导致高光处完全过曝丢失细节。
命令 [41] 的 ColorGrading 有可能在内部包含了 tonemapping 处理,但从 Lua 层我无法确认 ColorGrading 的 shader 内部做了什么,也不知道它有哪些可调参数。
发现 4:7 个 GaussianBlur pass 默认启用
命令 [42] 到 [48] 是 7 个高斯模糊 pass(3 轮水平+垂直模糊 + 最终合成)。不清楚这组模糊的设计用途是什么,以及它对最终画面会产生什么影响。但 7 个全屏 pass 的额外开销是客观存在的。
我尝试过的修复
通过 rp:SetShaderParameter() 在 Lua 层调整 BloomHDR 的参数:
local rp = viewport:GetRenderPath()
rp:SetShaderParameter("BloomHDRThreshold", Variant(0.95))
rp:SetShaderParameter("BloomHDRMix", Variant(Vector2(0.12, 0.88)))
把阈值从 0.4 提高到 0.95(只有很亮的区域才泛光),把合成比例从 (1.0, 0.2) 改成 (0.12, 0.88)(原图权重从 17% 提高到 88%)。这对 BloomHDR 有效,画面有一定改善。
但问题是:这只调整了第一套 BloomHDR 的参数,第二套 BloomHDRPlus 仍然在以默认参数全力运行。我不知道 BloomHDRPlus 的参数名叫什么,SetShaderParameter 无法控制它。我也尝试了 rp:SetEnabled("BloomHDRPlus", false),但不确定这个 API 对 pass 组(tag-based)是否真的有效,没有找到相关文档说明。
同样,我也无法确认 ColorGrading 有哪些可调参数,无法确定 GaussianBlur 是否可以安全禁用,也无法在 Lua 层修改 graphics.sRGB 的值。
这个问题的更广泛影响
这不仅仅是"我的项目颜色不对"这么简单。从诊断数据来看,这是一个系统性的管线配置问题,会影响所有使用 HDR + PBR 的项目:
对画面质量的影响:BloomHDRMix 默认 (1.0, 0.2) 意味着 PBR 材质系统计算出的颜色在最终画面中只占 17%。美术无论怎么调整 Albedo 贴图、Metallic、Roughness 参数,最终效果都会被泛光覆盖。暗色系的风格(哥特、暗黑、写实中世纪)几乎不可能实现,因为所有深色都会被洗白。场景的明暗对比和立体感也会丧失,因为泛光会把暗部也填亮。
对性能的影响:19 个 Bloom pass(每个都是全屏采样 + 渲染目标切换)在移动端是不小的开销。而且两套 Bloom 系统功能重复——都是做泛光效果——同时运行除了让画面更白、浪费更多 GPU 算力之外,没有明显的视觉收益。加上 7 个 GaussianBlur pass,仅泛光和模糊就占了 26 个后处理 pass。
对开发者的影响:HDR 模式变得实质上不可用——开启 HDR 就必然颜色失真,不开就没有 HDR 光照效果,开发者被卡在两难中。这个问题的排查成本非常高,我花了 10 多轮对话、编写了专用的运行时诊断工具才定位到根本原因,一般开发者可能直接放弃 HDR 或者以为是自己材质的问题反复调整。
诊断脚本说明
以上所有数据由自制的 RenderDiag v2.1 脚本在运行时采集,脚本位于 scripts/tools/RenderDiag.lua。它在运行时读取 graphics 和 renderer 的全局属性,遍历 RenderPath 的所有命令并打印名称/tag/参数,同时 dump 材质 shader 参数和纹理 sRGB 标志。如果需要复现,将游戏启动场景切换到 renderDiag 即可在控制台看到完整输出。
猜你想搜
taptap 制造pbr模型发白
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
68 赞
21 回复
03:06
为了不被斩杀,我只能做到这些了截图
为了不被斩杀,我只能做到这些了
之前一直申请不到计划3,之前说太花哨,后面说体量完成度不足,在我一番小作文下,编辑终于给了我解答,什么原生质感,玩家开局体验啥的。 本来计划2也够用,准备以后再优化了,结果计划2赠送的积分要砍半了,学生党实在消费不起,于是只能再冲一波计划3了 从周六中午到现在一天半时间,优化了一遍角色卡,战斗卡,还有抽卡界面,优化了新手教程,该说不说确实比之前要舒服些。 前半部分为新版,后半部分为旧版。 明天再次
32 赞
6 回复
求资格,想做一次自己的游戏截图
求资格,想做一次自己的游戏
从事游戏行业十多年了,老板买房买车,我穷途末路。 还记得当年第一次玩到《暗黑破坏神2》的震撼,《冰风谷》狂按空格的“沉着冷静”,《上古卷轴4》开放世界的沉迷。我想做这样的探索冒险游戏。 因为喜欢游戏,毕业后跑去去北京学习游戏原画设计,从页面数值小游戏入行,然后进入一家公司做一款电脑3D对抗竞技游戏。第三人称视角,末世科幻题材,多种族对抗,背景故事还写了编年体,从星球诞生开始。在魔兽世界称霸的年代算
11 赞
8 回复
开发第六天截图
开发第六天
重新改了玩法,并对46%内容细节进行了设定。 后台跑模拟了,玩法看似能走通。 但是考虑到数据本身的问题。 明天开始制造第一个demo。
2 赞
1 回复
第一次尝试截图
第一次尝试
今天熟练了一下操作,有一些错误流程。 一开始只是想做一个普通肉鸽看看怎么实现,后来有灵感,打算把它做成龙与地下城。今天实现了其中一个简单战斗流程,虽然配置都是错的,布局也不对。但是框架出来了,剩下就是一点点增加不同的框架。然后修补内容细节,增加美术效果。
7 赞
6 回复
开发第五天截图
开发第五天
连续两天讨论方案到3点半,加上这三天的班。 今天是办法再加了 说点今天发现塔拉拉会做的事情,也挺有趣的,放松一下。之前就感受到了,今天留意了一下。 大概就是 1,它会表扬你,说你对!提供情绪加值。 2,它会蒙混过关,一些明显错误它会假装不知道或者随便给你几个方案让你选。所以一定要细读,在小地方藏了一些错误。 3,记忆力差,很快就会忘掉之前敲定的设定,给出前后矛盾的方案。所以一定要让它记录讨论结果。
6 赞
9 回复
【创作资源申请】冒险日记截图
【创作资源申请】冒险日记
冒险日记 — 游戏简介 类型:3D 战棋策略 RPG 视角:俯视 平台:TapTap(横屏) 游戏链接: 一、游戏定位 D&D世界观的慢节奏跑团模拟器。玩家扮演一名冒险者队长,经营佣兵小队,在五年的职业生涯中从无名新手成长为传奇英雄。 ----------------------------------------------------------------------------------
7 赞
3 回复
开发第9天截图
开发第9天
1.节假日比平时更忙,开发时间反而更少。 2.游戏带代码成意大利面了,仿佛对比发现这其中一次更新加入了大量矛盾和它瞎编的设定。回滚,拆分后能跑通。 3.同时开始了第二个游戏,吸取第一个游戏的经验,速度快很多
4 赞
6 回复
刚刚发现有资格了截图
刚刚发现有资格了
以为没有拿到资格,上班眼花了看漏了。 刚刚下班才发现有资格了。 周末开始做游戏,先熟悉软件能力范围。 [表情_大笑][表情_大笑][表情_大笑][表情_大笑][表情_大笑]
5 赞
8 回复
01:27
《大二暑假,我用AI做了一款属于自己的游戏》截图
《大二暑假,我用AI做了一款属于自己的游戏》
本人自制游戏现已加入taptap封闭测试(仅适配安卓机型)欢迎大家前来尝试(八月十号可以正式开始游玩) 如果有建议或者bug反馈可以加入qq群928501443 #发现好游戏 #游戏日常 #浅评一下 #今天游戏圈发生了啥
3 赞