下载 App

引擎问题报告:3D模式下所有材质输出颜色发暗

06/1953 浏览BUG反馈
这问题已经有一个月了,导致3d的项目画面很难蚌。
horizontal linehorizontal line
horizontal linehorizontal line
horizontal linehorizontal line
提交对象:UrhoX 引擎团队 报告类型:渲染管线行为问题 / 颜色不可控 严重程度:中(影响所有依赖精确颜色的 Unlit 用法:标记色、卡通平涂、UI 风格色、数据可视化)
horizontal linehorizontal line

1. 问题概述

自上个月一次更新后开始,所有颜色会变的灰蒙蒙的,即使使用 Techniques/NoTextureUnlit.xml(无光照材质)渲染的 3D 物体,其 MatDiffColor 设置的颜色无法所见即所得地输出到屏幕。颜色在渲染管线的输出阶段被 ACES / filmic 色调映射处理,表现为:
  • 高饱和色被去饱和、并发生色相偏移(例:纯红的绿/蓝通道凭空升高)
  • 整体亮度被高光肩部曲线压缩(输入 1.0 的通道达不到屏幕 255)
直觉上,"Unlit / 无光照"应当意味着"不参与任何光照与后期着色,颜色直接输出"。但实测表明 Unlit 仅跳过了光照计算,仍然经过输出端的 tonemap pass,导致开发者无法精确控制其最终显示颜色。
horizontal linehorizontal line

2. 复现环境

项目配置
渲染模式renderer.hdrRendering = true
光照预设LightGroup/Daytime.xml
材质技法Techniques/NoTextureUnlit.xml
颜色设置mat:SetShaderParameter("MatDiffColor", Variant(Color(r, g, b, 1.0)))
测试模型Models/Sphere.mdl(StaticModel)
吸色误差截图取色经多软件交叉验证,误差 ±2 以内(已排除截图色彩管理因素)
horizontal linehorizontal line

3. 最小复现步骤

lua
-- 1) 加载官方光照预设 local lightGroup = scene_:CreateChild("LightGroup") lightGroup:LoadXML(cache:GetResource("XMLFile", "LightGroup/Daytime.xml"):GetRoot()) -- 2) 创建一个 Unlit 球 local mat = Material:new() mat:SetTechnique(0, cache:GetResource("Technique", "Techniques/NoTextureUnlit.xml")) mat:SetShaderParameter("MatDiffColor", Variant(Color(1.0, 0.0, 0.0, 1.0))) -- 纯红 local node = scene_:CreateChild("Ball") local m = node:CreateComponent("StaticModel") m:SetModel(cache:GetResource("Model", "Models/Sphere.mdl")) m:SetMaterial(mat) -- 3) 屏幕吸色球中心,对比期望值 #FF0000
horizontal linehorizontal line

4. 实测数据矩阵

所有"期望屏幕值"按"sRGB 感知颜色直出"计算(即 输入 × 255)。
#tonemapLUTHDR输入 (linear)期望屏幕实测屏幕关键观察
1默认(0.80, 0.95, 0.20)#CCF233#D6DB98 (214,219,152)去饱和、发灰
2默认(1, 0, 0) 纯红#FF0000#C6372E (198,55,46)R 压低、G/B 凭空串色
3默认(1, 1, 1) 纯白#FFFFFF#DDDDDD (221,221,221)中性无偏色,但被压暗
4默认(1, 0, 0)#FF0000#C6372E关 HDR 无变化
5推远(1, 0, 0)#FF0000#C6372E推远雾 无变化
6默认(1, 0, 0)#FF0000(232,2,0)G/B 串色消失,R 仍压低
7默认(1, 0, 0)#FF0000(232, 2, 0)再次确认 HDR 无关
8默认(2, 0, 0) 超量clamp #FF0000(245, 1, 0)R 随输入升高但渐近饱和
关键 sRGB→linear 换算(佐证"曲线"性质):
屏幕 RsRGBlinear
221(纯白输入1.0)0.8670.722
232(纯红输入1.0,tonemap关)0.9100.807
245(纯红输入2.0,tonemap关)0.9610.913
horizontal linehorizontal line

5. 根因分析

Unlit 颜色经过两层相互独立的处理,串成一条输出链:
MatDiffColor
   │
   ├─[A] 残余 filmic tone curve  →  高光肩部压缩亮度(输入1.0 → linear 0.81,且渐近 1.0 达不到)
   │
   ├─[B] ACES tonemapLUT         →  色域去饱和 + 色相偏移(纯红 G/B 串到 55/46)
   │
   └─ sRGB 输出 → 屏幕

层 A:ACES tonemapLUT(由 zone.tonemapLUTEnabled 控制)

  • 默认开启。负责去饱和与色相偏移
  • 证据:实验 2 → 6,关闭后纯红的 (G,B) 从 (55,46) 骤降到 (2,0),色相恢复纯净。
  • 这是"网球黄绿 #CCF233 变灰为 #D6DB98"、"纯红变暗橙红"的主因。

层 B:残余 tone curve(tonemapLUTEnabled 关不掉)

  • 即便关闭 tonemapLUTEnabled,纯红 R 仍被压到 232(linear 0.807),到不了 255。
  • 证据:实验 8,输入加倍 (2,0,0) 后 R 从 232 升到 245(linear 0.807→0.913)——随输入单调上升、增长递减、渐近上限。这是 filmic 高光肩部曲线的典型特征,而非硬钳(硬钳的话 R 不会随输入变化)。
  • 该曲线无法通过 Zone 级开关关闭,疑似位于更底层(RenderPath 的某个 tonemap command,或 shader 内置)。

重要补充:R=1.0 的压低不可能是 gamma

sRGB / gamma 变换的端点固定(1 的任何次方仍是 1),因此 R 从 1.0 被压到 0.81 不可能源于 gamma 编码,只能来自 tone curve。这进一步确认了层 B 的存在。
horizontal linehorizontal line

6. 已排除的因素(实验佐证)

假设因素排除依据
HDR 渲染管线(hdrRendering)实验 4、7:开关 HDR,结果完全不变
雾效(Zone fog)实验 5:雾推到极远,结果完全不变
环境光 / IBL / SH 漏入 Unlit关 tonemap 后 G/B≈(2,0),无加性环境项;且环境光只会加亮、不会压暗 R
gamma / sRGB 编码R=1.0 在任何 gamma 下恒为 1.0,无法解释 232
截图 / 显示色彩管理多软件交叉吸色,误差 ±2 以内
horizontal linehorizontal line

7. 期望行为与建议

期望

"Unlit / 无光照"材质应能精确所见即所得地输出 MatDiffColor,不被任何后期色调映射改写。这是 Unlit 在标记色、卡通平涂、UI/HUD 元素、数据可视化等场景的核心价值。

建议(任一即可缓解)

  1. 提供 Unlit 材质绕过 tonemap 的能力
  2. 例如新增一个 Techniques/NoTextureUnlitRaw.xml,或在材质上提供 shader 参数/flag(如 BypassTonemap),使其在最终合成阶段被排除出 tonemap pass。
  3. 打通 tone curve 的开关
  4. 当前 zone.tonemapLUTEnabled = false 只关掉了去饱和部分(层 A),残余 tone curve(层 B)仍生效。建议让该开关或新增开关能完整关闭整条曲线。
  5. 文档补充说明
  6. 在渲染文档中明确:"Unlit 材质仍会经过输出端 ACES tonemap",并给出在 ACES 下精确控制 Unlit 颜色的推荐做法(如预补偿公式 / HDR 输入值参考表)。

临时规避方案(开发者侧,供参考)

  • 保留 ACES:将目标颜色预补偿(提高亮度/饱和,高亮通道用 >1 的 HDR 输入)逼近期望屏幕值;缺点是高饱和纯色无法完美还原。
  • 全局关 ACESzone.tonemapLUTEnabled = false,使全场 Unlit 接近所见即所得;缺点是影响整个场景所有物体的观感,且残余 tone curve 仍留少量亮度压缩。
horizontal linehorizontal line
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
66 赞
20 回复
感谢官方大大真的让我通过了截图
感谢官方大大真的让我通过了
我抱着试一试的心态,用了这个聚光灯活动,活动免费白嫖的10万积分,做我不擅长的叙事游戏,我跟官方审核说清楚原因,升级开发者计划二用来做新游戏,没想到真的通过,牛牛牛( ఠൠఠ )ノ点赞点赞👍,效率真高,不过我记得开发者计划二以前不是有每日积分的吗,怎么只剩下周期积分了[表情_疑惑][表情_疑惑]
16 赞
16 回复
寻思做不太下去的东西要不要发出来?截图
寻思做不太下去的东西要不要发出来?
[心动小镇_点赞]虽然不发出来就烂手上了,但是想到要是没做完发了过了新发布期的流量或者把玩家劝退了那不是亏了?#TapTap制造 #开发心得 #脑洞实验室 另外这个可以试玩下,乐队少女卡牌:
4 赞
2 回复
【游戏自荐】猫猫从天而降!截图
【游戏自荐】猫猫从天而降!
关于比赛已经结束5天了咱才开始发游戏上新/自荐这回事。。。 虽然前面版本游戏逻辑是完整的,但是没有剧情就感觉缺点什么,于是添加了个第一章主线剧情才发这个游戏上新,之后慢慢更新吧。 误触变身器的猫咪,以高空坠落奏响净化音波。只要用箱子爬上高空,就能依靠重力踏出专属的魔法节奏秒掉大片噪音怪物。在明亮温馨的日常中,踏出独属于猫咪的净化节奏与羁绊。 #TapTap制造 #发现好游戏 #独立游戏开发 #Ta
6 赞
4 回复
03:06
为了不被斩杀,我只能做到这些了截图
为了不被斩杀,我只能做到这些了
之前一直申请不到计划3,之前说太花哨,后面说体量完成度不足,在我一番小作文下,编辑终于给了我解答,什么原生质感,玩家开局体验啥的。 本来计划2也够用,准备以后再优化了,结果计划2赠送的积分要砍半了,学生党实在消费不起,于是只能再冲一波计划3了 从周六中午到现在一天半时间,优化了一遍角色卡,战斗卡,还有抽卡界面,优化了新手教程,该说不说确实比之前要舒服些。 前半部分为新版,后半部分为旧版。 明天再次
28 赞
6 回复
05:39
游戏目前开发状态截图
游戏目前开发状态
基本玩法都做的差不多了,采集、探索、制作、建造。 全部都由塔塔完成。 塔塔太厉害了。
4 赞
4 回复
发个漫画风UI Skill截图
发个漫画风UI Skill
打包skill好贵啊 直接hub搜索《手绘漫画风 UI 系统》 目前还在审核,应该不至于过不了。 专为自己的跑商游戏做的UI风格,风格合适的情况下还是不错的,即使不怎么搭的时候起码比雷霆UI好。 #TapTap制造 #脑洞实验室 #独立游戏开发 #开发心得
10 赞
3 回复
01:27
《大二暑假,我用AI做了一款属于自己的游戏》截图
《大二暑假,我用AI做了一款属于自己的游戏》
本人自制游戏现已加入taptap封闭测试(仅适配安卓机型)欢迎大家前来尝试(八月十号可以正式开始游玩) 如果有建议或者bug反馈可以加入qq群928501443 #发现好游戏 #游戏日常 #浅评一下 #今天游戏圈发生了啥
3 赞
开发心得-界面布局心得截图
开发心得-界面布局心得
大家好,我正在用 TapTap 制造制作一款2D 治愈林间徒步旅行游戏《徒步荒野》。 我分享一下我的开发心得,希望能有用,下面是一些界面布局的心得。 第一步:定版式、操作 先确定游戏是横版还是竖版、需要哪些操作按钮,敲定整体玩法思路。 我的玩法灵感参考《边境之旅》,主打散步看风景、沿途触发随机事件。 原版是 3D,考虑到自己是新手,选择2D 横版街机式来做,制作更简单、好上手。 第二步:敲定全局美
6 赞
2 回复
00:37
放弃3d直接做伪3d效果一下子好了很多截图
放弃3d直接做伪3d效果一下子好了很多
按照某大佬的sprite stack 伪3D 教程拿着锤子找钉子做了个碰碰车,感觉还行吧,加点道具乱斗应该可以上了。#开发心得 #TapTap制造 #脑洞实验室 不过这个素材没法直接靠单独生成贴图得到,需要在生成合适贴图后丢到生成模型的ai里面过一遍,然后再把生成的模型体素化后转为序列帧。
8 赞