Browse Source

Shaders: first DistanceFieldVectorShader implementation.

Currently only fill and outline can be specified. Also crosslinked from
documentation of VectorShader and TextureTools::distanceField().
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
2d98dadb0a
  1. 4
      src/Shaders/CMakeLists.txt
  2. 85
      src/Shaders/DistanceFieldVectorShader.cpp
  3. 49
      src/Shaders/DistanceFieldVectorShader.frag
  4. 118
      src/Shaders/DistanceFieldVectorShader.h
  5. 5
      src/Shaders/Shaders.h
  6. 2
      src/Shaders/VectorShader.h
  7. 2
      src/TextureTools/DistanceField.h

4
src/Shaders/CMakeLists.txt

@ -2,16 +2,18 @@ corrade_add_resource(MagnumShaders_RCS MagnumShaders
AbstractVectorShader2D.vert AbstractVectorShader3D.vert
FlatShader2D.vert FlatShader3D.vert FlatShader.frag
PhongShader.vert PhongShader.frag
VectorShader.frag
VectorShader.frag DistanceFieldVectorShader.frag
VertexColorShader2D.vert VertexColorShader3D.vert VertexColorShader.frag
compatibility.glsl)
set(MagnumShaders_SRCS
DistanceFieldVectorShader.cpp
FlatShader.cpp
PhongShader.cpp
VectorShader.cpp
VertexColorShader.cpp
${MagnumShaders_RCS})
set(MagnumShaders_HEADERS
DistanceFieldVectorShader.h
AbstractVectorShader.h
FlatShader.h
PhongShader.h

85
src/Shaders/DistanceFieldVectorShader.cpp

@ -0,0 +1,85 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "DistanceFieldVectorShader.h"
#include <Utility/Resource.h>
#include "Context.h"
#include "Extensions.h"
#include "Shader.h"
namespace Magnum { namespace Shaders {
namespace {
template<UnsignedInt> constexpr const char* vertexShaderName();
template<> constexpr const char* vertexShaderName<2>() { return "AbstractVectorShader2D.vert"; }
template<> constexpr const char* vertexShaderName<3>() { return "AbstractVectorShader3D.vert"; }
}
template<UnsignedInt dimensions> DistanceFieldVectorShader<dimensions>::DistanceFieldVectorShader(): transformationProjectionMatrixUniform(0), colorUniform(1), outlineColorUniform(2), outlineRangeUniform(3), smoothnessUniform(4) {
Corrade::Utility::Resource rs("MagnumShaders");
#ifndef MAGNUM_TARGET_GLES
Version v = Context::current()->supportedVersion({Version::GL320, Version::GL210});
#else
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
Shader vertexShader(v, Shader::Type::Vertex);
vertexShader.addSource(rs.get("compatibility.glsl"));
vertexShader.addSource(rs.get(vertexShaderName<dimensions>()));
AbstractShaderProgram::attachShader(vertexShader);
Shader fragmentShader(v, Shader::Type::Fragment);
fragmentShader.addSource(rs.get("compatibility.glsl"));
fragmentShader.addSource(rs.get("DistanceFieldVectorShader.frag"));
AbstractShaderProgram::attachShader(fragmentShader);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
Context::current()->version() == Version::GL210) {
#else
if(!Context::current()->isVersionSupported(Version::GLES300)) {
#endif
AbstractShaderProgram::bindAttributeLocation(AbstractVectorShader<dimensions>::Position::Location, "position");
AbstractShaderProgram::bindAttributeLocation(AbstractVectorShader<dimensions>::TextureCoordinates::Location, "textureCoordinates");
}
AbstractShaderProgram::link();
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) {
#else
{
#endif
transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix");
colorUniform = AbstractShaderProgram::uniformLocation("color");
outlineColorUniform = AbstractShaderProgram::uniformLocation("outlineColor");
outlineRangeUniform = AbstractShaderProgram::uniformLocation("outlineRange");
smoothnessUniform = AbstractShaderProgram::uniformLocation("smoothness");
}
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>())
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"),
AbstractVectorShader<dimensions>::VectorTextureLayer);
#endif
}
template class DistanceFieldVectorShader<2>;
template class DistanceFieldVectorShader<3>;
}}

49
src/Shaders/DistanceFieldVectorShader.frag

@ -0,0 +1,49 @@
#ifndef NEW_GLSL
#define in varying
#define fragmentColor gl_FragColor
#endif
#ifndef GL_ES
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 1) uniform lowp vec4 color;
layout(location = 2) uniform lowp vec4 outlineColor;
layout(location = 3) uniform lowp vec2 outlineRange = vec2(0.5, 0.0);
layout(location = 4) uniform lowp float smoothness = 0.04;
#else
uniform lowp vec4 color;
uniform lowp vec4 outlineColor;
uniform lowp vec2 outlineRange = vec2(0.5, 0.0);
uniform lowp float smoothness = 0.04;
#endif
#else
uniform lowp vec4 color;
uniform lowp vec4 outlineColor;
uniform lowp vec2 outlineRange;
uniform lowp float smoothness;
#endif
#ifdef EXPLICIT_TEXTURE_LAYER
layout(binding = 16) uniform sampler2D vectorTexture;
#else
uniform lowp sampler2D vectorTexture;
#endif
in vec2 fragmentTextureCoordinates;
#ifdef NEW_GLSL
out vec4 fragmentColor;
#endif
void main() {
lowp float intensity = texture(vectorTexture, fragmentTextureCoordinates).r;
/* Fill color */
fragmentColor = smoothstep(outlineRange.x-smoothness, outlineRange.x+smoothness, intensity)*color;
/* Outline */
if(outlineRange.x < outlineRange.y) {
lowp float mid = (outlineRange.x + outlineRange.y)/2.0;
lowp float half = (outlineRange.y - outlineRange.x)/2.0;
fragmentColor += smoothstep(half+smoothness, half-smoothness, distance(mid, intensity))*outlineColor;
}
}

118
src/Shaders/DistanceFieldVectorShader.h

@ -0,0 +1,118 @@
#ifndef Magnum_Shaders_DistanceFieldVectorShader_h
#define Magnum_Shaders_DistanceFieldVectorShader_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Shaders::DistanceFieldVectorShader, typedef Magnum::Shaders::DistanceFieldVectorShader2D, Magnum::Shaders::DistanceFieldVectorShader3D
*/
#include "Math/Matrix3.h"
#include "Math/Matrix4.h"
#include "AbstractVectorShader.h"
#include "magnumShadersVisibility.h"
namespace Magnum { namespace Shaders {
/**
@brief Distance field vector shader
Renders vector art in form of signed distance field. See TextureTools::distanceField()
for more information. Note that the final rendered outlook will greatly depend
on radius of input distance field and value passed to setSmoothness().
@see DistanceFieldVectorShader2D, DistanceFieldVectorShader3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVectorShader: public AbstractVectorShader<dimensions> {
public:
DistanceFieldVectorShader();
/** @brief Set transformation and projection matrix */
inline DistanceFieldVectorShader* setTransformationProjectionMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) {
AbstractShaderProgram::setUniform(transformationProjectionMatrixUniform, matrix);
return this;
}
/**
* @brief Set fill color
* @return Pointer to self (for method chaining)
*
* @see setOutlineColor()
*/
inline DistanceFieldVectorShader* setColor(const Color4<>& color) {
AbstractShaderProgram::setUniform(colorUniform, color);
return this;
}
/**
* @brief Set outline color
* @return Pointer to self (for method chaining)
*
* @see setOutlineRange(), setColor()
*/
inline DistanceFieldVectorShader* setOutlineColor(const Color4<>& color) {
AbstractShaderProgram::setUniform(outlineColorUniform, color);
return this;
}
/**
* @brief Set outline range
* @return Pointer to self (for method chaining)
*
* Parameter @p start describes where fill ends and possible outline
* starts. Initial value is `0.5f`, smaller values will make the vector
* art look thinner, larger will make it look thicker.
*
* Parameter @p end describes where outline ends. If set to value
* smaller than @p start the outline is not drawn. Initial value is
* `0.0f`.
*
* @see setOutlineColor()
*/
inline DistanceFieldVectorShader* setOutlineRange(Float start, Float end) {
AbstractShaderProgram::setUniform(outlineRangeUniform, Vector2(start, end));
return this;
}
/**
* @brief Set smoothness radius
* @return Pointer to self (for method chaining)
*
* Larger values will make edges look less aliased (but blurry), smaller
* values will make them look more crisp (but possibly aliased). Initial
* value is `0.04f`.
*/
inline DistanceFieldVectorShader* setSmoothness(Float value) {
AbstractShaderProgram::setUniform(smoothnessUniform, value);
return this;
}
private:
Int transformationProjectionMatrixUniform,
colorUniform,
outlineColorUniform,
outlineRangeUniform,
smoothnessUniform;
};
/** @brief Two-dimensional distance field vector shader */
typedef DistanceFieldVectorShader<2> DistanceFieldVectorShader2D;
/** @brief Three-dimensional distance field vector shader */
typedef DistanceFieldVectorShader<3> DistanceFieldVectorShader3D;
}}
#endif

5
src/Shaders/Shaders.h

@ -25,6 +25,11 @@ namespace Magnum { namespace Shaders {
/** @todoc remove when doxygen is sane again */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt> class DistanceFieldVectorShader;
typedef DistanceFieldVectorShader<2> DistanceFieldVectorShader2D;
typedef DistanceFieldVectorShader<3> DistanceFieldVectorShader3D;
template<UnsignedInt> class AbstractVectorShader;
typedef AbstractVectorShader<2> AbstractVectorShader2D;
typedef AbstractVectorShader<3> AbstractVectorShader3D;

2
src/Shaders/VectorShader.h

@ -30,6 +30,8 @@ namespace Magnum { namespace Shaders {
/**
@brief Vector shader
Renders vector art in plain grayscale form. See also DistanceFieldVectorShader
for more advanced effects.
@see VectorShader2D, VectorShader3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorShader: public AbstractVectorShader<dimensions> {

2
src/TextureTools/DistanceField.h

@ -50,7 +50,7 @@ the pixel was originally black and nearest white pixel is farther than
The resulting texture can be used with bilinear filtering. It can be converted
back to binary form in shader using e.g. GLSL `smoothstep()` function with step
around `0.5` to create antialiased edges. Or you can exploit the distance field
features to create many other effects.
features to create many other effects. See also Shaders::DistanceFieldVectorShader.
Based on: *Chris Green - Improved Alpha-Tested Magnification for Vector Textures
and Special Effects, SIGGRAPH 2007,

Loading…
Cancel
Save