Shader "Hidden/Universal/HDRDebugView" { HLSLINCLUDE #pragma target 4.5 #pragma editor_sync_compilation #pragma multi_compile_fragment _ DEBUG_DISPLAY #pragma multi_compile_local_fragment _ HDR_ENCODING #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ACES.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/HDROutput.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/DebuggingFullscreen.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Debug.hlsl" #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" TEXTURE2D_X(_DebugScreenTexture); TEXTURE2D_X(_OverlayUITexture); TEXTURE2D_X(_SourceTexture); TEXTURE2D(_xyBuffer); int _DebugHDRMode; float4 _HDRDebugParams; // xy: brightness min/max, z: paper white brightness, w: color primairies #define _MinNits _HDRDebugParams.x #define _MaxNits _HDRDebugParams.y #define _PaperWhite _HDRDebugParams.z float2 RGBtoxy(float3 rgb) { float3 XYZ = RotateOutputSpaceToXYZ(rgb); return XYZtoxy(XYZ); } float3 uvToGamut(float2 uv) { float3 xyzColor = xyYtoXYZ(float3(uv.x, uv.y, 1.0f)); float3 linearRGB = RotateXYZToOutputSpace(xyzColor); float scale = 1.0f / length(linearRGB); float desat = dot(linearRGB, 0.333f); scale *= 1.0 + exp(-length(linearRGB - desat) * 2.0f) * 0.5f; linearRGB *= scale; return linearRGB; } bool IsInCIExyMapping(float2 xy) { return SAMPLE_TEXTURE2D_LOD(_xyBuffer, sampler_PointClamp, xy, 0.0).x != 0; } float3 ValuesAbovePaperWhite(half4 color, float2 uv) { float maxC = max(color.x, max(color.y, color.z)); float t = (maxC - _PaperWhite) / (_MaxNits - _PaperWhite); if (maxC > _PaperWhite) { return lerp(float3(_PaperWhite, _PaperWhite, 0), float3(_PaperWhite, 0, 0), saturate(t)); } else { return Luminance(color).xxx; } } void RenderDebugHDR(half4 color, float2 uv, inout half4 debugColor) { if (_DebugHDRMode == HDRDEBUGMODE_VALUES_ABOVE_PAPER_WHITE) { debugColor.xyz = ValuesAbovePaperWhite(color, uv); return; } int displayClip = (_DebugHDRMode == HDRDEBUGMODE_GAMUT_CLIP); int gamutPiPSize = _ScreenSize.x / 3.0f; float2 r_2020 = float2(0.708, 0.292); float2 g_2020 = float2(0.170, 0.797); float2 b_2020 = float2(0.131, 0.046); float2 r_709 = float2(0.64, 0.33); float2 g_709 = float2(0.3, 0.6); float2 b_709 = float2(0.15, 0.06); float2 pos = uv * _ScreenSize.xy; float lineThickness = 0.002; float2 xy = RGBtoxy(color.rgb); float3 rec2020Color = float3(_PaperWhite, 0, 0); float3 rec2020ColorDesat = float3(3.0, 0.5, 0.5); float3 rec709Color = float3(0, _PaperWhite, 0); float3 rec709ColorDesat = float3(0.4, 0.6, 0.4); //Display Gamut Clip Scene colour conversion if (displayClip) { float clipAlpha = 0.2f; if (IsPointInTriangle(xy, r_709, g_709, b_709)) { color.rgb = (color.rgb * (1 - clipAlpha) + clipAlpha * rec709Color); } else if (IsPointInTriangle(xy, r_2020, g_2020, b_2020)) { color.rgb = (color.rgb * (1 - clipAlpha) + clipAlpha * rec2020Color); } } float4 gamutColor = 0; if (all(pos < gamutPiPSize)) { float2 uv = pos / gamutPiPSize; // scale-down uv float4 lineColor = DrawSegment(uv, g_709, b_709, lineThickness, float3(0, 0, 0)) + DrawSegment(uv, b_709, r_709, lineThickness, float3(0, 0, 0)) + DrawSegment(uv, r_709, g_709, lineThickness, float3(0, 0, 0)) + DrawSegment(uv, g_2020, b_2020, lineThickness, float3(0, 0, 0)) + DrawSegment(uv, b_2020, r_2020, lineThickness, float3(0, 0, 0)) + DrawSegment(uv, r_2020, g_2020, lineThickness, float3(0, 0, 0)); float3 linearRGB = 0; bool pointInRec709 = true; if (IsPointInTriangle(uv, r_2020, g_2020, b_2020)) { linearRGB = uvToGamut(uv); if (displayClip) { if (IsPointInTriangle(uv, r_709, g_709, b_709)) { linearRGB.rgb = rec709ColorDesat; } else { pointInRec709 = false; linearRGB.rgb = rec2020ColorDesat; } } gamutColor.a = max(lineColor.a, 0.15); gamutColor.rgb = linearRGB * _PaperWhite; if (IsInCIExyMapping(uv)) { gamutColor.a = 1; if (displayClip) gamutColor.rgb = pointInRec709 ? rec709Color : rec2020Color; } } gamutColor.rgb = gamutColor.rgb * (1.0f - lineColor.a) + lineColor.rgb; } debugColor.rgb = gamutColor.rgb * gamutColor.a + color.rgb * (1 - gamutColor.a); } ENDHLSL SubShader { Tags{ "RenderPipeline" = "UniversalPipeline" } Pass { ZWrite Off ZTest Always ZClip Off Blend Off Cull Off HLSLPROGRAM #pragma vertex Vert #pragma fragment Frag RW_TEXTURE2D(float, _xyBufferRW); #define _SizePerDim _HDRDebugParams.xy half4 Frag(Varyings input) : SV_Target { float4 col = SAMPLE_TEXTURE2D_X(_DebugScreenTexture, sampler_PointClamp, input.texcoord); float2 xy = (RGBtoxy(col.rgb)); _xyBufferRW[(xy * _SizePerDim)] = 1; return col; } ENDHLSL } Pass { ZWrite Off ZTest Always ZClip Off Blend Off Cull Off HLSLPROGRAM #pragma vertex Vert #pragma fragment Frag half4 Frag(Varyings input) : SV_Target { float4 outCol = 0; float2 uv = input.texcoord; half4 col = SAMPLE_TEXTURE2D_X(_SourceTexture, sampler_PointClamp, uv); half4 outColor = 0; RenderDebugHDR(col, uv, outColor); #if defined(HDR_ENCODING) float4 uiSample = SAMPLE_TEXTURE2D_X(_OverlayUITexture, sampler_PointClamp, input.texcoord); outColor.rgb = SceneUIComposition(uiSample, outColor.rgb, _PaperWhite, _MaxNits); outColor.rgb = OETF(outColor.rgb); #endif #if defined(DEBUG_DISPLAY) half4 debugColor = 0; if (CanDebugOverrideOutputColor(outColor, uv, debugColor)) { return debugColor; } #endif return outColor; } ENDHLSL } } }