Files
UnrealEngineUWP/Engine/Shaders/Private/VirtualTextureMaterial.usf
jeremy moore 06c4ce76d4 Add option to sample landscape height per pixel when rendering to RVT.
When we do this we only need a single quad to render each landscape component subsection.
This reduces vertex shader cost which can sometimes dominate RVT rendering.
And it can remove the need to set difficult to understand landscape RVT LOD settings.
One downside is that bilinear texture map interpolation is different to triangle barycentric interpolation, so there is a subtle difference in extreme cases, but nothing visually bad. The difference will matter for VHM rendering though.

[CL 22968373 by jeremy moore in ue5-main branch]
2022-11-03 17:59:41 -04:00

148 lines
5.5 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
// Material shader for runtime virtual texture
#include "Common.ush"
#include "GammaCorrectionCommon.ush"
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
struct FVirtualTextureVSOutput
{
FVertexFactoryInterpolantsVSToPS FactoryInterpolants;
float4 Position : SV_POSITION;
};
#if VERTEXSHADER
void MainVS(
FVertexFactoryInput Input,
out FVirtualTextureVSOutput Output
)
{
ResolvedView = ResolveView();
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
#if VF_PER_PIXEL_HEIGHTMAP
if (HasVertexFactoryPerPixelHeight())
{
// Special case PerPixel Height for Landscape.
// Remove PerVertex Height and apply in Pixel Shader.
VFIntermediates.LocalPosition.z = 0;
}
#endif
float4 WorldPosition = VertexFactoryGetWorldPosition(Input, VFIntermediates);
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
{
float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPosition);
float4 ClipSpacePosition = mul(RasterizedWorldPosition, ResolvedView.TranslatedWorldToClip);
Output.Position = ClipSpacePosition;
}
Output.FactoryInterpolants = VertexFactoryGetInterpolantsVSToPS(Input, VFIntermediates, VertexParameters);
}
#endif // VERTEXSHADER
// Prepare for VirtualTextureUnpackNormal() in VirtualTextureCommon.h
float3 PackNormal( in float3 N )
{
return normalize(N) * (127.f / 255.f) + (127.f / 255.f);
}
// Prepare for VirtualTextureUnpackHeight() in VirtualTextureCommon.ush
// LWC_TODO: LWC scale/bias?
float PackWorldHeight( in FLWCScalar Height, in float2 PackHeightScaleBias )
{
return LWCSaturate(LWCAdd(LWCMultiply(Height, PackHeightScaleBias.x), PackHeightScaleBias.y));
}
void FPixelShaderInOut_MainPS(
in FVertexFactoryInterpolantsVSToPS Interpolants,
inout FPixelShaderIn In,
inout FPixelShaderOut Out )
{
ResolvedView = ResolveView();
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, In.SvPosition);
FPixelMaterialInputs PixelMaterialInputs;
CalcPixelMaterialInputs(MaterialParameters, PixelMaterialInputs);
float4 ScreenPosition = SvPositionToResolvedScreenPosition(In.SvPosition);
float3 TranslatedWorldPosition = SvPositionToResolvedTranslatedWorld(In.SvPosition);
#if VF_PER_PIXEL_HEIGHTMAP
if (HasVertexFactoryPerPixelHeight())
{
// Special case PerPixel Height for Landscape.
// Assumes Heightmap is camera aligned.
float3 LocalPositionDelta = float3(0, 0, GetVertexFactoryPerPixelHeight(Interpolants));
TranslatedWorldPosition += TransformLocalVectorToWorld(MaterialParameters, LocalPositionDelta);
}
#endif
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, In.SvPosition, ScreenPosition, In.bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
#if VIRTUAL_TEXTURE_OUTPUT
// Output is from a UMaterialExpressionRuntimeVirtualTextureOutput node
half3 BaseColor = GetVirtualTextureOutput0(MaterialParameters);
half Specular = GetVirtualTextureOutput1(MaterialParameters);
half Roughness = GetVirtualTextureOutput2(MaterialParameters);
half3 Normal = GetVirtualTextureOutput3(MaterialParameters);
FLWCScalar WorldHeight = GetVirtualTextureOutput4_LWC(MaterialParameters);
float Opacity = GetVirtualTextureOutput5(MaterialParameters);
float Mask = GetVirtualTextureOutput6(MaterialParameters);
#else
// Output is from standard material output attribute node
half3 BaseColor = GetMaterialBaseColor(PixelMaterialInputs);
half Specular = GetMaterialSpecular(PixelMaterialInputs);
half Roughness = GetMaterialRoughness(PixelMaterialInputs);
half3 Normal = MaterialParameters.WorldNormal;
FLWCScalar WorldHeight = LWCGetZ(MaterialParameters.AbsoluteWorldPosition);
float Opacity = GetMaterialOpacity(PixelMaterialInputs);
float Mask = 0.f;
#endif
// Apply debug shading
BaseColor = lerp(BaseColor, half3(In.SvPosition.xy * ResolvedView.ViewSizeAndInvSize.zw, 0), ResolvedView.RuntimeVirtualTextureDebugParams.x * 0.25);
#if defined(OUT_BASECOLOR)
Out.MRT[0] = float4(BaseColor, 1.f) * Opacity;
#elif defined(OUT_BASECOLOR_NORMAL_ROUGHNESS)
float3 PackedNormal = PackNormal(Normal);
//store basecolor in srgb space to improve image quality
Out.MRT[0] = float4(LinearToSrgb(BaseColor), 1.0) * Opacity;
//not enough channels for sign of normal z
Out.MRT[1] = float4(PackedNormal.x, Roughness, PackedNormal.y, 1.0) * Opacity;
#elif defined(OUT_BASECOLOR_NORMAL_SPECULAR)
float3 PackedNormal = PackNormal(Normal);
Out.MRT[0] = float4(BaseColor, 1.f) * Opacity;
Out.MRT[1] = float4(PackedNormal.xy, Mask, 1.f) * Opacity;
Out.MRT[2] = float4(Specular, Roughness, PackedNormal.z, 1.f) * Opacity;
#elif defined(OUT_WORLDHEIGHT)
float PackedHeight = PackWorldHeight(WorldHeight, ResolvedView.RuntimeVirtualTexturePackHeight);
Out.MRT[0] = float4(PackedHeight, 0, 0, 1);
#endif
}
#define PIXELSHADEROUTPUT_INTERPOLANTS 1
//#if defined(OUT_BASECOLOR)
//#define PIXELSHADEROUTPUT_MRT0 1
//#elif defined(OUT_BASECOLOR_NORMAL_SPECULAR)
//#define PIXELSHADEROUTPUT_MRT0 1
//#define PIXELSHADEROUTPUT_MRT1 1
//#define PIXELSHADEROUTPUT_MRT2 1
//#elif defined(OUT_WORLDHEIGHT)
//#define PIXELSHADEROUTPUT_MRT0 1
//#endif
// all PIXELSHADEROUTPUT_ and "void FPixelShaderInOut_MainPS()" need to be setup before this include
// this include generates the wrapper code to call MainPS(inout FPixelShaderOutput PixelShaderOutput)
#include "PixelShaderOutputCommon.ush"