Browse Source

TextureTools: add a DistanceField overload taking a framebuffer.

So one can directly read it back on GLES without having to wrap the
texture in a framebuffer again.

This change also puts the framebuffer completeness check *before* the
clear() and bind() which makes it no longer emit a GL error. The error
is still silent though, which isn't nice. Gotta fix that eventually as
well.
pull/617/head
Vladimír Vondruš 3 years ago
parent
commit
5f55f9e756
  1. 3
      doc/changelog.dox
  2. 30
      src/Magnum/TextureTools/DistanceField.cpp
  3. 21
      src/Magnum/TextureTools/DistanceField.h
  4. 22
      src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp

3
doc/changelog.dox

@ -329,6 +329,9 @@ See also:
- New @ref TextureTools::atlasArrayPowerOfTwo() utility for optimal packing
of power-of-two textures into a texture atlas array
- Added a @ref TextureTools::DistanceField::operator()() overload taking a
@ref GL::Framebuffer instead of a @ref GL::Texture as an output for an
easier ability to download the resulting image on OpenGL ES platforms
@subsubsection changelog-latest-new-trade Trade library

30
src/Magnum/TextureTools/DistanceField.cpp

@ -189,7 +189,7 @@ DistanceField::~DistanceField() = default;
UnsignedInt DistanceField::radius() const { return _state->radius; }
void DistanceField::operator()(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Vector2i&
void DistanceField::operator()(GL::Texture2D& input, GL::Framebuffer& output, const Range2Di& rectangle, const Vector2i&
#ifdef MAGNUM_TARGET_GLES
imageSize
#endif
@ -200,20 +200,17 @@ void DistanceField::operator()(GL::Texture2D& input, GL::Texture2D& output, cons
Vector2i imageSize = input.imageSize(0);
#endif
/* Framebuffer is instantiated here so it gets correctly unbound at the end
(and bound framebuffer reset back to the default) */
GL::Framebuffer framebuffer{rectangle};
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment(0), output, 0)
.clear(GL::FramebufferClear::Color)
.bind();
const GL::Framebuffer::Status status = framebuffer.checkStatus(GL::FramebufferTarget::Draw);
const GL::Framebuffer::Status status = output.checkStatus(GL::FramebufferTarget::Draw);
if(status != GL::Framebuffer::Status::Complete) {
Error() << "TextureTools::DistanceField: cannot render to given output texture, unexpected framebuffer status"
<< status;
return;
}
output
.clear(GL::FramebufferClear::Color)
.bind();
_state->shader.setScaling(Vector2(imageSize)/Vector2(rectangle.size()))
.bindTexture(input);
@ -230,4 +227,19 @@ void DistanceField::operator()(GL::Texture2D& input, GL::Texture2D& output, cons
_state->shader.draw(_state->mesh);
}
void DistanceField::operator()(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Vector2i&
#ifdef MAGNUM_TARGET_GLES
imageSize
#endif
) {
GL::Framebuffer framebuffer{rectangle};
framebuffer.attachTexture(GL::Framebuffer::ColorAttachment(0), output, 0);
operator()(input, framebuffer, rectangle
#ifdef MAGNUM_TARGET_GLES
, imageSize
#endif
);
}
}}

21
src/Magnum/TextureTools/DistanceField.h

@ -110,13 +110,32 @@ class MAGNUM_TEXTURETOOLS_EXPORT DistanceField {
UnsignedInt radius() const;
/**
* @brief Calculate the distance field
* @brief Calculate the distance field to a framebuffer
* @param input Input texture
* @param output Output framebuffer
* @param rectangle Rectangle in output texture where to render
* @param imageSize Input texture size. Needed only for OpenGL ES,
* on desktop GL the information is gathered automatically using
* @ref GL::Texture2D::imageSize().
* @m_since_latest
*/
void operator()(GL::Texture2D& input, GL::Framebuffer& output, const Range2Di& rectangle, const Vector2i& imageSize
#ifndef MAGNUM_TARGET_GLES
= {}
#endif
);
/**
* @brief Calculate the distance field to a texture
* @param input Input texture
* @param output Output texture
* @param rectangle Rectangle in output texture where to render
* @param imageSize Input texture size. Needed only for OpenGL ES,
* on desktop GL the information is gathered automatically using
* @ref GL::Texture2D::imageSize().
*
* Creates a framebuffer with @p output attached and calls
* @ref operator()(GL::Texture2D&, GL::Framebuffer&, const Range2Di&, const Vector2i&).
*/
void operator()(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Vector2i& imageSize
#ifndef MAGNUM_TARGET_GLES

22
src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp

@ -23,9 +23,11 @@
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <Corrade/Containers/String.h>
#include <Corrade/PluginManager/AbstractManager.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/DebugStl.h>
#ifdef CORRADE_TARGET_APPLE
#include <Corrade/Containers/Pair.h>
@ -64,6 +66,8 @@ namespace Magnum { namespace TextureTools { namespace Test { namespace {
struct DistanceFieldGLTest: GL::OpenGLTester {
explicit DistanceFieldGLTest();
/* This tests the GL::Texture overload, which itself calls into the
GL::Framebuffer overload so both are covered */
void test();
#ifndef MAGNUM_TARGET_WEBGL
void benchmark();
@ -170,24 +174,28 @@ void DistanceFieldGLTest::test() {
MAGNUM_VERIFY_NO_GL_ERROR();
std::ostringstream out;
{
Error redirectError{&out};
distanceField(input, output, {{}, Vector2i{64}}
#ifdef MAGNUM_TARGET_GLES
, inputImage->size()
#endif
);
}
#ifdef MAGNUM_TARGET_GLES
{
/* Probably due to the luminance target pixel format? Works with 4.1,
didn't find any commit in between that would clearly affect
this. */
CORRADE_EXPECT_FAIL_IF(GL::Context::current().versionString().contains("SwiftShader 4.0.0"_s),
"SwiftShader 4.0.0 has a bug where the framebuffer is considered incomplete.");
MAGNUM_VERIFY_NO_GL_ERROR();
if(GL::Context::current().versionString().contains("SwiftShader 4.0.0"_s))
CORRADE_SKIP("Skipping the rest of the test.");
}
if(GL::Context::current().versionString().contains("SwiftShader 4.0.0"_s)) {
CORRADE_COMPARE(out.str(), "TextureTools::DistanceField: cannot render to given output texture, unexpected framebuffer status GL::Framebuffer::Status::IncompleteAttachment\n");
CORRADE_SKIP("SwiftShader 4.0.0 has a bug where the framebuffer is considered incomplete.");
} else
#endif
{
CORRADE_COMPARE(out.str(), "");
}
Containers::Optional<Image2D> actualOutputImage;
#ifndef MAGNUM_TARGET_GLES2

Loading…
Cancel
Save