Browse Source

Split the OpenGL layer out, pt 19: adapted TextureTools.

pull/233/head
Vladimír Vondruš 8 years ago
parent
commit
22fa80b35f
  1. 76
      src/Magnum/TextureTools/DistanceField.cpp
  2. 21
      src/Magnum/TextureTools/DistanceField.h
  3. 19
      src/Magnum/TextureTools/distancefieldconverter.cpp

76
src/Magnum/TextureTools/DistanceField.cpp

@ -28,14 +28,14 @@
#include <Corrade/Utility/Resource.h> #include <Corrade/Utility/Resource.h>
#include "Magnum/Math/Range.h" #include "Magnum/Math/Range.h"
#include "Magnum/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/Buffer.h" #include "Magnum/GL/Buffer.h"
#include "Magnum/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/Framebuffer.h" #include "Magnum/GL/Framebuffer.h"
#include "Magnum/Mesh.h" #include "Magnum/GL/Mesh.h"
#include "Magnum/Shader.h" #include "Magnum/GL/Shader.h"
#include "Magnum/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Shaders/Implementation/CreateCompatibilityShader.h" #include "Magnum/Shaders/Implementation/CreateCompatibilityShader.h"
#ifdef MAGNUM_BUILD_STATIC #ifdef MAGNUM_BUILD_STATIC
@ -48,9 +48,9 @@ namespace Magnum { namespace TextureTools {
namespace { namespace {
class DistanceFieldShader: public AbstractShaderProgram { class DistanceFieldShader: public GL::AbstractShaderProgram {
public: public:
typedef Attribute<0, Vector2> Position; typedef GL::Attribute<0, Vector2> Position;
explicit DistanceFieldShader(); explicit DistanceFieldShader();
@ -69,7 +69,7 @@ class DistanceFieldShader: public AbstractShaderProgram {
return *this; return *this;
} }
DistanceFieldShader& bindTexture(Texture2D& texture) { DistanceFieldShader& bindTexture(GL::Texture2D& texture) {
texture.bind(TextureUnit); texture.bind(TextureUnit);
return *this; return *this;
} }
@ -91,27 +91,27 @@ DistanceFieldShader::DistanceFieldShader() {
Utility::Resource rs("MagnumTextureTools"); Utility::Resource rs("MagnumTextureTools");
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
const Version v = Context::current().supportedVersion({Version::GL320, Version::GL300, Version::GL210}); const GL::Version v = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL300, GL::Version::GL210});
#else #else
const Version v = Context::current().supportedVersion({Version::GLES300, Version::GLES200}); const GL::Version v = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200});
#endif #endif
Shader vert = Shaders::Implementation::createCompatibilityShader(rs, v, Shader::Type::Vertex); GL::Shader vert = Shaders::Implementation::createCompatibilityShader(rs, v, GL::Shader::Type::Vertex);
Shader frag = Shaders::Implementation::createCompatibilityShader(rs, v, Shader::Type::Fragment); GL::Shader frag = Shaders::Implementation::createCompatibilityShader(rs, v, GL::Shader::Type::Fragment);
vert.addSource(rs.get("FullScreenTriangle.glsl")) vert.addSource(rs.get("FullScreenTriangle.glsl"))
.addSource(rs.get("DistanceFieldShader.vert")); .addSource(rs.get("DistanceFieldShader.vert"));
frag.addSource(rs.get("DistanceFieldShader.frag")); frag.addSource(rs.get("DistanceFieldShader.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
attachShaders({vert, frag}); attachShaders({vert, frag});
/* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */ /* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isVersionSupported(Version::GL300)) if(!GL::Context::current().isVersionSupported(GL::Version::GL300))
#else #else
if(!Context::current().isVersionSupported(Version::GLES300)) if(!GL::Context::current().isVersionSupported(GL::Version::GLES300))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); bindAttributeLocation(Position::Location, "position");
@ -120,16 +120,16 @@ DistanceFieldShader::DistanceFieldShader() {
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>())
#endif #endif
{ {
radiusUniform = uniformLocation("radius"); radiusUniform = uniformLocation("radius");
scalingUniform = uniformLocation("scaling"); scalingUniform = uniformLocation("scaling");
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isVersionSupported(Version::GL320)) if(!GL::Context::current().isVersionSupported(GL::Version::GL320))
#else #else
if(!Context::current().isVersionSupported(Version::GLES300)) if(!GL::Context::current().isVersionSupported(GL::Version::GLES300))
#endif #endif
{ {
imageSizeInvertedUniform = uniformLocation("imageSizeInverted"); imageSizeInvertedUniform = uniformLocation("imageSizeInverted");
@ -137,7 +137,7 @@ DistanceFieldShader::DistanceFieldShader() {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>())
#endif #endif
{ {
setUniform(uniformLocation("textureData"), TextureUnit); setUniform(uniformLocation("textureData"), TextureUnit);
@ -146,13 +146,13 @@ DistanceFieldShader::DistanceFieldShader() {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangle, const Int radius, const Vector2i&) void distanceField(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Int radius, const Vector2i&)
#else #else
void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangle, const Int radius, const Vector2i& imageSize) void distanceField(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, const Int radius, const Vector2i& imageSize)
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::framebuffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::framebuffer_object);
#endif #endif
/** @todo Disable depth test, blending and then enable it back (if was previously) */ /** @todo Disable depth test, blending and then enable it back (if was previously) */
@ -161,13 +161,13 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl
Vector2i imageSize = input.imageSize(0); Vector2i imageSize = input.imageSize(0);
#endif #endif
Framebuffer framebuffer(rectangle); GL::Framebuffer framebuffer(rectangle);
framebuffer.attachTexture(Framebuffer::ColorAttachment(0), output, 0); framebuffer.attachTexture(GL::Framebuffer::ColorAttachment(0), output, 0);
framebuffer.bind(); framebuffer.bind();
framebuffer.clear(FramebufferClear::Color); framebuffer.clear(GL::FramebufferClear::Color);
const Framebuffer::Status status = framebuffer.checkStatus(FramebufferTarget::Draw); const GL::Framebuffer::Status status = framebuffer.checkStatus(GL::FramebufferTarget::Draw);
if(status != Framebuffer::Status::Complete) { if(status != GL::Framebuffer::Status::Complete) {
Error() << "TextureTools::distanceField(): cannot render to given output texture, unexpected framebuffer status" Error() << "TextureTools::distanceField(): cannot render to given output texture, unexpected framebuffer status"
<< status; << status;
return; return;
@ -179,24 +179,24 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl
.bindTexture(input); .bindTexture(input);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isVersionSupported(Version::GL320)) if(!GL::Context::current().isVersionSupported(GL::Version::GL320))
#else #else
if(!Context::current().isVersionSupported(Version::GLES300)) if(!GL::Context::current().isVersionSupported(GL::Version::GLES300))
#endif #endif
{ {
shader.setImageSizeInverted(1.0f/Vector2(imageSize)); shader.setImageSizeInverted(1.0f/Vector2(imageSize));
} }
Mesh mesh; GL::Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(GL::MeshPrimitive::Triangles)
.setCount(3); .setCount(3);
/* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */ /* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */
Buffer buffer; GL::Buffer buffer;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isVersionSupported(Version::GL300)) if(!GL::Context::current().isVersionSupported(GL::Version::GL300))
#else #else
if(!Context::current().isVersionSupported(Version::GLES300)) if(!GL::Context::current().isVersionSupported(GL::Version::GLES300))
#endif #endif
{ {
constexpr Vector2 triangle[] = { constexpr Vector2 triangle[] = {
@ -204,7 +204,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl
Vector2(-1.0, -3.0), Vector2(-1.0, -3.0),
Vector2( 3.0, 1.0) Vector2( 3.0, 1.0)
}; };
buffer.setData(triangle, BufferUsage::StaticDraw); buffer.setData(triangle, GL::BufferUsage::StaticDraw);
mesh.addVertexBuffer(buffer, 0, DistanceFieldShader::Position()); mesh.addVertexBuffer(buffer, 0, DistanceFieldShader::Position());
} }

21
src/Magnum/TextureTools/DistanceField.h

@ -29,11 +29,11 @@
* @brief Function @ref Magnum::TextureTools::distanceField() * @brief Function @ref Magnum::TextureTools::distanceField()
*/ */
#include "Magnum/Magnum.h"
#include "Magnum/GL/GL.h"
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
#include "Magnum/Math/Vector2.h" #include "Magnum/Math/Vector2.h"
#endif #endif
#include "Magnum/Magnum.h"
#include "Magnum/TextureTools/visibility.h" #include "Magnum/TextureTools/visibility.h"
namespace Magnum { namespace TextureTools { namespace Magnum { namespace TextureTools {
@ -46,7 +46,7 @@ namespace Magnum { namespace TextureTools {
@param radius Max lookup radius in input texture @param radius Max lookup radius in input texture
@param imageSize Input texture size. Needed only in OpenGL ES, in desktop @param imageSize Input texture size. Needed only in OpenGL ES, in desktop
OpenGL the information is gathered automatically using OpenGL the information is gathered automatically using
@ref Texture2D::imageSize(). @ref GL::Texture2D::imageSize().
Converts binary image (stored in red channel of @p input) to signed distance Converts binary image (stored in red channel of @p input) to signed distance
field (stored in red channel in @p rectangle of @p output). The purpose of this field (stored in red channel in @p rectangle of @p output). The purpose of this
@ -85,19 +85,20 @@ http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnifica
@note If internal format of @p output texture is not renderable, this function @note If internal format of @p output texture is not renderable, this function
prints message to error output and does nothing. In desktop OpenGL and prints message to error output and does nothing. In desktop OpenGL and
OpenGL ES 3.0 it's common to render to @ref TextureFormat::R8. In OpenGL ES OpenGL ES 3.0 it's common to render to @ref GL::TextureFormat::R8. In
2.0 you can use @ref TextureFormat::Red if @extension{EXT,texture_rg} is OpenGL ES 2.0 you can use @ref GL::TextureFormat::Red if
available, if not, the smallest but still inefficient supported format is @extension{EXT,texture_rg} is available, if not, the smallest but still
in most cases @ref TextureFormat::RGB, rendering to @ref TextureFormat::Luminance inefficient supported format is in most cases @ref GL::TextureFormat::RGB,
is not supported in most cases. rendering to @ref GL::TextureFormat::Luminance is not supported in most
cases.
@bug ES (and maybe GL < 3.20) implementation behaves slightly different @bug ES (and maybe GL < 3.20) implementation behaves slightly different
(jaggies, visible e.g. when rendering outlined fonts) (jaggies, visible e.g. when rendering outlined fonts)
*/ */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_TEXTURETOOLS_EXPORT distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangle, Int radius, const Vector2i& imageSize = Vector2i()); void MAGNUM_TEXTURETOOLS_EXPORT distanceField(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, Int radius, const Vector2i& imageSize = Vector2i());
#else #else
void MAGNUM_TEXTURETOOLS_EXPORT distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangle, Int radius, const Vector2i& imageSize); void MAGNUM_TEXTURETOOLS_EXPORT distanceField(GL::Texture2D& input, GL::Texture2D& output, const Range2Di& rectangle, Int radius, const Vector2i& imageSize);
#endif #endif
}} }}

19
src/Magnum/TextureTools/distancefieldconverter.cpp

@ -27,12 +27,12 @@
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include "Magnum/Math/Range.h"
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
#include "Magnum/Renderer.h" #include "Magnum/Math/Range.h"
#include "Magnum/Texture.h" #include "Magnum/GL/Renderer.h"
#include "Magnum/TextureFormat.h" #include "Magnum/GL/Texture.h"
#include "Magnum/GL/TextureFormat.h"
#include "Magnum/TextureTools/DistanceField.h" #include "Magnum/TextureTools/DistanceField.h"
#include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/AbstractImageConverter.h" #include "Magnum/Trade/AbstractImageConverter.h"
@ -87,7 +87,8 @@ Arguments:
- `--plugin-dir DIR` --- override base plugin dir - `--plugin-dir DIR` --- override base plugin dir
- `--output-size "X Y"` --- size of output image - `--output-size "X Y"` --- size of output image
- `--radius N` --- distance field computation radius - `--radius N` --- distance field computation radius
- `--magnum-...` --- engine-specific options (see @ref Context for details) - `--magnum-...` --- engine-specific options (see
@ref GL-Context-command-line for details)
Images with @ref PixelFormat::Red, @ref PixelFormat::RGB or @ref PixelFormat::RGBA Images with @ref PixelFormat::Red, @ref PixelFormat::RGB or @ref PixelFormat::RGBA
are accepted on input. are accepted on input.
@ -158,7 +159,7 @@ int DistanceFieldConverter::exec() {
} }
/* Decide about internal format */ /* Decide about internal format */
TextureFormat internalFormat; GL::TextureFormat internalFormat;
if(image->format() == PixelFormat::Red) internalFormat = TextureFormat::R8; if(image->format() == PixelFormat::Red) internalFormat = TextureFormat::R8;
else if(image->format() == PixelFormat::RGB) internalFormat = TextureFormat::RGB8; else if(image->format() == PixelFormat::RGB) internalFormat = TextureFormat::RGB8;
else if(image->format() == PixelFormat::RGBA) internalFormat = TextureFormat::RGBA8; else if(image->format() == PixelFormat::RGBA) internalFormat = TextureFormat::RGBA8;
@ -168,7 +169,7 @@ int DistanceFieldConverter::exec() {
} }
/* Input texture */ /* Input texture */
Texture2D input; GL::Texture2D input;
input.setMinificationFilter(Sampler::Filter::Linear) input.setMinificationFilter(Sampler::Filter::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
.setWrapping(Sampler::Wrapping::ClampToEdge) .setWrapping(Sampler::Wrapping::ClampToEdge)
@ -176,10 +177,10 @@ int DistanceFieldConverter::exec() {
.setSubImage(0, {}, *image); .setSubImage(0, {}, *image);
/* Output texture */ /* Output texture */
Texture2D output; GL::Texture2D output;
output.setStorage(1, TextureFormat::R8, args.value<Vector2i>("output-size")); output.setStorage(1, TextureFormat::R8, args.value<Vector2i>("output-size"));
CORRADE_INTERNAL_ASSERT(Renderer::error() == Renderer::Error::NoError); CORRADE_INTERNAL_ASSERT(GL::Renderer::error() == GL::Renderer::Error::NoError);
/* Do it */ /* Do it */
Debug() << "Converting image of size" << image->size() << "to distance field..."; Debug() << "Converting image of size" << image->size() << "to distance field...";

Loading…
Cancel
Save