Index: ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.vp =================================================================== --- ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.vp +++ ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.vp @@ -1,11 +1,14 @@ !!ARBvp1.0 -PARAM transform[4] = { program.local[0..3] }; +PARAM transform = program.local[0]; +PARAM translation = program.local[1]; TEMP position; -DP4 position.x, transform[0], vertex.position; -DP4 position.y, transform[1], vertex.position; +MUL position, transform, vertex.position.xyxy; +ADD position.x, position.x, position.y; +ADD position.y, position.z, position.w; +ADD position, position, translation; MOV position.z, 0.0; MOV position.w, 1.0; Index: ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.xml =================================================================== --- ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.xml +++ ps/trunk/binaries/data/mods/mod/shaders/arb/canvas2d.xml @@ -4,7 +4,8 @@ - + + Index: ps/trunk/binaries/data/mods/mod/shaders/glsl/canvas2d.vs =================================================================== --- ps/trunk/binaries/data/mods/mod/shaders/glsl/canvas2d.vs +++ ps/trunk/binaries/data/mods/mod/shaders/glsl/canvas2d.vs @@ -1,6 +1,7 @@ #version 110 -uniform mat4 transform; +uniform vec4 transform; +uniform vec2 translation; attribute vec2 a_vertex; attribute vec2 a_uv0; @@ -10,5 +11,5 @@ void main() { v_uv = a_uv0; - gl_Position = transform * vec4(a_vertex, 0.0, 1.0); + gl_Position = vec4(mat2(transform.xy, transform.zw) * a_vertex + translation, 0.0, 1.0); } Index: ps/trunk/source/graphics/Canvas2D.cpp =================================================================== --- ps/trunk/source/graphics/Canvas2D.cpp +++ ps/trunk/source/graphics/Canvas2D.cpp @@ -39,6 +39,7 @@ struct SBindingSlots { int32_t transform; + int32_t translation; int32_t colorAdd; int32_t colorMul; int32_t grayscaleFactor; @@ -111,14 +112,20 @@ Renderer::Backend::IShaderProgram* shader = Tech->GetShader(); BindingSlots.transform = shader->GetBindingSlot(str_transform); + BindingSlots.translation = shader->GetBindingSlot(str_translation); BindingSlots.colorAdd = shader->GetBindingSlot(str_colorAdd); BindingSlots.colorMul = shader->GetBindingSlot(str_colorMul); BindingSlots.grayscaleFactor = shader->GetBindingSlot(str_grayscaleFactor); BindingSlots.tex = shader->GetBindingSlot(str_tex); const CMatrix3D transform = GetTransform(); + TransformScale = CVector2D(transform._11, transform._22); + Translation = CVector2D(transform._14, transform._24); DeviceCommandContext->SetUniform( - BindingSlots.transform, transform.AsFloatArray()); + BindingSlots.transform, + transform._11, transform._21, transform._12, transform._22); + DeviceCommandContext->SetUniform( + BindingSlots.translation, Translation.AsFloatArray()); } void UnbindTech() @@ -153,6 +160,8 @@ uint32_t WidthInPixels = 1; uint32_t HeightInPixels = 1; float Scale = 1.0f; + CVector2D TransformScale; + CVector2D Translation; Renderer::Backend::IDeviceCommandContext* DeviceCommandContext = nullptr; CShaderTechniquePtr Tech; @@ -440,7 +449,8 @@ m->DeviceCommandContext->SetUniform( m->BindingSlots.grayscaleFactor, 0.0f); - textRenderer.Render(m->DeviceCommandContext, m->Tech->GetShader(), m->GetTransform()); + textRenderer.Render( + m->DeviceCommandContext, m->Tech->GetShader(), m->TransformScale, m->Translation); } void CCanvas2D::Flush() Index: ps/trunk/source/graphics/TextRenderer.h =================================================================== --- ps/trunk/source/graphics/TextRenderer.h +++ ps/trunk/source/graphics/TextRenderer.h @@ -105,7 +105,8 @@ */ void Render( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, - Renderer::Backend::IShaderProgram* shader, const CMatrix3D& transform); + Renderer::Backend::IShaderProgram* shader, + const CVector2D& transformScale, const CVector2D& translation); private: friend struct SBatchCompare; Index: ps/trunk/source/graphics/TextRenderer.cpp =================================================================== --- ps/trunk/source/graphics/TextRenderer.cpp +++ ps/trunk/source/graphics/TextRenderer.cpp @@ -203,7 +203,8 @@ void CTextRenderer::Render( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, - Renderer::Backend::IShaderProgram* shader, const CMatrix3D& transform) + Renderer::Backend::IShaderProgram* shader, + const CVector2D& transformScale, const CVector2D& translation) { std::vector indexes; std::vector vertexes; @@ -225,11 +226,11 @@ } const int32_t texBindingSlot = shader->GetBindingSlot(str_tex); - const int32_t transformBindingSlot = shader->GetBindingSlot(str_transform); + const int32_t translationBindingSlot = shader->GetBindingSlot(str_translation); const int32_t colorAddBindingSlot = shader->GetBindingSlot(str_colorAdd); const int32_t colorMulBindingSlot = shader->GetBindingSlot(str_colorMul); - bool transformChanged = false; + bool translationChanged = false; CTexture* lastTexture = nullptr; for (std::list::iterator it = m_Batches.begin(); it != m_Batches.end(); ++it) @@ -247,11 +248,10 @@ if (batch.translate.X != 0.0f || batch.translate.Y != 0.0f) { - CMatrix3D localTransform; - localTransform.SetTranslation(batch.translate.X, batch.translate.Y, 0.0f); - localTransform = transform * localTransform; - deviceCommandContext->SetUniform(transformBindingSlot, localTransform.AsFloatArray()); - transformChanged = true; + const CVector2D localTranslation = + translation + CVector2D(batch.translate.X * transformScale.X, batch.translate.Y * transformScale.Y); + deviceCommandContext->SetUniform(translationBindingSlot, localTranslation.AsFloatArray()); + translationChanged = true; } // ALPHA-only textures will have .rgb sampled as 0, so we need to @@ -346,6 +346,6 @@ m_Batches.clear(); - if (transformChanged) - deviceCommandContext->SetUniform(transformBindingSlot, transform.AsFloatArray()); + if (translationChanged) + deviceCommandContext->SetUniform(translationBindingSlot, translation.AsFloatArray()); } Index: ps/trunk/source/maths/Vector2D.h =================================================================== --- ps/trunk/source/maths/Vector2D.h +++ ps/trunk/source/maths/Vector2D.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -18,6 +18,8 @@ #ifndef INCLUDED_VECTOR2D #define INCLUDED_VECTOR2D +#include "ps/containers/Span.h" + #include class CSize2D; @@ -161,6 +163,19 @@ void operator+=(const CSize2D& size); void operator-=(const CSize2D& size); + // Returns 2 element array of floats, e.g. for vec2 uniforms. + PS::span AsFloatArray() const + { + // Additional check to prevent a weird compiler having a different + // alignement for an array and a class members. + static_assert( + sizeof(CVector2D) == sizeof(float) * 2u && + offsetof(CVector2D, X) == 0 && + offsetof(CVector2D, Y) == sizeof(float), + "Vector2D should be properly layouted to use AsFloatArray"); + return PS::span(&X, 2); + } + public: float X, Y; };