Skip to content

Commit 03705e2

Browse files
committed
update memories/Celshade.md
1 parent 466dcae commit 03705e2

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

.serena/memories/Celshade.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Celshade
2+
3+
## 概述
4+
Celshade 是 `Plugins/Renderer` 中 StudioModel 的风格化着色总管线,覆盖了基础 Celshade(分段明暗)、Outline、RimLight/RimDark、HairSpecular,以及与其强耦合的 HairShadow 与 Eyebrow-Passthrough(HairFaceColorMix)链路。
5+
6+
当前实现采用“Analysis + 多离屏几何 Pass + Normal Pass 屏幕空间采样”的组合:
7+
- Analysis 统计模型是否含 FACE/HAIR/透明网格;
8+
- HairShadow pass 把 FACE/HAIR 写入 FBO3 depth/stencil;
9+
- HairFaceColorMix pass 把 FACE 颜色+alpha 写入 FBO4;
10+
- Normal pass 在 FACE/Hair 分支分别采样 stencil 与 mixDiffuse/depth,完成阴影与透发效果。
11+
12+
## 职责
13+
- 维护 Celshade 资产标记协议(`STUDIO_NF_CELSHADE` / `STUDIO_NF_CELSHADE_FACE` / `STUDIO_NF_CELSHADE_HAIR`)与外部配置入口(`[model]_external.txt`)。
14+
- 在分析阶段统计 `r_draw_hasface / r_draw_hashair / r_draw_hasalpha / r_draw_hasadditive / r_draw_hasoutline`,驱动后续 pass 调度。
15+
- 通过 `renderfx` 切换 HairShadow 与 HairFaceColorMix 几何 pass,并管理 FBO3/FBO4 的绑定与清理。
16+
- 在 DrawPass 中构建 `StudioProgramState`,绑定 stencil/mixDiffuse/depth 等纹理输入并切换 shader 宏变体。
17+
- 在 shader 侧实现 face/body celshade、rim light/dark、hair Kajiya specular、face stencil 阴影压暗、hair 屏幕空间颜色混合。
18+
- 提供 cvar + 模型级覆盖(`studio_celshade_control`)双层参数体系,并支持 `r_studio_celshade_debug` 调试分支。
19+
20+
## 涉及文件 (不要带行号)
21+
- docs/Renderer.md
22+
- Plugins/Renderer/enginedef.h
23+
- Plugins/Renderer/gl_common.h
24+
- Plugins/Renderer/gl_local.h
25+
- Plugins/Renderer/gl_rmain.cpp
26+
- Plugins/Renderer/gl_studio.cpp
27+
- Build/svencoop/renderer/shader/common.h
28+
- Build/svencoop/renderer/shader/studio_shader.vert.glsl
29+
- Build/svencoop/renderer/shader/studio_shader.frag.glsl
30+
31+
## 架构
32+
整体流程(StudioModel Celshade):
33+
34+
```mermaid
35+
flowchart TD
36+
A["model_external.txt"] --> B["studio_texture / studio_celshade_control"]
37+
B --> C["Analysis Pass"]
38+
C --> D{"has FACE + HAIR"}
39+
D -- "否" --> E["Normal Pass + Outline"]
40+
D -- "是" --> F{"r_studio_hair_shadow > 0"}
41+
F -- "是" --> G["HairShadow Pass 写 FBO3 depth stencil"]
42+
F -- "否" --> H["跳过 HairShadow"]
43+
G --> I["HairFaceColorMix Pass 写 FBO4 color depth"]
44+
H --> I
45+
I --> E
46+
E --> J["FACE 读取 FBO3 stencil 并压暗阴影"]
47+
E --> K["HAIR 读取 FBO4 mixDiffuse depth 并执行透发混色"]
48+
```
49+
50+
关键实现点:
51+
- 启用判定:
52+
- `R_StudioHasHairShadow()``r_draw_hashair && r_draw_hasface && r_studio_hair_shadow>0 && !R_IsRenderingShadowView()`
53+
- `R_StudioHasHairFaceColorMix()``r_draw_hashair && r_draw_hasface && !R_IsRenderingShadowView()`
54+
- 状态位到 shader 宏:`R_UseStudioProgram()``StudioProgramState` 映射为 `#define`(如 `HAIR_SHADOW_ENABLED``HAIR_FACE_COLOR_MIX_ENABLED``STENCIL_TEXTURE_ENABLED``MIX_DIFFUSE_TEXTURE_ENABLED``DEPTH_TEXTURE_ENABLED`)。
55+
- 纠错逻辑:若出现 `STUDIO_NF_CELSHADE_FACE/HAIR` 但缺少 `STUDIO_NF_CELSHADE``R_UseStudioProgram()` 会自动补上 `STUDIO_NF_CELSHADE`
56+
- 全局开关:`R_StudioDrawMesh()` 在 mesh 级别执行 `if (!r_studio_celshade->value) flags &= ~STUDIO_NF_CELSHADE_ALLBITS;`,统一关断 Celshade 扩展位。
57+
58+
### Shader 核心
59+
- `R_StudioCelShade()`(frag):
60+
- 使用 `smoothstep(r_celshade_midpoint ± r_celshade_softness)` 生成明暗分段。
61+
- FACE 分支按头部朝向(`v_headfwd`)修正光向,减少极角下脸部跳变。
62+
- FACE + stencil 分支:命中 `STENCIL_MASK_HAS_SHADOW` 时强制 `litOrShadowArea = 0.0`
63+
- 非 FACE 分支叠加 rim light / rim dark;HAIR 分支叠加 Kajiya strand specular。
64+
- `R_GenerateAdjustedNormal()`:FACE 允许在原法线与球化法线之间插值(`flNormalMask`);与文档“蓝通道控制 face 球化法线比例”一致。
65+
- HairFaceColorMix pass(frag `HAIR_FACE_COLOR_MIX_ENABLED`):输出 face `diffuseColor`;若有 specular 贴图则 `diffuseColor.a *= rawSpecularColor.a`
66+
- Hair normal pass 混色(frag `STUDIO_NF_CELSHADE_HAIR && MIX_DIFFUSE_TEXTURE_ENABLED`):
67+
- 采样 `depthTex` 重建 `sceneWorldPos`
68+
- 仅在 `distance(sceneWorldPos, vWorldPos) < 4.0` 时,使用 `mixDiffuseColor.a` 混合 face/hair 颜色,降低跨层误混。
69+
- HairShadow 顶点偏移(vert `HAIR_SHADOW_ENABLED && STUDIO_NF_CELSHADE_HAIR`):沿调整后的光向 + Z 偏移应用 `r_hair_shadow_offset`
70+
71+
## 依赖
72+
- 标记位与 renderfx 协议:
73+
- `STUDIO_NF_CELSHADE / FACE / HAIR``STUDIO_NF_CELSHADE_ALLBITS`
74+
- `kRenderFxDrawHairShadowGeometry``kRenderFxDrawHairFaceColorMixGeometry``kRenderFxDrawOutline`
75+
- ProgramState 位:
76+
- `STUDIO_HAIR_SHADOW_ENABLED``STUDIO_HAIR_FACE_COLOR_MIX_ENABLED``STUDIO_STENCIL_TEXTURE_ENABLED``STUDIO_MIX_DIFFUSE_TEXTURE_ENABLED``STUDIO_DEPTH_TEXTURE_ENABLED`
77+
- 离屏资源:
78+
- `s_BackBufferFBO3`(stencil/depth 采样来源,含 stencil view)。
79+
- `s_BackBufferFBO4`(face mix diffuse + depth 采样来源)。
80+
- 纹理槽位:
81+
- `STUDIO_BIND_TEXTURE_STENCIL=6``STUDIO_BIND_TEXTURE_MIX_DIFFUSE=7``STUDIO_BIND_TEXTURE_DEPTH=8`
82+
- stencil 位语义:
83+
- `STENCIL_MASK_HAS_SHADOW=0x1``STENCIL_MASK_HAS_FACE=0x2`
84+
- 参数来源:
85+
- 全局 cvar:`r_studio_celshade*``r_studio_hair_*``r_studio_outline*``r_studio_rim*``r_studio_celshade_debug`
86+
- 模型级覆盖:`studio_celshade_control``R_StudioLoadExternalFile_Celshade`)。
87+
- 资产依赖:
88+
- `studio_texture.flags`,以及可选 `replacetexture/speculartexture`(用于 eyebrow alpha 与 HDR 贴图工作流)。
89+
90+
## 注意事项
91+
- `r_studio_celshade=0` 会在 mesh 入口清空 `STUDIO_NF_CELSHADE_ALLBITS`,所有 Celshade 扩展链路(含 HairShadow/HairFaceColorMix)都会失效。
92+
- HairFaceColorMix 启用条件不依赖 `r_studio_hair_shadow`:只要存在 FACE+HAIR 且非 ShadowView 就会执行该 pass。
93+
- Hair 混色阈值是固定世界空间距离 `4.0`,极端比例模型可能需要额外调参。
94+
- HairShadow pass 文档将 `r_studio_hair_shadow_offset` 描述为“screen space offset”,但实现是顶点几何偏移后再投影。
95+
- HairFaceColorMix pass 明确“不写 stencil”;face 阴影判定依赖前序 HairShadow pass 写入的 FBO3 stencil。
96+
-`s_BackBufferFBO3.s_hBackBufferStencilView``s_BackBufferFBO4` 深度视图不可用,会导致阴影判定/透发混色退化。
97+
- GlowShell 分支会移除 Celshade 位并改为 `STUDIO_NF_FLATSHADE`,因此 Celshade 视觉不会直接叠到 GlowShell pass。
98+
99+
## 调用方(可选)
100+
- `StudioRenderModel_Template`:驱动 Analysis、HairShadow、HairFaceColorMix、Normal、Outline 等 pass。
101+
- `R_StudioDrawMesh`:统一处理 mesh flags(含 Celshade 开关),并分流到 AnalysisPass/DrawPass。
102+
- `R_StudioDrawMesh_AnalysisPass`:收集 `hasface/hashair` 等统计位。
103+
- `R_StudioDrawMesh_DrawPass`:根据 `renderfx + flags` 组装 `StudioProgramState`,完成纹理绑定、状态设置与 `glDrawElements`
104+
- `R_UseStudioProgram`:状态位 -> shader 宏变体编译/缓存。
105+
- `R_CreateStudioRenderData` + `R_StudioLoadExternalFile`:初始化 CelshadeControl,并从 `studio_texture/studio_celshade_control` 加载覆盖参数。
106+
107+
## Pass渲染状态设置(按 Pass / Geometry 细分,重点 Stencil)
108+
109+
### 1) Analysis Pass
110+
- 入口:`r_draw_analyzingstudio = true`
111+
- 行为:仅统计 `r_draw_hasface / r_draw_hashair / r_draw_hasalpha / r_draw_hasadditive`
112+
- stencil:无写入。
113+
114+
### 2) HairShadow Geometry Pass(`renderfx = kRenderFxDrawHairShadowGeometry`
115+
- 调度:绑定 `s_BackBufferFBO3`,清 `depth/stencil``glDrawBuffer(GL_NONE)`
116+
- Geometry 过滤:仅 `STUDIO_NF_CELSHADE_FACE``STUDIO_NF_CELSHADE_HAIR`
117+
- stencil 写入:
118+
- FACE:`GL_BeginStencilWrite(STENCIL_MASK_HAS_FACE, STENCIL_MASK_HAS_FACE | STENCIL_MASK_HAS_SHADOW)`
119+
- HAIR:`GL_BeginStencilWrite(STENCIL_MASK_HAS_SHADOW, STENCIL_MASK_HAS_SHADOW)`
120+
- 状态:`glDisable(GL_BLEND)` + `glDepthMask(GL_TRUE)`;默认 `glCullFace(GL_FRONT)``DOUBLE_FACE` 则禁用剔除。
121+
122+
### 3) HairFaceColorMix Geometry Pass(`renderfx = kRenderFxDrawHairFaceColorMixGeometry`
123+
- 调度:绑定 `s_BackBufferFBO4`,清 color/depth/stencil。
124+
- Geometry 过滤:仅 `STUDIO_NF_CELSHADE_FACE`
125+
- 输出:face `diffuseColor`(可与 `specular.a` 相乘后写入 alpha)。
126+
- stencil:不写(代码注释 `No need to write stencil here`)。
127+
- 状态:`glDisable(GL_BLEND)` + `glDepthMask(GL_TRUE)`
128+
129+
### 4) Normal Pass(FACE)
130+
- 绑定:非 HairShadow/HairFaceColorMix 情况下,为 FACE 尝试绑定 `s_BackBufferFBO3.s_hBackBufferStencilView` 到 slot 6。
131+
- shader:`STUDIO_NF_CELSHADE_FACE && STENCIL_TEXTURE_ENABLED` 时读取 stencil,命中 `HAS_SHADOW` 强制阴影。
132+
133+
### 5) Normal Pass(HAIR)
134+
- 绑定:若启用 HairFaceColorMix,为 HAIR 绑定 `mixDiffuse`(slot 7)与 `depth`(slot 8)。
135+
- shader:重建场景世界坐标 + 距离阈值判定后,按 `mixDiffuse.a` 融合 face/hair 颜色(眉毛透发核心)。
136+
137+
### 6) DrawPass 收尾(每个 mesh)
138+
- 恢复:`glDepthMask(GL_TRUE)``glDisable(GL_BLEND)``glEnable(GL_CULL_FACE)``glEnable(GL_DEPTH_TEST)``glDepthFunc(GL_LEQUAL)`
139+
- 结束 stencil:`GL_EndStencil()`
140+
- 解绑:按状态位解绑 depth/mixDiffuse/stencil/normal/parallax/specular/animated 纹理。

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@
2626

2727
## Important rules
2828
- **ALWAYS** call Serena's `activate_project` on agent startup
29-
- **ALWAYS** use Serena's mcp tools to read or edit code.
29+
- Prefer Serena's mcp tools to read or edit code.

0 commit comments

Comments
 (0)