diff --git a/binaries/data/mods/mod/shaders/arb/canvas2d.fp b/binaries/data/mods/mod/shaders/arb/canvas2d.fp new file mode 100644 index 0000000000..2de2d68706 --- /dev/null +++ b/binaries/data/mods/mod/shaders/arb/canvas2d.fp @@ -0,0 +1,15 @@ +!!ARBfp1.0 + +TEMP colorTex; +TEX colorTex, fragment.texcoord[0], texture[0], 2D; + +PARAM colorAdd = program.local[1]; +PARAM colorMul = program.local[2]; + +TEMP color; +MUL color, colorTex, colorMul; +ADD color, color, colorAdd; + +MOV result.color, color; + +END diff --git a/binaries/data/mods/mod/shaders/arb/canvas2d.vp b/binaries/data/mods/mod/shaders/arb/canvas2d.vp new file mode 100644 index 0000000000..56d364990f --- /dev/null +++ b/binaries/data/mods/mod/shaders/arb/canvas2d.vp @@ -0,0 +1,16 @@ +!!ARBvp1.0 + +PARAM transform[4] = { program.local[0..3] }; + +TEMP position; + +DP4 position.x, transform[0], vertex.position; +DP4 position.y, transform[1], vertex.position; +MOV position.z, 0.0; +MOV position.w, 1.0; + +MOV result.position, position; + +MOV result.texcoord[0], vertex.texcoord[0]; + +END diff --git a/binaries/data/mods/mod/shaders/arb/canvas2d.xml b/binaries/data/mods/mod/shaders/arb/canvas2d.xml new file mode 100644 index 0000000000..c32d39265f --- /dev/null +++ b/binaries/data/mods/mod/shaders/arb/canvas2d.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/binaries/data/mods/mod/shaders/effects/canvas2d.xml b/binaries/data/mods/mod/shaders/effects/canvas2d.xml new file mode 100644 index 0000000000..5cd236fa47 --- /dev/null +++ b/binaries/data/mods/mod/shaders/effects/canvas2d.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/binaries/data/mods/mod/shaders/glsl/canvas2d.fs b/binaries/data/mods/mod/shaders/glsl/canvas2d.fs new file mode 100644 index 0000000000..b39ff8af0c --- /dev/null +++ b/binaries/data/mods/mod/shaders/glsl/canvas2d.fs @@ -0,0 +1,12 @@ +#version 110 + +uniform vec4 colorAdd; +uniform vec4 colorMul; +uniform sampler2D tex; + +varying vec2 v_uv; + +void main() +{ + gl_FragColor = clamp(texture2D(tex, v_uv) * colorMul + colorAdd, 0.0, 1.0); +} diff --git a/binaries/data/mods/mod/shaders/glsl/canvas2d.vs b/binaries/data/mods/mod/shaders/glsl/canvas2d.vs new file mode 100644 index 0000000000..9da970c42f --- /dev/null +++ b/binaries/data/mods/mod/shaders/glsl/canvas2d.vs @@ -0,0 +1,14 @@ +#version 110 + +uniform mat4 transform; + +attribute vec2 a_vertex; +attribute vec2 a_uv0; + +varying vec2 v_uv; + +void main() +{ + v_uv = a_uv0; + gl_Position = transform * vec4(a_vertex, 0.0, 1.0); +} diff --git a/binaries/data/mods/mod/shaders/glsl/canvas2d.xml b/binaries/data/mods/mod/shaders/glsl/canvas2d.xml new file mode 100644 index 0000000000..65ea4cd4fc --- /dev/null +++ b/binaries/data/mods/mod/shaders/glsl/canvas2d.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/source/graphics/Canvas2D.cpp b/source/graphics/Canvas2D.cpp index c67f448e3c..d7f1149a81 100644 --- a/source/graphics/Canvas2D.cpp +++ b/source/graphics/Canvas2D.cpp @@ -21,11 +21,15 @@ #include "graphics/Color.h" #include "graphics/ShaderManager.h" +#include "graphics/TextureManager.h" #include "gui/GUIMatrix.h" +#include "maths/Rect.h" #include "maths/Vector2D.h" #include "ps/CStrInternStatic.h" #include "renderer/Renderer.h" +#include + void CCanvas2D::DrawLine(const std::vector& points, const float width, const CColor& color) { std::vector vertices; @@ -45,8 +49,8 @@ void CCanvas2D::DrawLine(const std::vector& points, const float width CShaderProgramPtr shader = tech->GetShader(); shader->Uniform(str_transform, transform); - shader->Uniform(str_color, color ); - shader->VertexPointer(3, GL_FLOAT, 0, &vertices[0]); + shader->Uniform(str_color, color); + shader->VertexPointer(3, GL_FLOAT, 0, vertices.data()); shader->AssertPointersBound(); #if !CONFIG2_GLES @@ -62,3 +66,35 @@ void CCanvas2D::DrawLine(const std::vector& points, const float width tech->EndPass(); } + +void CCanvas2D::DrawRect(const CRect& rect, const CColor& color) +{ + const std::array uvs = { + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + }; + const std::array 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().GetWhiteTexture()); + 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(); +} diff --git a/source/graphics/Canvas2D.h b/source/graphics/Canvas2D.h index 40a5fc74de..0d5d09cd8f 100644 --- a/source/graphics/Canvas2D.h +++ b/source/graphics/Canvas2D.h @@ -22,6 +22,8 @@ #include +class CRect; + struct CColor; // Encapsulates 2D drawing functionality to hide and optimize @@ -30,6 +32,8 @@ class CCanvas2D { public: void DrawLine(const std::vector& points, const float width, const CColor& color); + + void DrawRect(const CRect& rect, const CColor& color); }; #endif // INCLUDED_CANVAS2D diff --git a/source/graphics/TextureManager.cpp b/source/graphics/TextureManager.cpp index 9e25995ae3..f6e23e15c4 100644 --- a/source/graphics/TextureManager.cpp +++ b/source/graphics/TextureManager.cpp @@ -19,6 +19,7 @@ #include "TextureManager.h" +#include "graphics/Color.h" #include "graphics/TextureConverter.h" #include "lib/allocators/shared_ptr.h" #include "lib/file/vfs/vfs_tree.h" @@ -38,6 +39,53 @@ #include #include +class SingleColorTexture +{ +public: + SingleColorTexture(const CColor& color, PIVFS vfs, const VfsPath& pathPlaceholder, const bool disableGL, CTextureManagerImpl* textureManager) + { + const SColor4ub color32 = color.AsSColor4ub(); + // Construct 1x1 32-bit texture + std::shared_ptr data(new u8[3], ArrayDeleter()); + data.get()[0] = color32.R; + data.get()[1] = color32.G; + data.get()[2] = color32.B; + data.get()[3] = color32.A; + + Tex t; + ignore_result(t.wrap(1, 1, 32, TEX_ALPHA, data, 0)); + + m_Handle = ogl_tex_wrap(&t, vfs, pathPlaceholder); + ignore_result(ogl_tex_set_filter(m_Handle, GL_LINEAR)); + if (!disableGL) + ignore_result(ogl_tex_upload(m_Handle)); + + CTextureProperties props(pathPlaceholder); + m_Texture = CTexturePtr(new CTexture(m_Handle, props, textureManager)); + m_Texture->m_State = CTexture::LOADED; + m_Texture->m_Self = m_Texture; + } + + ~SingleColorTexture() + { + ignore_result(ogl_tex_free(m_Handle)); + } + + CTexturePtr GetTexture() + { + return m_Texture; + } + + Handle GetHandle() + { + return m_Handle; + } + +private: + Handle m_Handle; + CTexturePtr m_Texture; +}; + struct TPhash { std::size_t operator()(CTextureProperties const& a) const @@ -80,8 +128,11 @@ class CTextureManagerImpl friend class CTexture; public: CTextureManagerImpl(PIVFS vfs, bool highQuality, bool disableGL) : - m_VFS(vfs), m_CacheLoader(vfs, L".dds"), m_DisableGL(disableGL), m_TextureConverter(vfs, highQuality), - m_DefaultHandle(0), m_ErrorHandle(0) + m_VFS(vfs), m_CacheLoader(vfs, L".dds"), m_DisableGL(disableGL), + m_TextureConverter(vfs, highQuality), m_DefaultHandle(0), + m_ErrorTexture(CColor(1.0f, 0.0f, 1.0f, 1.0f), vfs, L"(error texture)", disableGL, this), + m_WhiteTexture(CColor(1.0f, 1.0f, 1.0f, 1.0f), vfs, L"(white texture)", disableGL, this), + m_TransparentTexture(CColor(0.0f, 0.0f, 0.0f, 0.0f), vfs, L"(transparent texture)", disableGL, this) { // Initialise some textures that will always be available, // without needing to load any files @@ -103,29 +154,6 @@ public: ignore_result(ogl_tex_upload(m_DefaultHandle)); } - // Error texture (magenta) - if (!m_DisableGL) - { - // Construct 1x1 24-bit texture - std::shared_ptr data(new u8[3], ArrayDeleter()); - data.get()[0] = 255; - data.get()[1] = 0; - data.get()[2] = 255; - Tex t; - ignore_result(t.wrap(1, 1, 24, 0, data, 0)); - - m_ErrorHandle = ogl_tex_wrap(&t, m_VFS, L"(error texture)"); - ignore_result(ogl_tex_set_filter(m_ErrorHandle, GL_LINEAR)); - if (!m_DisableGL) - ignore_result(ogl_tex_upload(m_ErrorHandle)); - - // Construct a CTexture to return to callers who want an error texture - CTextureProperties props(L"(error texture)"); - m_ErrorTexture = CTexturePtr(new CTexture(m_ErrorHandle, props, this)); - m_ErrorTexture->m_State = CTexture::LOADED; - m_ErrorTexture->m_Self = m_ErrorTexture; - } - // Allow hotloading of textures RegisterFileReloadFunc(ReloadChangedFileCB, this); } @@ -135,12 +163,21 @@ public: UnregisterFileReloadFunc(ReloadChangedFileCB, this); ignore_result(ogl_tex_free(m_DefaultHandle)); - ignore_result(ogl_tex_free(m_ErrorHandle)); } CTexturePtr GetErrorTexture() { - return m_ErrorTexture; + return m_ErrorTexture.GetTexture(); + } + + CTexturePtr GetWhiteTexture() + { + return m_WhiteTexture.GetTexture(); + } + + CTexturePtr GetTransparentTexture() + { + return m_TransparentTexture.GetTexture(); } /** @@ -182,7 +219,7 @@ public: LOGERROR("Texture failed to load; \"%s\"", texture->m_Properties.m_Path.string8()); // Replace with error texture to make it obvious - texture->SetHandle(m_ErrorHandle); + texture->SetHandle(m_ErrorTexture.GetHandle()); return; } @@ -224,7 +261,7 @@ public: ogl_tex_free(h); // Replace with error texture to make it obvious - texture->SetHandle(m_ErrorHandle); + texture->SetHandle(m_ErrorTexture.GetHandle()); return; } @@ -279,7 +316,7 @@ public: // No source file or archive cache was found, so we can't load the // real texture at all - return the error texture instead LOGERROR("CCacheLoader failed to find archived or source file for: \"%s\"", texture->m_Properties.m_Path.string8()); - texture->SetHandle(m_ErrorHandle); + texture->SetHandle(m_ErrorTexture.GetHandle()); return true; } } @@ -352,7 +389,7 @@ public: else { LOGERROR("Texture failed to convert: \"%s\"", texture->m_Properties.m_Path.string8()); - texture->SetHandle(m_ErrorHandle); + texture->SetHandle(m_ErrorTexture.GetHandle()); } texture->m_State = CTexture::LOADED; return true; @@ -503,8 +540,9 @@ private: CTextureConverter m_TextureConverter; Handle m_DefaultHandle; - Handle m_ErrorHandle; - CTexturePtr m_ErrorTexture; + SingleColorTexture m_ErrorTexture; + SingleColorTexture m_WhiteTexture; + SingleColorTexture m_TransparentTexture; // Cache of all loaded textures using TextureCache = @@ -662,6 +700,16 @@ CTexturePtr CTextureManager::GetErrorTexture() return m->GetErrorTexture(); } +CTexturePtr CTextureManager::GetWhiteTexture() +{ + return m->GetWhiteTexture(); +} + +CTexturePtr CTextureManager::GetTransparentTexture() +{ + return m->GetTransparentTexture(); +} + bool CTextureManager::MakeProgress() { return m->MakeProgress(); diff --git a/source/graphics/TextureManager.h b/source/graphics/TextureManager.h index 0c7809df90..fb6adad372 100644 --- a/source/graphics/TextureManager.h +++ b/source/graphics/TextureManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -94,6 +94,16 @@ public: */ CTexturePtr GetErrorTexture(); + /** + * Returns a single color RGBA texture with CColor(1.0f, 1.0f, 1.0f, 1.0f). + */ + CTexturePtr GetWhiteTexture(); + + /** + * Returns a single color RGBA texture with CColor(0.0f, 0.0f, 0.0f, 0.0f). + */ + CTexturePtr GetTransparentTexture(); + /** * Work on asynchronous texture loading operations, if any. * Returns true if it did any work. @@ -209,6 +219,7 @@ private: class CTexture { friend class CTextureManagerImpl; + friend class SingleColorTexture; friend struct TextureCacheCmp; friend struct TPequal_to; friend struct TPhash; diff --git a/source/gui/ObjectTypes/CGUIDummyObject.h b/source/gui/ObjectTypes/CGUIDummyObject.h index 24f353c196..9ee74d353e 100644 --- a/source/gui/ObjectTypes/CGUIDummyObject.h +++ b/source/gui/ObjectTypes/CGUIDummyObject.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index a12ed58ba9..ea50ab22e4 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -24,6 +24,7 @@ #include "CConsole.h" +#include "graphics/Canvas2D.h" #include "graphics/FontMetrics.h" #include "graphics/ShaderManager.h" #include "graphics/TextRenderer.h" @@ -49,6 +50,8 @@ #include "scriptinterface/ScriptInterface.h" #include "scriptinterface/JSON.h" +#include + namespace { @@ -177,7 +180,6 @@ void CConsole::Update(const float deltaRealTime) } } -//Render Manager. void CConsole::Render() { if (! (m_bVisible || m_bToggle) ) return; @@ -187,25 +189,16 @@ void CConsole::Render() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid); - solidTech->BeginPass(); - CShaderProgramPtr solidShader = solidTech->GetShader(); - - CMatrix3D transform = GetDefaultGuiMatrix(); - - // animation: slide in from top of screen - const float DeltaY = (1.0f - m_fVisibleFrac) * m_fHeight; - transform.PostTranslate(m_fX, m_fY - DeltaY, 0.0f); // move to window position - solidShader->Uniform(str_transform, transform); - - DrawWindow(solidShader); - - solidTech->EndPass(); + DrawWindow(); CShaderTechniquePtr textTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text); textTech->BeginPass(); CTextRenderer textRenderer(textTech->GetShader()); textRenderer.Font(CStrIntern(CONSOLE_FONT)); + // animation: slide in from top of screen + CMatrix3D transform = GetDefaultGuiMatrix(); + const float DeltaY = (1.0f - m_fVisibleFrac) * m_fHeight; + transform.PostTranslate(m_fX, m_fY - DeltaY, 0.0f); // move to window position textRenderer.SetTransform(transform); DrawHistory(textRenderer); @@ -218,43 +211,32 @@ void CConsole::Render() glDisable(GL_BLEND); } - -void CConsole::DrawWindow(CShaderProgramPtr& shader) +void CConsole::DrawWindow() { - float boxVerts[] = { - m_fWidth, 0.0f, - 1.0f, 0.0f, - 1.0f, m_fHeight-1.0f, - m_fWidth, m_fHeight-1.0f + std::vector points = { + CVector2D{m_fWidth, 0.0f}, + CVector2D{1.0f, 0.0f}, + CVector2D{1.0f, m_fHeight - 1.0f}, + CVector2D{m_fWidth, m_fHeight - 1.0f}, + CVector2D{m_fWidth, 0.0f} }; + for (CVector2D& point : points) + point += CVector2D{m_fX, m_fY - (1.0f - m_fVisibleFrac) * m_fHeight}; - shader->VertexPointer(2, GL_FLOAT, 0, boxVerts); - - // Draw Background - // Set the color to a translucent blue - shader->Uniform(str_color, 0.0f, 0.0f, 0.5f, 0.6f); - shader->AssertPointersBound(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - // Draw Border - // Set the color to a translucent yellow - shader->Uniform(str_color, 0.5f, 0.5f, 0.0f, 0.6f); - shader->AssertPointersBound(); - glDrawArrays(GL_LINE_LOOP, 0, 4); + CCanvas2D canvas; + canvas.DrawRect(CRect(points[1], points[3]), CColor(0.0f, 0.0f, 0.5f, 0.6f)); + canvas.DrawLine(points, 1.0f, CColor(0.5f, 0.5f, 0.0f, 0.6f)); if (m_fHeight > m_iFontHeight + 4) { - float lineVerts[] = { - 0.0f, m_fHeight - (float)m_iFontHeight - 4.0f, - m_fWidth, m_fHeight - (float)m_iFontHeight - 4.0f + points = { + CVector2D{0.0f, m_fHeight - static_cast(m_iFontHeight) - 4.0f}, + CVector2D{m_fWidth, m_fHeight - static_cast(m_iFontHeight) - 4.0f} }; - shader->VertexPointer(2, GL_FLOAT, 0, lineVerts); - shader->AssertPointersBound(); - glDrawArrays(GL_LINES, 0, 2); + canvas.DrawLine(points, 1.0f, CColor(0.5f, 0.5f, 0.0f, 0.6f)); } } - void CConsole::DrawHistory(CTextRenderer& textRenderer) { int i = 1; diff --git a/source/ps/CConsole.h b/source/ps/CConsole.h index 4e758129a1..7d779967d9 100644 --- a/source/ps/CConsole.h +++ b/source/ps/CConsole.h @@ -111,7 +111,7 @@ private: bool m_bCursorVisState; // if the cursor should be drawn or not double m_cursorBlinkRate; // cursor blink rate in seconds, if greater than 0.0 - void DrawWindow(CShaderProgramPtr& shader); + void DrawWindow(); void DrawHistory(CTextRenderer& textRenderer); void DrawBuffer(CTextRenderer& textRenderer); void DrawCursor(CTextRenderer& textRenderer); diff --git a/source/ps/CStrInternStatic.h b/source/ps/CStrInternStatic.h index d0b0cc34ff..9b711b7f31 100644 --- a/source/ps/CStrInternStatic.h +++ b/source/ps/CStrInternStatic.h @@ -90,6 +90,7 @@ X(blurTex4) X(blurTex8) X(brightness) X(cameraPos) +X(canvas2d) X(color) X(colorAdd) X(colorMul)