262 lines
11 KiB
HLSL
262 lines
11 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#if SHADER_GBUFFER_PICKING
|
|
#define ALLOW_SSS_MATERIAL_OVERRIDE 0
|
|
#endif
|
|
|
|
#include "Common.ush"
|
|
#include "DeferredShadingCommon.ush"
|
|
#include "ScreenPass.ush"
|
|
|
|
#define SUPPORT_GBUFFER_FETCH (SHADING_PATH_DEFERRED && FEATURE_LEVEL >= FEATURE_LEVEL_SM5)
|
|
|
|
float2 Input_ExtentInverse;
|
|
|
|
Texture2D SceneColorTexture;
|
|
SamplerState SceneColorSampler;
|
|
|
|
Texture2D OriginalSceneColorTexture;
|
|
SamplerState OriginalSceneColorSampler;
|
|
|
|
#if SUPPORT_GBUFFER_FETCH
|
|
|
|
// 0: good, 1: heavy performance cost, 2:warning (very uncommon material), 3:error (impossible material attributes)
|
|
uint ComputeAdvice(FGBufferData BufferData, float3 OriginalSceneColor)
|
|
{
|
|
float SubsurfaceLum = 0;
|
|
const float OneThird = 1.0f / 3.0f;
|
|
|
|
FLATTEN if(BufferData.ShadingModelID != SHADINGMODELID_UNLIT)
|
|
{
|
|
FLATTEN if(BufferData.ShadingModelID == SHADINGMODELID_SUBSURFACE)
|
|
{
|
|
SubsurfaceLum = dot(OneThird.xxx, ExtractSubsurfaceColor(BufferData));
|
|
}
|
|
|
|
float DiffuseLum = dot(OneThird.xxx, BufferData.DiffuseColor);
|
|
float SpecularLum = dot(OneThird.xxx, BufferData.SpecularColor);
|
|
|
|
float TotalLum = DiffuseLum + SpecularLum + SubsurfaceLum;
|
|
|
|
float OriginalSceneColorLum = dot(OneThird.xxx, OriginalSceneColor);
|
|
|
|
FLATTEN if(TotalLum < 0.01f && OriginalSceneColorLum < 0.001f)
|
|
{
|
|
// The material is very dark.
|
|
// Such a material would be very unlikely (Maybe it can only be created in a lab).
|
|
return 2;
|
|
}
|
|
|
|
FLATTEN if(TotalLum > 1.2f)
|
|
{
|
|
// The diffuse and specular cause the material to emit more light than it receives.
|
|
return 3;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint ComputeAdvice(float2 UV)
|
|
{
|
|
// Ideally without GI as we want the emissive, we should do that later.
|
|
float3 OriginalSceneColor = Texture2DSample(OriginalSceneColorTexture, OriginalSceneColorSampler, UV).rgb;
|
|
FGBufferData BufferData = GetGBufferData(UV);
|
|
|
|
return ComputeAdvice(BufferData, OriginalSceneColor);
|
|
}
|
|
|
|
// to highlight areas that have unrealistic materials
|
|
void HighlightAdvice(inout float3 OutColor, float2 UV, uint2 PixelPos)
|
|
{
|
|
uint AdviceInner = ComputeAdvice(UV);
|
|
uint AdviceOuter = 0;
|
|
|
|
bool SpecialDotInArea = ((PixelPos.x + PixelPos.y) % 6) == 0 && ((PixelPos.x - PixelPos.y) % 6) == 0;
|
|
|
|
AdviceOuter = max(AdviceOuter, ComputeAdvice(UV + float2( 1, 0) * Input_ExtentInverse));
|
|
AdviceOuter = max(AdviceOuter, ComputeAdvice(UV + float2( 0, 1) * Input_ExtentInverse));
|
|
AdviceOuter = max(AdviceOuter, ComputeAdvice(UV + float2(-1, 0) * Input_ExtentInverse));
|
|
AdviceOuter = max(AdviceOuter, ComputeAdvice(UV + float2( 0, -1) * Input_ExtentInverse));
|
|
|
|
uint Advice = (AdviceInner == AdviceOuter && !SpecialDotInArea) ? 0 : AdviceOuter;
|
|
|
|
FLATTEN if(Advice)
|
|
{
|
|
FLATTEN if(Advice == 1)
|
|
{
|
|
// heavy shading cost
|
|
OutColor = float3(0, 0, 0.8f);
|
|
}
|
|
else
|
|
FLATTEN if(Advice == 2)
|
|
{
|
|
// warning
|
|
OutColor = float3(0.8f, 0.8f, 0);
|
|
}
|
|
else // if(Advice == 3)
|
|
{
|
|
// error
|
|
OutColor = float3(1, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void MainPS(noperspective float4 UVAndScreenPos : TEXCOORD0, float4 SvPosition : SV_POSITION, out float4 OutColor : SV_Target0)
|
|
{
|
|
float2 UV = UVAndScreenPos.xy;
|
|
int2 PixelPos = (uint2)SvPosition.xy;
|
|
|
|
// background is the scene color
|
|
OutColor = Texture2DSample(SceneColorTexture, SceneColorSampler, UV);
|
|
|
|
#if SUPPORT_GBUFFER_FETCH
|
|
HighlightAdvice(OutColor.rgb, UV, PixelPos);
|
|
#endif
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Debug
|
|
#if SHADER_GBUFFER_PICKING
|
|
|
|
#include "ShaderPrint.ush"
|
|
#include "SceneTextureParameters.ush"
|
|
#include "DeferredShadingCommon.ush"
|
|
#include "ShadingModels.ush"
|
|
#include "SubsurfaceProfileCommon.ush"
|
|
#include "PositionReconstructionCommon.ush"
|
|
|
|
void PrintShadingMode(inout FShaderPrintContext Ctx, uint In)
|
|
{
|
|
if (In == SHADINGMODELID_UNLIT) { Print(Ctx, TEXT("UNLIT"), FontRed); return; }
|
|
if (In == SHADINGMODELID_DEFAULT_LIT) { Print(Ctx, TEXT("DEFAULT_LIT"), FontRed); return; }
|
|
if (In == SHADINGMODELID_SUBSURFACE) { Print(Ctx, TEXT("SUBSURFACE"), FontRed); return; }
|
|
if (In == SHADINGMODELID_PREINTEGRATED_SKIN) { Print(Ctx, TEXT("PREINTEGRATED_SKIN"), FontRed); return; }
|
|
if (In == SHADINGMODELID_CLEAR_COAT) { Print(Ctx, TEXT("CLEAR_COAT"), FontRed); return; }
|
|
if (In == SHADINGMODELID_SUBSURFACE_PROFILE) { Print(Ctx, TEXT("SUBSURFACE_PROFILE"), FontRed); return; }
|
|
if (In == SHADINGMODELID_TWOSIDED_FOLIAGE) { Print(Ctx, TEXT("TWOSIDED_FOLIAGE"), FontRed); return; }
|
|
if (In == SHADINGMODELID_HAIR) { Print(Ctx, TEXT("HAIR"), FontRed); return; }
|
|
if (In == SHADINGMODELID_CLOTH) { Print(Ctx, TEXT("CLOTH"), FontRed); return; }
|
|
if (In == SHADINGMODELID_EYE) { Print(Ctx, TEXT("EYE"), FontRed); return; }
|
|
if (In == SHADINGMODELID_SINGLELAYERWATER) { Print(Ctx, TEXT("SINGLELAYERWATER"), FontRed); return; }
|
|
if (In == SHADINGMODELID_THIN_TRANSLUCENT) { Print(Ctx, TEXT("THIN_TRANSLUCENT"), FontRed); return; }
|
|
if (In == SHADINGMODELID_SUBSTRATE) { Print(Ctx, TEXT("SUBSTRATE"), FontRed); return; }
|
|
if (In == SHADINGMODELID_NUM) { Print(Ctx, TEXT("NUM"), FontRed); return; }
|
|
if (In == SHADINGMODELID_MASK) { Print(Ctx, TEXT("MASK"), FontRed); return; }
|
|
}
|
|
|
|
void Newline(inout FShaderPrintContext Ctx, inout float2 MaxRect)
|
|
{
|
|
MaxRect.x = max(MaxRect.x, Ctx.Pos.x);
|
|
MaxRect.y = Ctx.Pos.y;
|
|
Newline(Ctx);
|
|
}
|
|
|
|
void PrintBackgroundRect(inout FShaderPrintContext Ctx, float2 StartRect, float2 EndRect)
|
|
{
|
|
const float4 RectBackgroundColor = float4(1, 1, 1, 0.25f);
|
|
AddFilledQuadSS(
|
|
(StartRect - ShaderPrintData.FontSize) * ShaderPrintData.Resolution,
|
|
(EndRect + ShaderPrintData.FontSize) * ShaderPrintData.Resolution,
|
|
RectBackgroundColor);
|
|
}
|
|
|
|
[numthreads(1, 1, 1)]
|
|
void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|
{
|
|
#if (!SUBSTRATE_ENABLED || SUBTRATE_GBUFFER_FORMAT==0) && SUPPORT_GBUFFER_FETCH
|
|
// Draw stats
|
|
if (all(DispatchThreadId == 0))
|
|
{
|
|
FShaderPrintContext Ctx = InitShaderPrintContext(true, uint2(50, 50));
|
|
const FScreenSpaceData ScreenSpaceData = GetScreenSpaceDataUint(ShaderPrintData.CursorCoord, true);
|
|
const FGBufferData Data = ScreenSpaceData.GBuffer;
|
|
|
|
float2 RectMin = Ctx.Pos;
|
|
float2 RectMax = Ctx.StartPos;
|
|
|
|
RectMin = Ctx.Pos;
|
|
Print(Ctx, TEXT("Global"), FontOrange);Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Diffuse Color : "), FontWhite); Print(Ctx, Data.DiffuseColor, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Specular Color : "), FontWhite); Print(Ctx, Data.SpecularColor, FontYellow); Newline(Ctx, RectMax);
|
|
PrintBackgroundRect(Ctx, RectMin, RectMax);
|
|
Newline(Ctx);
|
|
|
|
RectMin = Ctx.Pos;
|
|
Print(Ctx, TEXT("Tangent basis"), FontOrange);Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("World Normal : "), FontWhite); Print(Ctx, Data.WorldNormal, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("World Tangent : "), FontWhite); Print(Ctx, Data.WorldTangent, FontYellow); Newline(Ctx, RectMax);
|
|
PrintBackgroundRect(Ctx, RectMin, RectMax);
|
|
Newline(Ctx);
|
|
|
|
RectMin = Ctx.Pos;
|
|
Print(Ctx, TEXT("Common"), FontOrange);Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("BaseColor : "), FontWhite); Print(Ctx, Data.BaseColor, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Metallic : "), FontWhite); Print(Ctx, Data.Metallic, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Specular : "), FontWhite); Print(Ctx, Data.Specular, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Roughness : "), FontWhite); Print(Ctx, Data.Roughness, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Anisotropy : "), FontWhite); Print(Ctx, Data.Anisotropy, FontYellow); Newline(Ctx, RectMax);
|
|
PrintBackgroundRect(Ctx, RectMin, RectMax);
|
|
Newline(Ctx);
|
|
|
|
RectMin = Ctx.Pos;
|
|
Print(Ctx, TEXT("Occlusion / Ind. Lighting"), FontOrange);Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Generic AO : "), FontWhite); Print(Ctx, Data.GenericAO, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("GBuffer AO : "), FontWhite); Print(Ctx, Data.GBufferAO, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Ind. Sample Occ. : "), FontWhite); Print(Ctx, Data.DiffuseIndirectSampleOcclusion, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Ind. Irradiance : "), FontWhite); Print(Ctx, Data.IndirectIrradiance, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Prec.Shadow Factor: "), FontWhite); Print(Ctx, Data.PrecomputedShadowFactors, FontYellow); Newline(Ctx, RectMax);
|
|
PrintBackgroundRect(Ctx, RectMin, RectMax);
|
|
Newline(Ctx);
|
|
|
|
RectMin = Ctx.Pos;
|
|
Print(Ctx, TEXT("Custom"), FontOrange);Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Shading Model ID : "), FontWhite); PrintShadingMode(Ctx, Data.ShadingModelID); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Custom Data : "), FontWhite); Print(Ctx, Data.CustomData, FontYellow); Newline(Ctx, RectMax);
|
|
if (Data.ShadingModelID == SHADINGMODELID_CLEAR_COAT)
|
|
{
|
|
Print(Ctx, TEXT("Clear Coat : "), FontWhite); Print(Ctx, Data.CustomData.x, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Clear Coat Roughn.: "), FontWhite); Print(Ctx, Data.CustomData.y, FontYellow); Newline(Ctx, RectMax);
|
|
}
|
|
else if (Data.ShadingModelID == SHADINGMODELID_CLOTH)
|
|
{
|
|
Print(Ctx, TEXT("Fuzz Color : "), FontWhite); Print(Ctx, Data.CustomData.xyz, FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Fuzz Amount : "), FontWhite); Print(Ctx, Data.CustomData.a, FontYellow); Newline(Ctx, RectMax);
|
|
}
|
|
else if (Data.ShadingModelID == SHADINGMODELID_SUBSURFACE || Data.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN || Data.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
|
|
{
|
|
Print(Ctx, TEXT("Subsurface Color : "), FontWhite); Print(Ctx, ExtractSubsurfaceColor(Data), FontYellow); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("Opacity : "), FontWhite); Print(Ctx, Data.CustomData.a, FontYellow); Newline(Ctx, RectMax);
|
|
}
|
|
else if (Data.ShadingModelID == SHADINGMODELID_SUBSURFACE_PROFILE)
|
|
{
|
|
const uint SSSProfileID = ExtractSubsurfaceProfileInt(Data.CustomData.x);
|
|
const half Opacity = Data.CustomData.a;
|
|
float LobeMix = 0;
|
|
float Lobe0Roughness = 0;
|
|
float Lobe1Roughness = 0;
|
|
GetProfileDualSpecular(SSSProfileID, Data.Roughness, Opacity, Lobe0Roughness, Lobe1Roughness, LobeMix);
|
|
|
|
Print(Ctx, TEXT("SSS Profil ID : "), FontWhite); Print(Ctx, SSSProfileID); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("SSS Lobe Mix : "), FontWhite); Print(Ctx, LobeMix); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("SSS Roughness0 : "), FontWhite); Print(Ctx, Lobe0Roughness); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("SSS Roughness1 : "), FontWhite); Print(Ctx, Lobe1Roughness); Newline(Ctx, RectMax);
|
|
Print(Ctx, TEXT("SSS SpecColor : "), FontWhite); Print(Ctx, Data.SpecularColor); Newline(Ctx, RectMax);
|
|
|
|
}
|
|
PrintBackgroundRect(Ctx, RectMin, RectMax);
|
|
Newline(Ctx);
|
|
|
|
// Draw tangent vector (strands)
|
|
{
|
|
const float2 UV = (ShaderPrintData.CursorCoord + 0.5f) * View.BufferSizeAndInvSize.zw;
|
|
const float3 WorldPosition = ReconstructTranslatedWorldPositionFromDepth(UV, Data.Depth);
|
|
AddLineTWS(WorldPosition, WorldPosition + Data.WorldNormal, ColorRed, ColorYellow);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif // SHADER_GBUFFER_PICKING |