Files
BlueRoseNote/03-UnrealEngine/卡通渲染相关资料/渲染功能/ARC/Rendering/正交投影混合.md

137 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 正交投影混合
date: 2026-05-03 00:00:00
excerpt: OrthoBlend 透视校正技术,实现动画风格的透视扁平化效果
tags:
- ARC
- Rendering
- VertexFactory
- Toon
rating: ⭐
---
# 正交投影混合
返回 [[Rendering]]
## 概述
正交投影混合OrthoBlend是 ARC 引擎实现**动画风格透视扁平化**的核心技术。在动画/格斗游戏中,角色需要减少透视畸变以保持美术控制的外观,这通过在透视投影和正交投影之间进行混合来实现。
引擎提供了两个版本:
- **V1** (`USES_ORTHO_BLEND_POSITION`):简单的 X 轴正交混合
- **V2** (`USES_ORTHO_BLEND_POSITION2`):基于物体中心距离的全透视校正("Purse correction"
## 实现细节
### V1X 轴正交混合
`Common.ush` 中定义:
```hlsl
float4 GetOrthoBlendPosition(
float4 WorldPosition,
float4x4 ViewProjectionMatrix,
float weight)
{
float4 ScreenPosition = mul(WorldPosition, ViewProjectionMatrix);
// 计算正交投影的 X 坐标
float OrthoScreenPositionX = dot(
ResolvedView.OrthoViewProjectionX, WorldPosition);
// 在透视和正交之间混合 X 轴
ScreenPosition.x = lerp(
ScreenPosition.x,
OrthoScreenPositionX * ScreenPosition.w,
weight * ResolvedView.OrthoBlendParameter);
return ScreenPosition;
}
```
`OrthoBlendParameter` 从 C++ 端通过 `ViewUniformShaderParameters` 传入,全局控制混合强度。`weight` 来自材质属性 `MP_OrthoBlendWeight`,允许逐材质控制。
### V2全透视校正
```hlsl
float4 GetOrthoBlendPosition2(
float4 WorldPosition,
float4x4 ViewProjectionMatrix,
float weight,
float3 ObjWorldPosition)
{
// 计算顶点相对于物体中心的偏移
float3 offset = WorldPosition.xyz - ObjWorldPosition.xyz;
// 物体中心到相机的距离(沿视线方向)
float dist = abs(dot(
ObjWorldPosition.xyz - ResolvedView.WorldCameraOrigin.xyz,
ResolvedView.ViewForward.xyz));
// 将顶点"拍平"到与物体中心相同距离的平面
float3 origin = ResolvedView.WorldCameraOrigin.xyz
+ ResolvedView.ViewForward.xyz * dist;
WorldPosition.xy = origin.xy + offset.xy;
// ... 后续投影变换
}
```
V2 的原理:将所有顶点投影到与物体中心等距的平面上,消除了前后肢体因透视导致的大小差异。
### 全 VertexFactory 覆盖
两个版本均在所有顶点着色器中实现:
| 顶点着色器 | 文件 |
|-----------|------|
| BasePass | `BasePassVertexShader.usf` |
| DepthOnly | `DepthOnlyVertexShader.usf` |
| PositionOnlyDepth | `PositionOnlyDepthVertexShader.usf` |
| HitProxy | `HitProxyVertexShader.usf` |
| DebugViewMode | `DebugViewModeVertexShader.usf` |
覆盖的 VertexFactory
- `LocalVertexFactory.ush`
- `GpuSkinVertexFactory.ush`
- `LandscapeVertexFactory.ush`
- `MeshParticleVertexFactory.ush`
- 所有 Particle VertexFactory
## 材质属性
通过 `MP_OrthoBlendWeight` 材质属性控制每个材质的混合权重:
```cpp
// MaterialTemplate.ush
float GetMaterialOrthoBlendWeight(FMaterialVertexParameters Parameters)
{
%s; // 由材质图生成
}
```
## C++ 端支持
- `SceneRendering.cpp`:计算 `OrthoBlendParameter` 并写入 ViewUniformBuffer
- `SceneTypes.h``MP_OrthoBlendWeight` 枚举值
- `HLSLMaterialTranslator.cpp`:材质编译支持
## 关联文档
- [[自定义材质属性]] — `MP_OrthoBlendWeight` 的定义
- [[屏幕对齐网格]] — 另一种屏幕空间变换方案
- [[局部位置缩放]] — 局部空间的顶点变换
## 修改文件列表
| 文件 | 修改类型 |
|------|---------|
| `Shaders/Private/Common.ush` | 新增 `GetOrthoBlendPosition` / `GetOrthoBlendPosition2` |
| `Shaders/Private/BasePassVertexShader.usf` | 调用正交混合 |
| `Shaders/Private/DepthOnlyVertexShader.usf` | 调用正交混合 |
| `Shaders/Private/PositionOnlyDepthVertexShader.usf` | 调用正交混合 |
| `Shaders/Private/HitProxyVertexShader.usf` | 调用正交混合 |
| `Shaders/Private/DebugViewModeVertexShader.usf` | 调用正交混合 |
| 所有 VertexFactory `.ush` | 提供 ObjWorldPosition |