Browse Source

Shaders: implement instancing in MeshVisualizerGL shaders.

Mainly to have feature parity with Flat and Phong -- otherwise switching
to draw a wireframe on an instanced mesh would be too annoying. Also, if
we have multidraw there already, why not instancing as well.
pull/547/head
Vladimír Vondruš 4 years ago
parent
commit
0190e9d178
  1. 3
      doc/changelog.dox
  2. 40
      doc/snippets/MagnumShaders-gl.cpp
  3. 45
      src/Magnum/Shaders/MeshVisualizer.vert
  4. 24
      src/Magnum/Shaders/MeshVisualizerGL.cpp
  5. 144
      src/Magnum/Shaders/MeshVisualizerGL.h
  6. 9
      src/Magnum/Shaders/Test/CMakeLists.txt
  7. 441
      src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp
  8. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-instancedobjectid2D.tga
  9. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-instancedobjectid3D.tga
  10. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-vertexid2D.tga
  11. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-vertexid3D.tga
  12. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-nogeo2D.tga
  13. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-nogeo3D.tga
  14. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-tbn3D.tga
  15. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe2D.tga
  16. BIN
      src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe3D.tga

3
doc/changelog.dox

@ -207,6 +207,9 @@ See also:
available also in multi-draw and instanced scenarios
- @ref Shaders::FlatGL and @ref Shaders::PhongGL now support object ID
textures in addition to uniform and per-vertex object ID
- Support for instanced drawing in @ref Shaders::MeshVisualizerGL2D and
@ref Shaders::MeshVisualizerGL3D for better feature parity with the other
sahders
- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
recently added @ref Trade::MaterialAttribute::NormalTextureScale material
attribute

40
doc/snippets/MagnumShaders-gl.cpp

@ -615,6 +615,22 @@ mesh.setInstanceCount(Containers::arraySize(instanceData))
/* [PhongGL-usage-instancing] */
}
{
GL::Mesh mesh;
/* [MeshVisualizerGL2D-usage-instancing] */
Matrix3 instancedTransformations[] {
Matrix3::translation({1.0f, 2.0f}),
Matrix3::translation({2.0f, 1.0f}),
Matrix3::translation({3.0f, 0.0f}),
// ...
};
mesh.setInstanceCount(Containers::arraySize(instancedTransformations))
.addVertexBufferInstanced(GL::Buffer{instancedTransformations}, 1, 0,
Shaders::MeshVisualizerGL2D::TransformationMatrix{});
/* [MeshVisualizerGL2D-usage-instancing] */
}
/* internal compiler error: in gimplify_init_constructor, at gimplify.c:4271
on GCC 4.8 in the [60] array */
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
@ -801,6 +817,30 @@ shader
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
{
GL::Mesh mesh;
/* [MeshVisualizerGL3D-usage-instancing] */
struct {
Matrix4 transformation;
Matrix3x3 normal;
} instanceData[] {
{Matrix4::translation({1.0f, 2.0f, 0.0f}), {}},
{Matrix4::translation({2.0f, 1.0f, 0.0f}), {}},
{Matrix4::translation({3.0f, 0.0f, 1.0f}), {}},
// ...
};
for(auto& instance: instanceData)
instance.normal = instance.transformation.normalMatrix();
mesh.setInstanceCount(Containers::arraySize(instanceData))
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
Shaders::MeshVisualizerGL3D::TransformationMatrix{},
Shaders::MeshVisualizerGL3D::NormalMatrix{});
/* [MeshVisualizerGL3D-usage-instancing] */
}
#endif
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [PhongGL-usage-colored1] */

45
src/Magnum/Shaders/MeshVisualizer.vert

@ -255,6 +255,26 @@ layout(location = OBJECT_ID_ATTRIBUTE_LOCATION)
in highp uint instanceObjectId;
#endif
#ifdef INSTANCED_TRANSFORMATION
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION)
#endif
in highp
#ifdef TWO_DIMENSIONS
mat3
#else
mat4
#endif
instancedTransformationMatrix;
#if defined(TANGENT_DIRECTION) || defined(BITANGENT_FROM_TANGENT_DIRECTION) || defined(BITANGENT_DIRECTION) || defined(NORMAL_DIRECTION)
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = NORMAL_MATRIX_ATTRIBUTE_LOCATION)
#endif
in highp mat3 instancedNormalMatrix;
#endif
#endif
/* Outputs */
#if defined(WIREFRAME_RENDERING) && defined(NO_GEOMETRY_SHADER)
@ -342,25 +362,40 @@ void main() {
#endif
#ifdef TWO_DIMENSIONS
gl_Position.xywz = vec4(transformationProjectionMatrix*vec3(position, 1.0), 0.0);
gl_Position.xywz = vec4(transformationProjectionMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedTransformationMatrix*
#endif
vec3(position, 1.0), 0.0);
#elif defined(THREE_DIMENSIONS)
highp const vec4 transformedPosition4 = transformationMatrix*position;
highp const vec4 transformedPosition4 = transformationMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedTransformationMatrix*
#endif
position;
gl_Position = projectionMatrix*transformedPosition4;
#else
#error
#endif
#if defined(TANGENT_DIRECTION) || defined(BITANGENT_FROM_TANGENT_DIRECTION) || defined(BITANGENT_DIRECTION) || defined(NORMAL_DIRECTION)
mat3 finalNormalMatrix = normalMatrix
#ifdef INSTANCED_TRANSFORMATION
*instancedNormalMatrix
#endif
;
#endif
#ifdef TANGENT_DIRECTION
tangentEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(normalMatrix*tangent.xyz)*lineLength, 0.0));
tangentEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(finalNormalMatrix*tangent.xyz)*lineLength, 0.0));
#endif
#ifdef BITANGENT_FROM_TANGENT_DIRECTION
vec3 bitangent = cross(normal, tangent.xyz)*tangent.w;
#endif
#if defined(BITANGENT_DIRECTION) || defined(BITANGENT_FROM_TANGENT_DIRECTION)
bitangentEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(normalMatrix*bitangent)*lineLength, 0.0));
bitangentEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(finalNormalMatrix*bitangent)*lineLength, 0.0));
#endif
#ifdef NORMAL_DIRECTION
normalEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(normalMatrix*normal)*lineLength, 0.0));
normalEndpoint = projectionMatrix*(transformedPosition4 + vec4(normalize(finalNormalMatrix*normal)*lineLength, 0.0));
#endif
#if defined(WIREFRAME_RENDERING) && defined(NO_GEOMETRY_SHADER)

24
src/Magnum/Shaders/MeshVisualizerGL.cpp

@ -162,6 +162,9 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra
vert.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif
.addSource(_flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "")
#endif
@ -414,6 +417,8 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES
if(!context.isVersionSupported(GL::Version::GL310))
@ -732,6 +737,13 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection))
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
#endif
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & Flag::TangentDirection ||
flags & Flag::BitangentFromTangentDirection)
@ -1014,6 +1026,9 @@ Debug& operator<<(Debug& debug, const MeshVisualizerGL2D::Flag value) {
#ifndef MAGNUM_TARGET_GLES2
_c(ObjectId)
_c(InstancedObjectId)
#endif
_c(InstancedTransformation)
#ifndef MAGNUM_TARGET_GLES2
_c(VertexId)
#ifndef MAGNUM_TARGET_WEBGL
_c(PrimitiveId)
@ -1048,6 +1063,9 @@ Debug& operator<<(Debug& debug, const MeshVisualizerGL3D::Flag value) {
#ifndef MAGNUM_TARGET_GLES2
_c(ObjectId)
_c(InstancedObjectId)
#endif
_c(InstancedTransformation)
#ifndef MAGNUM_TARGET_GLES2
_c(VertexId)
#ifndef MAGNUM_TARGET_WEBGL
_c(PrimitiveId)
@ -1074,6 +1092,9 @@ Debug& operator<<(Debug& debug, const MeshVisualizerGL2D::Flags value) {
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::Flag::InstancedObjectId, /* Superset of ObjectId */
MeshVisualizerGL2D::Flag::ObjectId,
#endif
MeshVisualizerGL2D::Flag::InstancedTransformation,
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::Flag::VertexId,
MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */
#ifndef MAGNUM_TARGET_WEBGL
@ -1102,6 +1123,9 @@ Debug& operator<<(Debug& debug, const MeshVisualizerGL3D::Flags value) {
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL3D::Flag::InstancedObjectId, /* Superset of ObjectId */
MeshVisualizerGL3D::Flag::ObjectId,
#endif
MeshVisualizerGL3D::Flag::InstancedTransformation,
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL3D::Flag::VertexId,
MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */
#ifndef MAGNUM_TARGET_WEBGL

144
src/Magnum/Shaders/MeshVisualizerGL.h

@ -49,6 +49,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgr
complex */
Wireframe = 1 << 0,
NoGeometryShader = 1 << 1,
InstancedTransformation = 1 << 13,
#ifndef MAGNUM_TARGET_GLES2
ObjectId = 1 << 12,
InstancedObjectId = (1 << 2)|ObjectId,
@ -142,7 +143,25 @@ configure the shader.
The shader expects that you enable wireframe visualization by passing an
appropriate @ref Flag to the constructor --- there's no default behavior with
nothing enabled. The shader is a 2D variant of @ref MeshVisualizerGL3D with
mostly identical workflow. See its documentation for more information.
mostly identical workflow. See its documentation for more information,
workflows that differ are shown below.
@section Shaders-MeshVisualizerGL2D-instancing Instanced rendering
Enabling @ref Flag::InstancedTransformation will turn the shader into an
instanced one. It'll take per-instance transformation from the
@ref TransformationMatrix attribute, applying it before the matrix set by
@ref setTransformationProjectionMatrix(). The snippet below shows adding a
buffer with per-instance transformation to a mesh:
@snippet MagnumShaders-gl.cpp MeshVisualizerGL2D-usage-instancing
@requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
@gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays}
in OpenGL ES 2.0.
@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL
1.0.
*/
class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase {
public:
@ -177,6 +196,21 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
typedef GenericGL2D::ObjectId ObjectId;
#endif
/**
* @brief (Instanced) transformation matrix
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3.
* Used only if @ref Flag::InstancedTransformation is set.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
*/
typedef GenericGL2D::TransformationMatrix TransformationMatrix;
enum: UnsignedInt {
/**
* Color shader output. @ref shaders-generic "Generic output",
@ -259,6 +293,24 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
#endif
#endif
/**
* Instanced transformation. Retrieves a per-instance
* transformation matrix from the @ref TransformationMatrix
* attribute and uses it together with the matrix coming from
* @ref setTransformationProjectionMatrix() or
* @ref TransformationProjectionUniform2D::transformationProjectionMatrix
* (first the per-instance, then the uniform matrix). See
* @ref Shaders-MeshVisualizerGL2D-instancing for more information.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
* @m_since_latest
*/
InstancedTransformation = 1 << 13,
#ifndef MAGNUM_TARGET_GLES2
/**
* Use uniform buffers. Expects that uniform data are supplied via
@ -420,7 +472,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
* @brief Set transformation and projection matrix
* @return Reference to self (for method chaining)
*
* Initial value is an identity matrix.
* Initial value is an identity matrix. If
* @ref Flag::InstancedTransformation is set, the per-instance
* transformation matrix coming from the @ref TransformationMatrix
* attribute is applied first, before this one.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref TransformationProjectionUniform2D::transformationProjectionMatrix
@ -855,6 +910,27 @@ non-indexed @ref MeshPrimitive::Triangles.
is not available in WebGL 1.0.
@requires_webgl20 `gl_VertexID` is not available in WebGL 1.0.
@section Shaders-MeshVisualizerGL3D-instancing Instanced rendering
Enabling @ref Flag::InstancedTransformation will turn the shader into an
instanced one. It'll take per-instance transformation from the
@ref TransformationMatrix attribute, applying it before the matrix set by
@ref setTransformationMatrix(). If one of @ref Flag::TangentDirection,
@ref Flag::BitangentDirection or @ref Flag::NormalDirection is set,
additionally also a normal matrix from the @ref NormalMatrix attribute is
taken, applied before the matrix set by @ref setNormalMatrix(). The snippet
below shows adding a buffer with per-instance transformation to a mesh,
including a normal matrix attribute for correct TBN visualization:
@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-instancing
@requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
@gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays}
in OpenGL ES 2.0.
@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL
1.0.
@section Shaders-MeshVisualizerGL3D-ubo Uniform buffers
See @ref shaders-usage-ubo for a high-level overview that applies to all
@ -974,6 +1050,40 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
typedef GenericGL3D::ObjectId ObjectId;
#endif
/**
* @brief (Instanced) transformation matrix
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Matrix4.
* Used only if @ref Flag::InstancedTransformation is set.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
*/
typedef GenericGL3D::TransformationMatrix TransformationMatrix;
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief (Instanced) normal matrix
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3x3.
* Used only if @ref Flag::InstancedTransformation and at least one of
* @ref Flag::TangentDirection, @ref Flag::BitangentDirection or
* @ref Flag::NormalDirection is set.
* @requires_gl33 Extension @gl_extension{ARB,geometry_shader4} and
* @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Not defined in OpenGL ES 2.0.
* @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a}
* / @gl_extension{EXT,geometry_shader}
* @requires_gles Geometry shaders are not available in WebGL.
*/
typedef GenericGL3D::NormalMatrix NormalMatrix;
#endif
enum: UnsignedInt {
/**
* Color shader output. @ref shaders-generic "Generic output",
@ -1164,6 +1274,26 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
NormalDirection = 1 << 9,
#endif
/**
* Instanced transformation. Retrieves a per-instance
* transformation and normal matrix from the
* @ref TransformationMatrix / @ref NormalMatrix attributes and
* uses them together with matrices coming from
* @ref setTransformationMatrix() and @ref setNormalMatrix() or
* @ref TransformationUniform3D::transformationMatrix and
* @ref MeshVisualizerDrawUniform3D::normalMatrix (first the
* per-instance, then the uniform matrix). See
* @ref Shaders-MeshVisualizerGL3D-instancing for more information.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
* @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
* @m_since_latest
*/
InstancedTransformation = 1 << 13,
#ifndef MAGNUM_TARGET_GLES2
/**
* Use uniform buffers. Expects that uniform data are supplied via
@ -1355,7 +1485,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
* @brief Set transformation matrix
* @return Reference to self (for method chaining)
*
* Initial value is an identity matrix.
* Initial value is an identity matrix. If
* @ref Flag::InstancedTransformation is set, the per-instance
* transformation coming from the @ref TransformationMatrix attribute
* is applied first, before this one.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref TransformationUniform3D::transformationMatrix and call
@ -1387,7 +1520,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
* @ref Flag::BitangentDirection or @ref Flag::NormalDirection is
* enabled. The matrix doesn't need to be normalized, as
* renormalization is done per-fragment anyway.
* Initial value is an identity matrix.
* Initial value is an identity matrix. If
* @ref Flag::InstancedTransformation is set, the per-instance normal
* matrix coming from the @ref NormalMatrix attribute is applied first,
* before this one.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref MeshVisualizerDrawUniform3D::normalMatrix and call

9
src/Magnum/Shaders/Test/CMakeLists.txt

@ -234,6 +234,15 @@ if(BUILD_GL_TESTS)
MeshVisualizerTestFiles/wireframe-wide3D.tga
MeshVisualizerTestFiles/wireframe2D.tga
MeshVisualizerTestFiles/wireframe3D.tga
MeshVisualizerTestFiles/instanced-wireframe2D.tga
MeshVisualizerTestFiles/instanced-wireframe3D.tga
MeshVisualizerTestFiles/instanced-wireframe-nogeo2D.tga
MeshVisualizerTestFiles/instanced-wireframe-nogeo3D.tga
MeshVisualizerTestFiles/instanced-wireframe-tbn3D.tga
MeshVisualizerTestFiles/instanced-vertexid2D.tga
MeshVisualizerTestFiles/instanced-vertexid3D.tga
MeshVisualizerTestFiles/instanced-instancedobjectid2D.tga
MeshVisualizerTestFiles/instanced-instancedobjectid3D.tga
MeshVisualizerTestFiles/multidraw-wireframe2D.tga
MeshVisualizerTestFiles/multidraw-wireframe3D.tga
MeshVisualizerTestFiles/multidraw-wireframe-tbn3D.tga

441
src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp

@ -49,6 +49,7 @@
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h"
#include "Magnum/Math/Swizzle.h"
#include "Magnum/MeshTools/Combine.h"
#include "Magnum/MeshTools/Compile.h"
#include "Magnum/MeshTools/Duplicate.h"
@ -160,6 +161,9 @@ struct MeshVisualizerGLTest: GL::OpenGLTester {
template<MeshVisualizerGL3D::Flag flag = MeshVisualizerGL3D::Flag{}> void renderTangentBitangentNormal();
#endif
template<MeshVisualizerGL2D::Flag flag = MeshVisualizerGL2D::Flag{}> void renderInstanced2D();
template<MeshVisualizerGL3D::Flag flag = MeshVisualizerGL3D::Flag{}> void renderInstanced3D();
#ifndef MAGNUM_TARGET_GLES2
void renderMulti2D();
void renderMulti3D();
@ -593,6 +597,65 @@ constexpr struct {
};
#endif
const struct {
const char* name;
const char* expected;
MeshVisualizerGL2D::Flags flags;
Float maxThreshold, meanThreshold;
} RenderInstancedData2D[]{
#ifndef MAGNUM_TARGET_WEBGL
{"wireframe", "instanced-wireframe2D.tga",
MeshVisualizerGL2D::Flag::Wireframe,
0.0f, 0.0f},
#endif
{"wireframe w/o GS", "instanced-wireframe-nogeo2D.tga",
MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader,
/* SwiftShader has a few rounding errors on edges */
73.67f, 0.230f},
#ifndef MAGNUM_TARGET_GLES2
{"vertex ID", "instanced-vertexid2D.tga",
MeshVisualizerGL2D::Flag::VertexId,
/* SwiftShader has a few rounding errors on edges */
138.7f, 0.08f},
{"instanced object ID", "instanced-instancedobjectid2D.tga",
MeshVisualizerGL2D::Flag::InstancedObjectId,
/* SwiftShader has a few rounding errors on edges */
133.0f, 0.12f},
#endif
};
const struct {
const char* name;
const char* expected;
MeshVisualizerGL3D::Flags flags;
Float maxThreshold, meanThreshold;
} RenderInstancedData3D[]{
#ifndef MAGNUM_TARGET_WEBGL
{"wireframe", "instanced-wireframe3D.tga",
MeshVisualizerGL3D::Flag::Wireframe,
0.0f, 0.0f},
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
{"wireframe + TBN", "instanced-wireframe-tbn3D.tga",
MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection,
0.0f, 0.0f},
#endif
{"wireframe w/o GS", "instanced-wireframe-nogeo3D.tga",
MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader,
/* SwiftShader has a minor rounding error */
7.334f, 0.192f},
#ifndef MAGNUM_TARGET_GLES2
{"vertex ID", "instanced-vertexid3D.tga",
MeshVisualizerGL3D::Flag::VertexId,
/* SwiftShader has a minor rounding error */
5.667f, 0.034f},
{"instanced object ID", "instanced-instancedobjectid3D.tga",
MeshVisualizerGL3D::Flag::InstancedObjectId,
/* SwiftShader has an off-by-one error on certain colors */
0.334f, 0.042f},
#endif
};
#ifndef MAGNUM_TARGET_GLES2
constexpr struct {
const char* name;
@ -945,6 +1008,28 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() {
&MeshVisualizerGLTest::renderTeardown);
#endif
/* MSVC needs explicit type due to default template args */
addInstancedTests<MeshVisualizerGLTest>({
&MeshVisualizerGLTest::renderInstanced2D,
#ifndef MAGNUM_TARGET_GLES2
&MeshVisualizerGLTest::renderInstanced2D<MeshVisualizerGL2D::Flag::UniformBuffers>,
#endif
},
Containers::arraySize(RenderInstancedData2D),
&MeshVisualizerGLTest::renderSetup,
&MeshVisualizerGLTest::renderTeardown);
/* MSVC needs explicit type due to default template args */
addInstancedTests<MeshVisualizerGLTest>({
&MeshVisualizerGLTest::renderInstanced3D,
#ifndef MAGNUM_TARGET_GLES2
&MeshVisualizerGLTest::renderInstanced3D<MeshVisualizerGL3D::Flag::UniformBuffers>,
#endif
},
Containers::arraySize(RenderInstancedData3D),
&MeshVisualizerGLTest::renderSetup,
&MeshVisualizerGLTest::renderTeardown);
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&MeshVisualizerGLTest::renderMulti2D},
Containers::arraySize(RenderMultiData2D),
@ -2060,7 +2145,8 @@ template<MeshVisualizerGL2D::Flag flag> void MeshVisualizerGLTest::renderDefault
/* Dropping the alpha channel, as it's always 1.0 */
Containers::arrayCast<Color3ub>(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels<Color4ub>()),
Utility::Directory::join(_testDir, "MeshVisualizerTestFiles/defaults-objectid2D.tga"),
(DebugTools::CompareImageToFile{_manager}));
/* SwiftShader has a few rounding errors on edges */
(DebugTools::CompareImageToFile{_manager, 24.67f, 0.11f}));
}
template<MeshVisualizerGL3D::Flag flag> void MeshVisualizerGLTest::renderDefaultsObjectId3D() {
@ -2116,7 +2202,9 @@ template<MeshVisualizerGL3D::Flag flag> void MeshVisualizerGLTest::renderDefault
/* Dropping the alpha channel, as it's always 1.0 */
Containers::arrayCast<Color3ub>(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels<Color4ub>()),
Utility::Directory::join(_testDir, "MeshVisualizerTestFiles/defaults-objectid3D.tga"),
(DebugTools::CompareImageToFile{_manager}));
/* SwiftShader has a few rounding errors on edges and off-by-two
pixels */
(DebugTools::CompareImageToFile{_manager, 24.67f, 2.55f}));
}
template<MeshVisualizerGL2D::Flag flag> void MeshVisualizerGLTest::renderDefaultsInstancedObjectId2D() {
@ -3425,6 +3513,355 @@ template<MeshVisualizerGL3D::Flag flag> void MeshVisualizerGLTest::renderTangent
}
#endif
template<MeshVisualizerGL2D::Flag flag> void MeshVisualizerGLTest::renderInstanced2D() {
auto&& data = RenderInstancedData2D[testCaseInstanceId()];
setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES2
if(flag == MeshVisualizerGL2D::Flag::UniformBuffers) {
setTestCaseTemplateName("Flag::UniformBuffers");
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::geometry_shader4>())
CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::geometry_shader>())
CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported.");
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
if((data.flags & MeshVisualizerGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
#endif
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::instanced_arrays>())
CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_WEBGL
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>() &&
!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::instanced_arrays>() &&
!GL::Context::current().isExtensionSupported<GL::Extensions::NV::instanced_arrays>())
CORRADE_SKIP("GL_{ANGLE,EXT,NV}_instanced_arrays is not supported");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>())
CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported.");
#endif
#endif
Trade::MeshData circleData = Primitives::circle2DSolid(8);
/* For a GS-less wireframe we have to deindex the mesh (but first turn the
triangle fan into an indexed mesh) */
if(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)
circleData = MeshTools::duplicate(MeshTools::generateIndices(circleData));
GL::Mesh circle = MeshTools::compile(circleData);
/* Three circles, each in a different location */
struct {
Matrix3 transformation;
UnsignedInt objectId;
} instanceData[] {
/* 6 gets added to objectId, wrapping it around to 0, making it
visually close to the multidraw test */
{Matrix3::translation({-1.25f, -1.25f}), 6},
{Matrix3::translation({ 1.25f, -1.25f}), 10},
{Matrix3::translation({ 0.00f, 1.25f}), 14},
};
circle
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
MeshVisualizerGL2D::TransformationMatrix{},
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::ObjectId{}
#else
4
#endif
)
.setInstanceCount(3);
MeshVisualizerGL2D shader{
MeshVisualizerGL2D::Flag::InstancedTransformation|data.flags|flag};
shader.setViewportSize(Vector2{RenderSize});
#ifndef MAGNUM_TARGET_GLES2
if(data.flags & (MeshVisualizerGL2D::Flag::VertexId|MeshVisualizerGL2D::Flag::ObjectId))
shader.bindColorMapTexture(_colorMapTexture);
#endif
if(flag == MeshVisualizerGL2D::Flag{}) {
shader
.setColor(0xffffcc_rgbf)
.setTransformationProjectionMatrix(
Matrix3::projection({2.1f, 2.1f})*
Matrix3::scaling(Vector2{0.4f}));
if(data.flags & MeshVisualizerGL2D::Flag::Wireframe)
shader.setWireframeColor(0xcc0000_rgbf);
#ifndef MAGNUM_TARGET_GLES2
if(data.flags & MeshVisualizerGL2D::Flag::VertexId)
shader.setColorMapTransformation(0.5f/circleData.vertexCount(), 1.0f/circleData.vertexCount());
else if(data.flags & MeshVisualizerGL2D::Flag::ObjectId) {
/* To make this visually close to the multidraw test */
shader
.setObjectId(6)
.setColorMapTransformation(0.5f/12, 1.0f/12);
}
#endif
shader.draw(circle);
}
#ifndef MAGNUM_TARGET_GLES2
else if(flag == MeshVisualizerGL2D::Flag::UniformBuffers) {
GL::Buffer transformationProjectionUniform{GL::Buffer::TargetHint::Uniform, {
TransformationProjectionUniform2D{}
.setTransformationProjectionMatrix(
Matrix3::projection({2.1f, 2.1f})*
Matrix3::scaling(Vector2{0.4f})
)
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
MeshVisualizerDrawUniform2D{}
.setObjectId(6)
}};
MeshVisualizerMaterialUniform materialUniformData[1];
(*materialUniformData)
.setColor(0xffffcc_rgbf)
.setWireframeColor(0xcc0000_rgbf);
if(data.flags & MeshVisualizerGL2D::Flag::VertexId)
materialUniformData->setColorMapTransformation(0.5f/circleData.vertexCount(), 1.0f/circleData.vertexCount());
else if(data.flags & MeshVisualizerGL2D::Flag::ObjectId)
materialUniformData->setColorMapTransformation(0.5f/12, 1.0f/12);
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, materialUniformData};
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(circle);
}
#endif
else CORRADE_INTERNAL_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_GL_ERROR();
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
/*
First circle should be lower left, second lower right, third up center.
- Wireframe all looking the same (the only instanced thing that can
differ is the transformation
- Vertex ID should all have the full color map range
- Object ID should be visually close to the multidraw case, except
that each circle is just a single color
*/
CORRADE_COMPARE_WITH(
/* Dropping the alpha channel, as it's always 1.0 */
Containers::arrayCast<Color3ub>(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels<Color4ub>()),
Utility::Directory::join({_testDir, "MeshVisualizerTestFiles", data.expected}),
(DebugTools::CompareImageToFile{_manager, data.maxThreshold, data.meanThreshold}));
}
template<MeshVisualizerGL3D::Flag flag> void MeshVisualizerGLTest::renderInstanced3D() {
auto&& data = RenderInstancedData3D[testCaseInstanceId()];
setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES2
if(flag == MeshVisualizerGL3D::Flag::UniformBuffers) {
setTestCaseTemplateName("Flag::UniformBuffers");
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::geometry_shader4>())
CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::geometry_shader>())
CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported.");
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
if((data.flags & MeshVisualizerGL3D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
#endif
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::instanced_arrays>())
CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_WEBGL
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>() &&
!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::instanced_arrays>() &&
!GL::Context::current().isExtensionSupported<GL::Extensions::NV::instanced_arrays>())
CORRADE_SKIP("GL_{ANGLE,EXT,NV}_instanced_arrays is not supported");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>())
CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported.");
#endif
#endif
Trade::MeshData sphereData = Primitives::uvSphereSolid(2, 4, Primitives::UVSphereFlag::Tangents);
/* For a GS-less wireframe we have to deindex the mesh */
if(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)
sphereData = MeshTools::duplicate(sphereData);
GL::Mesh sphere = MeshTools::compile(sphereData);
/* Three spheres, each in a different location. To test normal matrix
concatenation, everything is rotated 90° on Y, thus X is now -Z and Z is
now X. */
struct {
Matrix4 transformation;
Matrix3x3 normal;
UnsignedInt objectId;
} instanceData[] {
{Matrix4::translation(Math::gather<'z', 'y', 'x'>(Vector3{-1.25f, -1.25f, 0.0f}))*Matrix4::rotationY(-45.0_degf)*Matrix4::rotationX(45.0_degf),
/* to test also per-instance normal matrix is applied properly --
the first sphere should *not* have axis-aligned TBN directions */
(Matrix4::rotationY(-45.0_degf)*Matrix4::rotationX(45.0_degf)).normalMatrix(),
/* 6 gets added to the uniform objectId, wrapping it around to 0,
making it visually close to the multidraw test */
6},
{Matrix4::translation(Math::gather<'z', 'y', 'x'>(Vector3{ 1.25f, -1.25f, 0.0f})),
{},
10},
{Matrix4::translation(Math::gather<'z', 'y', 'x'>(Vector3{ 0.0f, 1.0f, -1.0f})),
{},
14}
};
sphere
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
MeshVisualizerGL3D::TransformationMatrix{},
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
MeshVisualizerGL3D::NormalMatrix{},
#else
sizeof(Matrix3x3),
#endif
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL3D::ObjectId{}
#else
4
#endif
)
.setInstanceCount(3);
MeshVisualizerGL3D shader{
MeshVisualizerGL3D::Flag::InstancedTransformation|data.flags|flag};
shader.setViewportSize(Vector2{RenderSize});
#ifndef MAGNUM_TARGET_GLES2
if(data.flags & (MeshVisualizerGL3D::Flag::VertexId|MeshVisualizerGL3D::Flag::ObjectId))
shader.bindColorMapTexture(_colorMapTexture);
#endif
if(flag == MeshVisualizerGL3D::Flag{}) {
shader
.setColor(0xffffcc_rgbf)
.setTransformationMatrix(
Matrix4::translation(Vector3::zAxis(-2.15f))*
Matrix4::rotationY(90.0_degf)*
Matrix4::scaling(Vector3{0.4f}))
.setProjectionMatrix(
Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f));
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))
shader
.setNormalMatrix(Matrix4::rotationY(90.0_degf).normalMatrix())
.setLineLength(0.25f);
#endif
if(data.flags & MeshVisualizerGL3D::Flag::Wireframe)
shader.setWireframeColor(0xcc0000_rgbf);
#ifndef MAGNUM_TARGET_GLES2
if(data.flags & MeshVisualizerGL3D::Flag::VertexId)
shader.setColorMapTransformation(0.5f/sphereData.vertexCount(), 1.0f/sphereData.vertexCount());
else if(data.flags & MeshVisualizerGL3D::Flag::ObjectId)
/* To make this visually close to the multidraw test */
shader
.setObjectId(6)
.setColorMapTransformation(0.5f/12, 1.0f/12);
#endif
shader.draw(sphere);
}
#ifndef MAGNUM_TARGET_GLES2
else if(flag == MeshVisualizerGL3D::Flag::UniformBuffers) {
GL::Buffer projectionUniform{GL::Buffer::TargetHint::Uniform, {
ProjectionUniform3D{}.setProjectionMatrix(
Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)
)
}};
GL::Buffer transformationUniform{GL::Buffer::TargetHint::Uniform, {
TransformationUniform3D{}.setTransformationMatrix(
Matrix4::translation(Vector3::zAxis(-2.15f))*
Matrix4::rotationY(90.0_degf)*
Matrix4::scaling(Vector3{0.4f})
)
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
MeshVisualizerDrawUniform3D{}
.setNormalMatrix(Matrix4::rotationY(90.0_degf).normalMatrix())
.setObjectId(6)
}};
MeshVisualizerMaterialUniform materialUniformData[1];
(*materialUniformData)
.setColor(0xffffcc_rgbf)
.setWireframeColor(0xcc0000_rgbf)
.setLineLength(0.25f);
if(data.flags & MeshVisualizerGL3D::Flag::VertexId)
materialUniformData->setColorMapTransformation(0.5f/sphereData.vertexCount(), 1.0f/sphereData.vertexCount());
else if(data.flags & MeshVisualizerGL3D::Flag::ObjectId)
materialUniformData->setColorMapTransformation(0.5f/12, 1.0f/12);
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, materialUniformData};
shader.bindProjectionBuffer(projectionUniform)
.bindTransformationBuffer(transformationUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(sphere);
}
#endif
else CORRADE_INTERNAL_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_GL_ERROR();
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
/*
First circle should be lower left, second lower right, third up center.
- Wireframe all looking the same (the only instanced thing that can
differ is the transformation
- TBN should have the lower right with different orientation than the
other two
- Vertex ID should all have the full color map range
- Object ID should be visually close to the multidraw case, except
that each circle is just a single color
*/
CORRADE_COMPARE_WITH(
/* Dropping the alpha channel, as it's always 1.0 */
Containers::arrayCast<Color3ub>(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels<Color4ub>()),
Utility::Directory::join({_testDir, "MeshVisualizerTestFiles", data.expected}),
(DebugTools::CompareImageToFile{_manager, data.maxThreshold, data.meanThreshold}));
}
#ifndef MAGNUM_TARGET_GLES2
void MeshVisualizerGLTest::renderMulti2D() {
auto&& data = RenderMultiData2D[testCaseInstanceId()];

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-instancedobjectid2D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-instancedobjectid3D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-vertexid2D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-vertexid3D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-nogeo2D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-nogeo3D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe-tbn3D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe2D.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/MeshVisualizerTestFiles/instanced-wireframe3D.tga

Binary file not shown.
Loading…
Cancel
Save