Always clear window with black color instead of background color

Always use black color to clear the window with all graphics backends, instead of using `cl_background_color` or `cl_background_entities_color`, respectively, as the clear color. The respective map background color is rendered using a quad in `CMapLayers` instead, so this should not affect appearance of maps. This does not have any noticeable effect on FPS. Previously, the unused part of the window (when it is resized smaller than 5:4 aspect ratio), was colored using the map background color, whereas now it will be cleared black consistently.

The color parameters of the `IGraphics::Clear` function and of the `SCommand_Clear` command are removed, as we always expect the screen to be cleared black now.

The parameter `ForceClearNow` of the `IGraphics::Clear` function was already unused previously and is also removed.
This commit is contained in:
Robert Müller 2024-05-14 23:06:22 +02:00
parent fcacef5fbb
commit caa062c88c
11 changed files with 36 additions and 67 deletions

View file

@ -937,7 +937,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_
{ {
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(ClipWasEnabled) if(ClipWasEnabled)
{ {

View file

@ -414,8 +414,6 @@ bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_vTextures.resize(CCommandBuffer::MAX_TEXTURES); m_vTextures.resize(CCommandBuffer::MAX_TEXTURES);
m_ClearColor.r = m_ClearColor.g = m_ClearColor.b = -1.f;
// fix the alignment to allow even 1byte changes, e.g. for alpha components // fix the alignment to allow even 1byte changes, e.g. for alpha components
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -687,11 +685,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Clear(const CCommandBuffer::SComma
{ {
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
if(pCommand->m_Color.r != m_ClearColor.r || pCommand->m_Color.g != m_ClearColor.g || pCommand->m_Color.b != m_ClearColor.b) glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
{
glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f);
m_ClearColor = pCommand->m_Color;
}
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
if(ClipWasEnabled) if(ClipWasEnabled)
{ {

View file

@ -67,8 +67,6 @@ protected:
std::vector<TWGLuint> m_vBufferObjectIndices; std::vector<TWGLuint> m_vBufferObjectIndices;
CCommandBuffer::SColorf m_ClearColor;
void InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, class CGLSLCompiler *pCompiler, class IStorage *pStorage, bool Textured, bool Rotationless); void InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, class CGLSLCompiler *pCompiler, class IStorage *pStorage, bool Textured, bool Rotationless);
bool IsNewApi() override { return true; } bool IsNewApi() override { return true; }

View file

@ -1059,8 +1059,6 @@ private:
SDL_Window *m_pWindow; SDL_Window *m_pWindow;
std::array<float, 4> m_aClearColor = {0, 0, 0, 0};
struct SRenderCommandExecuteBuffer struct SRenderCommandExecuteBuffer
{ {
CCommandBuffer::ECommandBufferCMD m_Command; CCommandBuffer::ECommandBufferCMD m_Command;
@ -1077,8 +1075,6 @@ private:
VkBuffer m_IndexBuffer; VkBuffer m_IndexBuffer;
bool m_ClearColorInRenderThread = false;
bool m_HasDynamicState = false; bool m_HasDynamicState = false;
VkViewport m_Viewport; VkViewport m_Viewport;
VkRect2D m_Scissor; VkRect2D m_Scissor;
@ -2445,7 +2441,7 @@ protected:
RenderPassInfo.renderArea.offset = {0, 0}; RenderPassInfo.renderArea.offset = {0, 0};
RenderPassInfo.renderArea.extent = m_VKSwapImgAndViewportExtent.m_SwapImageViewport; RenderPassInfo.renderArea.extent = m_VKSwapImgAndViewportExtent.m_SwapImageViewport;
VkClearValue ClearColorVal = {{{m_aClearColor[0], m_aClearColor[1], m_aClearColor[2], m_aClearColor[3]}}}; VkClearValue ClearColorVal = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
RenderPassInfo.clearValueCount = 1; RenderPassInfo.clearValueCount = 1;
RenderPassInfo.pClearValues = &ClearColorVal; RenderPassInfo.pClearValues = &ClearColorVal;
@ -6715,37 +6711,19 @@ public:
void Cmd_Clear_FillExecuteBuffer(SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand) void Cmd_Clear_FillExecuteBuffer(SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand)
{ {
if(!pCommand->m_ForceClear)
{
bool ColorChanged = m_aClearColor[0] != pCommand->m_Color.r || m_aClearColor[1] != pCommand->m_Color.g ||
m_aClearColor[2] != pCommand->m_Color.b || m_aClearColor[3] != pCommand->m_Color.a;
m_aClearColor[0] = pCommand->m_Color.r;
m_aClearColor[1] = pCommand->m_Color.g;
m_aClearColor[2] = pCommand->m_Color.b;
m_aClearColor[3] = pCommand->m_Color.a;
if(ColorChanged)
ExecBuffer.m_ClearColorInRenderThread = true;
}
else
{
ExecBuffer.m_ClearColorInRenderThread = true;
}
ExecBuffer.m_EstimatedRenderCallCount = 0; ExecBuffer.m_EstimatedRenderCallCount = 0;
} }
[[nodiscard]] bool Cmd_Clear(const SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand) [[nodiscard]] bool Cmd_Clear(const SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand)
{ {
if(ExecBuffer.m_ClearColorInRenderThread) std::array<VkClearAttachment, 1> aAttachments = {VkClearAttachment{VK_IMAGE_ASPECT_COLOR_BIT, 0, VkClearValue{VkClearColorValue{{0.0f, 0.0f, 0.0f, 0.0f}}}}};
{ std::array<VkClearRect, 1> aClearRects = {VkClearRect{{{0, 0}, m_VKSwapImgAndViewportExtent.m_SwapImageViewport}, 0, 1}};
std::array<VkClearAttachment, 1> aAttachments = {VkClearAttachment{VK_IMAGE_ASPECT_COLOR_BIT, 0, VkClearValue{VkClearColorValue{{pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, pCommand->m_Color.a}}}}};
std::array<VkClearRect, 1> aClearRects = {VkClearRect{{{0, 0}, m_VKSwapImgAndViewportExtent.m_SwapImageViewport}, 0, 1}};
VkCommandBuffer *pCommandBuffer; VkCommandBuffer *pCommandBuffer;
if(!GetGraphicCommandBuffer(pCommandBuffer, ExecBuffer.m_ThreadIndex)) if(!GetGraphicCommandBuffer(pCommandBuffer, ExecBuffer.m_ThreadIndex))
return false; return false;
auto &CommandBuffer = *pCommandBuffer; auto &CommandBuffer = *pCommandBuffer;
vkCmdClearAttachments(CommandBuffer, aAttachments.size(), aAttachments.data(), aClearRects.size(), aClearRects.data()); vkCmdClearAttachments(CommandBuffer, aAttachments.size(), aAttachments.data(), aClearRects.size(), aClearRects.data());
}
return true; return true;
} }

View file

@ -891,17 +891,7 @@ const char *CClient::ErrorString() const
void CClient::Render() void CClient::Render()
{ {
if(g_Config.m_ClOverlayEntities) Graphics()->Clear();
{
ColorRGBA bg = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClBackgroundEntitiesColor));
Graphics()->Clear(bg.r, bg.g, bg.b);
}
else
{
ColorRGBA bg = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClBackgroundColor));
Graphics()->Clear(bg.r, bg.g, bg.b);
}
GameClient()->OnRender(); GameClient()->OnRender();
DebugRender(); DebugRender();
@ -2728,7 +2718,7 @@ void CClient::Run()
} }
// make sure the first frame just clears everything to prevent undesired colors when waiting for io // make sure the first frame just clears everything to prevent undesired colors when waiting for io
Graphics()->Clear(0, 0, 0); Graphics()->Clear();
Graphics()->Swap(); Graphics()->Swap();
// init sound, allowed to fail // init sound, allowed to fail
@ -3783,7 +3773,7 @@ void CClient::UpdateAndSwap()
{ {
Input()->Update(); Input()->Update();
Graphics()->Swap(); Graphics()->Swap();
Graphics()->Clear(0, 0, 0); Graphics()->Clear();
} }
void CClient::ServerBrowserUpdate() void CClient::ServerBrowserUpdate()

View file

@ -833,14 +833,9 @@ void CGraphics_Threaded::TextureSet(CTextureHandle TextureId)
m_State.m_Texture = TextureId.Id(); m_State.m_Texture = TextureId.Id();
} }
void CGraphics_Threaded::Clear(float r, float g, float b, bool ForceClearNow) void CGraphics_Threaded::Clear()
{ {
CCommandBuffer::SCommand_Clear Cmd; CCommandBuffer::SCommand_Clear Cmd;
Cmd.m_Color.r = r;
Cmd.m_Color.g = g;
Cmd.m_Color.b = b;
Cmd.m_Color.a = 0;
Cmd.m_ForceClear = ForceClearNow;
AddCmd(Cmd); AddCmd(Cmd);
} }

View file

@ -213,8 +213,6 @@ public:
{ {
SCommand_Clear() : SCommand_Clear() :
SCommand(CMD_CLEAR) {} SCommand(CMD_CLEAR) {}
SColorf m_Color;
bool m_ForceClear;
}; };
struct SCommand_Signal : public SCommand struct SCommand_Signal : public SCommand
@ -991,7 +989,7 @@ public:
void TextureSet(CTextureHandle TextureId) override; void TextureSet(CTextureHandle TextureId) override;
void Clear(float r, float g, float b, bool ForceClearNow = false) override; void Clear() override;
void QuadsBegin() override; void QuadsBegin() override;
void QuadsEnd() override; void QuadsEnd() override;

View file

@ -306,8 +306,7 @@ public:
virtual void WindowDestroyNtf(uint32_t WindowId) = 0; virtual void WindowDestroyNtf(uint32_t WindowId) = 0;
virtual void WindowCreateNtf(uint32_t WindowId) = 0; virtual void WindowCreateNtf(uint32_t WindowId) = 0;
// ForceClearNow forces the backend to trigger a clear, even at performance cost, else it might be delayed by one frame virtual void Clear() = 0;
virtual void Clear(float r, float g, float b, bool ForceClearNow = false) = 0;
virtual void ClipEnable(int x, int y, int w, int h) = 0; virtual void ClipEnable(int x, int y, int w, int h) = 0;
virtual void ClipDisable() = 0; virtual void ClipDisable() = 0;

View file

@ -1412,6 +1412,23 @@ void CMapLayers::OnRender()
CUIRect Screen; CUIRect Screen;
Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h); Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h);
if(m_Type == TYPE_BACKGROUND || m_Type == TYPE_BACKGROUND_FORCE)
{
Graphics()->TextureClear();
Graphics()->QuadsBegin();
if(g_Config.m_ClOverlayEntities)
{
Graphics()->SetColor(color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClBackgroundEntitiesColor)));
}
else
{
Graphics()->SetColor(color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClBackgroundColor)));
}
IGraphics::CQuadItem QuadItem(Screen.x, Screen.y, Screen.w, Screen.h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
}
vec2 Center = GetCurCamera()->m_Center; vec2 Center = GetCurCamera()->m_Center;
bool PassedGameLayer = false; bool PassedGameLayer = false;

View file

@ -1092,12 +1092,12 @@ void CGameClient::RenderShutdownMessage()
dbg_assert(false, "Invalid client state for quitting message"); dbg_assert(false, "Invalid client state for quitting message");
// This function only gets called after the render loop has already terminated, so we have to call Swap manually. // This function only gets called after the render loop has already terminated, so we have to call Swap manually.
Graphics()->Clear(0.0f, 0.0f, 0.0f); Graphics()->Clear();
Ui()->MapScreen(); Ui()->MapScreen();
TextRender()->TextColor(TextRender()->DefaultTextColor()); TextRender()->TextColor(TextRender()->DefaultTextColor());
Ui()->DoLabel(Ui()->Screen(), pMessage, 16.0f, TEXTALIGN_MC); Ui()->DoLabel(Ui()->Screen(), pMessage, 16.0f, TEXTALIGN_MC);
Graphics()->Swap(); Graphics()->Swap();
Graphics()->Clear(0.0f, 0.0f, 0.0f); Graphics()->Clear();
} }
void CGameClient::OnRconType(bool UsernameReq) void CGameClient::OnRconType(bool UsernameReq)

View file

@ -7718,7 +7718,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
void CEditor::Render() void CEditor::Render()
{ {
// basic start // basic start
Graphics()->Clear(0.0f, 0.0f, 0.0f); Graphics()->Clear();
CUIRect View = *Ui()->Screen(); CUIRect View = *Ui()->Screen();
Ui()->MapScreen(); Ui()->MapScreen();
m_CursorType = CURSOR_NORMAL; m_CursorType = CURSOR_NORMAL;