3.5 KiB
3.5 KiB
早几年学习后处理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.xy,zw为倒数值。
- MF_ScreenResolution:具体有VisibleResolution(就是ViewSize节点输出结果) 与BufferResolution(ViewProperty的RenderTargetSize)
- SceneTexelSize(场景纹素大小):这是一个float2的值,对应着UV,(u,v),uv均为正数。
- MF_ScreenAlignedPixelToPixelUVs:RenderTargetSize / TextureSize。 其中TextureSize可以是ViewSize。可以用来实现一些修改View大小后,后处理尺寸不变得效果。
- 后处理节点的Size:ClampSceneTextureUV(ViewportUVToSceneTextureUV,SceneTextureId)