BlueRoseNote/03-UnrealEngine/Rendering/Shader/Effect/Ue4 PostProcess 效果大小错误解决方法.md

57 lines
3.5 KiB
Markdown
Raw Normal View History

2023-06-29 11:55:02 +08:00
早几年学习后处理Shader的时候遇到编辑器视口中的渲染结果与视口大小不匹配的问题
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/PostProcessMaterialError.png)
PS.该问题不会在使用SceneTexture节点制作的后处理效果材质中发生。但它不易于维护与修改。所以我花了些时间来解决这个问题。
## 问题成因与解决方法
可以看得出这个问题是因为ViewSize与BufferSize不一造成的。经过一系列测试使用ViewportUVToBufferUV()对UV坐标进行转换就可以解决问题该函数位于Common.h。
```c#
float2 ViewportUVToBufferUV(float2 ViewportUV)
{
float2 PixelPos = ViewportUV * View.ViewSizeAndInvSize.xy;
return (PixelPos + View.ViewRectMin.xy) * View.BufferSizeAndInvSize.zw;
}
```
ScreenUV使用GetViewportUV(Parameters)来获取Step为ResolvedView.ViewSizeAndInvSize.zw用法大致如下
```c#
float GetDepthTestWeight(float2 ScreenUV,float Stepx, float Stepy, float3x3 KernelX, float3x3 KernelY,float DepthTestThreshold)
{
float3x3 image;
float CurrentPixelDepth=GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV)).GBuffer.Depth;
image = float3x3(
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(-Stepx,Stepy))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(0,Stepy))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(Stepx,Stepy))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(-Stepx,0))).GBuffer.Depth-CurrentPixelDepth),
0,
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(Stepx,0))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(-Stepx,-Stepy))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(0,-Stepy))).GBuffer.Depth-CurrentPixelDepth),
length(GetScreenSpaceData(ViewportUVToBufferUV(ScreenUV + float2(Stepx,-Stepy))).GBuffer.Depth-CurrentPixelDepth)
);
UNROLL
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// image[i][j] = image[i][j] > CurrentPixelDepth * DepthTestThreshold ? 1 : 0;
image[i][j] = saturate(image[i][j] / (CurrentPixelDepth * DepthTestThreshold));
}
}
float2 StrokeWeight;
StrokeWeight.x = convolve(KernelX, image);
StrokeWeight.y = convolve(KernelY, image);
return length(StrokeWeight);
}
```
当然如果是直接在渲染管线里添加渲染Pass的方式来实现后处理效果那也不会出现这个问题因为每帧都会按照View大小创建新的buffer所以不会出现这个问题。
## 材质编辑器的相关大小节点。
- ScreenPosition代码为GetViewportUV(FMaterialVertexParameters Parameters)。
- ViewSize可视视口的大小。代码为View.ViewSizeAndInvSize.xyzw为倒数值。
- MF_ScreenResolution具体有VisibleResolution(就是ViewSize节点输出结果) 与BufferResolution(ViewProperty的RenderTargetSize)
- SceneTexelSize场景纹素大小这是一个float2的值对应着UVuvuv均为正数。
- MF_ScreenAlignedPixelToPixelUVsRenderTargetSize / TextureSize。 其中TextureSize可以是ViewSize。可以用来实现一些修改View大小后后处理尺寸不变得效果。
- 后处理节点的SizeClampSceneTextureUV(ViewportUVToSceneTextureUVSceneTextureId)