diff --git a/source/graphics/Canvas2D.cpp b/source/graphics/Canvas2D.cpp index fd95e3bb78..622d5bf47d 100644 --- a/source/graphics/Canvas2D.cpp +++ b/source/graphics/Canvas2D.cpp @@ -30,6 +30,38 @@ #include +namespace +{ + +// Array of 2D elements unrolled into 1D array. +using PlaneArray2D = std::array; + +void DrawTextureImpl(CTexturePtr texture, + const PlaneArray2D& vertices, const PlaneArray2D& uvs, + const CColor& multiply, const CColor& add) +{ + CShaderDefines defines; + CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect( + str_canvas2d, g_Renderer.GetSystemShaderDefines(), defines); + tech->BeginPass(); + CShaderProgramPtr shader = tech->GetShader(); + + shader->BindTexture(str_tex, texture); + shader->Uniform(str_transform, GetDefaultGuiMatrix()); + shader->Uniform(str_colorAdd, add); + shader->Uniform(str_colorMul, multiply); + shader->VertexPointer(2, GL_FLOAT, 0, vertices.data()); + shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, uvs.data()); + shader->AssertPointersBound(); + + if (!g_Renderer.DoSkipSubmit()) + glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size() / 2); + + tech->EndPass(); +} + +} // anonymous namespace + void CCanvas2D::DrawLine(const std::vector& points, const float width, const CColor& color) { std::vector vertices; @@ -69,32 +101,51 @@ void CCanvas2D::DrawLine(const std::vector& points, const float width void CCanvas2D::DrawRect(const CRect& rect, const CColor& color) { - const std::array uvs = { + const PlaneArray2D uvs = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - const std::array vertices = { + const PlaneArray2D vertices = { rect.left, rect.bottom, rect.right, rect.bottom, rect.right, rect.top, rect.left, rect.top }; - CShaderDefines defines; - CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect( - str_canvas2d, g_Renderer.GetSystemShaderDefines(), defines); - tech->BeginPass(); - CShaderProgramPtr shader = tech->GetShader(); - - shader->BindTexture(str_tex, g_Renderer.GetTextureManager().GetTransparentTexture()); - shader->Uniform(str_transform, GetDefaultGuiMatrix()); - shader->Uniform(str_colorAdd, color); - shader->Uniform(str_colorMul, CColor(0.0f, 0.0f, 0.0f, 0.0f)); - shader->VertexPointer(2, GL_FLOAT, 0, vertices.data()); - shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, uvs.data()); - shader->AssertPointersBound(); - - if (!g_Renderer.DoSkipSubmit()) - glDrawArrays(GL_TRIANGLE_FAN, 0, vertices.size() / 2); - - tech->EndPass(); + DrawTextureImpl( + g_Renderer.GetTextureManager().GetTransparentTexture(), + vertices, uvs, CColor(0.0f, 0.0f, 0.0f, 0.0f), color); } + +void CCanvas2D::DrawTexture(CTexturePtr texture, const CRect& destination) +{ + DrawTexture(texture, + destination, CRect(0, 0, texture->GetWidth(), texture->GetHeight()), + CColor(1.0f, 1.0f, 1.0f, 1.0f), CColor(0.0f, 0.0f, 0.0f, 0.0f)); +} + +void CCanvas2D::DrawTexture( + CTexturePtr texture, const CRect& destination, const CRect& source, + const CColor& multiply, const CColor& add) +{ + PlaneArray2D uvs = { + source.left, source.bottom, + source.right, source.bottom, + source.right, source.top, + source.left, source.top + }; + for (size_t idx = 0; idx < uvs.size() / 2; idx += 2) + { + uvs[idx + 0] /= texture->GetWidth(); + uvs[idx + 1] /= texture->GetHeight(); + } + const PlaneArray2D vertices = { + destination.left, destination.bottom, + destination.right, destination.bottom, + destination.right, destination.top, + destination.left, destination.top + }; + + DrawTextureImpl( + g_Renderer.GetTextureManager().GetTransparentTexture(), + vertices, uvs, multiply, add); +} \ No newline at end of file diff --git a/source/graphics/Canvas2D.h b/source/graphics/Canvas2D.h index 0d5d09cd8f..3a58287fc4 100644 --- a/source/graphics/Canvas2D.h +++ b/source/graphics/Canvas2D.h @@ -18,6 +18,7 @@ #ifndef INCLUDED_CANVAS2D #define INCLUDED_CANVAS2D +#include "graphics/Texture.h" #include "maths/Vector2D.h" #include @@ -31,9 +32,32 @@ struct CColor; class CCanvas2D { public: - void DrawLine(const std::vector& points, const float width, const CColor& color); + /** + * Draws a line by the given points with the width and color. + */ + void DrawLine( + const std::vector& points, + const float width, const CColor& color); + /** + * Draws the rect filled with the color. + */ void DrawRect(const CRect& rect, const CColor& color); + + /** + * Draws a piece of the texture from the source rect into the + * destination rect. The result color is set by the following formula: + * TEXTURE_COLOR * COLOR_MULTIPLY + COLOR_ADD + */ + void DrawTexture(CTexturePtr texture, + const CRect& destination, const CRect& source, + const CColor& multiply, const CColor& add); + + /** + * A simpler version of the previous one, draws the texture into the + * destination rect without color modifications. + */ + void DrawTexture(CTexturePtr texture, const CRect& destination); }; #endif // INCLUDED_CANVAS2D diff --git a/source/gui/GUIRenderer.cpp b/source/gui/GUIRenderer.cpp index f42b301fda..c8c5d6f213 100644 --- a/source/gui/GUIRenderer.cpp +++ b/source/gui/GUIRenderer.cpp @@ -213,24 +213,22 @@ void GUIRenderer::UpdateDrawCallCache(const CGUI& pGUI, DrawCalls& Calls, const texture->Prefetch(); Call.m_HasTexture = true; Call.m_Texture = texture; - Call.m_EnableBlending = false; // will be overridden if the texture has an alpha channel - Call.m_ObjectSize = ObjectSize; } else { Call.m_HasTexture = false; - // Enable blending if it's transparent (allowing a little error in the calculations) - Call.m_EnableBlending = !(fabs((*cit)->m_BackColor.a - 1.0f) < 0.0000001f); + Call.m_EnableBlending = true; } Call.m_BackColor = &(*cit)->m_BackColor; - if (!Call.m_HasTexture) { - Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid); Call.m_Material = str_gui_solid; + Call.m_ColorAdd = *Call.m_BackColor; + Call.m_ColorMultiply = CColor(0.0f, 0.0f, 0.0f, 0.0f); + Call.m_Texture = g_Renderer.GetTextureManager().GetTransparentTexture(); } else if ((*cit)->m_Effects) { @@ -406,7 +404,9 @@ void GUIRenderer::Draw(DrawCalls& Calls, CCanvas2D& canvas) std::swap(rect.right, rect.left); if (rect.bottom < rect.top) std::swap(rect.bottom, rect.top); - canvas.DrawRect(rect, *(cit->m_BackColor)); + canvas.DrawTexture(cit->m_Texture, + rect, CRect(0, 0, cit->m_Texture->GetWidth(), cit->m_Texture->GetHeight()), + cit->m_ColorMultiply, cit->m_ColorAdd); if (cit->m_EnableBlending) glDisable(GL_BLEND); diff --git a/source/gui/GUIRenderer.h b/source/gui/GUIRenderer.h index 5526be9361..31d161be5e 100644 --- a/source/gui/GUIRenderer.h +++ b/source/gui/GUIRenderer.h @@ -60,6 +60,9 @@ namespace GUIRenderer // Temporary type to make a soft transition to canvas rendering. CStrIntern m_Material; + + CColor m_ColorAdd; + CColor m_ColorMultiply; }; class DrawCalls : public std::vector diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index ea50ab22e4..c665fb9a62 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -233,6 +233,8 @@ void CConsole::DrawWindow() CVector2D{0.0f, m_fHeight - static_cast(m_iFontHeight) - 4.0f}, CVector2D{m_fWidth, m_fHeight - static_cast(m_iFontHeight) - 4.0f} }; + for (CVector2D& point : points) + point += CVector2D{m_fX, m_fY - (1.0f - m_fVisibleFrac) * m_fHeight}; canvas.DrawLine(points, 1.0f, CColor(0.5f, 0.5f, 0.0f, 0.6f)); } }