Browse Source

[wip more]

pull/610/head
Vladimír Vondruš 4 years ago
parent
commit
42efcddfba
  1. 2
      src/Magnum/MeshTools/Test/GenerateLinesTest.cpp
  2. 10
      src/Magnum/Shaders/FlatGL.cpp
  3. 7
      src/Magnum/Shaders/Line.frag
  4. 73
      src/Magnum/Shaders/Line.vert
  5. 212
      src/Magnum/Shaders/Test/LineGLTest.cpp
  6. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute-overlapping-cap.tga
  7. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute-round-caps.tga
  8. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute.tga
  9. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-obtuse-round-caps.tga
  10. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-obtuse.tga
  11. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap-acute-round.tga
  12. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap-acute.tga
  13. BIN
      src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap.tga
  14. BIN
      src/Magnum/Shaders/Test/LineTestFiles/line-caps-round.tga
  15. BIN
      src/Magnum/Shaders/Test/LineTestFiles/line-caps-square-flat.tga
  16. BIN
      src/Magnum/Shaders/Test/LineTestFiles/line-caps-square.tga
  17. BIN
      src/Magnum/Shaders/Test/LineTestFiles/line-caps-triangle.tga

2
src/Magnum/MeshTools/Test/GenerateLinesTest.cpp

@ -25,6 +25,8 @@
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include "Magnum/MeshTools/GenerateLines.h"
namespace Magnum { namespace MeshTools { namespace Test { namespace { namespace Magnum { namespace MeshTools { namespace Test { namespace {
struct GenerateLinesTest: TestSuite::Tester { struct GenerateLinesTest: TestSuite::Tester {

10
src/Magnum/Shaders/FlatGL.cpp

@ -164,7 +164,9 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Flat.vert")); .addSource(rs.getString("Flat.vert"))
.submitCompile();
frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
@ -189,10 +191,8 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
} }
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Flat.frag")); .addSource(rs.getString("Flat.frag"))
.submitCompile();
vert.submitCompile();
frag.submitCompile();
FlatGL<dimensions> out{NoInit}; FlatGL<dimensions> out{NoInit};
out._flags = flags; out._flags = flags;

7
src/Magnum/Shaders/Line.frag

@ -176,17 +176,15 @@ void main() {
lowp const vec4 color = materials[materialId].color; lowp const vec4 color = materials[materialId].color;
#endif #endif
// TODO this comment is plain wrong
/* Pixels with `abs(centerDistanceSigned) <= [d+w,w]` are foreground, /* Pixels with `abs(centerDistanceSigned) <= [d+w,w]` are foreground,
pixels with `abs(centerDistanceSigned) > [d+w+s,w+s]` are background, pixels with `abs(centerDistanceSigned) > [d+w+s,w+s]` are background,
smoothstep in between */ smoothstep in between */
highp const vec2 edge = vec2(halfSegmentLength+0.5*width, width*0.5); highp const vec2 edge = vec2(halfSegmentLength+0.5*width, width*0.5);
// lowp const vec2 factor = smoothstep( // TODO CSE
// edge - vec2(smoothness),
// edge + vec2(smoothness), abs(centerDistanceSigned));
// lowp const vec2 factor = step(edge, abs(centerDistanceSigned));
// TODO better names ffs // TODO better names ffs
highp vec2 distance_ = vec2(max(abs(centerDistanceSigned.x) - halfSegmentLength, 0.0), abs(centerDistanceSigned.y)); highp vec2 distance_ = vec2(max(abs(centerDistanceSigned.x) - halfSegmentLength, 0.0), abs(centerDistanceSigned.y));
// TODO document what is this
if(hasCap < 0.0) distance_.x = 0.0; if(hasCap < 0.0) distance_.x = 0.0;
#ifdef CAP_STYLE_SQUARE #ifdef CAP_STYLE_SQUARE
@ -207,7 +205,6 @@ void main() {
const highp float factorX = factor.x; const highp float factorX = factor.x;
#endif #endif
// fragmentColor.ba = vec2(0.0);
fragmentColor = mix( fragmentColor = mix(
#ifdef VERTEX_COLOR #ifdef VERTEX_COLOR
interpolatedVertexColor* interpolatedVertexColor*

73
src/Magnum/Shaders/Line.vert

@ -194,6 +194,7 @@ in highp mat4 instancedTransformationMatrix;
/* Outputs */ /* Outputs */
// TODO document, maybe join together?
out highp vec2 centerDistanceSigned; out highp vec2 centerDistanceSigned;
out highp float halfSegmentLength; out highp float halfSegmentLength;
out lowp float hasCap; out lowp float hasCap;
@ -264,12 +265,14 @@ void main() {
highp const vec2 neighborDirection = (gl_VertexID & 2) == 0 ? highp const vec2 neighborDirection = (gl_VertexID & 2) == 0 ?
transformedPosition - transformedPreviousPosition : transformedPosition - transformedPreviousPosition :
transformedNextPosition - transformedPosition; transformedNextPosition - transformedPosition;
highp const vec2 firstPoint = (gl_VertexID & 2) == 0 ?
transformedPosition : transformedPreviousPosition;
highp const vec2 neighborEndPoint = (gl_VertexID & 2) == 0 ?
transformedPreviousPosition : transformedNextPosition;
highp const float directionLength = length(direction); highp const float directionLength = length(direction);
// TODO since this is used just for AA, set to a special value in case of
// a line joint that shouldn't be AAd?
halfSegmentLength = length(direction*0.5*viewportSize/2.0); halfSegmentLength = length(direction*0.5*viewportSize/2.0);
// TODO zero-sized lines better? // TODO zero-sized lines better? average from prev/next?
highp const vec2 directionNormalized = directionLength == 0.0 ? vec2(1.0, 0.0) : direction/directionLength; highp const vec2 directionNormalized = directionLength == 0.0 ? vec2(1.0, 0.0) : direction/directionLength;
/* Line width includes also twice the smoothness radius, some extra padding /* Line width includes also twice the smoothness radius, some extra padding
@ -282,7 +285,7 @@ void main() {
position is always either `A` or `B` for all four quad corners, the `d` position is always either `A` or `B` for all four quad corners, the `d`
comes in the direction attribute, `pd`/`nd` in neighborDirection and comes in the direction attribute, `pd`/`nd` in neighborDirection and
the vertex order, which is (4n +) 0/1/2/3, in gl_VertexID. the vertex order, which is (4n +) 0/1/2/3, in gl_VertexID.
// TODO redo all this here, the whole comment is outdated
0-d->-------2-d-> 0-d->-------2-d->
| / \ | / \
A---------B nd A---------B nd
@ -291,7 +294,6 @@ void main() {
\ \ . \ \ .
nd . . nd . .
v C . */ v C . */
// TODO redo all this here
/* The perpendicular direction is rotating 90° counterclockwise. Which /* The perpendicular direction is rotating 90° counterclockwise. Which
means for points 1 and 3 (i.e., gl_VertexID not divisible by 2) we need means for points 1 and 3 (i.e., gl_VertexID not divisible by 2) we need
to negate it to point the other way. */ to negate it to point the other way. */
@ -337,61 +339,70 @@ void main() {
For points 0 and 1 it'll be in the negative direction `d`, for points 2 For points 0 and 1 it'll be in the negative direction `d`, for points 2
and 3 in positive `d`. */ and 3 in positive `d`. */
// TODO make the 0.7 configurable if(all(isnan(neighborDirection)) ||
if(all(isnan(neighborDirection)) || dot(normalize(direction), normalize(neighborDirection)) < -0.7) { /* Cap limit */
// TODO make the 0.7 configurable; no actually drop it altogether
dot(normalize(direction), normalize(neighborDirection)) < -0.99 ||
/* Neighbor segment too short */
// TODO why the 2*?? why the square??
(abs(dot(perpendicular(normalize(direction))*viewportSize/2.0, (neighborEndPoint - firstPoint)*viewportSize/2.0)) < 2*edgeDistance*edgeDistance &&
// TODO this is a wrong attempt to handle colinear, needs to
// calculate proper distance from a line segment instead or do
// something else entirely ffs
dot(direction, neighborDirection) <= 0.0)
) {
edgeDirection = edgeDirection =
(directionNormalized*capSign + (directionNormalized*capSign +
perpendicular(directionNormalized)*edgeSign)*edgeDistance*2.0/viewportSize perpendicular(directionNormalized)*edgeSign)*edgeDistance*2.0/viewportSize
; ;
centerDistanceSigned.x = (edgeDistance + halfSegmentLength)*capSign; centerDistanceSigned.x = (edgeDistance + halfSegmentLength)*capSign;
hasCap = 1.0; // TODO uhhhhhhh some extra offset for the cap here??
/* Otherwise we need to create a tight joint with the neighboring line /* Otherwise we need to create a tight joint with the neighboring line
segment, as shown with the points 2 and 3. Given normalized direction segment, as shown with the points 2 and 3. Given normalized direction
`d` and neighbor direction `nd`, `normalized(d + nd)` is the "average" `d` and neighbor direction `nd`, `normalized(d + nd)` is the "average"
direction of the two and `perpendicular(normalized(d + nd))` gives us direction of the two and `perpendicular(normalized(d + nd))` gives us
the direction from B to 2: the direction from B to 2 (or from 3 to B):
--------+----2 --------+---2
| / alpha/2 | α/
w | / j w | / j
|/ |/
--d->-B +_-----d->-B
alpha/2 / \ -_ α/α\
/ nd -_ / nd
/ v d + nd /-_ v
----3 ----3 -_ \
-+
With `alpha` being the angle between `d` and `nd`, `alpha/2` appears in
two right triangles and the following holds, `w` being the edge distance With `2α` being the angle between `d` and `nd`, `α` appears in two right
from above, and `j` being the length that's needed to scale `perpendicular(normalized(d + nd))` to get point 2: triangles and the following holds, `w` being the edge distance from
above, and `j` being the length that's needed to scale
`perpendicular(normalized(d + nd))` to get point 2:
|d + nd| w 2 w |d + nd| w 2 w
sin(alpha/2) = -------- = --- --> j = -------- sin(α) = -------- = --- --> j = --------
2 |d| j |d + nd| 2 |d| j |d + nd|
Point 3 is then just in the opposite direction; for the other side it's Point 3 is then just in the opposite direction; for the other side it's
done equivalently. */ done equivalently. */
} else { } else {
// edgeDirection = perpendicular(directionNormalized)*edgeSign*edgeDistance*2.0/viewportSize;
const highp vec2 averageDirection = capSign*(directionNormalized + normalize(neighborDirection)); const highp vec2 averageDirection = capSign*(directionNormalized + normalize(neighborDirection));
const highp float averageDirectionLength = length(averageDirection); const highp float averageDirectionLength = length(averageDirection);
const highp float j = 2.0*edgeDistance/averageDirectionLength; const highp float j = 2.0*edgeDistance/averageDirectionLength;
edgeDirection = (normalize(perpendicular(averageDirection))*capSign*edgeSign*j)*2.0/viewportSize; edgeDirection = (normalize(perpendicular(averageDirection))*capSign*edgeSign*j)*2.0/viewportSize;
// const float ex = sqrt((4.0*edgeDistance*edgeDistance/(averageDirectionLength*averageDirectionLength)) - edgeDistance*edgeDistance);
const highp float ex = sqrt(j*j - edgeDistance*edgeDistance); const highp float ex = sqrt(j*j - edgeDistance*edgeDistance);
// edgeDirection = -perpendicular(averageDirection)*(1.0*edgeDistance*edgeSign*capSign/averageDirectionLength) centerDistanceSigned.x = halfSegmentLength*capSign + ex*sign(dot(direction*capSign, (perpendicular(averageDirection))*edgeSign));
// *2.0/viewportSize;
// TODO the ex should be included in here, why it isn't??
centerDistanceSigned.x = halfSegmentLength*capSign;// + ex*sign(dot(direction*capSign, (perpendicular(averageDirection))*capSign*edgeSign));
hasCap = -1.0; // TODO uhhh some extra offset here so 0 is in the center?
} }
/* Cap is there only if neighbors are NaN, otherwise a joint is rendered */
// TODO uhhhhh document why the sign comparison
if(all(isnan(neighborDirection)) || sign(centerDistanceSigned.x) != sign(halfSegmentLength*capSign))
hasCap = abs(centerDistanceSigned.x);
else
hasCap = -abs(centerDistanceSigned.x);
gl_Position.xyzw = vec4(transformedPosition + edgeDirection, 0.0, 1.0); gl_Position.xyzw = vec4(transformedPosition + edgeDirection, 0.0, 1.0);
#elif defined(THREE_DIMENSIONS) #elif defined(THREE_DIMENSIONS)
// TODO 3D, how to handle perspective? multiply edgeDistance with w? // TODO 3D, how to handle perspective? multiply edgeDistance with w?

212
src/Magnum/Shaders/Test/LineGLTest.cpp

@ -26,6 +26,7 @@
#include <sstream> #include <sstream>
#include <Corrade/Containers/StridedArrayView.h> #include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Algorithms.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
@ -42,6 +43,7 @@
#include "Magnum/GL/Renderbuffer.h" #include "Magnum/GL/Renderbuffer.h"
#include "Magnum/GL/RenderbufferFormat.h" #include "Magnum/GL/RenderbufferFormat.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/FunctionsBatch.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Matrix4.h"
#include "Magnum/Shaders/Generic.h" #include "Magnum/Shaders/Generic.h"
@ -122,6 +124,7 @@ struct LineGLTest: GL::OpenGLTester {
GL::Framebuffer _framebuffer{NoCreate}; GL::Framebuffer _framebuffer{NoCreate};
}; };
using namespace Containers::Literals;
using namespace Math::Literals; using namespace Math::Literals;
const struct { const struct {
@ -180,27 +183,153 @@ const struct {
Containers::Array<Vector2> lineSegments; Containers::Array<Vector2> lineSegments;
Float width; Float width;
Float smoothness; Float smoothness;
LineGL2D::CapStyle capStyle;
bool reverse;
Matrix3 transform;
bool expectOverlap;
const char* expected; const char* expected;
} Render2DData[]{ } Render2DData[]{
// TODO cap variants, short & long {"line caps default, flat", {InPlaceInit, {
{-0.8f, 0.8f}, {-0.8f, 0.8f},
{-0.8f, 0.4f}, {-0.4f, 0.4f},
{-0.8f, 0.0f}, { 0.0f, 0.0f},
{-0.8f, -0.4f}, { 0.4f, -0.4f},
{-0.8f, -0.8f}, { 0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, false, {},
false, "line-caps-square-flat.tga"},
{"line caps square", {InPlaceInit, {
{-0.8f, 0.8f}, {-0.8f, 0.8f},
{-0.8f, 0.4f}, {-0.4f, 0.4f},
{-0.8f, 0.0f}, { 0.0f, 0.0f},
{-0.8f, -0.4f}, { 0.4f, -0.4f},
{-0.8f, -0.8f}, { 0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Square, false, {},
false, "line-caps-square.tga"},
{"line caps round", {InPlaceInit, {
{-0.8f, 0.8f}, {-0.8f, 0.8f},
{-0.8f, 0.4f}, {-0.4f, 0.4f},
{-0.8f, 0.0f}, { 0.0f, 0.0f},
{-0.8f, -0.4f}, { 0.4f, -0.4f},
{-0.8f, -0.8f}, { 0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, false, {},
false, "line-caps-round.tga"},
{"line caps triangle", {InPlaceInit, {
{-0.8f, 0.8f}, {-0.8f, 0.8f},
{-0.8f, 0.4f}, {-0.4f, 0.4f},
{-0.8f, 0.0f}, { 0.0f, 0.0f},
{-0.8f, -0.4f}, { 0.4f, -0.4f},
{-0.8f, -0.8f}, { 0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Triangle, false, {},
false, "line-caps-triangle.tga"},
{"joint angles, obtuse", {InPlaceInit, { {"joint angles, obtuse", {InPlaceInit, {
{ 0.2f, 0.8f}, {0.2f, 0.4f}, {0.2f, 0.4f}, {0.8f, 0.4f}, { 0.4f, 0.8f}, {0.4f, 0.4f}, {0.4f, 0.4f}, {0.8f, 0.4f},
{-0.4f, 0.4f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.8f, 0.0f}, {-0.2f, 0.4f}, {0.2f, 0.0f}, {0.2f, 0.0f}, {0.8f, 0.0f},
{-0.8f, -0.0f}, {0.0f, -0.4f}, {0.0f, -0.4f}, {0.8f, -0.4f}, {-0.8f, -0.0f}, {0.2f, -0.4f}, {0.2f, -0.4f}, {0.8f, -0.4f},
{-0.8f, -0.8f}, {0.0f, -0.8f}, {0.0f, -0.8f}, {0.8f, -0.8f}, {-0.8f, -0.8f}, {0.2f, -0.8f}, {0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, "joint-angles-obtuse.tga"}, }}, 10.0f, 0.0f, {}, false, {},
// TODO cap variants here also false, "joint-angles-obtuse.tga"},
{"joint angles, obtuse, reverse direction", {InPlaceInit, {
/* Same as "joint angles, obtuse" */
{ 0.4f, 0.8f}, {0.4f, 0.4f}, {0.4f, 0.4f}, {0.8f, 0.4f},
{-0.2f, 0.4f}, {0.2f, 0.0f}, {0.2f, 0.0f}, {0.8f, 0.0f},
{-0.8f, -0.0f}, {0.2f, -0.4f}, {0.2f, -0.4f}, {0.8f, -0.4f},
{-0.8f, -0.8f}, {0.2f, -0.8f}, {0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, true, {},
false, "joint-angles-obtuse.tga"},
{"joint angles, obtuse, transformed", {InPlaceInit, {
/* Same as "joint angles, obtuse" */
{ 0.4f, 0.8f}, {0.4f, 0.4f}, {0.4f, 0.4f}, {0.8f, 0.4f},
{-0.2f, 0.4f}, {0.2f, 0.0f}, {0.2f, 0.0f}, {0.8f, 0.0f},
{-0.8f, -0.0f}, {0.2f, -0.4f}, {0.2f, -0.4f}, {0.8f, -0.4f},
{-0.8f, -0.8f}, {0.2f, -0.8f}, {0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, true,
Matrix3::scaling({100.0f, 2.0f})*Matrix3::rotation(45.0_degf),
false, "joint-angles-obtuse.tga"},
{"joint angles, obtuse, round caps", {InPlaceInit, {
/* Same as "joint angles, obtuse" */
{ 0.4f, 0.8f}, {0.4f, 0.4f}, {0.4f, 0.4f}, {0.8f, 0.4f},
{-0.2f, 0.4f}, {0.2f, 0.0f}, {0.2f, 0.0f}, {0.8f, 0.0f},
{-0.8f, -0.0f}, {0.2f, -0.4f}, {0.2f, -0.4f}, {0.8f, -0.4f},
{-0.8f, -0.8f}, {0.2f, -0.8f}, {0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, false, {},
false, "joint-angles-obtuse-round-caps.tga"},
{"joint angles, obtuse, round caps, reverse direction", {InPlaceInit, {
/* Same as "joint angles, obtuse" */
{ 0.4f, 0.8f}, {0.4f, 0.4f}, {0.4f, 0.4f}, {0.8f, 0.4f},
{-0.2f, 0.4f}, {0.2f, 0.0f}, {0.2f, 0.0f}, {0.8f, 0.0f},
{-0.8f, -0.0f}, {0.2f, -0.4f}, {0.2f, -0.4f}, {0.8f, -0.4f},
{-0.8f, -0.8f}, {0.2f, -0.8f}, {0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, true, {},
false, "joint-angles-obtuse-round-caps.tga"},
{"joint angles, acute", {InPlaceInit, { {"joint angles, acute", {InPlaceInit, {
{ 0.4f, 0.8f}, {0.0f, 0.4f}, {0.0f, 0.4f}, {0.8f, 0.4f}, { 0.1f, 0.8f}, {-0.2f, 0.5f}, {-0.2f, 0.5f}, {0.8f, 0.5f},
{ 0.8f, 0.0f}, {0.0f, -0.4f}, {0.0f, -0.4f}, {0.8f, -0.4f}, { 0.6f, 0.2f}, {-0.2f, -0.2f}, {-0.2f, -0.2f}, {0.8f, -0.2f},
{ 0.8f, -0.8f}, {0.0f, -0.8f}, {0.0f, -0.8f}, {0.8f, -0.8f}, { 0.6f, -0.5f}, {-0.2f, -0.8f}, {-0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, "joint-angles-acute.tga"}, }}, 10.0f, 0.0f, {}, false, {},
// TODO cap variants here also false, "joint-angles-acute.tga"},
{"joint angles, acute, short", {InPlaceInit, { // TODO joint styles
{ -0.25f, 0.45f}, {-0.3f, 0.4f}, {-0.3f, 0.4f}, {0.6f, 0.4f}, {"joint angles, acute, reverse direction", {InPlaceInit, {
{ -0.25f, -0.45f}, {-0.3f, -0.4f}, {-0.3f, -0.4f}, {0.6f, -0.4f}, /* Same as "joint angles, acute" */
}}, 20.0f, 0.0f, "joint-angles-acute-short.tga"}, { 0.1f, 0.8f}, {-0.2f, 0.5f}, {-0.2f, 0.5f}, {0.8f, 0.5f},
// TODO cap variants here also { 0.6f, 0.2f}, {-0.2f, -0.2f}, {-0.2f, -0.2f}, {0.8f, -0.2f},
{ 0.6f, -0.5f}, {-0.2f, -0.8f}, {-0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, true, {},
false, "joint-angles-acute.tga"},
{"joint angles, acute, transformed", {InPlaceInit, {
/* Same as "joint angles, transformed" */
{ 0.1f, 0.8f}, {-0.2f, 0.5f}, {-0.2f, 0.5f}, {0.8f, 0.5f},
{ 0.6f, 0.2f}, {-0.2f, -0.2f}, {-0.2f, -0.2f}, {0.8f, -0.2f},
{ 0.6f, -0.5f}, {-0.2f, -0.8f}, {-0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, false,
Matrix3::scaling({100.0f, 2.0f})*Matrix3::rotation(45.0_degf),
false, "joint-angles-acute.tga"},
{"joint angles, acute, round caps", {InPlaceInit, {
/* Same as "joint angles, acute" */
{ 0.1f, 0.8f}, {-0.2f, 0.5f}, {-0.2f, 0.5f}, {0.8f, 0.5f},
{ 0.6f, 0.2f}, {-0.2f, -0.2f}, {-0.2f, -0.2f}, {0.8f, -0.2f},
{ 0.6f, -0.5f}, {-0.2f, -0.8f}, {-0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, false, {},
false, "joint-angles-acute-round-caps.tga"},
{"joint angles, acute, round caps, reverse direction", {InPlaceInit, {
/* Same as "joint angles, acute" */
{ 0.1f, 0.8f}, {-0.2f, 0.5f}, {-0.2f, 0.5f}, {0.8f, 0.5f},
{ 0.6f, 0.2f}, {-0.2f, -0.2f}, {-0.2f, -0.2f}, {0.8f, -0.2f},
{ 0.6f, -0.5f}, {-0.2f, -0.8f}, {-0.2f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, true, {},
false, "joint-angles-acute-round-caps.tga"},
{"joint angles, short cap", {InPlaceInit, {
{-0.3f, 0.6f}, {-0.6f, 0.6f}, {-0.6f, 0.6f}, {-0.6f, -0.6f}, {-0.6f, -0.6f}, {-0.4f, -0.6f},
{ 0.6f, 0.6f}, {0.5f, 0.6f}, {0.5f, 0.6f}, {0.5f, -0.6f}, {0.5f, -0.6f}, {0.51f, -0.6f},
}}, 20.0f, 1.0f, LineGL2D::CapStyle::Round, false, {},
true, "joint-angles-short-cap.tga"},
{"joint angles, short cap, reversed", {InPlaceInit, {
{-0.3f, 0.6f}, {-0.6f, 0.6f}, {-0.6f, 0.6f}, {-0.6f, -0.6f}, {-0.6f, -0.6f}, {-0.4f, -0.6f},
{ 0.6f, 0.6f}, {0.5f, 0.6f}, {0.5f, 0.6f}, {0.5f, -0.6f}, {0.5f, -0.6f}, {0.51f, -0.6f},
}}, 20.0f, 1.0f, LineGL2D::CapStyle::Round, true, {}, // TODO no difference
true, "joint-angles-short-cap.tga"},
{"joint angles, short cap, acute", {InPlaceInit, {
{ 0.6f, 0.8f}, {0.0f, 0.6f}, {0.0f, 0.6f}, {0.8f, 0.6f},
{ 0.6f, 0.2f}, {0.0f, 0.05f}, {0.0f, 0.05f}, {0.8f, 0.05f},
{ 0.6f, -0.35f}, {0.0f, -0.45f}, {0.0f, -0.45f}, {0.8f, -0.45f},
{ 0.6f, -0.8f}, {0.0f, -0.8f}, {0.0f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, false, {},
true, "joint-angles-short-cap-acute.tga"},
{"joint angles, short cap, acute reverse direction", {InPlaceInit, {
/* Same as "joint angles, short cap, acute" */
{ 0.6f, 0.8f}, {0.0f, 0.6f}, {0.0f, 0.6f}, {0.8f, 0.6f},
{ 0.6f, 0.2f}, {0.0f, 0.05f}, {0.0f, 0.05f}, {0.8f, 0.05f},
{ 0.6f, -0.35f}, {0.0f, -0.45f}, {0.0f, -0.45f}, {0.8f, -0.45f},
{ 0.6f, -0.8f}, {0.0f, -0.8f}, {0.0f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 0.0f, {}, true, {},
true, "joint-angles-short-cap-acute.tga"},
{"joint angles, short cap, acute, round", {InPlaceInit, {
/* Same as "joint angles, short cap, acute" */
{ 0.6f, 0.8f}, {0.0f, 0.6f}, {0.0f, 0.6f}, {0.8f, 0.6f},
{ 0.6f, 0.2f}, {0.0f, 0.05f}, {0.0f, 0.05f}, {0.8f, 0.05f},
{ 0.6f, -0.35f}, {0.0f, -0.45f}, {0.0f, -0.45f}, {0.8f, -0.45f},
{ 0.6f, -0.8f}, {0.0f, -0.8f}, {0.0f, -0.8f}, {0.8f, -0.8f},
}}, 10.0f, 1.0f, LineGL2D::CapStyle::Round, false, {},
true, "joint-angles-short-cap-acute-round.tga"},
}; };
LineGLTest::LineGLTest() { LineGLTest::LineGLTest() {
@ -655,7 +784,7 @@ void LineGLTest::renderTeardown() {
_color = GL::Renderbuffer{NoCreate}; _color = GL::Renderbuffer{NoCreate};
} }
template<UnsignedInt dimensions> GL::Mesh generateLineMesh(Containers::ArrayView<const VectorTypeFor<dimensions, Float>> lineSegments) { template<UnsignedInt dimensions> GL::Mesh generateLineMesh(Containers::StridedArrayView1D<const VectorTypeFor<dimensions, Float>> lineSegments) {
struct Vertex { struct Vertex {
VectorTypeFor<dimensions, Float> previousPosition; VectorTypeFor<dimensions, Float> previousPosition;
VectorTypeFor<dimensions, Float> position; VectorTypeFor<dimensions, Float> position;
@ -663,7 +792,8 @@ template<UnsignedInt dimensions> GL::Mesh generateLineMesh(Containers::ArrayView
}; };
CORRADE_INTERNAL_ASSERT(lineSegments.size() % 2 == 0); CORRADE_INTERNAL_ASSERT(lineSegments.size() % 2 == 0);
Containers::Array<Vertex> vertices{NoInit, lineSegments.size()*2}; /* Not NoInit, because we're subsequently checking for NaNs */
Containers::Array<Vertex> vertices{ValueInit, lineSegments.size()*2};
for(std::size_t i = 0; i != lineSegments.size(); ++i) for(std::size_t i = 0; i != lineSegments.size(); ++i)
vertices[i*2 + 0].position = vertices[i*2 + 1].position = lineSegments[i]; vertices[i*2 + 0].position = vertices[i*2 + 1].position = lineSegments[i];
@ -766,6 +896,13 @@ template<LineGL2D::Flag flag> void LineGLTest::renderDefaults2D() {
.setFlags(flag)}; .setFlags(flag)};
shader.setViewportSize(Vector2{RenderSize}); shader.setViewportSize(Vector2{RenderSize});
/* Enabling blending and a half-transparent color -- there should be no
overlaps */
GL::Renderer::enable(GL::Renderer::Feature::Blending);
GL::Renderer::setBlendFunction(
GL::Renderer::BlendFunction::One,
GL::Renderer::BlendFunction::OneMinusSourceAlpha);
if(flag == LineGL2D::Flag{}) { if(flag == LineGL2D::Flag{}) {
shader.draw(lines); shader.draw(lines);
} }
@ -789,6 +926,8 @@ template<LineGL2D::Flag flag> void LineGLTest::renderDefaults2D() {
#endif #endif
else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); else CORRADE_INTERNAL_ASSERT_UNREACHABLE();
GL::Renderer::disable(GL::Renderer::Feature::Blending);
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
@ -817,19 +956,30 @@ template<LineGL2D::Flag flag> void LineGLTest::render2D() {
} }
#endif #endif
GL::Mesh lines = generateLineMesh<2>(data.lineSegments); Containers::Array<Vector2> transformedLineSegments{NoInit, data.lineSegments.size()};
Utility::copy(data.lineSegments, transformedLineSegments);
for(Vector2& i: transformedLineSegments)
i = data.transform.transformPoint(i);
GL::Mesh lines = generateLineMesh<2>(
data.reverse ? stridedArrayView(transformedLineSegments).flipped<0>() : transformedLineSegments);
LineGL2D shader{LineGL2D::Configuration{} LineGL2D shader{LineGL2D::Configuration{}
.setFlags(flag)}; .setFlags(flag)
.setCapStyle(data.capStyle)};
shader.setViewportSize(Vector2{RenderSize}); shader.setViewportSize(Vector2{RenderSize});
shader shader
.setWidth(data.width) .setWidth(data.width)
.setSmoothness(data.smoothness) .setSmoothness(data.smoothness)
// .setBackgroundColor(0xff0000ff_rgbaf) .setTransformationProjectionMatrix(data.transform.inverted())
// .setColor(0x557766_rgbf) .setColor(0x80808080_rgbaf);
;
// TODO test with blending -- there should be no self-intersection /* Enabling blending and a half-transparent color -- there should be no
overlaps */
GL::Renderer::enable(GL::Renderer::Feature::Blending);
GL::Renderer::setBlendFunction(
GL::Renderer::BlendFunction::One,
GL::Renderer::BlendFunction::OneMinusSourceAlpha);
if(flag == LineGL2D::Flag{}) { if(flag == LineGL2D::Flag{}) {
shader.draw(lines); shader.draw(lines);
@ -854,17 +1004,27 @@ template<LineGL2D::Flag flag> void LineGLTest::render2D() {
#endif #endif
else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); else CORRADE_INTERNAL_ASSERT_UNREACHABLE();
GL::Renderer::disable(GL::Renderer::Feature::Blending);
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found."); CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
Image2D image = _framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
CORRADE_COMPARE_WITH( CORRADE_COMPARE_WITH(
/* Dropping the alpha channel, as it's always 1.0 */ /* Dropping the alpha channel, as it's always 1.0 */
Containers::arrayCast<Color3ub>(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels<Color4ub>()), Containers::arrayCast<Color3ub>(image.pixels<Color4ub>()),
Utility::Path::join({SHADERS_TEST_DIR, "LineTestFiles", data.expected}), Utility::Path::join({SHADERS_TEST_DIR, "LineTestFiles", data.expected}),
(DebugTools::CompareImageToFile{_manager})); (DebugTools::CompareImageToFile{_manager}));
{
CORRADE_EXPECT_FAIL_IF(data.expectOverlap, "Rendered with overlapping geometry at the moment.");
CORRADE_COMPARE(Math::max(image.pixels<Color4ub>().asContiguous()), 0x888888ff_rgba);
}
} }
}}}} }}}}

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute-overlapping-cap.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute-round-caps.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-acute.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-obtuse-round-caps.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-obtuse.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap-acute-round.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap-acute.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/joint-angles-short-cap.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/line-caps-round.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/line-caps-square-flat.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/line-caps-square.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/LineTestFiles/line-caps-triangle.tga

Binary file not shown.
Loading…
Cancel
Save