diff --git a/doc/changelog.dox b/doc/changelog.dox index 20584cba7..c1fe68d91 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -247,8 +247,8 @@ See also: - New @ref Shaders::MeshVisualizer2D for 2D mesh visualization - Tangent space visualization in @ref Shaders::MeshVisualizer3D -- Object and primitive ID visualization in @ref Shaders::MeshVisualizer2D - and @ref Shaders::MeshVisualizer3D +- Object, vertex and primitive ID visualization in + @ref Shaders::MeshVisualizer2D and @ref Shaders::MeshVisualizer3D - Texture coordinate transformation in @ref Shaders::DistanceFieldVector, @ref Shaders::Flat, @ref Shaders::Phong and @ref Shaders::Vector - Ability to render Per-instance / per-vertex object ID in @ref Shaders::Flat diff --git a/src/Magnum/Shaders/MeshVisualizer.cpp b/src/Magnum/Shaders/MeshVisualizer.cpp index 03c78a1ba..72f886ea5 100644 --- a/src/Magnum/Shaders/MeshVisualizer.cpp +++ b/src/Magnum/Shaders/MeshVisualizer.cpp @@ -57,10 +57,11 @@ MeshVisualizerBase::MeshVisualizerBase(FlagsBase flags): _flags{flags} { #ifndef CORRADE_NO_ASSERT Int countMutuallyExclusive = 0; if(flags & FlagBase::InstancedObjectId) ++countMutuallyExclusive; + if(flags & FlagBase::VertexId) ++countMutuallyExclusive; if(flags & FlagBase::PrimitiveIdFromVertexId) ++countMutuallyExclusive; #endif CORRADE_ASSERT(countMutuallyExclusive <= 1, - "Shaders::MeshVisualizer: Flag::InstancedObjectId and Flag::PrimitiveId are mutually exclusive", ); + "Shaders::MeshVisualizer: Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive", ); #endif #ifndef MAGNUM_TARGET_GLES2 @@ -113,6 +114,7 @@ GL::Version MeshVisualizerBase::setupShaders(GL::Shader& vert, GL::Shader& frag, vert.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(_flags & FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "") #endif #ifdef MAGNUM_TARGET_WEBGL @@ -126,6 +128,7 @@ GL::Version MeshVisualizerBase::setupShaders(GL::Shader& vert, GL::Shader& frag, .addSource(_flags & FlagBase::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(_flags & FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(_flags & FlagBase::PrimitiveId ? (_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : @@ -138,8 +141,8 @@ GL::Version MeshVisualizerBase::setupShaders(GL::Shader& vert, GL::Shader& frag, MeshVisualizerBase& MeshVisualizerBase::setColor(const Color4& color) { #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(_flags & (FlagBase::Wireframe|FlagBase::InstancedObjectId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/primitive ID enabled", *this); + CORRADE_ASSERT(_flags & (FlagBase::Wireframe|FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), + "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled", *this); #else CORRADE_ASSERT(_flags & FlagBase::Wireframe, "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled", *this); @@ -164,15 +167,15 @@ MeshVisualizerBase& MeshVisualizerBase::setWireframeWidth(const Float width) { #ifndef MAGNUM_TARGET_GLES2 MeshVisualizerBase& MeshVisualizerBase::setColorMapTransformation(const Float offset, const Float scale) { - CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/primitive ID enabled", *this); + CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), + "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled", *this); setUniform(_colorMapOffsetScaleUniform, Vector2{offset, scale}); return *this; } MeshVisualizerBase& MeshVisualizerBase::bindColorMapTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/primitive ID enabled", *this); + CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), + "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled", *this); texture.bind(ColorMapTextureUnit); return *this; } @@ -182,7 +185,7 @@ MeshVisualizerBase& MeshVisualizerBase::bindColorMapTexture(GL::Texture2D& textu MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisualizerBase{Implementation::MeshVisualizerBase::FlagBase(UnsignedShort(flags))} { #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), + CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), "Shaders::MeshVisualizer2D: at least one visualization feature has to be enabled", ); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), @@ -212,6 +215,7 @@ MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisua (*geom) .addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n") .addSource(_flags & FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(_flags & FlagBase::PrimitiveId ? (_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : @@ -264,7 +268,7 @@ MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisua _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); if(flags & (Flag::Wireframe #ifndef MAGNUM_TARGET_GLES2 - |Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId + |Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId #endif )) _colorUniform = uniformLocation("color"); @@ -276,7 +280,7 @@ MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisua _viewportSizeUniform = uniformLocation("viewportSize"); } #ifndef MAGNUM_TARGET_GLES2 - if(flags & (Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId)) { + if(flags & (Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId)) { _colorMapOffsetScaleUniform = uniformLocation("colorMapOffsetScale"); setUniform(uniformLocation("colorMapTexture"), ColorMapTextureUnit); } @@ -299,7 +303,7 @@ MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisua setSmoothness(2.0f); } #ifndef MAGNUM_TARGET_GLES2 - if(flags & (Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId)) + if(flags & (Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId)) setColorMapTransformation(1.0f/512.0f, 1.0f/256.0f); #endif #endif @@ -329,7 +333,7 @@ MeshVisualizer2D& MeshVisualizer2D::setSmoothness(const Float smoothness) { MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisualizerBase{Implementation::MeshVisualizerBase::FlagBase(UnsignedShort(flags))} { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), + CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), "Shaders::MeshVisualizer3D: at least one visualization feature has to be enabled", ); CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), "Shaders::MeshVisualizer3D: geometry shader has to be enabled when rendering TBN direction", ); @@ -394,6 +398,7 @@ MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisua .addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices)) .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(_flags & FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(_flags & FlagBase::PrimitiveId ? (_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : @@ -461,7 +466,7 @@ MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisua _projectionMatrixUniform = uniformLocation("projectionMatrix"); if(flags & (Flag::Wireframe #ifndef MAGNUM_TARGET_GLES2 - |Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId + |Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId #endif )) _colorUniform = uniformLocation("color"); @@ -479,7 +484,7 @@ MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisua _viewportSizeUniform = uniformLocation("viewportSize"); } #ifndef MAGNUM_TARGET_GLES2 - if(flags & (Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId)) { + if(flags & (Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId)) { _colorMapOffsetScaleUniform = uniformLocation("colorMapOffsetScale"); setUniform(uniformLocation("colorMapTexture"), ColorMapTextureUnit); } @@ -516,7 +521,7 @@ MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisua setSmoothness(2.0f); } #ifndef MAGNUM_TARGET_GLES2 - if(flags & (Flag::InstancedObjectId|Flag::PrimitiveIdFromVertexId)) + if(flags & (Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId)) setColorMapTransformation(1.0f/512.0f, 1.0f/256.0f); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -602,6 +607,7 @@ Debug& operator<<(Debug& debug, const MeshVisualizer2D::Flag value) { _c(Wireframe) #ifndef MAGNUM_TARGET_GLES2 _c(InstancedObjectId) + _c(VertexId) #ifndef MAGNUM_TARGET_WEBGL _c(PrimitiveId) #endif @@ -630,6 +636,7 @@ Debug& operator<<(Debug& debug, const MeshVisualizer3D::Flag value) { #endif #ifndef MAGNUM_TARGET_GLES2 _c(InstancedObjectId) + _c(VertexId) #ifndef MAGNUM_TARGET_WEBGL _c(PrimitiveId) #endif @@ -649,6 +656,7 @@ Debug& operator<<(Debug& debug, const MeshVisualizer2D::Flags value) { MeshVisualizer2D::Flag::NoGeometryShader, #ifndef MAGNUM_TARGET_GLES2 MeshVisualizer2D::Flag::InstancedObjectId, + MeshVisualizer2D::Flag::VertexId, MeshVisualizer2D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ #ifndef MAGNUM_TARGET_WEBGL MeshVisualizer2D::Flag::PrimitiveId @@ -670,6 +678,7 @@ Debug& operator<<(Debug& debug, const MeshVisualizer3D::Flags value) { #endif #ifndef MAGNUM_TARGET_GLES2 MeshVisualizer3D::Flag::InstancedObjectId, + MeshVisualizer3D::Flag::VertexId, MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ #ifndef MAGNUM_TARGET_WEBGL MeshVisualizer3D::Flag::PrimitiveId diff --git a/src/Magnum/Shaders/MeshVisualizer.frag b/src/Magnum/Shaders/MeshVisualizer.frag index 483d3ab58..0d301f1b1 100644 --- a/src/Magnum/Shaders/MeshVisualizer.frag +++ b/src/Magnum/Shaders/MeshVisualizer.frag @@ -44,7 +44,7 @@ #extension GL_NV_shader_noperspective_interpolation: require #endif -#if (defined(WIREFRAME_RENDERING) || defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID)) && !defined(TBN_DIRECTION) +#if (defined(WIREFRAME_RENDERING) || defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID)) && !defined(TBN_DIRECTION) #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 1) #endif @@ -95,12 +95,14 @@ uniform lowp float smoothness ; #endif -#if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) +#if defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) #ifdef EXPLICIT_TEXTURE_LAYER layout(binding = 4) #endif uniform lowp sampler2D colorMapTexture; +#endif +#if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 6) #endif @@ -127,6 +129,9 @@ in lowp vec3 barycentric; #ifdef INSTANCED_OBJECT_ID flat in highp uint interpolatedInstanceObjectId; #endif +#ifdef VERTEX_ID +in highp float interpolatedMappedVertexId; +#endif #ifdef PRIMITIVE_ID_FROM_VERTEX_ID flat in highp uint interpolatedPrimitiveId; #endif @@ -144,21 +149,34 @@ out lowp vec4 fragmentColor; #endif void main() { - /* Map object/primitive ID to a color. Will be either combined with the - wireframe background color (if wireframe is enabled), ignored (if + /* Map object/vertex/primitive ID to a color. Will be either combined with + the wireframe background color (if wireframe is enabled), ignored (if rendering TBN direction) or used as-is if nothing else is enabled */ - #if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) - lowp vec4 faceColor = texture(colorMapTexture, vec2(colorMapOffset + float( - #ifdef INSTANCED_OBJECT_ID - interpolatedInstanceObjectId - #elif defined(PRIMITIVE_ID) - gl_PrimitiveID - #elif defined(PRIMITIVE_ID_FROM_VERTEX_ID) - interpolatedPrimitiveId + #if defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) + lowp vec4 faceColor = texture(colorMapTexture, vec2( + /* Object/primitive IDs are constant across the whole primitive so we + do the offset/scale mapping here */ + #if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) + colorMapOffset + float( + #ifdef INSTANCED_OBJECT_ID + interpolatedInstanceObjectId + #elif defined(PRIMITIVE_ID) + gl_PrimitiveID + #elif defined(PRIMITIVE_ID_FROM_VERTEX_ID) + interpolatedPrimitiveId + #else + #error mosra messed up + #endif + )*colorMapScale + + /* Vertex ID changes, so the offset/scale mapping was done already in + a VS/GS and we just pass the interpolated result to a texture */ + #elif defined(VERTEX_ID) + interpolatedMappedVertexId #else - #error mosra messed up + #error mosra messed up, again #endif - )*colorMapScale, 0.0)); + , 0.0)); #endif /* 1. For wireframe the line is on the triangle edges, thus dist = 0 at @@ -195,7 +213,7 @@ void main() { #else fragmentColor = backgroundColor; #endif - #if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) + #if defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) fragmentColor *= faceColor; #endif @@ -244,8 +262,8 @@ void main() { fragmentColor = mix(wireframeColor, fragmentColor, nearest); #endif - /* Object / Primitive ID visualization using a colormap */ - #elif defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) + /* Object / Vertex / Primitive ID visualization using a colormap */ + #elif defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) fragmentColor = color*faceColor; #else diff --git a/src/Magnum/Shaders/MeshVisualizer.geom b/src/Magnum/Shaders/MeshVisualizer.geom index 2bf1cd751..8c638e3cb 100644 --- a/src/Magnum/Shaders/MeshVisualizer.geom +++ b/src/Magnum/Shaders/MeshVisualizer.geom @@ -103,6 +103,10 @@ out lowp vec3 dist; flat in highp uint interpolatedVsInstanceObjectId[]; flat out highp uint interpolatedInstanceObjectId; #endif +#ifdef VERTEX_ID +in highp float interpolatedVsMappedVertexId[]; +out highp float interpolatedMappedVertexId; +#endif #ifdef PRIMITIVE_ID_FROM_VERTEX_ID flat in highp uint interpolatedVsPrimitiveId[]; flat out highp uint interpolatedPrimitiveId; @@ -180,7 +184,7 @@ void main() { gl_PrimitiveID = gl_PrimitiveIDIn; #endif - /* Screen position of each vertex */ + /* Screen position of each vertex + TBN direction */ vec2 p[3]; #ifdef TANGENT_DIRECTION vec2 t[3]; @@ -216,7 +220,8 @@ void main() { const float area = abs(dot(vec2(-v[1].y, v[1].x), v[2])); /* If wireframe is enabled, add distance to opposite side to each vertex. - Otherwise make all distances the same to avoid any lines being drawn. */ + Otherwise make all distances the same to avoid any lines being drawn. + Propagate also mapped vertex ID, since that changes per-vertex also. */ for(int i = 0; i != 3; ++i) { dist = vec3(0.0, 0.0, 0.0); #ifdef WIREFRAME_RENDERING @@ -224,6 +229,9 @@ void main() { #else dist = vec3(area/length(v[i])); #endif + #ifdef VERTEX_ID + interpolatedMappedVertexId = interpolatedVsMappedVertexId[i]; + #endif #if defined(TANGENT_DIRECTION) || defined(BITANGENT_DIRECTION) || defined(NORMAL_DIRECTION) backgroundColor = color; lineColor = wireframeColor; diff --git a/src/Magnum/Shaders/MeshVisualizer.h b/src/Magnum/Shaders/MeshVisualizer.h index bd4cffad0..9c5393be0 100644 --- a/src/Magnum/Shaders/MeshVisualizer.h +++ b/src/Magnum/Shaders/MeshVisualizer.h @@ -51,8 +51,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerBase: public GL::AbstractShaderProgram NoGeometryShader = 1 << 1, #ifndef MAGNUM_TARGET_GLES2 InstancedObjectId = 1 << 2, - PrimitiveId = 1 << 3, - PrimitiveIdFromVertexId = (1 << 4)|PrimitiveId + VertexId = 1 << 3, + PrimitiveId = 1 << 4, + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId #endif }; typedef Containers::EnumSet FlagsBase; @@ -189,16 +190,19 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer2D: public Implementation::MeshVisuali /** @copydoc MeshVisualizer3D::Flag::InstancedObjectId */ InstancedObjectId = 1 << 2, + /** @copydoc MeshVisualizer3D::Flag::VertexId */ + VertexId = 1 << 3, + #ifndef MAGNUM_TARGET_WEBGL /** @copydoc MeshVisualizer3D::Flag::PrimitiveId */ - PrimitiveId = 1 << 3, + PrimitiveId = 1 << 4, #endif /** @copydoc MeshVisualizer3D::Flag::PrimitiveIdFromVertexId */ #ifndef MAGNUM_TARGET_WEBGL - PrimitiveIdFromVertexId = (1 << 4)|PrimitiveId + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId #else - PrimitiveIdFromVertexId = (1 << 4)|(1 << 3) + PrimitiveIdFromVertexId = (1 << 5)|(1 << 4) #endif #endif }; @@ -447,7 +451,7 @@ Rendering setup: @snippet MagnumShaders.cpp MeshVisualizer-usage-tbn2 -@section Shaders-MeshVisualizer-object-id Object and primitive ID visualization +@section Shaders-MeshVisualizer-object-id Object, vertex and primitive ID visualization If the mesh contains a per-vertex (or instanced) @ref ObjectId, it can be visualized by enabling @ref Flag::InstancedObjectId. For the actual @@ -458,14 +462,19 @@ the @f$ [0, 1] @f$ texture range. Various colormap presets are in the @snippet MagnumShaders.cpp MeshVisualizer-usage-object-id -If you enable @ref Flag::PrimitiveId instead, the shader will use the color map -to visualize the order in which primitives are drawn. That's useful for example -to see how well is the mesh optimized for a post-transform vertex cache. This -by default relies on the @glsl gl_PrimitiveID @ce GLSL builtin; with -@ref Flag::PrimitiveIdFromVertexId it's emulated using @glsl gl_VertexID @ce, -expecting you to draw a non-indexed triangle mesh. You can use -@ref MeshTools::duplicate() (and potentially @ref MeshTools::generateIndices()) -to conveniently convert the mesh to a non-indexed @ref MeshPrimitive::Triangles. +If you enable @ref Flag::VertexId, the shader will use the color map to +visualize how are vertices shared among primitives. That's useful for +inspecting mesh connectivity --- primitives sharing vertices will have a smooth +color map transition while duplicated vertices will cause a sharp edge. This +relies on the @glsl gl_VertexID @ce GLSL builtin. + +The @ref Flag::PrimitiveId then visualizes the order in which primitives are +drawn. That's useful for example to see to see how well is the mesh optimized +for a post-transform vertex cache. This by default relies on the @glsl gl_PrimitiveID @ce GLSL builtin; with @ref Flag::PrimitiveIdFromVertexId it's +emulated using @glsl gl_VertexID @ce, expecting you to draw a non-indexed +triangle mesh. You can use @ref MeshTools::duplicate() (and potentially +@ref MeshTools::generateIndices()) to conveniently convert the mesh to a +non-indexed @ref MeshPrimitive::Triangles. @requires_gl32 The `gl_PrimitiveID` shader variable is not available on OpenGL 3.1 and lower. @@ -606,7 +615,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali /** * Visualize instanced object ID. You need to provide the * @ref ObjectId attribute in the mesh. Mutually exclusive with - * @ref Flag::PrimitiveId. + * @ref Flag::VertexId and @ref Flag::PrimitiveId. * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} * @requires_gles30 Object ID output requires integer support in * shaders, which is not available in OpenGL ES 2.0 or WebGL @@ -615,10 +624,27 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali */ InstancedObjectId = 1 << 2, + /** + * Visualize vertex ID (@cpp gl_VertexID @ce). Useful for + * visualizing mesh connectivity --- primitives sharing vertices + * will have a smooth color map transition while duplicated + * vertices will cause a sharp edge. Mutually exclusive with + * @ref Flag::InstancedObjectId and @ref Flag::PrimitiveId. + * @requires_gl30 The `gl_VertexID` shader variable is not + * available on OpenGL 2.1. + * @requires_gles30 The `gl_VertexID` shader variable is not + * available on OpenGL ES 2.0. + * @requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. + * @m_since_latest + */ + VertexId = 1 << 3, + #ifndef MAGNUM_TARGET_WEBGL /** - * Visualize primitive ID (@cpp gl_PrimitiveID @ce). Mutually - * exclusive with @ref Flag::InstancedObjectId. See also + * Visualize primitive ID (@cpp gl_PrimitiveID @ce). Useful for + * visualizing how well is the mesh optimized for a post-transform + * vertex cache. Mutually exclusive with + * @ref Flag::InstancedObjectId and @ref Flag::VertexId. See also * @ref Flag::PrimitiveIdFromVertexId. * @requires_gl32 The `gl_PrimitiveID` shader variable is not * available on OpenGL 3.1 and lower. @@ -628,7 +654,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @requires_gles `gl_PrimitiveID` is not available in WebGL. * @m_since_latest */ - PrimitiveId = 1 << 3, + PrimitiveId = 1 << 4, #endif /** @@ -646,9 +672,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @m_since_latest */ #ifndef MAGNUM_TARGET_WEBGL - PrimitiveIdFromVertexId = (1 << 4)|PrimitiveId, + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId, #else - PrimitiveIdFromVertexId = (1 << 4)|(1 << 3), + PrimitiveIdFromVertexId = (1 << 5)|(1 << 4), #endif #endif @@ -666,7 +692,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @requires_gles Geometry shaders are not available in WebGL. * @m_since_latest */ - TangentDirection = 1 << 5, + TangentDirection = 1 << 6, /** * Visualize bitangent direction with green lines pointing out of @@ -683,7 +709,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @requires_gles Geometry shaders are not available in WebGL. * @m_since_latest */ - BitangentFromTangentDirection = 1 << 6, + BitangentFromTangentDirection = 1 << 7, /** * Visualize bitangent direction with green lines pointing out of @@ -700,7 +726,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @requires_gles Geometry shaders are not available in WebGL. * @m_since_latest */ - BitangentDirection = 1 << 7, + BitangentDirection = 1 << 8, /** * Visualize normal direction with blue lines pointing out of @@ -714,7 +740,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisuali * @requires_gles Geometry shaders are not available in WebGL. * @m_since_latest */ - NormalDirection = 1 << 8 + NormalDirection = 1 << 9 #endif }; diff --git a/src/Magnum/Shaders/MeshVisualizer.vert b/src/Magnum/Shaders/MeshVisualizer.vert index 4443dd8c7..6a4085e98 100644 --- a/src/Magnum/Shaders/MeshVisualizer.vert +++ b/src/Magnum/Shaders/MeshVisualizer.vert @@ -62,6 +62,19 @@ uniform highp mat4 projectionMatrix #error #endif +#ifdef VERTEX_ID +#ifdef EXPLICIT_UNIFORM_LOCATION +layout(location = 6) +#endif +uniform lowp vec2 colorMapOffsetScale + #ifndef GL_ES + = vec2(1.0/512.0, 1.0/256.0) + #endif + ; +#define colorMapOffset colorMapOffsetScale.x +#define colorMapScale colorMapOffsetScale.y +#endif + #if defined(TANGENT_DIRECTION) || defined(BITANGENT_FROM_TANGENT_DIRECTION) || defined(BITANGENT_DIRECTION) || defined(NORMAL_DIRECTION) #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 8) @@ -139,6 +152,14 @@ flat out highp uint interpolatedVsInstanceObjectId; #endif #endif +#ifdef VERTEX_ID +#ifdef NO_GEOMETRY_SHADER +out highp float interpolatedMappedVertexId; +#else +out highp float interpolatedVsMappedVertexId; +#endif +#endif + #ifdef PRIMITIVE_ID_FROM_VERTEX_ID #ifdef NO_GEOMETRY_SHADER flat out highp uint interpolatedPrimitiveId; @@ -206,6 +227,14 @@ void main() { #endif = instanceObjectId; #endif + #ifdef VERTEX_ID + #ifdef NO_GEOMETRY_SHADER + interpolatedMappedVertexId + #else + interpolatedVsMappedVertexId + #endif + = colorMapOffset + float(gl_VertexID)*colorMapScale; + #endif #ifdef PRIMITIVE_ID_FROM_VERTEX_ID #ifdef NO_GEOMETRY_SHADER interpolatedPrimitiveId diff --git a/src/Magnum/Shaders/Test/CMakeLists.txt b/src/Magnum/Shaders/Test/CMakeLists.txt index a062724b2..d42a759fc 100644 --- a/src/Magnum/Shaders/Test/CMakeLists.txt +++ b/src/Magnum/Shaders/Test/CMakeLists.txt @@ -159,6 +159,8 @@ if(BUILD_GL_TESTS) MeshVisualizerTestFiles/defaults-primitiveid2D.tga MeshVisualizerTestFiles/defaults-primitiveid3D.tga MeshVisualizerTestFiles/defaults-tbn.tga + MeshVisualizerTestFiles/defaults-vertexid2D.tga + MeshVisualizerTestFiles/defaults-vertexid3D.tga MeshVisualizerTestFiles/defaults-wireframe2D.tga MeshVisualizerTestFiles/defaults-wireframe3D.tga MeshVisualizerTestFiles/objectid2D.tga @@ -168,6 +170,8 @@ if(BUILD_GL_TESTS) MeshVisualizerTestFiles/primitiveid3D.tga MeshVisualizerTestFiles/tbn-wide.tga MeshVisualizerTestFiles/tbn.tga + MeshVisualizerTestFiles/vertexid2D.tga + MeshVisualizerTestFiles/vertexid3D.tga MeshVisualizerTestFiles/wireframe-nogeo2D.tga MeshVisualizerTestFiles/wireframe-nogeo3D.tga MeshVisualizerTestFiles/wireframe-nogeo-objectid2D.tga @@ -175,6 +179,8 @@ if(BUILD_GL_TESTS) MeshVisualizerTestFiles/wireframe-perspective.tga MeshVisualizerTestFiles/wireframe-primitiveid-tn.tga MeshVisualizerTestFiles/wireframe-tn-smooth.tga + MeshVisualizerTestFiles/wireframe-vertexid2D.tga + MeshVisualizerTestFiles/wireframe-vertexid3D.tga MeshVisualizerTestFiles/wireframe-wide2D.tga MeshVisualizerTestFiles/wireframe-wide3D.tga MeshVisualizerTestFiles/wireframe2D.tga diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index c65c88e7b..1dfbcc486 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -106,6 +106,8 @@ struct MeshVisualizerGLTest: GL::OpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void renderDefaultsObjectId2D(); void renderDefaultsObjectId3D(); + void renderDefaultsVertexId2D(); + void renderDefaultsVertexId3D(); void renderDefaultsPrimitiveId2D(); void renderDefaultsPrimitiveId3D(); #endif @@ -115,8 +117,8 @@ struct MeshVisualizerGLTest: GL::OpenGLTester { void renderWireframe2D(); void renderWireframe3D(); #ifndef MAGNUM_TARGET_GLES2 - void renderObjectPrimitiveId2D(); - void renderObjectPrimitiveId3D(); + void renderObjectVertexPrimitiveId2D(); + void renderObjectVertexPrimitiveId3D(); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void renderWireframe3DPerspective(); @@ -140,10 +142,11 @@ struct MeshVisualizerGLTest: GL::OpenGLTester { - Mesa Intel - Mesa AMD + . Mesa llvmpipe - SwiftShader ES2/ES3 - ARM Mali (Huawei P10) ES2/ES3 (except TBN visualization) - - WebGL 1 / 2 (on Mesa Intel) (except primitive/object ID) - - iPhone 6 w/ iOS 12.4 (except primitive/object ID) + - WebGL 1 / 2 (on Mesa Intel) (except primitive/vertex/object ID) + - iPhone 6 w/ iOS 12.4 (except primitive/vertex/object ID) */ using namespace Math::Literals; @@ -155,6 +158,7 @@ constexpr struct { {"wireframe w/o GS", MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", MeshVisualizer2D::Flag::InstancedObjectId}, + {"vertex ID", MeshVisualizer2D::Flag::VertexId}, #ifndef MAGNUM_TARGET_WEBGL {"primitive ID", MeshVisualizer2D::Flag::PrimitiveId}, #endif @@ -169,6 +173,7 @@ constexpr struct { {"wireframe w/o GS", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", MeshVisualizer3D::Flag::InstancedObjectId}, + {"vertex ID", MeshVisualizer3D::Flag::VertexId}, #ifndef MAGNUM_TARGET_WEBGL {"primitive ID", MeshVisualizer3D::Flag::InstancedObjectId}, #endif @@ -188,8 +193,10 @@ constexpr struct { {"normal direction", MeshVisualizer3D::Flag::NormalDirection}, {"tbn direction", MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentDirection|MeshVisualizer3D::Flag::NormalDirection}, {"tbn direction with bitangent from tangent", MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentFromTangentDirection|MeshVisualizer3D::Flag::NormalDirection}, + {"wireframe + vertex id", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::VertexId}, {"wireframe + t/n direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::NormalDirection}, - {"wireframe + object id + t/n direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::NormalDirection} + {"wireframe + object id + t/n direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::NormalDirection}, + {"wireframe + vertex id + t/b direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentDirection} }; #endif @@ -209,7 +216,10 @@ constexpr struct { #ifndef MAGNUM_TARGET_GLES2 {"both object and primitive id", MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::PrimitiveIdFromVertexId, - ": Flag::InstancedObjectId and Flag::PrimitiveId are mutually exclusive"} + ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"}, + {"both object and vertex id", + MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::VertexId, + ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"} #endif }; @@ -229,7 +239,10 @@ constexpr struct { #ifndef MAGNUM_TARGET_GLES2 {"both object and primitive id", MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, - ": Flag::InstancedObjectId and Flag::PrimitiveId are mutually exclusive"} + ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"}, + {"both vertex and primitive id", + MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, + ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"} #endif }; @@ -293,11 +306,15 @@ constexpr struct { MeshVisualizer3D::Flags flags3D; const char* file2D; const char* file3D; -} ObjectPrimitiveIdData[] { +} ObjectVertexPrimitiveIdData[] { {"object ID", MeshVisualizer2D::Flag::InstancedObjectId, MeshVisualizer3D::Flag::InstancedObjectId, "objectid2D.tga", "objectid3D.tga"}, + {"vertex ID", + MeshVisualizer2D::Flag::VertexId, + MeshVisualizer3D::Flag::VertexId, + "vertexid2D.tga", "vertexid3D.tga"}, #ifndef MAGNUM_TARGET_WEBGL {"primitive ID", MeshVisualizer2D::Flag::PrimitiveId, @@ -317,7 +334,11 @@ constexpr struct { MeshVisualizer2D::Flag::NoGeometryShader, MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::Wireframe| MeshVisualizer3D::Flag::NoGeometryShader, - "wireframe-nogeo-objectid2D.tga", "wireframe-nogeo-objectid3D.tga"} + "wireframe-nogeo-objectid2D.tga", "wireframe-nogeo-objectid3D.tga"}, + {"wireframe + vertex ID", + MeshVisualizer2D::Flag::VertexId|MeshVisualizer2D::Flag::Wireframe, + MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::Wireframe, + "wireframe-vertexid2D.tga", "wireframe-vertexid3D.tga"} }; #endif @@ -438,6 +459,8 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() { #ifndef MAGNUM_TARGET_GLES2 addTests({ + &MeshVisualizerGLTest::renderDefaultsVertexId2D, + &MeshVisualizerGLTest::renderDefaultsVertexId3D, &MeshVisualizerGLTest::renderDefaultsPrimitiveId2D, &MeshVisualizerGLTest::renderDefaultsPrimitiveId3D, #ifndef MAGNUM_TARGET_WEBGL @@ -459,9 +482,9 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() { &MeshVisualizerGLTest::renderTeardown); #ifndef MAGNUM_TARGET_GLES2 - addInstancedTests({&MeshVisualizerGLTest::renderObjectPrimitiveId2D, - &MeshVisualizerGLTest::renderObjectPrimitiveId3D}, - Containers::arraySize(ObjectPrimitiveIdData), + addInstancedTests({&MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D, + &MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D}, + Containers::arraySize(ObjectVertexPrimitiveIdData), &MeshVisualizerGLTest::renderSetup, &MeshVisualizerGLTest::renderTeardown); #endif @@ -778,7 +801,7 @@ void MeshVisualizerGLTest::setWireframeNotEnabled2D() { #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/primitive ID enabled\n"); + "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); #else CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled\n"); @@ -813,7 +836,7 @@ void MeshVisualizerGLTest::setWireframeNotEnabled3D() { #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/primitive ID enabled\n"); + "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); #else CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled\n"); @@ -846,8 +869,8 @@ void MeshVisualizerGLTest::setColorMapNotEnabled2D() { .bindColorMapTexture(texture); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/primitive ID enabled\n" - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/primitive ID enabled\n"); + "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" + "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); } void MeshVisualizerGLTest::setColorMapNotEnabled3D() { @@ -864,8 +887,8 @@ void MeshVisualizerGLTest::setColorMapNotEnabled3D() { .bindColorMapTexture(texture); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/primitive ID enabled\n" - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/primitive ID enabled\n"); + "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" + "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); } #endif @@ -1133,6 +1156,61 @@ void MeshVisualizerGLTest::renderDefaultsObjectId3D() { (DebugTools::CompareImageToFile{_manager, 150.67f, 0.165f})); } +void MeshVisualizerGLTest::renderDefaultsVertexId2D() { + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if( + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + MeshVisualizer2D{MeshVisualizer2D::Flag::VertexId} + .bindColorMapTexture(_colorMapTexture) + .draw(MeshTools::compile(Primitives::circle2DSolid(16))); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + CORRADE_COMPARE_WITH( + /* Dropping the alpha channel, as it's always 1.0 */ + Containers::arrayCast(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels()), + Utility::Directory::join(_testDir, "MeshVisualizerTestFiles/defaults-vertexid2D.tga"), + (DebugTools::CompareImageToFile{_manager, 1.0f, 0.017f})); +} + +void MeshVisualizerGLTest::renderDefaultsVertexId3D() { + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if( + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + MeshVisualizer2D{MeshVisualizer2D::Flag::VertexId} + .bindColorMapTexture(_colorMapTexture) + .draw(MeshTools::compile(Primitives::icosphereSolid(0))); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + CORRADE_COMPARE_WITH( + /* Dropping the alpha channel, as it's always 1.0 */ + Containers::arrayCast(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels()), + Utility::Directory::join(_testDir, "MeshVisualizerTestFiles/defaults-vertexid3D.tga"), + (DebugTools::CompareImageToFile{_manager, 1.0f, 0.012f})); +} void MeshVisualizerGLTest::renderDefaultsPrimitiveId2D() { if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) @@ -1461,8 +1539,8 @@ void MeshVisualizerGLTest::renderWireframe3D() { } #ifndef MAGNUM_TARGET_GLES2 -void MeshVisualizerGLTest::renderObjectPrimitiveId2D() { - auto&& data = ObjectPrimitiveIdData[testCaseInstanceId()]; +void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { + auto&& data = ObjectVertexPrimitiveIdData[testCaseInstanceId()]; setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES @@ -1519,15 +1597,23 @@ void MeshVisualizerGLTest::renderObjectPrimitiveId2D() { /* Shouldn't assert (nor warn) when wireframe is not enabled */ .setViewportSize({80, 80}) .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) - /* Should cover the first half of the colormap, in reverse order; for - primitive ID the whole colormap due to the repeat wrapping */ - .setColorMapTransformation(0.5f, -1.0f/16.0f) .bindColorMapTexture(_colorMapTexture); /* OTOH the wireframe color should stay at full channels, not mixed */ if(data.flags3D & MeshVisualizer3D::Flag::Wireframe) shader.setWireframeColor(0xffffff_rgbf); + /* For vertex ID we don't want any repeat/wraparound as that causes + disruptions in the gradient and test failures. There's 17 vertices + also. */ + if(data.flags2D & MeshVisualizer2D::Flag::VertexId) + shader.setColorMapTransformation(1.0f, -1.0f/17.0f); + /* For object/primitive ID there's no gradient so a wraparound is okay. + This should cover the first half of the colormap, in reverse order; for + primitive ID the whole colormap due to the repeat wrapping */ + else + shader.setColorMapTransformation(0.5f, -1.0f/16.0f); + shader.draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1545,8 +1631,8 @@ void MeshVisualizerGLTest::renderObjectPrimitiveId2D() { (DebugTools::CompareImageToFile{_manager, 4.0f, 0.141f})); } -void MeshVisualizerGLTest::renderObjectPrimitiveId3D() { - auto&& data = ObjectPrimitiveIdData[testCaseInstanceId()]; +void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { + auto&& data = ObjectVertexPrimitiveIdData[testCaseInstanceId()]; setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES @@ -1605,15 +1691,22 @@ void MeshVisualizerGLTest::renderObjectPrimitiveId3D() { Matrix4::rotationY(-15.0_degf)* Matrix4::rotationX(15.0_degf)) .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)) - /* Should cover the first half of the colormap, in reverse order; for - primitive ID the whole colormap due to the repeat wrapping */ - .setColorMapTransformation(0.5f, -1.0f/40.0f) .bindColorMapTexture(_colorMapTexture); /* OTOH the wireframe color should stay at full channels, not mixed */ if(data.flags2D & MeshVisualizer2D::Flag::Wireframe) shader.setWireframeColor(0xffffff_rgbf); + /* For vertex ID we don't want any repeat/wraparound as that causes + disruptions in the gradient and test failures. There's 42 vertices also. */ + if(data.flags2D & MeshVisualizer2D::Flag::VertexId) + shader.setColorMapTransformation(1.0f, -1.0f/42.0f); + /* For object/primitive ID there's no gradient so a wraparound is okay. + This should cover the first half of the colormap, in reverse order; for + primitive ID the whole colormap due to the repeat wrapping */ + else + shader.setColorMapTransformation(0.5f, -1.0f/40.0f); + shader.draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid2D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid2D.tga new file mode 100644 index 000000000..f75b1b7a6 Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid2D.tga differ diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid3D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid3D.tga new file mode 100644 index 000000000..79c223972 Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/defaults-vertexid3D.tga differ diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid2D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid2D.tga new file mode 100644 index 000000000..cde23e7ea Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid2D.tga differ diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid3D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid3D.tga new file mode 100644 index 000000000..2f4fc8afa Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/vertexid3D.tga differ diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid2D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid2D.tga new file mode 100644 index 000000000..beec3a958 Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid2D.tga differ diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid3D.tga b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid3D.tga new file mode 100644 index 000000000..666913719 Binary files /dev/null and b/src/Magnum/Shaders/Test/MeshVisualizerTestFiles/wireframe-vertexid3D.tga differ