template<UnsignedInt dimensions>
Magnum::Shaders::LineGL class new in Git master

Line GL shader.

Renders lines expanded to quads in screen space. Compared to builtin GPU line rendering, the lines can be of arbitrary width, with configurable join and cap styles, and antialiased independently of MSAA being used or not.

Image

Usage

The shader doesn't work with MeshPrimitive::Lines, MeshPrimitive::LineStrip or MeshPrimitive::LineLoop directly, as that would only be implementable with a relatively expensive geometry shader. Instead, it requires the input data to be organized in quads, with Position, PreviousPosition and NextPosition attributes describing point wíth their surroundings, and Annotation with point-specific annotation such as whether given point is a line cap or a join with neighboring segment. The data layout is described in detail in Line mesh representation below, however in practice it's easiest to convert an existing line Trade::MeshData to a form accepted by this shader with MeshTools::generateLines() and then compile it to a GL::Mesh with MeshTools::compileLines():

Trade::MeshData circle = Primitives::circle2DWireframe(16);
GL::Mesh mesh = MeshTools::compileLines(MeshTools::generateLines(circle));

For rendering use setTransformationProjectionMatrix(), setColor(), setWidth() and others. It's important to pass viewport size in setViewportSize() as the line width is interpreted relative to it.

Shaders::LineGL2D shader;
shader
    .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
    .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
    .setColor(0x2f83cc_rgbf)
    .setWidth(4.0f)
    .draw(mesh);

Line triangulation

Each line segment is rendered as a quad consisting of two triangles. Standalone segments have cap style configurable via Configuration::setCapStyle() with the following styles, segments of zero length can be also used to render points. The white lines show generated triangles, the blue line is the actually visible edge between foreground and background:

Joins between consecutive segments in contiguous line strips are expanded to form a gap-less mesh without overlaps. Depending on join style picked in Configuration::setJoinStyle() and angle between the segments the area between points A, B and C may be filled with another triangle:

Antialiasing

The lines aren't smoothed out by default, use setSmoothness() to pick a tradeoff between the line being aliased and blurry. This is implemented by interpolating between the foreground color and the background, which assumes blending is set up for pre-multiplied alpha. If you're drawing lines on a single-color background, you can setBackgroundColor() to a color matching the background and keep blending disabled, but note that you may get artifacts if the lines are self-overlapping.

GL::Renderer::enable(GL::Renderer::Feature::Blending);
GL::Renderer::setBlendFunction(
    GL::Renderer::BlendFunction::One,
    GL::Renderer::BlendFunction::OneMinusSourceAlpha);

Shaders::LineGL2D shader;
shader
    
    .setSmoothness(1.0f)
    .draw(mesh);

Lines in 3D

The 3D variant of this shader renders the geometry with depth values derived from the original line endpoints, however without any perspective shortening applied — the line width is the same viewport-relative value independently of the depth the point is at.

Object ID output

The shader supports writing object ID to the framebuffer for object picking or other annotation purposes. Enable it using Flag::ObjectId and set up an integer buffer attached to the ObjectIdOutput attachment. If you have a batch of meshes with different object IDs, enable Flag::InstancedObjectId and supply per-vertex IDs to the ObjectId attribute. The output will contain a sum of the per-vertex ID and ID coming from setObjectId().

The functionality is practically the same as in the FlatGL shader, see its documentation for more information and usage example.

Note that the object ID is emitted for the whole triangle area, including transparent areas of caps when using LineCapStyle::Round or LineCapStyle::Triangle as well as semi-transparent edges with smoothness values larger than zero. In particular, the object ID output will be aliased even if the color output isn't.

Instanced rendering

Enabling Flag::InstancedTransformation will turn the shader into an instanced one. It'll take per-instance transformation from the TransformationMatrix attribute, applying it before the matrix set by setTransformationProjectionMatrix(). Besides that, Flag::VertexColor (and the Color3 / Color4) attributes can work as both per-vertex and per-instance. The functionality is practically the same as in the FlatGL shader, see its documentation for more information and usage example.

Uniform buffers

See Using uniform buffers for a high-level overview that applies to all shaders. In this particular case, because the shader doesn't need a separate projection and transformation matrix, a combined one is supplied via a TransformationProjectionUniform2D / TransformationProjectionUniform3D buffer bound with bindTransformationProjectionBuffer(). To maximize use of the limited uniform buffer memory, materials are supplied separately in a LineMaterialUniform buffer bound with bindMaterialBuffer() and then referenced via materialId from a LineDrawUniform bound with bindDrawBuffer(). A uniform buffer setup equivalent to the snippet at the top would look like this — note that setViewportSize() is an immediate uniform here as well, as it's assumed to be set globally and rarely changed:

GL::Buffer transformationProjectionUniform, materialUniform, drawUniform;
transformationProjectionUniform.setData({
    Shaders::TransformationProjectionUniform2D{}
        .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
});
materialUniform.setData({
    Shaders::LineMaterialUniform{}
        .setColor(0x2f83cc_rgbf)
});
drawUniform.setData({
    Shaders::LineDrawUniform{}
        .setMaterialId(0)
});

Shaders::LineGL2D shader{Shaders::LineGL2D::Configuration{}
    .setFlags(Shaders::LineGL2D::Flag::UniformBuffers)};
shader
    .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
    .bindTransformationProjectionBuffer(transformationProjectionUniform)
    .bindMaterialBuffer(materialUniform)
    .bindDrawBuffer(drawUniform)
    .draw(mesh);

For a multidraw workflow enable Flag::MultiDraw and supply desired material and draw count via Configuration::setMaterialCount() and setDrawCount(). For every draw then specify material references. Besides that, the usage is similar for all shaders, see Multidraw and reducing driver overhead for an example.

Line mesh representation

In order to avoid performing expensive CPU-side expansion of the quads every time the transformation, line width and other parameters change, the shader gets just the original line segment endpoints as an input, transforms them in 2D or 3D as usual, and then expands them in screen space for a desired line width.

Ignoring all complexity related to line caps and joins for now, an example expansion of three line segments into quads is shown above — the first two segments form a join at the blue point, the third segment is standalone. In order to form a quad, each of the points has to be present twice in the vertex stream, with first copy expanding up and second copy expanding down. The Position data needed to render quads would then look like below, color-coded to match the above, and in order following the segment direction. An index buffer would then form two triangles out of every four points — {0, 1, 2, 2, 1, 3, }.

To figure out the direction in which to expand, for given endpoint position the shader needs also screen-space direction to the other endpoint. But since a 2D / 3D transformation has to be applied for both endpoints before calculating their screen-space position, it makes more sense to supply directly its position instead, and calculate the direction only after transforming both points. The input data would then look like this, with "previous" positions shown above and "next" positions shown below:

With line joins and caps present, the quad expansion changes in the following way. In the general case, to avoid overlapping geometry and gaps, points B and D collapse to a single position and the area in between is filled with an extra triangle. Depending on the transformation, it can however also happen that A and C collapse into a single point instead, for example if the azure point would appear above the green one instead of below. Thus the index buffer needs to handle both cases — {, 2, 3, 4, 4, 3, 5, } — and one of them always denegerates to a zero-area triangle.

A C B D

To handle the join, the shader needs to know whether there's a neighboring line segment to join with, and what is the position of its other endpoint. Thus, every vertex gets two neighboring positions, a PreviousPosition and a NextPosition. Both of them are filled only in case the point forms a line join; if the point is a line cap, one of them is left unspecified.

U·B ··B U·· ··· A B C D UJ· ·J· UJB ·JB U·B ··B ··· U··

What's left is giving the shader an ability to distinguish the direction in which to expand the point (LineVertexAnnotation::Up or downwards), whether it's a Join or a cap and whether the point is a Begin or an end of the segment in order to know what the neigboring positions represent. This info is stored in the Annotation attribute and shown with U, J and B letters above. In this particular case the info could also be inferred from the vertex index and for example NaNs in the neigbor positions, but a dedicated attribute makes it more flexible for optimized data layouts explained below.

Overlapping layouts with less data redundancy

Assuming a 3D line mesh with floating-point position attributes, the Annotation attribute packed into a single byte and MeshIndexType::UnsignedShort indices, a a single contiguous line strip consisting of $ n $ line segments would need $ (4(36 + 1) + 24)n = 172n $ bytes of data. In comparison, CPU-side-generated indexed quads would need just $ (24 + 18)n + 24 = 42n + 24 $ bytes, and a (non-indexed) MeshPrimitive::LineStrip only $ 12n + 12 $ bytes, which is ~14x less. Fortunately, the position data can be organized in a way that makes it possible to reuse them for previous and next positions as well, by binding the same data again under an offset.

There's the following possibilites, each with different tradeoffs depending on the use case. Such data layout variants require no special-casing in the shader, only a different mesh setup, making it possible to pick the best option for each line mesh without having to pay for expensive shader switching.

Standalone line segments without joins

If the mesh consists just of loose line segments and no joints need to be drawn, the Position attribute can be bound with an offset of -2 elements to the PreviousPosition and +2 elements to the NextPosition. To avoid out-of-bound reads, the position buffer needs to be padded with two elements at the front and at the end. Together with no indices needed for joint triangles the memory requirement would be reduced to $ (4(12 + 1) + 12)n + 12 = 64 n + 12 $ bytes, which is roughly the same amount of data as for loose CPU-side-generated indexed quads, and ~2.7x as much as $ 24n $ bytes a sufficiently large (non-indexed) MeshPrimitive::Lines would need.

U·· ··· U·B ··B U·B ··B ··· U·· U·B ··B U·· ··· A B C D

Generic lines

For arbitrary lines that consist of both joined strips and standalone segments and the joins can be of any style in any direction, the Position attribute has to be additionally padded with two elements at begin and end of every contiguous line strip together with skipping the elements in the index buffer appropriately, and then bound with an offset of -4 elements to the PreviousPosition and +4 elements to the NextPosition.

This needs only one triangle in the index buffer for each join instead of two and has a memory requirement of $ (4(12 + 1) + 24)n + (4(12 + 1) - 12)l + 12 $ bytes, with $ l $ being the line strip count. With a mesh consisting of just a single strip this is $ 76n + 52 $ bytes, which is ~1.8x as much as CPU-side-generated indexed quads and ~6.3x as much as a MeshPrimitive::LineStrip would need.

UJ· ·J· UJB ·JB U·B ··B ··· U·· U·B ··B U·· ··· A B C D

Lines with fixed join directions

If the joint direction is known to be fixed, i.e. the B and D points always collapse to the same position independently of the transform used, the two points can be replaced with just one. This is commonly the case in 2D if negative transformation scaling isn't involved and with planar line art in 3D if it additionally also isn't viewed from the back side. This allows padding of the Position attribute at the begin and end of every contiguous line strip to be reduced to just one element, binding it with an offset of -3 elements to the PreviousPosition and +3 elements to the NextPosition.

This has a memory requirement of $ (3(12 + 1) + 18)n + (3(12 + 1) - 6)l + 12 $ bytes. With a mesh consisting of just a single strip this is $ 57n + 45 $ bytes, which is ~1.4x as much as CPU-side-generated indexed quads and ~4.75x as much as a MeshPrimitive::LineStrip would need.

UJ· ·J? UJB U·B ··B ··· U·· U·B ··B U·· ··· A B/D C

Lines with miter joins only

The final and most data-efficient case is for line meshes where the contiguous segments consist of miter joints only (i.e., with the assumption that the angle between two segments is never too sharp to fall back to LineJoinStyle::Bevel), resulting in the join collapsing to just two vertices, with no triangle in between:

A C B D

This is the usual case for finely subdivided curves. Generic line art can be patched in a preprocessing step, subdividing sharp corners to a sequence of joins with larger angles. This layout doesn't require any padding of the Position attribute between contiguous line strips, and it's bound with an offset of -2 elements to the PreviousPosition and +2 elements to the NextPosition.

The memory requirement is $ (2(12 + 1) + 12)n + 2(12 + 1)l + 12 $ bytes. With a mesh consisting of a single strip it's $ 38n + 38 $ bytes. This is roughly the same memory use as $ 36n + 24 $ bytes for CPU-side-generated quads with miter joins only, and ~3.2x as much as a MeshPrimitive::LineStrip would need.

··· ··· A/C B/D UJ? ·J? U·B ··B U·· U·B ··B U··

Base classes

class Magnum::GL::AbstractShaderProgram
Base for shader program implementations.

Derived classes

class Magnum::Shaders::LineGL::CompileState
Asynchronous compilation state.

Public types

class CompileState
Asynchronous compilation state.
class Configuration
Configuration.
enum (anonymous): UnsignedInt { ColorOutput = GenericGL<dimensions>::ColorOutput, ObjectIdOutput = GenericGL<dimensions>::ObjectIdOutput }
enum class Flag: UnsignedShort { VertexColor = 1 << 0, ObjectId = 1 << 1, InstancedObjectId = (1 << 2)|ObjectId, InstancedTransformation = 1 << 3, UniformBuffers = 1 << 4, ShaderStorageBuffers = UniformBuffers|(1 << 6) new in Git master, MultiDraw = UniformBuffers|(1 << 5) }
Flag.
using Position = GenericGL<dimensions>::Position
Vertex position.
using PreviousPosition = GL::Attribute<3, VectorTypeFor<dimensions, Float>>
Previous position.
using NextPosition = GL::Attribute<5, VectorTypeFor<dimensions, Float>>
Next position.
using Annotation = GL::Attribute<1, UnsignedInt>
Vertex annotation.
using Color3 = GenericGL<dimensions>::Color3
Three-component vertex color.
using Color4 = GenericGL<dimensions>::Color4
Four-component vertex color.
using ObjectId = GenericGL<dimensions>::ObjectId
(Instanced) object ID
using TransformationMatrix = GenericGL<dimensions>::TransformationMatrix
(Instanced) transformation matrix
using Flags = Containers::EnumSet<Flag>
Flags.

Public static functions

static auto compile(const Configuration& configuration = Configuration{}) -> CompileState
Compile asynchronously.

Constructors, destructors, conversion operators

LineGL(const Configuration& configuration = Configuration{}) explicit
Constructor.
LineGL(CompileState&& state) explicit
Finalize an asynchronous compilation.
LineGL(NoCreateT) explicit noexcept
Construct without creating the underlying OpenGL object.
LineGL(const LineGL<dimensions>&) deleted
Copying is not allowed.
LineGL(LineGL<dimensions>&&) defaulted noexcept
Move constructor.

Public functions

auto operator=(const LineGL<dimensions>&) -> LineGL<dimensions>& deleted
Copying is not allowed.
auto operator=(LineGL<dimensions>&&) -> LineGL<dimensions>& defaulted noexcept
Move assignment.
auto flags() const -> Flags
Flags.
auto capStyle() const -> LineCapStyle
Cap style.
auto joinStyle() const -> LineJoinStyle
Join style.
auto materialCount() const -> UnsignedInt
Material count.
auto drawCount() const -> UnsignedInt
Draw count.
auto setViewportSize(const Vector2& size) -> LineGL<dimensions>&
Set viewport size.

Uniform setters

Used only if Flag::UniformBuffers is not set.

auto setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) -> LineGL<dimensions>&
Set transformation and projection matrix.
auto setBackgroundColor(const Magnum::Color4& color) -> LineGL<dimensions>&
Set background color.
auto setColor(const Magnum::Color4& color) -> LineGL<dimensions>&
Set color.
auto setWidth(Float width) -> LineGL<dimensions>&
Set line width.
auto setSmoothness(Float smoothness) -> LineGL<dimensions>&
Set line smoothness.
auto setMiterLengthLimit(Float limit) -> LineGL<dimensions>&
Set miter length limit.
auto setMiterAngleLimit(Rad limit) -> LineGL<dimensions>&
Set miter angle limit.
auto setObjectId(UnsignedInt id) -> LineGL<dimensions>&
Set object ID.

Enum documentation

template<UnsignedInt dimensions>
enum Magnum::Shaders::LineGL<dimensions>::(anonymous): UnsignedInt

Enumerators
ColorOutput

Color shader output. Present always, expects three- or four-component floating-point or normalized buffer attachment.

ObjectIdOutput

Object ID shader output. Generic output, present only if Flag::ObjectId is set. Expects a single-component unsigned integral attachment. Writes the value set in setObjectId() and possibly also a per-vertex ID and an ID fetched from a texture, see Object ID output for more information.

template<UnsignedInt dimensions>
enum class Magnum::Shaders::LineGL<dimensions>::Flag: UnsignedShort

Flag.

Enumerators
VertexColor

Multiply the color with a vertex color. Requires either the Color3 or Color4 attribute to be present.

ObjectId

Enable object ID output. See Object ID output for more information.

InstancedObjectId

Instanced object ID. Retrieves a per-instance / per-vertex object ID from the ObjectId attribute, outputting a sum of the per-vertex ID and ID coming from setObjectId() or LineDrawUniform::objectId. Implicitly enables Flag::ObjectId. See Object ID output for more information.

InstancedTransformation

Instanced transformation. Retrieves a per-instance transformation matrix from the TransformationMatrix attribute and uses it together with the matrix coming from setTransformationProjectionMatrix() or TransformationProjectionUniform2D::transformationProjectionMatrix / TransformationProjectionUniform3D::transformationProjectionMatrix (first the per-instance, then the uniform matrix). See Instanced rendering for more information.

UniformBuffers

Use uniform buffers. Expects that uniform data are supplied via bindTransformationProjectionBuffer(), bindDrawBuffer() and bindMaterialBuffer() instead of direct uniform setters.

ShaderStorageBuffers new in Git master

Use shader storage buffers. Superset of functionality provided by Flag::UniformBuffers, compared to it doesn't have any size limits on Configuration::setMaterialCount() and setDrawCount() in exchange for potentially more costly access and narrower platform support.

MultiDraw

Enable multidraw functionality. Implies Flag::UniformBuffers and adds the value from setDrawOffset() with the gl_DrawID builtin, which makes draws submitted via GL::AbstractShaderProgram::draw(const Containers::Iterable<MeshView>&) and related APIs pick up per-draw parameters directly, without having to rebind the uniform buffers or specify setDrawOffset() before each draw. In a non-multidraw scenario, gl_DrawID is 0, which means a shader with this flag enabled can be used for regular draws as well.

Typedef documentation

template<UnsignedInt dimensions>
typedef GenericGL<dimensions>::Position Magnum::Shaders::LineGL<dimensions>::Position

Vertex position.

Generic attribute, Vector2 in 2D, Vector3 in 3D.

template<UnsignedInt dimensions>
typedef GL::Attribute<3, VectorTypeFor<dimensions, Float>> Magnum::Shaders::LineGL<dimensions>::PreviousPosition

Previous position.

Vector2 in 2D, Vector3 in 3D. Uses the same location as GenericGL::Tangent with the assumption that lines don't need tangent space information.

If LineVertexAnnotation::Begin is set in Annotation, contains the other point of the neighboring line segment if LineVertexAnnotation::Join is also set, and is ignored otherwise. If LineVertexAnnotation::Begin is not set in Annotation, contains the other point of the line segment.

template<UnsignedInt dimensions>
typedef GL::Attribute<5, VectorTypeFor<dimensions, Float>> Magnum::Shaders::LineGL<dimensions>::NextPosition

Next position.

Vector2 in 2D, Vector3 in 3D. Uses the same location as GenericGL::Normal with the assumption that lines don't need tangent space information.

If LineVertexAnnotation::Begin is set in Annotation, contains the other point of the line segment. If LineVertexAnnotation::Begin is not set in Annotation, contains the other point of the neighboring line segment if LineVertexAnnotation::Join is set, and is ignored otherwise.

template<UnsignedInt dimensions>
typedef GL::Attribute<1, UnsignedInt> Magnum::Shaders::LineGL<dimensions>::Annotation

Vertex annotation.

Uses the same location as GenericGL::TextureCoordinates with the assumption that lines don't need a two-dimensional texture space information.

Contains a set of LineVertexAnnotation bits, see their documentation for more information. The values are guaranteed to fit into 8 bits.

template<UnsignedInt dimensions>
typedef GenericGL<dimensions>::Color3 Magnum::Shaders::LineGL<dimensions>::Color3

Three-component vertex color.

Generic attribute, Magnum::Color3. Use either this or the Color4 attribute.

template<UnsignedInt dimensions>
typedef GenericGL<dimensions>::Color4 Magnum::Shaders::LineGL<dimensions>::Color4

Four-component vertex color.

Generic attribute, Magnum::Color4. Use either this or the Color3 attribute.

template<UnsignedInt dimensions>
typedef GenericGL<dimensions>::ObjectId Magnum::Shaders::LineGL<dimensions>::ObjectId

(Instanced) object ID

Generic attribute, UnsignedInt. Used only if Flag::InstancedObjectId is set.

template<UnsignedInt dimensions>
typedef GenericGL<dimensions>::TransformationMatrix Magnum::Shaders::LineGL<dimensions>::TransformationMatrix

(Instanced) transformation matrix

Generic attribute, Matrix3 in 2D, Matrix4 in 3D. Used only if Flag::InstancedTransformation is set.

template<UnsignedInt dimensions>
typedef Containers::EnumSet<Flag> Magnum::Shaders::LineGL<dimensions>::Flags

Flags.

Function documentation

template<UnsignedInt dimensions>
static CompileState Magnum::Shaders::LineGL<dimensions>::compile(const Configuration& configuration = Configuration{})

Compile asynchronously.

Compared to LineGL(const Configuration&) can perform an asynchronous compilation and linking. See Async shader compilation and linking for more information.

template<UnsignedInt dimensions>
Magnum::Shaders::LineGL<dimensions>::LineGL(CompileState&& state) explicit

Finalize an asynchronous compilation.

Takes an asynchronous compilation state returned by compile() and forms a ready-to-use shader object. See Async shader compilation and linking for more information.

template<UnsignedInt dimensions>
Magnum::Shaders::LineGL<dimensions>::LineGL(NoCreateT) explicit noexcept

Construct without creating the underlying OpenGL object.

The constructed instance is equivalent to a moved-from state. Useful in cases where you will overwrite the instance later anyway. Move another object over it to make it useful.

This function can be safely used for constructing (and later destructing) objects even without any OpenGL context being active. However note that this is a low-level and a potentially dangerous API, see the documentation of NoCreate for alternatives.

template<UnsignedInt dimensions>
Flags Magnum::Shaders::LineGL<dimensions>::flags() const

Flags.

template<UnsignedInt dimensions>
LineCapStyle Magnum::Shaders::LineGL<dimensions>::capStyle() const

Cap style.

template<UnsignedInt dimensions>
LineJoinStyle Magnum::Shaders::LineGL<dimensions>::joinStyle() const

Join style.

template<UnsignedInt dimensions>
UnsignedInt Magnum::Shaders::LineGL<dimensions>::materialCount() const

Material count.

Statically defined size of the LineMaterialUniform uniform buffer bound with bindMaterialBuffer(). Has use only if Flag::UniformBuffers is set and Flag::ShaderStorageBuffers is not set.

template<UnsignedInt dimensions>
UnsignedInt Magnum::Shaders::LineGL<dimensions>::drawCount() const

Draw count.

Statically defined size of each of the TransformationProjectionUniform2D / TransformationProjectionUniform3D and LineDrawUniform uniform buffers bound with bindTransformationProjectionBuffer() and bindDrawBuffer(). Has use only if Flag::UniformBuffers is set and Flag::ShaderStorageBuffers is not set.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setViewportSize(const Vector2& size)

Set viewport size.

Returns Reference to self (for method chaining)

Line width and smoothness set in either setWidth() / setSmoothness() or LineMaterialUniform::width / LineMaterialUniform::smoothness depends on this value — i.e., a value of 1.0f is one pixel only if setViewportSize() is called with the actual pixel size of the viewport. Initial value is a zero vector.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix)

Set transformation and projection matrix.

Returns Reference to self (for method chaining)

Initial value is an identity matrix. If Flag::InstancedTransformation is set, the per-instance transformation matrix coming from the TransformationMatrix attribute is applied first, before this one.

Expects that Flag::UniformBuffers is not set, in that case fill TransformationProjectionUniform2D::transformationProjectionMatrix / TransformationProjectionUniform3D::transformationProjectionMatrix and call bindTransformationProjectionBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setBackgroundColor(const Magnum::Color4& color)

Set background color.

Returns Reference to self (for method chaining)

Initial value is 0x00000000_rgbaf. Used for edge smoothing if smoothness is non-zero, and for background areas if LineCapStyle::Round or LineCapStyle::Triangle is used. If smoothness is zero and LineCapStyle::Butt or LineCapStyle::Square is used, only the foreground color is used.

Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::backgroundColor and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setColor(const Magnum::Color4& color)

Set color.

Returns Reference to self (for method chaining)

Initial value is 0xffffffff_rgbaf.

Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::color and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setWidth(Float width)

Set line width.

Returns Reference to self (for method chaining)

Screen-space, interpreted depending on the viewport size — i.e., a value of 1.0f is one pixel only if setViewportSize() is called with the actual pixel size of the viewport. Initial value is 1.0f.

Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::width and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setSmoothness(Float smoothness)

Set line smoothness.

Returns Reference to self (for method chaining)

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 1.0f is one pixel only if setViewportSize() is called with the actual pixel size of the viewport. Initial value is 0.0f.

Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::smoothness and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setMiterLengthLimit(Float limit)

Set miter length limit.

Returns Reference to self (for method chaining)

Maximum length (relative to line width) over which a LineJoinStyle::Miter join is converted to a LineJoinStyle::Bevel in order to avoid sharp corners extending too much. Default value is 4.0f, which corresponds to approximately 29 degrees. Alternatively you can set the limit as an angle using setMiterAngleLimit(). Miter length is calculated using the following formula, where $ w $ is line half-width, $ l $ is miter length and $ \theta $ is angle between two line segments:

\[ \frac{w}{l} = \sin(\frac{\theta}{2}) \]

Expects that joinStyle() is LineJoinStyle::Miter and limit is greater than or equal to 1.0f and finite. Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::miterLimit using LineMaterialUniform::setMiterLengthLimit() and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setMiterAngleLimit(Rad limit)

Set miter angle limit.

Returns Reference to self (for method chaining)

Like setMiterLengthLimit(), but specified as a minimum angle between two line segments below which a LineJoinStyle::Miter join is converted to a LineJoinStyle::Bevel in order to avoid sharp corners extending too much. Default value is approximately 28.955_degf, see setMiterLengthLimit() above for more information.

Expects that joinStyle() is LineJoinStyle::Miter and limit is greater than 0.0_radf. Expects that Flag::UniformBuffers is not set, in that case fill LineMaterialUniform::miterLimit using LineMaterialUniform::setMiterAngleLimit() and call bindMaterialBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setObjectId(UnsignedInt id)

Set object ID.

Returns Reference to self (for method chaining)

Expects that the shader was created with Flag::ObjectId enabled. Value set here is written to the ObjectIdOutput, see Object ID output for more information. Initial value is 0. If Flag::InstancedObjectId is enabled as well, this value is added to the ID coming from the ObjectId attribute.

Expects that Flag::UniformBuffers is not set, in that case fill LineDrawUniform::objectId and call bindDrawBuffer() instead.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::setDrawOffset(UnsignedInt offset)

Bind a draw offset.

Returns Reference to self (for method chaining)

Specifies which item in the TransformationProjectionUniform2D / TransformationProjectionUniform3D and LineDrawUniform buffers bound with bindTransformationProjectionBuffer() and bindDrawBuffer() should be used for current draw. Expects that Flag::UniformBuffers is set and offset is less than drawCount(). Initial value is 0, if drawCount() is 1, the function is a no-op as the shader assumes draw offset to be always zero.

If Flag::MultiDraw is set, gl_DrawID is added to this value, which makes each draw submitted via GL::AbstractShaderProgram::draw(const Containers::Iterable<MeshView>&) pick up its own per-draw parameters.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindTransformationProjectionBuffer(GL::Buffer& buffer)

Bind a transformation and projection uniform / shader storage buffer.

Returns Reference to self (for method chaining)

Expects that Flag::UniformBuffers is set. The buffer is expected to contain drawCount() instances of TransformationProjectionUniform2D / TransformationProjectionUniform3D. At the very least you need to call also bindDrawBuffer() and bindMaterialBuffer().

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindTransformationProjectionBuffer(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindDrawBuffer(GL::Buffer& buffer)

Bind a draw uniform / shader storage buffer.

Returns Reference to self (for method chaining)

Expects that Flag::UniformBuffers is set. The buffer is expected to contain drawCount() instances of LineDrawUniform. At the very least you need to call also bindTransformationProjectionBuffer() and bindMaterialBuffer().

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindDrawBuffer(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindMaterialBuffer(GL::Buffer& buffer)

Bind a material uniform / shader storage buffer.

Returns Reference to self (for method chaining)

Expects that Flag::UniformBuffers is set. The buffer is expected to contain materialCount() instances of LineMaterialUniform. At the very least you need to call also bindTransformationProjectionBuffer() and bindDrawBuffer().

template<UnsignedInt dimensions>
LineGL<dimensions>& Magnum::Shaders::LineGL<dimensions>::bindMaterialBuffer(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<UnsignedInt dimensions> template<UnsignedInt dimensions>
Debug& operator<<(Debug& debug, LineGL<dimensions>::Flag value) new in Git master

Debug output operator.

template<UnsignedInt dimensions> template<UnsignedInt dimensions>
Debug& operator<<(Debug& debug, LineGL<dimensions>::Flags value) new in Git master

Debug output operator.