// 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 , which won't read the X28_G8UINT format properly. Texture2D VisualizeDepthStencil; Texture2D VisualizeUINT8Texture2D; #if FEATURE_LEVEL >= FEATURE_LEVEL_SM5 Texture2DMS 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; }