mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
6.1 KiB
152 lines
6.1 KiB
#ifndef Magnum_TextureTools_DistanceField_h |
|
#define Magnum_TextureTools_DistanceField_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
/** @file |
|
* @brief Function @ref Magnum::TextureTools::distanceField() |
|
*/ |
|
|
|
#include "Magnum/configure.h" |
|
|
|
#ifdef MAGNUM_TARGET_GL |
|
#include <Corrade/Containers/Pointer.h> |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/GL/GL.h" |
|
#ifndef MAGNUM_TARGET_GLES |
|
#include "Magnum/Math/Vector2.h" |
|
#endif |
|
#include "Magnum/TextureTools/visibility.h" |
|
|
|
namespace Magnum { namespace TextureTools { |
|
|
|
/** |
|
@brief Create a signed distance field |
|
|
|
Converts a binary black/white image (stored in the red channel of @p input) to |
|
a signed distance field (stored in the red channel of @p output @p rectangle). |
|
The purpose of this function is to convert a high-resolution binary image (such |
|
as vector artwork or font glyphs) to a low-resolution grayscale image. The |
|
image will then occupy much less memory and can be scaled without aliasing |
|
issues. Additionally it provides foundation for features like outlining, glow |
|
or drop shadow essentially for free. |
|
|
|
You can also use the @ref magnum-distancefieldconverter "magnum-distancefieldconverter" |
|
utility to do distance field conversion on command-line. This functionality is |
|
also used inside the @ref magnum-fontconverter "magnum-fontconverter" utility. |
|
|
|
@section TextureTools-DistanceField-algorithm The algorithm |
|
|
|
For each pixel inside the @p output sub-rectangle the algorithm looks at |
|
corresponding pixel in the input and tries to find nearest pixel of opposite |
|
color in an area defined @p radius. Signed distance between the points is then |
|
saved as value of given pixel in @p output. Value of 1.0 means that the pixel |
|
was originally colored white and nearest black pixel is farther than @p radius, |
|
value of 0.0 means that the pixel was originally black and nearest white pixel |
|
is farther than @p radius. Values around 0.5 are around edges. |
|
|
|
The resulting texture can be used with bilinear filtering. It can be converted |
|
back to binary form in shader using e.g. GLSL @glsl smoothstep() @ce function |
|
with step around 0.5 to create antialiased edges. Or you can exploit the |
|
distance field features to create many other effects. See also |
|
@ref Shaders::DistanceFieldVector. |
|
|
|
Based on: *Chris Green - Improved Alpha-Tested Magnification for Vector Textures |
|
and Special Effects, SIGGRAPH 2007, |
|
http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf* |
|
|
|
@attention This is a GPU-only implementation, so it expects an active GL |
|
context. |
|
|
|
@note If internal format of @p output texture is not renderable, this function |
|
prints a message to error output and does nothing. On desktop OpenGL and |
|
OpenGL ES 3.0 it's common to render to @ref GL::TextureFormat::R8. On |
|
OpenGL ES 2.0 you can use @ref GL::TextureFormat::Red if |
|
@gl_extension{EXT,texture_rg} is available; if not, the smallest but still |
|
inefficient supported format is in most cases @ref GL::TextureFormat::RGB, |
|
rendering to @ref GL::TextureFormat::Luminance is not supported in most |
|
cases. |
|
|
|
@note This function is available only if Magnum is compiled with |
|
@ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features |
|
for more information. |
|
*/ |
|
class MAGNUM_TEXTURETOOLS_EXPORT DistanceField { |
|
public: |
|
/** |
|
* @brief Constructor |
|
* @param radius Max lookup radius in the input texture |
|
* |
|
* Prepares the shader and other internal state for given @p radius. |
|
*/ |
|
explicit DistanceField(UnsignedInt radius); |
|
|
|
~DistanceField(); |
|
|
|
/** @brief Max lookup radius */ |
|
UnsignedInt radius() const; |
|
|
|
/** |
|
* @brief Calculate the distance field |
|
* @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(). |
|
*/ |
|
void operator()(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Vector2i& imageSize |
|
#ifndef MAGNUM_TARGET_GLES |
|
= {} |
|
#endif |
|
); |
|
|
|
private: |
|
struct State; |
|
Containers::Pointer<State> _state; |
|
}; |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
@brief Create a signed distance field |
|
@deprecated Deprecated due to inefficiency of its statelessness when doing |
|
batch processing. Use the @ref DistanceField class instead. |
|
*/ |
|
inline CORRADE_DEPRECATED("use the DistanceField class instead") void distanceField(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, Int radius, const Vector2i& imageSize |
|
#ifndef MAGNUM_TARGET_GLES |
|
= Vector2i{} |
|
#endif |
|
) { |
|
DistanceField{UnsignedInt(radius)}(input, output, rectangle, imageSize); |
|
} |
|
#endif |
|
|
|
}} |
|
#else |
|
#error this header is available only in the OpenGL build |
|
#endif |
|
|
|
#endif
|
|
|