BlueRoseNote/03-UnrealEngine/Rendering/Shader/Effect/Ue4 PostProcess 效果大小错误解决方法.md
2023-06-29 11:55:02 +08:00

3.5 KiB
Raw Blame History

早几年学习后处理Shader的时候遇到编辑器视口中的渲染结果与视口大小不匹配的问题

PS.该问题不会在使用SceneTexture节点制作的后处理效果材质中发生。但它不易于维护与修改。所以我花了些时间来解决这个问题。

问题成因与解决方法

可以看得出这个问题是因为ViewSize与BufferSize不一造成的。经过一系列测试使用ViewportUVToBufferUV()对UV坐标进行转换就可以解决问题该函数位于Common.h。

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用法大致如下

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)