Skip to content

Commit

Permalink
Fixed imgui colors (close #17)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Jun 9, 2023
1 parent 87203b8 commit ea06955
Showing 1 changed file with 196 additions and 18 deletions.
214 changes: 196 additions & 18 deletions Imgui/src/ImGuiDiligentRenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 Diligent Graphics LLC
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -30,11 +30,50 @@
#include "RenderDevice.h"
#include "DeviceContext.h"
#include "MapHelper.hpp"
#include "GraphicsAccessories.hpp"

namespace Diligent
{

static const char* VertexShaderHLSL = R"(
// Intentionally or not, all imgui examples render everything in sRGB space.
// Whether imgui expected it or not, the display engine then transforms colors to linear space
// https://stackoverflow.com/a/66401423/4347276
// We, however, (correctly) render everything in linear space letting the GPU to transform colors to sRGB,
// so that the display engine then properly shows them.
//
// As a result, there is a problem with alpha-blending: imgui performs blending directly in gamma-space, and
// gamma-to-linear conversion is done by the display engine:
//
// Px_im = GammaToLinear(Src * A + Dst * (1 - A)) (1)
//
// If we only convert imgui colors from sRGB to linear, we will be performing the following (normally)
// correct blending:
//
// Px_dg = GammaToLinear(Src) * A + GammaToLinear(Dst) * (1 - A) (2)
//
// However in case of imgui, this produces significantly different colors. Consider black background (Dst = 0):
//
// Px_im = GammaToLinear(Src * A)
// Px_dg = GammaToLinear(Src) * A
//
// We use the following equation that approximates (1):
//
// Px_dg = GammaToLinear(Src * A) + GammaToLinear(Dst) * GammaToLinear(1 - A) (3)
//
// Clearly (3) is not quite the same thing as (1), however it works surprisingly well in practice.
// Color pickers, in particular look properly.


// Note that approximate gamma-to-linear conversion pow(gamma, 2.2) produces considerably different colors.
static constexpr char GAMMA_TO_LINEAR[] = "((Gamma) < 0.04045 ? (Gamma) / 12.92 : pow(max((Gamma) + 0.055, 0.0) / 1.055, 2.4))";
static constexpr char SRGBA_TO_LINEAR[] =
"col.r = GAMMA_TO_LINEAR(col.r); "
"col.g = GAMMA_TO_LINEAR(col.g); "
"col.b = GAMMA_TO_LINEAR(col.b); "
"col.a = 1.0 - GAMMA_TO_LINEAR(1.0 - col.a);";


static constexpr char VertexShaderHLSL[] = R"(
cbuffer Constants
{
float4x4 ProjectionMatrix;
Expand Down Expand Up @@ -62,7 +101,7 @@ void main(in VSInput VSIn, out PSInput PSIn)
}
)";

static const char* PixelShaderHLSL = R"(
static constexpr char PixelShaderHLSL[] = R"(
struct PSInput
{
float4 pos : SV_POSITION;
Expand All @@ -75,13 +114,15 @@ SamplerState Texture_sampler;
float4 main(in PSInput PSIn) : SV_Target
{
return PSIn.col * Texture.Sample(Texture_sampler, PSIn.uv);
float4 col = Texture.Sample(Texture_sampler, PSIn.uv) * PSIn.col;
col.rgb *= col.a;
SRGBA_TO_LINEAR(col)
return col;
}
)";



static const char* VertexShaderGLSL = R"(
static constexpr char VertexShaderGLSL[] = R"(
#ifdef VULKAN
# define BINDING(X) layout(binding=X)
# define OUT_LOCATION(X) layout(location=X) // Requires separable programs
Expand Down Expand Up @@ -116,7 +157,7 @@ void main()
}
)";

static const char* PixelShaderGLSL = R"(
static constexpr char PixelShaderGLSL[] = R"(
#ifdef VULKAN
# define BINDING(X) layout(binding=X)
# define IN_LOCATION(X) layout(location=X) // Requires separable programs
Expand All @@ -133,7 +174,10 @@ layout(location = 0) out vec4 psout_col;
void main()
{
psout_col = vsout_col * texture(Texture, vsout_uv);
vec4 col = vsout_col * texture(Texture, vsout_uv);
col.rgb *= col.a;
SRGBA_TO_LINEAR(col)
psout_col = col;
}
)";

Expand Down Expand Up @@ -186,7 +230,7 @@ static constexpr uint32_t VertexShader_SPIRV[] =

static constexpr uint32_t FragmentShader_SPIRV[] =
{
0x07230203,0x00010000,0x0008000a,0x00000018,0x00000000,0x00020011,0x00000001,0x0006000b,
0x07230203,0x00010000,0x0008000a,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0008000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x00000014,
0x00030010,0x00000004,0x00000007,0x00030003,0x00000002,0x000001a4,0x00040005,0x00000004,
Expand All @@ -202,16 +246,116 @@ static constexpr uint32_t FragmentShader_SPIRV[] =
0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x0003001b,0x0000000e,
0x0000000d,0x00040020,0x0000000f,0x00000000,0x0000000e,0x0004003b,0x0000000f,0x00000010,
0x00000000,0x00040017,0x00000012,0x00000006,0x00000002,0x00040020,0x00000013,0x00000001,
0x00000012,0x0004003b,0x00000013,0x00000014,0x00000001,0x00050036,0x00000002,0x00000004,
0x00000012,0x0004003b,0x00000013,0x00000014,0x00000001,0x00040015,0x00000018,0x00000020,
0x00000000,0x0004002b,0x00000018,0x00000019,0x00000003,0x00040020,0x0000001a,0x00000003,
0x00000006,0x00040017,0x0000001d,0x00000006,0x00000003,0x00050036,0x00000002,0x00000004,
0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003d,0x00000007,0x0000000c,0x0000000b,
0x0004003d,0x0000000e,0x00000011,0x00000010,0x0004003d,0x00000012,0x00000015,0x00000014,
0x00050057,0x00000007,0x00000016,0x00000011,0x00000015,0x00050085,0x00000007,0x00000017,
0x0000000c,0x00000016,0x0003003e,0x00000009,0x00000017,0x000100fd,0x00010038
0x0000000c,0x00000016,0x0003003e,0x00000009,0x00000017,0x00050041,0x0000001a,0x0000001b,
0x00000009,0x00000019,0x0004003d,0x00000006,0x0000001c,0x0000001b,0x0004003d,0x00000007,
0x0000001e,0x00000009,0x0008004f,0x0000001d,0x0000001f,0x0000001e,0x0000001e,0x00000000,
0x00000001,0x00000002,0x0005008e,0x0000001d,0x00000020,0x0000001f,0x0000001c,0x0004003d,
0x00000007,0x00000021,0x00000009,0x0009004f,0x00000007,0x00000022,0x00000021,0x00000020,
0x00000004,0x00000005,0x00000006,0x00000003,0x0003003e,0x00000009,0x00000022,0x000100fd,
0x00010038
};

static constexpr uint32_t FragmentShader_Gamma_SPIRV[] =
{
0x07230203,0x00010000,0x0008000a,0x0000007b,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0008000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x00000014,
0x00030010,0x00000004,0x00000007,0x00030003,0x00000002,0x000001a4,0x00040005,0x00000004,
0x6e69616d,0x00000000,0x00050005,0x00000009,0x756f7370,0x6f635f74,0x0000006c,0x00050005,
0x0000000b,0x756f7376,0x6f635f74,0x0000006c,0x00040005,0x00000010,0x74786554,0x00657275,
0x00050005,0x00000014,0x756f7376,0x76755f74,0x00000000,0x00040047,0x00000009,0x0000001e,
0x00000000,0x00040047,0x0000000b,0x0000001e,0x00000000,0x00040047,0x00000010,0x00000022,
0x00000000,0x00040047,0x00000010,0x00000021,0x00000000,0x00040047,0x00000014,0x0000001e,
0x00000001,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040020,0x0000000a,0x00000001,
0x00000007,0x0004003b,0x0000000a,0x0000000b,0x00000001,0x00090019,0x0000000d,0x00000006,
0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x0003001b,0x0000000e,
0x0000000d,0x00040020,0x0000000f,0x00000000,0x0000000e,0x0004003b,0x0000000f,0x00000010,
0x00000000,0x00040017,0x00000012,0x00000006,0x00000002,0x00040020,0x00000013,0x00000001,
0x00000012,0x0004003b,0x00000013,0x00000014,0x00000001,0x00040015,0x00000018,0x00000020,
0x00000000,0x0004002b,0x00000018,0x00000019,0x00000003,0x00040020,0x0000001a,0x00000003,
0x00000006,0x00040017,0x0000001d,0x00000006,0x00000003,0x0004002b,0x00000018,0x00000023,
0x00000000,0x0004002b,0x00000006,0x00000026,0x3d25aee6,0x00020014,0x00000027,0x00040020,
0x00000029,0x00000007,0x00000006,0x0004002b,0x00000006,0x0000002f,0x414eb852,0x0004002b,
0x00000006,0x00000034,0x3d6147ae,0x0004002b,0x00000006,0x00000036,0x00000000,0x0004002b,
0x00000006,0x00000038,0x3f870a3d,0x0004002b,0x00000006,0x0000003a,0x4019999a,0x0004002b,
0x00000018,0x0000003e,0x00000001,0x0004002b,0x00000018,0x00000051,0x00000002,0x0004002b,
0x00000006,0x00000064,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,
0x000200f8,0x00000005,0x0004003b,0x00000029,0x0000002a,0x00000007,0x0004003b,0x00000029,
0x00000042,0x00000007,0x0004003b,0x00000029,0x00000055,0x00000007,0x0004003b,0x00000029,
0x00000069,0x00000007,0x0004003d,0x00000007,0x0000000c,0x0000000b,0x0004003d,0x0000000e,
0x00000011,0x00000010,0x0004003d,0x00000012,0x00000015,0x00000014,0x00050057,0x00000007,
0x00000016,0x00000011,0x00000015,0x00050085,0x00000007,0x00000017,0x0000000c,0x00000016,
0x0003003e,0x00000009,0x00000017,0x00050041,0x0000001a,0x0000001b,0x00000009,0x00000019,
0x0004003d,0x00000006,0x0000001c,0x0000001b,0x0004003d,0x00000007,0x0000001e,0x00000009,
0x0008004f,0x0000001d,0x0000001f,0x0000001e,0x0000001e,0x00000000,0x00000001,0x00000002,
0x0005008e,0x0000001d,0x00000020,0x0000001f,0x0000001c,0x0004003d,0x00000007,0x00000021,
0x00000009,0x0009004f,0x00000007,0x00000022,0x00000021,0x00000020,0x00000004,0x00000005,
0x00000006,0x00000003,0x0003003e,0x00000009,0x00000022,0x00050041,0x0000001a,0x00000024,
0x00000009,0x00000023,0x0004003d,0x00000006,0x00000025,0x00000024,0x000500b8,0x00000027,
0x00000028,0x00000025,0x00000026,0x000300f7,0x0000002c,0x00000000,0x000400fa,0x00000028,
0x0000002b,0x00000031,0x000200f8,0x0000002b,0x00050041,0x0000001a,0x0000002d,0x00000009,
0x00000023,0x0004003d,0x00000006,0x0000002e,0x0000002d,0x00050088,0x00000006,0x00000030,
0x0000002e,0x0000002f,0x0003003e,0x0000002a,0x00000030,0x000200f9,0x0000002c,0x000200f8,
0x00000031,0x00050041,0x0000001a,0x00000032,0x00000009,0x00000023,0x0004003d,0x00000006,
0x00000033,0x00000032,0x00050081,0x00000006,0x00000035,0x00000033,0x00000034,0x0007000c,
0x00000006,0x00000037,0x00000001,0x00000028,0x00000035,0x00000036,0x00050088,0x00000006,
0x00000039,0x00000037,0x00000038,0x0007000c,0x00000006,0x0000003b,0x00000001,0x0000001a,
0x00000039,0x0000003a,0x0003003e,0x0000002a,0x0000003b,0x000200f9,0x0000002c,0x000200f8,
0x0000002c,0x0004003d,0x00000006,0x0000003c,0x0000002a,0x00050041,0x0000001a,0x0000003d,
0x00000009,0x00000023,0x0003003e,0x0000003d,0x0000003c,0x00050041,0x0000001a,0x0000003f,
0x00000009,0x0000003e,0x0004003d,0x00000006,0x00000040,0x0000003f,0x000500b8,0x00000027,
0x00000041,0x00000040,0x00000026,0x000300f7,0x00000044,0x00000000,0x000400fa,0x00000041,
0x00000043,0x00000048,0x000200f8,0x00000043,0x00050041,0x0000001a,0x00000045,0x00000009,
0x0000003e,0x0004003d,0x00000006,0x00000046,0x00000045,0x00050088,0x00000006,0x00000047,
0x00000046,0x0000002f,0x0003003e,0x00000042,0x00000047,0x000200f9,0x00000044,0x000200f8,
0x00000048,0x00050041,0x0000001a,0x00000049,0x00000009,0x0000003e,0x0004003d,0x00000006,
0x0000004a,0x00000049,0x00050081,0x00000006,0x0000004b,0x0000004a,0x00000034,0x0007000c,
0x00000006,0x0000004c,0x00000001,0x00000028,0x0000004b,0x00000036,0x00050088,0x00000006,
0x0000004d,0x0000004c,0x00000038,0x0007000c,0x00000006,0x0000004e,0x00000001,0x0000001a,
0x0000004d,0x0000003a,0x0003003e,0x00000042,0x0000004e,0x000200f9,0x00000044,0x000200f8,
0x00000044,0x0004003d,0x00000006,0x0000004f,0x00000042,0x00050041,0x0000001a,0x00000050,
0x00000009,0x0000003e,0x0003003e,0x00000050,0x0000004f,0x00050041,0x0000001a,0x00000052,
0x00000009,0x00000051,0x0004003d,0x00000006,0x00000053,0x00000052,0x000500b8,0x00000027,
0x00000054,0x00000053,0x00000026,0x000300f7,0x00000057,0x00000000,0x000400fa,0x00000054,
0x00000056,0x0000005b,0x000200f8,0x00000056,0x00050041,0x0000001a,0x00000058,0x00000009,
0x00000051,0x0004003d,0x00000006,0x00000059,0x00000058,0x00050088,0x00000006,0x0000005a,
0x00000059,0x0000002f,0x0003003e,0x00000055,0x0000005a,0x000200f9,0x00000057,0x000200f8,
0x0000005b,0x00050041,0x0000001a,0x0000005c,0x00000009,0x00000051,0x0004003d,0x00000006,
0x0000005d,0x0000005c,0x00050081,0x00000006,0x0000005e,0x0000005d,0x00000034,0x0007000c,
0x00000006,0x0000005f,0x00000001,0x00000028,0x0000005e,0x00000036,0x00050088,0x00000006,
0x00000060,0x0000005f,0x00000038,0x0007000c,0x00000006,0x00000061,0x00000001,0x0000001a,
0x00000060,0x0000003a,0x0003003e,0x00000055,0x00000061,0x000200f9,0x00000057,0x000200f8,
0x00000057,0x0004003d,0x00000006,0x00000062,0x00000055,0x00050041,0x0000001a,0x00000063,
0x00000009,0x00000051,0x0003003e,0x00000063,0x00000062,0x00050041,0x0000001a,0x00000065,
0x00000009,0x00000019,0x0004003d,0x00000006,0x00000066,0x00000065,0x00050083,0x00000006,
0x00000067,0x00000064,0x00000066,0x000500b8,0x00000027,0x00000068,0x00000067,0x00000026,
0x000300f7,0x0000006b,0x00000000,0x000400fa,0x00000068,0x0000006a,0x00000070,0x000200f8,
0x0000006a,0x00050041,0x0000001a,0x0000006c,0x00000009,0x00000019,0x0004003d,0x00000006,
0x0000006d,0x0000006c,0x00050083,0x00000006,0x0000006e,0x00000064,0x0000006d,0x00050088,
0x00000006,0x0000006f,0x0000006e,0x0000002f,0x0003003e,0x00000069,0x0000006f,0x000200f9,
0x0000006b,0x000200f8,0x00000070,0x00050041,0x0000001a,0x00000071,0x00000009,0x00000019,
0x0004003d,0x00000006,0x00000072,0x00000071,0x00050083,0x00000006,0x00000073,0x00000064,
0x00000072,0x00050081,0x00000006,0x00000074,0x00000073,0x00000034,0x0007000c,0x00000006,
0x00000075,0x00000001,0x00000028,0x00000074,0x00000036,0x00050088,0x00000006,0x00000076,
0x00000075,0x00000038,0x0007000c,0x00000006,0x00000077,0x00000001,0x0000001a,0x00000076,
0x0000003a,0x0003003e,0x00000069,0x00000077,0x000200f9,0x0000006b,0x000200f8,0x0000006b,
0x0004003d,0x00000006,0x00000078,0x00000069,0x00050083,0x00000006,0x00000079,0x00000064,
0x00000078,0x00050041,0x0000001a,0x0000007a,0x00000009,0x00000019,0x0003003e,0x0000007a,
0x00000079,0x000100fd,0x00010038
};

// clang-format on


static const char* ShadersMSL = R"(
static constexpr char ShadersMSL[] = R"(
#include <metal_stdlib>
#include <simd/simd.h>
Expand Down Expand Up @@ -255,7 +399,11 @@ fragment PSOut ps_main(VSOut in [[stage_in]],
sampler Texture_sampler [[sampler(0)]])
{
PSOut out = {};
out.col = in.col * Texture.sample(Texture_sampler, in.uv);
float4 col = in.col * Texture.sample(Texture_sampler, in.uv);
col.rgb *= col.a;
SRGBA_TO_LINEAR(col)
out.col = col;
return out;
}
)";
Expand Down Expand Up @@ -323,6 +471,27 @@ void ImGuiDiligentRenderer::CreateDeviceObjects()
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_DEFAULT;

const auto IsSRB = GetTextureFormatAttribs(m_BackBufferFmt).ComponentType == COMPONENT_TYPE_UNORM_SRGB;
if (IsSRB)
{
static constexpr ShaderMacro Macros[] =
{
{"GAMMA_TO_LINEAR(Gamma)", GAMMA_TO_LINEAR},
{"SRGBA_TO_LINEAR(col)", SRGBA_TO_LINEAR},
{},
};
ShaderCI.Macros = Macros;
}
else
{
static constexpr ShaderMacro Macros[] =
{
{"SRGBA_TO_LINEAR(col)", ""},
{},
};
ShaderCI.Macros = Macros;
}

const auto DeviceType = m_pDevice->GetDeviceInfo().Type;

RefCntAutoPtr<IShader> pVS;
Expand Down Expand Up @@ -362,8 +531,16 @@ void ImGuiDiligentRenderer::CreateDeviceObjects()
switch (DeviceType)
{
case RENDER_DEVICE_TYPE_VULKAN:
ShaderCI.ByteCode = FragmentShader_SPIRV;
ShaderCI.ByteCodeSize = sizeof(FragmentShader_SPIRV);
if (IsSRB)
{
ShaderCI.ByteCode = FragmentShader_Gamma_SPIRV;
ShaderCI.ByteCodeSize = sizeof(FragmentShader_Gamma_SPIRV);
}
else
{
ShaderCI.ByteCode = FragmentShader_SPIRV;
ShaderCI.ByteCodeSize = sizeof(FragmentShader_SPIRV);
}
break;

case RENDER_DEVICE_TYPE_D3D11:
Expand Down Expand Up @@ -404,9 +581,10 @@ void ImGuiDiligentRenderer::CreateDeviceObjects()
GraphicsPipeline.RasterizerDesc.ScissorEnable = True;
GraphicsPipeline.DepthStencilDesc.DepthEnable = False;

auto& RT0 = GraphicsPipeline.BlendDesc.RenderTargets[0];
RT0.BlendEnable = True;
RT0.SrcBlend = BLEND_FACTOR_SRC_ALPHA;
auto& RT0 = GraphicsPipeline.BlendDesc.RenderTargets[0];
RT0.BlendEnable = True;
// Use alpha-premultiplied blending, see eq. (3).
RT0.SrcBlend = BLEND_FACTOR_ONE;
RT0.DestBlend = BLEND_FACTOR_INV_SRC_ALPHA;
RT0.BlendOp = BLEND_OPERATION_ADD;
RT0.SrcBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
Expand Down

0 comments on commit ea06955

Please sign in to comment.