137 lines
7.5 KiB
Markdown
137 lines
7.5 KiB
Markdown
# Graphics 高级渲染与屏幕空间效果
|
||
|
||
[返回模块概览](../graphics.md)
|
||
|
||
### 可编译渲染控制与 GBuffer
|
||
|
||
`RenderControl` 用字符串特性开关,再 `compile()` 成有序 Pass(默认:shadow → forward → hair):
|
||
|
||
```squirrel
|
||
local rc = gfx.getRenderControl();
|
||
rc.enable("gbuffer"); // 额外填充可采样深度/法线
|
||
rc.enable("gbufferAlbedo");
|
||
rc.compile();
|
||
gfx.render3D();
|
||
local gb = rc.getGBuffer();
|
||
if (gb.isValid()) {
|
||
local depth = gb.getDepthTexture(); // RGBA8,R = 线性深度 0..1(Canvas / 体积雾)
|
||
local hwDepth = gb.getHwDepthTexture(); // D32,.r = Vulkan NDC z(3D AO / GI)
|
||
local nrm = gb.getNormalTexture(); // RGB = 法线*0.5+0.5
|
||
}
|
||
```
|
||
|
||
3D 前向仍启用硬件 z-buffer;GBuffer 是给 AO / 体积雾 / 风格描边等中后期用的采样目标。阴影仍走 CSM shadow map。
|
||
|
||
一帧里各 buffer 谁写谁读、对应函数和 shader,见开发文档 [`3D渲染管线.md`](../../../dev/3D渲染管线.md)。
|
||
|
||
大面积平铺 albedo(地面、墙面)若出现明显重复,可对实体调用 `setTexCellBomb(cellScale, strength, rotAmount=1)`:按 UV 划分 cell,对邻接 cell 做随机偏移/旋转并混合。`strength=0`(默认)关闭,行为与原先一致;`cellScale` 一般为 2~16。
|
||
|
||
砖墙、石板等需要假深度时,用 `setHeightTexture(heightTex)` + `setParallax(scale, minLayers=8, maxLayers=32)` 开启视差遮蔽贴图(POM)。高度图取 **R 通道**(白=凸起朝向观察者);`scale=0`(默认)关闭。典型 `scale` 为 0.02~0.08;掠射角下层数会自适应增加。
|
||
|
||
### 毛发 / 皮毛渲染(Hair Cards)
|
||
|
||
适用于 VRoid / 角色发片、动物皮毛等 alpha 卡片网格。引擎提供内置 **Kajiya-Kay 各向异性高光** shader,并在 `RenderSystem3D` 中于不透明物体之后、按距离从远到近绘制。
|
||
|
||
```squirrel
|
||
local hairShader = gfx.newHairShader()
|
||
hairShader.sendFloat("specExp", 90.0)
|
||
hairShader.sendFloat("specStrength", 0.9)
|
||
hairShader.sendFloat("alphaCutoff", 0.12)
|
||
|
||
local hair = Renderable3D.create()
|
||
hair.setMesh(hairCardMesh)
|
||
hair.setTexture(hairAlbedo)
|
||
hair.setShader(hairShader)
|
||
hair.setHair(true) // 启用透明毛发 pass(背面优先排序)
|
||
hair.setCastShadow(false) // 发片通常不参与阴影投射
|
||
```
|
||
|
||
可调 push 参数:`specExp`、`specStrength`、`primaryShift`、`secondaryShift`、`alphaCutoff`、`rimStrength`、`strandDirX/Y/Z`(发束方向,全 0 时由顶点自动推导)。
|
||
|
||
### 屏幕空间体积光(尘雾光柱)与体积雾
|
||
|
||
`vol <- gfx.newVolumetric()`。`setQuality("low"|"medium"|"high")` 控制采样与 `resolutionFor`。
|
||
|
||
- **screenspace**:`beginOcclusionMap` → `drawOccluders2D` → `scatter`;或 `applyFromScene`
|
||
- **raymarch**:`setMode("raymarch")` + `setCamera` + 线性深度 → `rayMarch`
|
||
- **fog**:`setMode("fog")` + `setFogHeight*` / `setFogStart`/`End` + 线性深度 → `applyFog`(雾色 alpha 叠加场景)
|
||
- **froxel**:`configureFroxelGrid` → `clearFroxelGrid` →
|
||
`injectFroxelHeightFog` → `integrateFroxel` → `uploadFroxel`;在
|
||
`gfx.render3D()` 后将 GBuffer 线性深度传给 `applyFroxel` 或
|
||
`applyFroxelTo`。介质未变化时不必每帧重新上传。
|
||
- **cloud**:`setMode("cloud")`,用 `setCloudLayer`、`setCloudCoverage`、
|
||
`setCloudDensity`、`setCloudScale`、`setCloudWind` 和 `setCloudLightColor`
|
||
调整云层;线性深度输入通过 `renderClouds` 或 `renderCloudsTo` 渲染,
|
||
`getCloudShader` 可用于高级参数检查与调试。
|
||
|
||
细节见 [`体积光模块设计.md`](../../../dev/体积光模块设计.md)。
|
||
|
||
### 屏幕空间环境光遮蔽(SSAO / HBAO / GTAO)
|
||
|
||
`ao <- gfx.newAmbientOcclusion()`。`setMode("ssao"|"hbao"|"gtao")`,`setQuality` 控制采样与 `resolutionFor`。
|
||
|
||
1. `setCamera` + 线性深度纹理(与体积雾相同约定)
|
||
2. `compute` / `computeTo` → AO 图(RGB=遮蔽因子,A=深度)
|
||
3. 可选 `blur` / `blurTo`(双边)
|
||
4. `applyOverlay` 以黑 + `alpha=(1-ao)*intensity` 叠到已有场景
|
||
|
||
3D 默认路径:`RenderControl` 特性 `"ao"`(默认开)会在 forward 之后对 GBuffer 的 D32 + 法线做 `applyFromGBuffer`,不必手动建 Canvas。Canvas 上的 `compute` 仍用 8-bit 线性深度。
|
||
|
||
细节见 [`环境光遮蔽模块设计.md`](../../../dev/环境光遮蔽模块设计.md)。
|
||
|
||
### 屏幕空间全局光照(SSGI)
|
||
|
||
`gi <- gfx.newGlobalIllumination()`。`setQuality` 控制采样数与半径;`setLightDirection` / `setLightColor` 提供反弹用的太阳光。
|
||
|
||
3D 默认路径:`RenderControl` 特性 `"gi"` 仍默认开(mesh 半球天空/地面 + wrap fill)。fullscreen `applyFromScene` 不会自动叠到 3D 回读:从 lit scene color 采样会把帘子/花盆印到地面上形成游走鬼影。需要时仍可手动 `applyFromScene` / `applyFromDepth`。Canvas 测试仍可用打包的 `applyFromDepth`(A=线性深度)。
|
||
|
||
```squirrel
|
||
local rc = gfx.getRenderControl();
|
||
rc.enable("gi"); // 默认已开
|
||
rc.compile();
|
||
```
|
||
|
||
### AAA 时域反射链(TAA + RTGI + SSR)
|
||
|
||
`"reflectionChain"` 一次启用 TAA、fullscreen RTGI、PBR 感知 SSR 及其 GBuffer 依赖,并默认关闭重复的硬件 MSAA 成本。基础材质的环境 IBL 是 SSR 未命中、出屏和高粗糙度区域的后备反射;SSR 结果按时域置信度覆盖,避免屏幕边界硬切。
|
||
|
||
```squirrel
|
||
local rc = gfx.getRenderControl();
|
||
rc.setPostProcessQuality("high"); // low | medium | high | ultra
|
||
rc.enable("reflectionChain");
|
||
rc.compile();
|
||
```
|
||
|
||
室内或盒状空间可在相机环境 cubemap 上启用 box-projected reflection probe,使墙面和物体反射对应有限房间而不是无限远天空:
|
||
|
||
```squirrel
|
||
camera.setEnvMap(roomCubemap);
|
||
camera.setEnvIntensity(1.0);
|
||
camera.setEnvProbe(0, 2, 0, 8, 2, 6); // center xyz, half-extent xyz
|
||
```
|
||
|
||
只有位于 probe AABB 内的 fragment 会修正镜面反射方向;盒外自动使用普通环境方向。`camera.clearEnvProbe()` 恢复无限远 IBL。任一 extent 为零时 probe 视为关闭。
|
||
|
||
运行时切档会同步更新 TAA、RTGI 与 SSR,并废弃不兼容的历史帧;`ultra` 在 TAA 上映射到其最高 `high` 档,在 RTGI/SSR 上使用原生 `ultra`。关闭 `reflectionChain` 会同步关闭三个子链路;如果需要逐项调试,也可分别启用 `"taa"`、`"rtgi"`、`"ssr"`。
|
||
|
||
### 抗锯齿(硬件 MSAA + 经典后处理)
|
||
|
||
**硬件 MSAA**(3D 模型/体素边缘效果最好):3D scene color pass 默认 4x 多重采样再 resolve。用 `RenderControl "msaa"`(默认开)开关,`gfx.setMsaaSamples(n)` 设采样数(0/1=关,2/4/8 按设备能力 clamp):
|
||
|
||
```squirrel
|
||
gfx.setMsaaSamples(8); // 升到 8x(若设备支持)
|
||
gfx.setMsaaSamples(0); // 关闭硬件 MSAA
|
||
rc.disable("msaa"); // 或通过 RenderControl 特性关
|
||
```
|
||
|
||
**经典后处理**:`aa <- gfx.newAntiAliasing()`。`setQuality("low"|"medium"|"high")` 调整阈值与搜索;`setMode` 选择算法:
|
||
|
||
- **fxaa**:FXAA 3.11 风格亮度边搜索
|
||
- **smaa**:SMAA 启发的单 Pass 形态学 AA
|
||
- **ssaa**:超采样 Resolve(先画到 `resolutionFor` 尺寸的 Canvas)
|
||
- **nfaa**:沿亮度梯度切向的 Normal Filter AA
|
||
|
||
典型流程:场景 → Canvas → `aa.applyCanvas` / `applyCanvasTo` → 屏幕。
|
||
|
||
3D 默认路径:`begin3DFrame` 画到可采样的 scene color(`"msaa"` 开时先 Nx 多重采样再 resolve 到 1x),present 时按 `RenderControl "aa"`(默认开)做 FXAA resolve 再叠 AO/HUD。手动 Canvas 路径仍然可用。细节见 [`抗锯齿模块设计.md`](../../../dev/抗锯齿模块设计.md)。
|