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.
484 lines
17 KiB
484 lines
17 KiB
#ifndef Magnum_Shaders_Line_h |
|
#define Magnum_Shaders_Line_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022, 2023 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 Struct @ref Magnum::Shaders::LineDrawUniform, @ref Magnum::Shaders::LineMaterialUniform, enum @ref Magnum::Shaders::LineCapStyle, @ref Magnum::Shaders::LineJoinStyle, @ref Magnum::Shaders::LineVertexAnnotation, enum set @ref Magnum::Shaders::LineVertexAnnotations |
|
* @m_since_latest |
|
*/ |
|
|
|
#include <Corrade/Containers/EnumSet.h> |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/Math/Color.h" |
|
#include "Magnum/Shaders/visibility.h" |
|
|
|
namespace Magnum { namespace Shaders { |
|
|
|
/** |
|
@brief Line cap style |
|
@m_since_latest |
|
|
|
@see @ref LineGL::capStyle(), @ref LineGL::Configuration::setCapStyle() |
|
*/ |
|
enum class LineCapStyle: UnsignedByte { |
|
/** |
|
* [Butt cap](https://en.wikipedia.org/wiki/Butt_joint). The line is cut |
|
* off right at the endpoint. Lines of zero length will be invisible. |
|
* |
|
* @htmlinclude line-cap-butt.svg |
|
*/ |
|
Butt, |
|
|
|
/** |
|
* Square cap. The line is extended by half of its width past the endpoint. |
|
* Lines of zero length will be shown as squares. |
|
* |
|
* @htmlinclude line-cap-square.svg |
|
*/ |
|
Square, |
|
|
|
/** |
|
* Round cap. The line is extended by half of its width past the endpoint. |
|
* It's still rendered as a quad but pixels outside of the half-circle have |
|
* the background color. Lines of zero length will be shown as circles. |
|
* |
|
* @htmlinclude line-cap-round.svg |
|
* |
|
* @see @ref LineMaterialUniform::backgroundColor, |
|
* @ref LineGL::setBackgroundColor() |
|
*/ |
|
Round, |
|
|
|
/** |
|
* Triangle cap. The line is extended by half of its width past the |
|
* endpoint. It's still rendered as a quad but pixels outside of the |
|
* triangle have the background color. Lines of zero length will be shown |
|
* as squares rotated by 45°. |
|
* |
|
* @htmlinclude line-cap-triangle.svg |
|
* |
|
* @see @ref LineMaterialUniform::backgroundColor, |
|
* @ref LineGL::setBackgroundColor() |
|
*/ |
|
Triangle |
|
}; |
|
|
|
/** |
|
@brief Line join style |
|
@m_since_latest |
|
|
|
@see @ref LineGL::joinStyle(), @ref LineGL::Configuration::setJoinStyle() |
|
*/ |
|
enum class LineJoinStyle: UnsignedByte { |
|
/** |
|
* [Miter join](https://en.wikipedia.org/wiki/Miter_joint). The outer edges |
|
* of both line segments extend until they intersect. |
|
* |
|
* @htmlinclude line-join-miter.svg |
|
* |
|
* In this style, the points `A`, `B` and `C` collapse to a zero-area |
|
* triangle. If the miter length `l` would be larger than the limit set in |
|
* @ref LineGL::setMiterLengthLimit() / |
|
* @ref LineMaterialUniform::setMiterLengthLimit() or the angle between the |
|
* two segments `α` would be less than the limit set in |
|
* @ref LineGL::setMiterAngleLimit() / |
|
* @ref LineMaterialUniform::setMiterAngleLimit(), it switches to |
|
* @ref LineJoinStyle::Bevel instead. |
|
*/ |
|
Miter, |
|
|
|
/** |
|
* [Bevel join](https://en.wikipedia.org/wiki/Bevel). Outer edges of both |
|
* line segments are cut off at a right angle at their endpoints. |
|
* |
|
* @htmlinclude line-join-bevel.svg |
|
* |
|
* The area between points `A`, `B` and `C` is filled with an extra |
|
* triangle. |
|
*/ |
|
Bevel |
|
}; |
|
|
|
/** |
|
@brief Line vertex annotation |
|
@m_since_latest |
|
|
|
A line segment drawn by the @ref LineGL shader consists of four vertices, first |
|
two having the @ref LineGL::Position attribute set to the first point of the |
|
segment and second two having it set to the second point of the segment. In |
|
order to distinguish the direction in which the point should be expanded to |
|
form a quad and whether the expansion should be for a line join or line cap, |
|
each vertex contains @ref LineVertexAnnotations in the @ref LineGL::Annotation |
|
attribute. |
|
|
|
@htmlinclude line-annotation.svg |
|
|
|
In the above diagram, there's a line strip consisting of three line segments |
|
and six pairs of points, with @m_span{m-label m-success} green @m_endspan and |
|
@m_span{m-label m-default} white @m_endspan forming (square) line caps, while |
|
@m_span{m-label m-primary} azure @m_endspan, |
|
@m_span{m-label m-danger} red @m_endspan form a miter line join, and |
|
@m_span{m-label m-info} blue @m_endspan and |
|
@m_span{m-label m-warning} yellow @m_endspan form a bevel join. The |
|
twelve corresponding annotations, forming three quads (and one extra triangle |
|
for the bevel), are shown with `U`, `J` and `B` letters, color-coded to show |
|
which original line point they correspond to. Line cap style and join style |
|
isn't a part of the annotation, it's set with @ref LineCapStyle and |
|
@ref LineJoinStyle at shader compilation time instead. |
|
|
|
The type is 32-bit in order to match the default type of the |
|
@ref LineGL::Annotation attribute, but the values are guaranteed to fit into 8 |
|
bits. |
|
*/ |
|
enum class LineVertexAnnotation: UnsignedInt { |
|
/** |
|
* The point extends upwards assuming a left-to-right direction of the line |
|
* segment. If not set, it extends downwards. Visualized as `U` in the |
|
* above diagram. |
|
*/ |
|
Up = 1 << 0, |
|
|
|
/** |
|
* The point is forming a join with a neighboring line segment defined by |
|
* either @ref LineGL::PreviousPosition or @ref LineGL::NextPosition based |
|
* on whether @ref LineVertexAnnotation::Begin is set. If not set, the |
|
* point is forming a line cap, extending in the opposite of the line |
|
* segment direction if @ref LineVertexAnnotation::Begin is set, and in the |
|
* direction if not set. Visualized as `J` in the above diagram. |
|
*/ |
|
Join = 1 << 1, |
|
|
|
/** |
|
* The point is forming the beginning of the line segment, i.e. |
|
* @ref LineGL::NextPosition contains the other point of the line segment. |
|
* If not set, @ref LineGL::PreviousPosition contains the other point of |
|
* the line segment instead. |
|
* |
|
* If @ref LineVertexAnnotation::Join is set as well, the point is a common |
|
* point of two neighboring line segments and @ref LineGL::PreviousPosition |
|
* contains the other point of the neighboring line segment. If |
|
* @ref LineVertexAnnotation::Join is set and this bit is not set, |
|
* @ref LineGL::NextPosition contaons the other point of the neighboring |
|
* line segment instead. Visualized as `B` in the above diagram. |
|
*/ |
|
Begin = 1 << 2, |
|
}; |
|
|
|
/** |
|
@brief Line vertex annotations |
|
@m_since_latest |
|
|
|
Contents of the @ref LineGL::Annotation attribute. See |
|
@ref LineVertexAnnotation for more information. |
|
*/ |
|
typedef Containers::EnumSet<LineVertexAnnotation> LineVertexAnnotations; |
|
|
|
CORRADE_ENUMSET_OPERATORS(LineVertexAnnotations) |
|
|
|
/** |
|
* @debugoperatorenum{LineCapStyle} |
|
* @m_since_latest |
|
*/ |
|
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, LineCapStyle value); |
|
|
|
/** |
|
* @debugoperatorenum{LineJoinStyle} |
|
* @m_since_latest |
|
*/ |
|
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, LineJoinStyle value); |
|
|
|
/** |
|
* @debugoperatorenum{LineVertexAnnotation} |
|
* @m_since_latest |
|
*/ |
|
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, LineVertexAnnotation value); |
|
|
|
/** |
|
* @debugoperatorenum{LineVertexAnnotations} |
|
* @m_since_latest |
|
*/ |
|
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, LineVertexAnnotations value); |
|
|
|
/** |
|
@brief Per-draw uniform for line shaders |
|
@m_since_latest |
|
|
|
Together with the generic @ref TransformationProjectionUniform2D / |
|
@ref TransformationProjectionUniform3D contains parameters that are specific to |
|
each draw call. Material-related properties are expected to be shared among multiple draw calls and thus are provided in a separate |
|
@ref LineMaterialUniform structure, referenced by @ref materialId. |
|
@see @ref LineGL::bindDrawBuffer() |
|
*/ |
|
struct LineDrawUniform { |
|
/** @brief Construct with default parameters */ |
|
constexpr explicit LineDrawUniform(DefaultInitT = DefaultInit) noexcept: materialId{0}, objectId{0} {} |
|
|
|
/** @brief Construct without initializing the contents */ |
|
explicit LineDrawUniform(NoInitT) noexcept {} |
|
|
|
/** @{ |
|
* @name Convenience setters |
|
* |
|
* Provided to allow the use of method chaining for populating a structure |
|
* in a single expression, otherwise equivalent to accessing the fields |
|
* directly. Also guaranteed to provide backwards compatibility when |
|
* packing of the actual fields changes. |
|
*/ |
|
|
|
/** |
|
* @brief Set the @ref materialId field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineDrawUniform& setMaterialId(UnsignedInt id) { |
|
materialId = id; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Set the @ref objectId field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineDrawUniform& setObjectId(UnsignedInt id) { |
|
objectId = id; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** @var materialId |
|
* @brief Material ID |
|
* |
|
* References a particular material from a @ref LineMaterialUniform array. |
|
* Useful when an UBO with more than one material is supplied or in a |
|
* multi-draw scenario. Should be less than the material count passed to |
|
* @ref LineGL::Configuration::setMaterialCount(), if material count is |
|
* @cpp 1 @ce, this field is assumed to be @cpp 0 @ce and isn't even read |
|
* by the shader. Default value is @cpp 0 @ce, meaning the first material |
|
* gets used. |
|
*/ |
|
|
|
/* This field is an UnsignedInt in the shader and materialId is extracted |
|
as (value & 0xffff), so the order has to be different on BE */ |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
alignas(4) UnsignedShort materialId; |
|
/* warning: Member __pad0__ is not documented. FFS DOXYGEN WHY DO YOU THINK |
|
I MADE THOSE UNNAMED, YOU DUMB FOOL */ |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
UnsignedShort:16; /* reserved */ |
|
#endif |
|
#else |
|
alignas(4) UnsignedShort:16; /* reserved */ |
|
UnsignedShort materialId; |
|
#endif |
|
|
|
/** |
|
* @brief Object ID |
|
* |
|
* Used only for the object ID framebuffer output, not to access any other |
|
* uniform data. Default value is @cpp 0 @ce. |
|
* |
|
* Used only if @ref LineGL::Flag::ObjectId is enabled, ignored otherwise. |
|
* If @ref LineGL::Flag::InstancedObjectId is enabled as well, this value |
|
* is added to the ID coming from the @ref LineGL::ObjectId attribute. |
|
* @see @ref LineGL::setObjectId() |
|
*/ |
|
UnsignedInt objectId; |
|
|
|
/* warning: Member __pad1__ is not documented. FFS DOXYGEN WHY DO YOU THINK |
|
I MADE THOSE UNNAMED, YOU DUMB FOOL */ |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
Int:32; |
|
Int:32; |
|
#endif |
|
}; |
|
|
|
/** |
|
@brief Material uniform for line shaders |
|
@m_since_latest |
|
|
|
Describes material properties referenced from |
|
@ref LineDrawUniform::materialId. |
|
@see @ref LineGL::bindMaterialBuffer() |
|
*/ |
|
struct MAGNUM_SHADERS_EXPORT LineMaterialUniform { |
|
/** @brief Construct with default parameters */ |
|
constexpr explicit LineMaterialUniform(DefaultInitT = DefaultInit) noexcept: backgroundColor{0.0f, 0.0f, 0.0f, 0.0f}, color{1.0f, 1.0f, 1.0f, 1.0f}, width{1.0f}, smoothness{0.0f}, miterLimit{0.875f} {} |
|
|
|
/** @brief Construct without initializing the contents */ |
|
explicit LineMaterialUniform(NoInitT) noexcept: color{NoInit} {} |
|
|
|
/** @{ |
|
* @name Convenience setters |
|
* |
|
* Provided to allow the use of method chaining for populating a structure |
|
* in a single expression, otherwise equivalent to accessing the fields |
|
* directly. Also guaranteed to provide backwards compatibility when |
|
* packing of the actual fields changes. |
|
*/ |
|
|
|
/** |
|
* @brief Set the @ref color field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineMaterialUniform& setColor(const Color4& color) { |
|
this->color = color; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Set the @ref backgroundColor field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineMaterialUniform& setBackgroundColor(const Color4& color) { |
|
backgroundColor = color; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Set the @ref width field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineMaterialUniform& setWidth(Float width) { |
|
this->width = width; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Set the @ref smoothness field |
|
* @return Reference to self (for method chaining) |
|
*/ |
|
LineMaterialUniform& setSmoothness(Float smoothness) { |
|
this->smoothness = smoothness; |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Set the @ref miterLimit field to a length value |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Expects that @p limit is greater than or equal to @cpp 1.0f @ce and |
|
* finite. |
|
*/ |
|
LineMaterialUniform& setMiterLengthLimit(Float limit); |
|
|
|
/** |
|
* @brief Set the @ref miterLimit field to an angle value |
|
* @return Reference to self (for method chaining) |
|
* |
|
* Expects that @p limit is greater than @cpp 0.0_radf @ce. |
|
*/ |
|
LineMaterialUniform& setMiterAngleLimit(Rad limit); |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @brief Background color |
|
* |
|
* Default value is @cpp 0x00000000_rgbaf @ce. Used for edge smoothing if |
|
* smoothness is non-zero, and for background areas if |
|
* @ref LineCapStyle::Round or @ref LineCapStyle::Triangle is used. If |
|
* smoothness is zero and @ref LineCapStyle::Butt or |
|
* @ref LineCapStyle::Square is used, only the foreground color is used. |
|
* @see @ref LineGL::setBackgroundColor(), @ref LineGL::setSmoothness(), |
|
* @ref LineGL::Configuration::setCapStyle() |
|
*/ |
|
Color4 backgroundColor; |
|
|
|
/** |
|
* @brief Color |
|
* |
|
* Default value is @cpp 0xffffffff_rgbaf @ce. |
|
* |
|
* If @ref LineGL::Flag::VertexColor is enabled, the color is multiplied |
|
* with a color coming from the @ref LineGL::Color3 / @ref LineGL::Color4 |
|
* attribute. |
|
* @see @ref LineGL::setColor() |
|
*/ |
|
Color4 color; |
|
|
|
/** |
|
* @brief Line width |
|
* |
|
* Screen-space, interpreted depending on the viewport size --- i.e., a |
|
* value of @cpp 1.0f @ce is one pixel only if @ref LineGL::setViewportSize() |
|
* is called with the actual pixel size of the viewport. Default value is |
|
* @cpp 1.0f @ce. |
|
* @see @ref LineGL::setWidth() |
|
*/ |
|
Float width; |
|
|
|
/** |
|
* @brief Line smoothness |
|
* |
|
* Larger values will make edges look less aliased (but blurry), smaller |
|
* values will make them more crisp (but possibly aliased). Screen-space, |
|
* interpreted depending on the viewport size --- i.e., a value of |
|
* @cpp 1.0f @ce is one pixel only if @ref LineGL::setViewportSize() is |
|
* called with the actual pixel size of the viewport. Initial value is |
|
* @cpp 0.0f @ce. |
|
* @see @ref LineGL::setSmoothness() |
|
*/ |
|
Float smoothness; |
|
|
|
/** |
|
* @brief Miter limit |
|
* |
|
* Limit at which a @ref LineJoinStyle::Miter join is converted to a |
|
* @ref LineJoinStyle::Bevel in order to avoid sharp corners extending too |
|
* much. If joint style is not @ref LineJoinStyle::Miter, this value is |
|
* unused. |
|
* |
|
* Represented as a cosine of the angle between two neighboring line |
|
* segments, with @ref LineJoinStyle::Bevel used for angles below the limit |
|
* (thus their cosine larger than this value). For length-based limits, |
|
* the relation between angle @f$ \theta @f$, miter length @f$ l @f$ and |
|
* line half-width @f$ w @f$ is as follows: @f[ |
|
* \frac{w}{l} = \sin(\frac{\theta}{2}) |
|
* @f] |
|
* |
|
* For convenience it's recommended to use the @ref setMiterLengthLimit() |
|
* and @ref setMiterAngleLimit() helpers instead of setting this value |
|
* directly. |
|
* @see @ref LineGL::setMiterLengthLimit(), |
|
* @ref LineGL::setMiterAngleLimit() |
|
*/ |
|
Float miterLimit; |
|
|
|
/* warning: Member __pad0__ is not documented. FFS DOXYGEN WHY DO YOU THINK |
|
I MADE THOSE UNNAMED, YOU DUMB FOOL */ |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
Int:32; /* reserved for dynamic cap/join style */ |
|
#endif |
|
}; |
|
|
|
}} |
|
|
|
#endif
|
|
|