Files
UnrealEngine/Engine/Shaders/Private/Tools/VisualizeTexture.usf
2025-05-18 13:04:45 +08:00

223 lines
7.8 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VisualizeTexture.usf: VisualizeTexture shader
=============================================================================*/
#include "../Common.ush"
#define INPUT_MAPPING_COLOR 0
#define INPUT_MAPPING_DEPTH 1
#define INPUT_MAPPING_SHADOW 2
// to visualize the content of a texture to the screen, useful for debugging
// use "VisualizeTexture" in the console to activate
Texture2D VisualizeTexture2D;
SamplerState VisualizeTexture2DSampler;
Texture3D VisualizeTexture3D;
SamplerState VisualizeTexture3DSampler;
TextureCube VisualizeTextureCube;
SamplerState VisualizeTextureCubeSampler;
//default Texture2D type is <float4>, which won't read the X28_G8UINT format properly.
Texture2D<uint4> VisualizeDepthStencil;
Texture2D<uint> VisualizeUINT8Texture2D;
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
Texture2DMS<float4> VisualizeTexture2DMS;
TextureCubeArray VisualizeTextureCubeArray;
SamplerState VisualizeTextureCubeArraySampler;
#endif
// [0]: r:RGBAdd, g:SingleChannelMul, b:Add, a:FracScale
// [1]: r:BlinkState=0/1, g:Frac when 0, saturate when 1, b:array index, a:custom mip
// [2]: r:0=normal 1=depth, 2=shadow depth, g:unwrapcubemap, b:singlechannel(0-3), a:unused
float4 VisualizeParam[3];
// x, y (0 for 2D textures), z(only !=0 if 3d texture), w unused
float3 TextureExtent;
void VisualizeTexturePS(
float4 SvPosition : SV_POSITION,
out float4 OutColor : SV_Target0)
{
float2 UV = SvPosition.xy / TextureExtent.xy;
// Longitude Latitude unwrapping
float3 SpherePos;
{
float2 Angles = float2(2 * PI * (UV.x + 0.5f), PI * (1 - UV.y));
float s = sin(Angles.y);
SpherePos = float3(s * sin(Angles.x), -s * cos(Angles.x), -cos(Angles.y));
}
// Pixel based cube map unwrapping -- assumes 4x3 aspect ratio. Produces a seamless panorama in the middle, connected to adjacent sky / floor faces.
float3 CubePixelPos;
{
float2 LerpCoords = UV * float2(4.0, 3.0);
float FaceCoords[3] =
{
frac(LerpCoords.x) * 2.0 - 1.0,
frac(LerpCoords.y) * 2.0 - 1.0,
1.0
};
// Table selecting a UV coordinate or "1" for each of the XYZ axes using a hex digit, preceded by a "0" or "2" to specify whether the axis should be negated.
uint FaceUVMappingTable[12] =
{
0x010002, // Positive Z faces (different rotations to line up with panoramic neighbor below)
0x200102,
0x212002,
0x002102,
0x020021, // Positive X
0x200221, // Positive Y
0x222021, // Negative X
0x002221, // Negative Y
0x210022, // Negative Z faces (different rotations to line up with panoramic neighbor above)
0x202122,
0x012022,
0x000122,
};
uint FaceUVMapping = FaceUVMappingTable[floor(LerpCoords.x) + floor(LerpCoords.y) * 4.0];
CubePixelPos = float3(
FaceCoords[(FaceUVMapping >> 16) & 0xf] * (1.0 - ((float) ((FaceUVMapping >> 20) & 0xf))),
FaceCoords[(FaceUVMapping >> 8) & 0xf] * (1.0 - ((float) ((FaceUVMapping >> 12) & 0xf))),
FaceCoords[(FaceUVMapping >> 0) & 0xf] * (1.0 - ((float) ((FaceUVMapping >> 4) & 0xf))));
}
// volume texture unwrapping
float3 VolumePos;
{
uint LayerCount = TextureExtent.z;
uint LayerUCount = (uint)sqrt(TextureExtent.z);
uint LayerVCount = LayerCount / LayerUCount;
uint LayerUId = (uint)(UV.x * LayerUCount);
uint LayerVId = (uint)(UV.y * LayerVCount);
uint LayerId = LayerUId + LayerUCount * LayerVId;
VolumePos.z = LayerId / (TextureExtent.z - 1);
VolumePos.x = frac(UV.x * LayerUCount);
VolumePos.y = frac(UV.y * LayerVCount);
}
float MipLevel = VisualizeParam[1].a;
float ArrayIndex = VisualizeParam[1].b;
#if TEXTURE_TYPE == 0
// Select pixel accurate map coordinates if the visualization is 4x3 aspect ratio
float4 TexLookup = TextureCubeSampleLevel(VisualizeTextureCube, VisualizeTextureCubeSampler, TextureExtent.x*0.75 == TextureExtent.y ? CubePixelPos : SpherePos, MipLevel);
#elif TEXTURE_TYPE == 2 || TEXTURE_TYPE == 6
float4 TexLookup = Texture2DSampleLevel(VisualizeTexture2D, VisualizeTexture2DSampler, UV, MipLevel);
#elif TEXTURE_TYPE == 3
#if FEATURE_LEVEL < FEATURE_LEVEL_SM4
float4 TexLookup = float4(1.0f, 0.0f, 1.0f, 1.0f);
#else
float4 TexLookup = Texture3DSampleLevel(VisualizeTexture3D, VisualizeTexture3DSampler, VolumePos, MipLevel);
#endif
#elif TEXTURE_TYPE == 4
#if FEATURE_LEVEL < FEATURE_LEVEL_SM5
float4 TexLookup = float4(1.0f, 0.0f, 1.0f, 1.0f);
#else
float4 TexLookup = TextureCubeArraySampleLevel(VisualizeTextureCubeArray, VisualizeTextureCubeArraySampler, SpherePos, ArrayIndex, MipLevel);
#endif
#elif TEXTURE_TYPE == 5
float4 TexLookup = float4(1,1,0,0); // yellow, not yet supported
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
TexLookup = VisualizeTexture2DMS.Load(int2(UV * TextureExtent.xy), 0);
#endif
#elif TEXTURE_TYPE == 7
float IntTexLookup = float(VisualizeUINT8Texture2D.Load(int3(UV * TextureExtent.xy, 0)));
float4 TexLookup = IntTexLookup.xxxx;
#elif TEXTURE_TYPE == 8
// 32 bits int, rather arbitrarily visualized as spread over the rgba channels
int IntTexLookup = VisualizeUINT8Texture2D.Load(int3(UV * TextureExtent.xy, 0));
float4 TexLookup;
TexLookup.r = IntTexLookup & 0xFF;
TexLookup.g = (IntTexLookup >> 8) & 0xFF;
TexLookup.b = (IntTexLookup >> 16) & 0xFF;
TexLookup.a = (IntTexLookup >> 24) & 0xFF;
#endif
uint InputValueMapping = (uint)VisualizeParam[2].r;
if(InputValueMapping != INPUT_MAPPING_COLOR)
{
float Depth = TexLookup.r;
if (InputValueMapping == INPUT_MAPPING_DEPTH)
{
// current z buffer is negated (1 is near, 0 is far)
#if HAS_INVERTED_Z_BUFFER
Depth = 1 - Depth;
#endif
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
// map depth to nice colors
float Scale = 64.0; // This 64 looks like a hardware limit.
Depth = (exp2(Depth * Scale) - 1.0) * (1.0 / (exp2(Scale) - 1.0));
Depth *= Depth;
Depth *= Depth;
float Value = Depth * Depth;
TexLookup = float4(pow(Value, 0.25f), pow(Value, 1), pow(Value, 4), 0);
}
else if (InputValueMapping == INPUT_MAPPING_SHADOW)
{
// linearly blend from White (near) to Teal (far).
float3 TealBlue = float3(54.f/255.f, 117.f/255.f, 136.f/255.f);
float3 White = float3(1.0f, 1.0f, 1.0f);
TexLookup.rgb = lerp(White, TealBlue, Depth);
}
#if TEXTURE_TYPE == 6
// inside #ifdef to avoid D3DDebug error:
// The resource return type for component 0 declared in the shader code (UINT) is not compatible with the Shader Resource View format bound to slot 1 of the Pixel Shader unit (UNORM). This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #361: DEVICE_DRAW_RESOURCE_RETURN_TYPE_MISMATCH]
float fStencil = VisualizeDepthStencil.Load(int3(UV * TextureExtent.xy, 0)).g;
fStencil /= 255.0f;
TexLookup.a = fStencil;
#endif
#else
}
TexLookup.r = Depth;
#endif
}
float4 RGBAMask = 0;
int SingleChannel = (int)VisualizeParam[2].z;
switch (SingleChannel)
{
case 0: RGBAMask = float4(1,0,0,0); break;
case 1: RGBAMask = float4(0,1,0,0); break;
case 2: RGBAMask = float4(0,0,1,0); break;
case 3: RGBAMask = float4(0,0,0,1); break;
default: RGBAMask = float4(0,0,0,0); break;
}
float Add = dot( TexLookup, RGBAMask ) * VisualizeParam[0].y + VisualizeParam[0].z;
OutColor.rgb = TexLookup.rgb * VisualizeParam[0].xxx + Add.xxx;
float3 ScaledColor = OutColor.rgb * VisualizeParam[0].w;
float3 FracOutColor = lerp(ScaledColor, saturate(ScaledColor), VisualizeParam[1].y);
float3 AlternateColor = FracOutColor;
// blink red if <0
if(OutColor.r < 0.0f || OutColor.g < 0.0f || OutColor.b < 0.0f)
{
AlternateColor = float3(1, 0, 0);
}
// blink blue if not finite
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
if (isfinite(OutColor.rgb).x == false)
{
AlternateColor = float3(0, 0, 1);
}
#endif
OutColor.rgb = lerp(FracOutColor, AlternateColor, VisualizeParam[1].x);
OutColor.a = 0;
}