场景画面效果优化
This commit is contained in:
@@ -46,10 +46,92 @@ Godot 4.7.2(Forward+,Jolt Physics,D3D12)。编辑器位于
|
||||
- `shader/toon_apply.gd`(@tool Node3D)给每个 MeshInstance3D 复制一份独立材质,
|
||||
因为**每个模型有各自的贴图**,所以必须独立(不能共享一份材质)。
|
||||
- 已在项目设置里用了 **global uniform**:`diffuse_curve`、`specular_smoothness`、
|
||||
`fresnel_smoothness`、`outline_width`、`outline_color` —— 这几项调参本来就是全局实时生效。
|
||||
`fresnel_smoothness`、`outline_width`、`outline_color`。
|
||||
⚠️ **但"全局实时生效"是错的**(2026-10-15 实测纠正):编辑器只在**启动时**
|
||||
把 `[shader_globals]` 注册进 RenderingServer,之后外部改 project.godot(或
|
||||
MCP 的 `project_manage settings_set`)**不会**影响正在运行的编辑器视口。
|
||||
手动改完全局参数必须**重启编辑器**(或临时用 `test_run` 跑一段
|
||||
`RenderingServer.global_shader_parameter_set()` 把值推进去)才能看到效果。
|
||||
这正是当初"改了 outline_width 却毫无变化"的原因。
|
||||
- `outline_width` 的实际像素宽度约为 `width × 0.057`(1364px 视口实测校准),
|
||||
所以**原来的 2.0 实际只有约 0.1px —— 等于没描边**。要看到 2px 描边需要 width ≈ 30。
|
||||
- 贴图尺寸极不统一(289 张 PNG / 24 种尺寸,1024²、512²、4096²、32² 混杂),
|
||||
因此**不适合** Texture2DArray + per-instance uniform 方案(显存会爆且要额外打包流水线)。
|
||||
- 编辑器插件 `addons/toon_refresh/`:改 toon.tres 时自动重刷 toon_apply 材质。
|
||||
**只覆盖材质级参数**(color/specular/fresnel/uv),管不到 global uniform。
|
||||
- ⚠️ **`fresnel`(轮廓光)不能给大平面用**:`fresnel_light()` 以
|
||||
`1 - dot(normal, view)` 为激活量,水平地面/天花板稍远就是掠射角 → 直接饱和成满强度,
|
||||
整片平面被 `fresnel_color` 点亮。**"远处地面发白"就是这么来的**
|
||||
(原来是 (0,0,0) 贡献恒 0 所以没暴露,2026-10-15 改成 (0.4,0.55,0.8) 后显形)。
|
||||
真要留轮廓光就把 `a` 压到 ≤0.05,或把颜色调暗到接近物色。
|
||||
- ⚠️ **MCP `material_manage(op="apply_to_node")` 直接改磁盘 .tscn**,
|
||||
且重新序列化时会**删除失去引用的子资源与 ext_resource**
|
||||
(实测:地板实验后 `ShaderMaterial_mmyc1`/`tyxef` + 3 个 ext_resource 全被清掉,
|
||||
`saved_to:""` 也照样落盘)。拿 MCP 做材质实验前先备份,事后用 `git diff` 逐行核对恢复。
|
||||
|
||||
## 卡通渲染调参(2026-10-15 定的基线取值)
|
||||
|
||||
- `shader/toon_ramp_1d.tres`(新,替代已删除的 `new_gradient_texture_1d.tres`):
|
||||
三级 cel 明暗带,灰阶 0.24 / 0.60 / 1.00,转场各留 0.08 软边。
|
||||
注意 `diffuse_sample()` **只取红通道**,所以渐变做成彩色也没用。
|
||||
- `specular_smoothness = 0.08`、`fresnel_smoothness = 0.12`;
|
||||
原值 10.0 会把高光压到几乎不可见(`smoothstep(0.05, 10.05, x)`)。
|
||||
- `outline_width = 30`、`outline_color = Color(0.08, 0.07, 0.1, 1)`。
|
||||
- `toon.tres` 的 `specular` / `fresnel` **RGB 原来都是纯黑 = 两个模块完全失效**,
|
||||
现已改为 `specular=(0.12,0.12,0.12,α0.45)`、`fresnel=(0.4,0.55,0.8,α0.18)`。
|
||||
注意 specular 的 α 只用来推 gloss 指数,**亮度只能靠 rgb 调**。
|
||||
- MCP `settings_set` 写不了 Color:传 dict 会落成 `{"r":..}` 嵌套字典(引擎无法绑定),
|
||||
传 `"#rrggbb"` 会落成 String。**正确做法是手改 project.godot 写成 `Color(r,g,b,a)`。**
|
||||
int 型也一样:会落成 `={"type": "int","value": 4.0}` 的字典块,**用完记得手改回 `=4`**。
|
||||
|
||||
## 阴影质量(2026-10-15 定位完毕)
|
||||
|
||||
- **`DirectionalLight3D.light_angular_distance` 是本项目阴影锯齿的元凶。**
|
||||
它开启 PCSS 软阴影:半影半径 = 遮挡距离 × tan(角径),但 Godot 的 PCSS
|
||||
采样数固定 → 半径一大就变成**稀疏采样尖刺**,表现为:
|
||||
1) 大面积表面(沙发扶手内侧面)上出现**成片的「梳齿/蕨叶」黑纹**;
|
||||
2) 物体投影(白盘子)边缘出现**阶梯 + 毛刺**。
|
||||
实测 `0.8°` 时 artifact 明显,**改成 `0.0` 后两者同时消失**。
|
||||
⚠️ 别以为角径越大越"柔软自然"——在这个引擎里它只会换来尖刺。
|
||||
- 工程设置 `rendering/lights_and_shadows/{directional_shadow,positional_shadow}/soft_shadow_filter_quality`
|
||||
**默认只有 2(Soft Low)**,提到 **4(Soft High)** 实测高频噪点能量降 40%。枚举顺序:
|
||||
`0 Hard, 1 Soft Very Low, 2 Soft Low, 3 Soft Medium, 4 Soft High, 5 Soft Ultra`。
|
||||
- `shadow_blur`(0~10,默认 1.0)在 angular=0 时**几乎测不出影响**,不用调。
|
||||
- `shadow_bias` / `shadow_normal_bias` **别低于引擎默认 0.1 / 2.0**:
|
||||
归零会让全身自阴影爆发(阴影面积 18484px → 114706px)。原场景的 0.05 / 1.5 偏低。
|
||||
- ⚠️ **`shadow_normal_bias = 0` + `shadow_blur = 0` 同时出现 = 整幅画面三角颗粒/摩尔纹**
|
||||
(2026-10-15 实测,相邻像素亮度差 0.58 → 12.73,20 倍):
|
||||
`normal_bias = 0` 让**每个阴影贴图纹素**都自阴影抖动,而 `shadow_blur` 就是 PCF 半径,
|
||||
归零后抖动不再被平滑,于是按贴图纹素频率原样显现(纹素斜投影 → 三角/四边颗粒)。
|
||||
任意恢复其中一个即可(0.638 / 0.566)。只想锐化就把 blur 取 0、**normal_bias 留 2.0**。
|
||||
- ⚠️ **提高阴影贴图分辨率救不了锯齿**:`directional_shadow/size 4096 → 8192`
|
||||
在正常配置下只改善 ~8%,在坏配置下**反而更糟**(12.73 → 17.92),
|
||||
因为纹素越细抖动频率越高。"锯齿 = 贴图不够大"是错误直觉。
|
||||
- 室内场景可把 `directional_shadow_max_distance` 收到 45(原来 60),近场纹素密度提高 1.3×。
|
||||
|
||||
## 验证"启动时固化"的设置(可复用套路)
|
||||
|
||||
`[shader_globals]`、`rendering/lights_and_shadows/*`(阴影贴图尺寸、软阴影滤波质量)、
|
||||
MSAA 等**只在引擎启动时读一次**,改 project.godot 对运行中的编辑器视口无效。
|
||||
不要靠编辑器截图验证这类改动,走这条独立进程路线:
|
||||
|
||||
1. 造一个探针场景 `tools/_probe.tscn` + `tools/_probe.gd`:`extends Node3D`,
|
||||
在 `_ready()` 里 `load("res://world/xxx.tscn").instantiate()`、加一台 Camera3D、
|
||||
等 ~60 帧、`await RenderingServer.frame_post_draw` 后
|
||||
`get_viewport().get_texture().get_image().save_png(...)`、`quit()`。
|
||||
2. `DisplayServer.window_set_position(Vector2i(-6000,-6000))` 把窗口挪到屏幕外,不打扰用户。
|
||||
3. 用 `--resolution 1364x772` + 位置参数指定场景跑:
|
||||
`godot --path <proj> --resolution 1364x772 res://tools/_probe.tscn`(**别加 `--headless`**,
|
||||
dummy 渲染后端出不了图)。
|
||||
4. 想在探针里改灯的参数做单变量对照,直接在脚本里改 `DirectionalLight3D` 的属性再截图,
|
||||
一次进程就能出多张对照图。
|
||||
5. **要像素级对齐编辑器视口**:`res://tests/test_xxx.gd`(`@tool` + `extends McpTestSuite`,
|
||||
`print` 抓不到,得用 `FileAccess` 写文件)里读
|
||||
`EditorInterface.get_editor_viewport_3d(0).get_camera_3d().global_transform`,
|
||||
再 `test_run` 执行,就能拿到确切机位/ FOV。本项目的 sofa 机位是
|
||||
`origin(-12.070005, 4.639197, -2.615989)`,`fov 70.01`,视口 1364×772。
|
||||
6. 注意 main2 的「联机测试」UI 是 **autoload(`autoload/net.tscn`)**,不在场景树里,
|
||||
探针要递归隐藏 `get_tree().root` 下的 `CanvasLayer`/`Control` 才遮不掉画面。
|
||||
|
||||
## 坐标系陷阱 + 上游着色器的边界(重要)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user