2026-05-03 20:37:58 +08:00
|
|
|
|
---
|
|
|
|
|
|
title: 屏幕空间深度偏移
|
|
|
|
|
|
date: 2026-05-03 00:00:00
|
|
|
|
|
|
excerpt: 在屏幕空间偏移顶点深度,防止 Z-fighting 或强制分层
|
|
|
|
|
|
tags:
|
|
|
|
|
|
- ARC
|
|
|
|
|
|
- Rendering
|
|
|
|
|
|
- VertexFactory
|
|
|
|
|
|
rating: ⭐
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 屏幕空间深度偏移
|
|
|
|
|
|
|
|
|
|
|
|
返回 [[Rendering]]
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
在顶点着色器中直接偏移输出深度值,用于防止卡通描边的 Z-fighting 或强制控制元素的渲染层级。
|
|
|
|
|
|
|
|
|
|
|
|
## 实现
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
#if USES_SCREEN_SPACE_DEPTH_OFFSET
|
|
|
|
|
|
{
|
|
|
|
|
|
Output.Position.z += GetMaterialScreenSpaceDepthOffset(VertexParameters)
|
|
|
|
|
|
* DEPTH_OFFSET_SIGN;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`DEPTH_OFFSET_SIGN` 根据平台的深度缓冲方向(正向/反向 Z)自动调整符号。
|
|
|
|
|
|
|
|
|
|
|
|
## 使用场景
|
|
|
|
|
|
|
|
|
|
|
|
- 卡通描边网格的深度偏移(避免与本体 Z-fighting)
|
|
|
|
|
|
- 半透明元素的强制排序
|
|
|
|
|
|
- 面部特征的深度分层(眉毛、头发等)
|
|
|
|
|
|
|
|
|
|
|
|
## 材质属性
|
|
|
|
|
|
|
|
|
|
|
|
`MP_ScreenSpaceDepthOffset`(float)通过材质图控制。参见 [[自定义材质属性]]。
|
|
|
|
|
|
|
2026-05-03 21:38:46 +08:00
|
|
|
|
## 完整代码解析
|
2026-05-03 20:37:58 +08:00
|
|
|
|
|
2026-05-03 21:38:46 +08:00
|
|
|
|
### Common.ush — 深度偏移方向宏定义
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
// Common.ush — 深度偏移方向宏定义
|
|
|
|
|
|
// ASW Change : 2016/06/07 15:20:36 Takuro.K
|
|
|
|
|
|
#if USES_SCREEN_SPACE_DEPTH_OFFSET
|
|
|
|
|
|
// 根据深度缓冲方向确定偏移符号
|
|
|
|
|
|
// 反向 Z(近=1,远=0):偏移为负 = 向远处推
|
|
|
|
|
|
// 正向 Z(近=0,远=1):偏移为正 = 向远处推
|
|
|
|
|
|
#if HAS_INVERTED_Z_BUFFER
|
|
|
|
|
|
#define DEPTH_OFFSET_SIGN -1.0f
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define DEPTH_OFFSET_SIGN 1.0f
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### BasePassVertexShader.usf — 应用深度偏移
|
|
|
|
|
|
|
|
|
|
|
|
```hlsl
|
|
|
|
|
|
// BasePassVertexShader.usf — 应用深度偏移
|
|
|
|
|
|
// ASW Change : 2016/06/07 15:20:36 Takuro.K
|
|
|
|
|
|
#if USES_SCREEN_SPACE_DEPTH_OFFSET
|
|
|
|
|
|
{
|
|
|
|
|
|
// 从材质图获取偏移值,乘以方向符号
|
|
|
|
|
|
// 正值 = 向远处推(在屏幕上看起来更远)
|
|
|
|
|
|
// 负值 = 向近处拉
|
|
|
|
|
|
Output.Position.z += GetMaterialScreenSpaceDepthOffset(VertexParameters)
|
|
|
|
|
|
* DEPTH_OFFSET_SIGN;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 代码修改情况
|
|
|
|
|
|
|
|
|
|
|
|
| 文件路径 | 行号 | 修改类型 | 修改内容 |
|
|
|
|
|
|
|---------|------|---------|---------|
|
|
|
|
|
|
| `Shaders/Private/Common.ush` | L1803~L1810 | 新增 | `DEPTH_OFFSET_SIGN` 宏定义(根据 Z-buffer 方向) |
|
|
|
|
|
|
| `Shaders/Private/BasePassVertexShader.usf` | L158~L163 | 新增 | `Output.Position.z += offset * DEPTH_OFFSET_SIGN` |
|
|
|
|
|
|
| `Shaders/Private/DepthOnlyVertexShader.usf` | — | 新增 | 同上深度偏移应用 |
|
|
|
|
|
|
| `Shaders/Private/PositionOnlyDepthVertexShader.usf` | L49~L59 | 新增 | 同上 |
|
|
|
|
|
|
| `Shaders/Private/MaterialTemplate.ush` | L2255~L2260 | 新增 | `GetMaterialScreenSpaceDepthOffset` 材质访问函数 |
|