diff --git a/src/OpenGL.h b/src/OpenGL.h index 534cc43d2..796f1ad42 100644 --- a/src/OpenGL.h +++ b/src/OpenGL.h @@ -33,7 +33,7 @@ /* Desktop OpenGL */ #ifndef MAGNUM_TARGET_GLES - #include + #include "OpenGL/GL/gl_magnum.h" /* NaCl has its own gl2.h, the official one causes linker issues. Additionaly to NaCl's gl2ext.h we are including our own to prevent undeclared symbol @@ -45,19 +45,19 @@ #include #include #undef __gl2ext_h_ - #include + #include "OpenGL/GLES2/gl2ext.h" /* Generic OpenGL ES */ #else - #include + #include "OpenGL/KHR/khrplatform.h" #ifndef MAGNUM_TARGET_GLES2 - #include - #include + #include "OpenGL/GLES3/gl3platform.h" + #include "OpenGL/GLES3/gl3.h" #else - #include - #include + #include "OpenGL/GLES2/gl2platform.h" + #include "OpenGL/GLES2/gl2.h" #endif - #include + #include "OpenGL/GLES2/gl2ext.h" #endif #endif diff --git a/src/Shaders/Flat.cpp b/src/Shaders/Flat.cpp index 4ccd75d8e..d0b12c383 100644 --- a/src/Shaders/Flat.cpp +++ b/src/Shaders/Flat.cpp @@ -81,7 +81,7 @@ template Flat::Flat(const Flags flags): tran #endif { transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); - if(!(flags & Flag::Textured)) colorUniform = uniformLocation("color"); + colorUniform = uniformLocation("color"); } #ifndef MAGNUM_TARGET_GLES @@ -90,6 +90,11 @@ template Flat::Flat(const Flags flags): tran { if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureLayer); } + + /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ + #ifdef MAGNUM_TARGET_GLES + setColor(Color4(1.0f)); // Default to white, with full transperancy (so we can see the texture) + #endif } template class Flat<2>; diff --git a/src/Shaders/Flat.frag b/src/Shaders/Flat.frag index 35e85bfcd..c2ea645cf 100644 --- a/src/Shaders/Flat.frag +++ b/src/Shaders/Flat.frag @@ -34,12 +34,20 @@ layout(binding = 0) uniform sampler2D textureData; #else uniform sampler2D textureData; #endif -#else +#endif + #ifdef EXPLICIT_UNIFORM_LOCATION +# ifndef GL_ES +layout(location = 1) uniform vec4 color = vec4(1.0f, 1.0f, 1.0f, 1.0f); +# else layout(location = 1) uniform vec4 color; +# endif #else -uniform lowp vec4 color; -#endif +# ifndef GL_ES +uniform lowp vec4 color = vec4(1.0f, 1.0f, 1.0f, 1.0f); +# else +unfirom lowp vec4 color; +# endif #endif #ifdef TEXTURED @@ -52,7 +60,7 @@ out lowp vec4 fragmentColor; void main() { #ifdef TEXTURED - fragmentColor = texture(textureData, interpolatedTextureCoordinates); + fragmentColor = color * texture(textureData, interpolatedTextureCoordinates); #else fragmentColor = color; #endif diff --git a/src/Shaders/Flat.h b/src/Shaders/Flat.h index 8e2b69627..955a62f2e 100644 --- a/src/Shaders/Flat.h +++ b/src/Shaders/Flat.h @@ -124,7 +124,8 @@ template class MAGNUM_SHADERS_EXPORT Flat: public Abstra * @brief Set color * @return Reference to self (for method chaining) * - * Has no effect if @ref Flag::Textured is set. + * Color will be multiplied with texture + * if @ref Flag::Textured is set. */ Flat& setColor(const Color4& color); @@ -144,7 +145,7 @@ typedef Flat<3> Flat3D; CORRADE_ENUMSET_OPERATORS(Implementation::FlatFlags) template inline Flat& Flat::setColor(const Color4& color) { - if(!(_flags & Flag::Textured)) setUniform(colorUniform, color); + setUniform(colorUniform, color); return *this; } diff --git a/src/Text/AbstractFont.h b/src/Text/AbstractFont.h index 24d8ecdea..21f620c8c 100644 --- a/src/Text/AbstractFont.h +++ b/src/Text/AbstractFont.h @@ -152,17 +152,28 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** @brief Close font */ void close(); - /** @brief Font size */ + /** + * @brief Font size + * + * Returns scale in which @ref lineHeight() and @ref glyphAdvance() is + * returned. + */ Float size() const { return _size; } - /** @brief Line height */ + /** + * @brief Line height + * + * Returns line height scaled to font size. + * @see @ref size() + */ Float lineHeight() const { return _lineHeight; } /** * @brief Glyph ID for given character * - * @note This function is not meant to be used in performance-critical - * code, only for font observations and conversions. + * @note This function is meant to be used only for font observations + * and conversions. In performance-critical code the @ref layout() + * function should be used instead. */ UnsignedInt glyphId(char32_t character); @@ -170,9 +181,11 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { * @brief Glyph advance * @param glyph Glyph ID * - * @note This function is not meant to be used in performance-critical - * code, only for font observations and conversions. - * @see @ref glyphId() + * Returns glyph advance scaled to font size. + * @note This function is meant to be used only for font observations + * and conversions. In performance-critical code the @ref layout() + * function should be used instead. + * @see @ref glyphId(), @ref size() */ Vector2 glyphAdvance(UnsignedInt glyph); diff --git a/src/Text/Renderer.cpp b/src/Text/Renderer.cpp index b38ee4059..f7127d4f7 100644 --- a/src/Text/Renderer.cpp +++ b/src/Text/Renderer.cpp @@ -44,7 +44,7 @@ template void createIndices(void* output, const UnsignedInt glyphCount) 1---3 1 3---4 */ const T vertex = T(i)*4; - const T pos = T(i)*6; + const UnsignedInt pos = T(i)*6; out[pos] = vertex; out[pos+1] = vertex+1; out[pos+2] = vertex+2; @@ -61,16 +61,18 @@ struct Vertex { Vector2 position, textureCoordinates; }; -std::tuple, Range2D> renderVerticesInternal(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, const Alignment alignment) { +std::tuple, Range2D> renderVerticesInternal(AbstractFont& font, const GlyphCache& cache, const Float size, const std::string& text, const Alignment alignment) { /* Output data, reserve memory as when the text would be ASCII-only. In reality the actual vertex count will be smaller, but allocating more at once is better than reallocating many times later. */ std::vector vertices; vertices.reserve(text.size()*4); - /* Total rendered bounds, intial line position, last+1 vertex on previous line */ + /* Total rendered bounds, intial line position, line increment, last+1 + vertex on previous line */ Range2D rectangle; Vector2 linePosition; + const Vector2 lineAdvance = Vector2::yAxis(font.lineHeight()*size/font.size()); std::size_t lastLineLastVertex = 0; /* Temp buffer so we don't allocate for each new line */ @@ -149,7 +151,7 @@ std::tuple, Range2D> renderVerticesInternal(AbstractFont& fo /* Move to next line */ } while(prevPos = pos+1, - linePosition -= Vector2::yAxis(font.lineHeight()), + linePosition -= lineAdvance, lastLineLastVertex = vertices.size(), pos != std::string::npos); @@ -178,11 +180,11 @@ std::pair, Mesh::IndexType> renderIndicesIntern Containers::Array indices; Mesh::IndexType indexType; - if(vertexCount < 255) { + if(vertexCount <= 256) { indexType = Mesh::IndexType::UnsignedByte; indices = Containers::Array(indexCount*sizeof(UnsignedByte)); createIndices(indices, glyphCount); - } else if(vertexCount < 65535) { + } else if(vertexCount <= 65536) { indexType = Mesh::IndexType::UnsignedShort; indices = Containers::Array(indexCount*sizeof(UnsignedShort)); createIndices(indices, glyphCount); @@ -203,7 +205,6 @@ std::tuple renderInternal(AbstractFont& font, const GlyphCache& c vertexBuffer.setData(vertices, usage); const UnsignedInt glyphCount = vertices.size()/4; - const UnsignedInt vertexCount = glyphCount*4; const UnsignedInt indexCount = glyphCount*6; /* Render indices and upload them */ @@ -217,7 +218,7 @@ std::tuple renderInternal(AbstractFont& font, const GlyphCache& c Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .setIndexCount(indexCount) - .setIndexBuffer(indexBuffer, 0, indexType, 0, vertexCount); + .setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size()); return std::make_tuple(std::move(mesh), rectangle); } diff --git a/src/Text/Test/RendererGLTest.cpp b/src/Text/Test/RendererGLTest.cpp index 7822b74ab..c3a8b1e9d 100644 --- a/src/Text/Test/RendererGLTest.cpp +++ b/src/Text/Test/RendererGLTest.cpp @@ -34,6 +34,7 @@ class RendererGLTest: public Magnum::Test::AbstractOpenGLTester { void renderData(); void renderMesh(); + void renderMeshIndexType(); void mutableText(); void multiline(); @@ -42,6 +43,7 @@ class RendererGLTest: public Magnum::Test::AbstractOpenGLTester { RendererGLTest::RendererGLTest() { addTests({&RendererGLTest::renderData, &RendererGLTest::renderMesh, + &RendererGLTest::renderMeshIndexType, &RendererGLTest::mutableText, &RendererGLTest::multiline}); @@ -169,7 +171,8 @@ void RendererGLTest::renderMesh() { Mesh mesh; Buffer vertexBuffer, indexBuffer; Range2D bounds; - std::tie(mesh, bounds) = Text::Renderer3D::render(font, *static_cast(nullptr), 0.25f, "abc", vertexBuffer, indexBuffer, BufferUsage::StaticDraw, Alignment::TopCenter); + std::tie(mesh, bounds) = Text::Renderer3D::render(font, *static_cast(nullptr), + 0.25f, "abc", vertexBuffer, indexBuffer, BufferUsage::StaticDraw, Alignment::TopCenter); MAGNUM_VERIFY_NO_ERROR(); /* Alignment offset */ @@ -181,7 +184,8 @@ void RendererGLTest::renderMesh() { /** @todo How to verify this on ES? */ #ifndef MAGNUM_TARGET_GLES /* Vertex buffer contents */ - Containers::Array vertices = vertexBuffer.data(); + const Containers::Array vertices = vertexBuffer.data(); + CORRADE_COMPARE(vertices.size(), 3*4*(2 + 2)); CORRADE_COMPARE(std::vector(vertices.begin(), vertices.end()), (std::vector{ 0.0f + offset.x(), 0.5f + offset.y(), 0.0f, 10.0f, 0.0f + offset.x(), 0.0f + offset.y(), 0.0f, 0.0f, @@ -199,7 +203,8 @@ void RendererGLTest::renderMesh() { 5.0f + offset.x(), -0.5f + offset.y(), 18.0f, 0.0f })); - Containers::Array indices = indexBuffer.data(); + const Containers::Array indices = indexBuffer.data(); + CORRADE_COMPARE(indices.size(), 3*6); CORRADE_COMPARE(std::vector(indices.begin(), indices.end()), (std::vector{ 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, @@ -208,6 +213,45 @@ void RendererGLTest::renderMesh() { #endif } +void RendererGLTest::renderMeshIndexType() { + #ifndef MAGNUM_TARGET_GLES + TestFont font; + Mesh mesh; + Buffer vertexBuffer, indexBuffer; + + /* Sizes: four vertices per glyph, each vertex has 2D position and 2D + texture coordinates, each float is four bytes; six indices per glyph. */ + + /* 8-bit indices (exactly 256 vertices) */ + std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, *static_cast(nullptr), + 1.0f, std::string(64, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw); + MAGNUM_VERIFY_NO_ERROR(); + Containers::Array indicesByte = indexBuffer.data(); + CORRADE_COMPARE(vertexBuffer.size(), 256*(2 + 2)*4); + CORRADE_COMPARE(indicesByte.size(), 64*6); + CORRADE_COMPARE(std::vector(indicesByte.begin(), indicesByte.begin()+18), (std::vector{ + 0, 1, 2, 1, 3, 2, + 4, 5, 6, 5, 7, 6, + 8, 9, 10, 9, 11, 10 + })); + + /* 16-bit indices (260 vertices) */ + std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, *static_cast(nullptr), + 1.0f, std::string(65, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw); + MAGNUM_VERIFY_NO_ERROR(); + Containers::Array indicesShort = indexBuffer.data(); + CORRADE_COMPARE(vertexBuffer.size(), 260*(2 + 2)*4); + CORRADE_COMPARE(indicesShort.size(), 65*6); + CORRADE_COMPARE(std::vector(indicesShort.begin(), indicesShort.begin()+18), (std::vector{ + 0, 1, 2, 1, 3, 2, + 4, 5, 6, 5, 7, 6, + 8, 9, 10, 9, 11, 10 + })); + #else + CORRADE_SKIP("Can't verify buffer contents on OpenGL ES."); + #endif +} + void RendererGLTest::mutableText() { TestFont font; Text::Renderer2D renderer(font, *static_cast(nullptr), 0.25f); @@ -264,7 +308,7 @@ void RendererGLTest::mutableText() { void RendererGLTest::multiline() { class Layouter: public Text::AbstractLayouter { public: - explicit Layouter(UnsignedInt glyphs): AbstractLayouter(glyphs) {} + explicit Layouter(UnsignedInt glyphCount): AbstractLayouter(glyphCount) {} private: std::tuple doRenderGlyph(UnsignedInt) override { @@ -284,7 +328,7 @@ void RendererGLTest::multiline() { std::pair doOpenFile(const std::string&, Float) { _opened = true; - return {0, 3.0f}; + return {0.5f, 0.75f}; } UnsignedInt doGlyphId(char32_t) override { return 0; } @@ -303,7 +347,12 @@ void RendererGLTest::multiline() { std::vector indices; std::vector positions, textureCoordinates; std::tie(positions, textureCoordinates, indices, rectangle) = Text::Renderer2D::render(font, - *static_cast(nullptr), 0.0f, "abcd\nef\n\nghi", Alignment::MiddleCenter); + *static_cast(nullptr), 2.0f, "abcd\nef\n\nghi", Alignment::MiddleCenter); + + /* We're rendering text at 2.0f size and the font is scaled to 0.3f, so the + line advance should be 0.75f*2.0f/0.5f = 3.0f */ + CORRADE_COMPARE(font.size(), 0.5f); + CORRADE_COMPARE(font.lineHeight(), 0.75f); /* Bounds */ CORRADE_COMPARE(rectangle, Range2D({-3.5f, -5.0f}, {3.5f, 5.0f}));