From 02525527a4d2ab981ff169af4a2b0879c564e1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 30 Mar 2020 18:07:15 +0200 Subject: [PATCH] Shaders: ability to render instanced object ID in Flat/Phong. --- doc/changelog.dox | 2 + src/Magnum/Shaders/Flat.cpp | 8 ++++ src/Magnum/Shaders/Flat.frag | 10 ++++- src/Magnum/Shaders/Flat.h | 40 +++++++++++++++-- src/Magnum/Shaders/Flat.vert | 14 ++++++ src/Magnum/Shaders/Phong.cpp | 8 ++++ src/Magnum/Shaders/Phong.frag | 10 ++++- src/Magnum/Shaders/Phong.h | 43 ++++++++++++++++--- src/Magnum/Shaders/Phong.vert | 14 ++++++ src/Magnum/Shaders/Test/FlatGLTest.cpp | 57 ++++++++++++++++++++----- src/Magnum/Shaders/Test/FlatTest.cpp | 20 ++++++++- src/Magnum/Shaders/Test/PhongGLTest.cpp | 38 ++++++++++++++--- src/Magnum/Shaders/Test/PhongTest.cpp | 20 ++++++++- 13 files changed, 256 insertions(+), 28 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 3c4598e2b..466ac0a52 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -223,6 +223,8 @@ See also: - Tangent space visualization in @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 + and @ref Shaders::Phong, in addition to uniform object ID - New attribute definitions and an location allocation scheme in @ref Shaders::Generic --- @ref Shaders::Generic::Tangent4, @ref Shaders::Generic::Bitangent, @ref Shaders::Generic::ObjectId plus diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/Flat.cpp index e029d635b..f126cba5e 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/Flat.cpp @@ -69,6 +69,9 @@ template Flat::Flat(const Flags flags): _fla .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n") + #ifndef MAGNUM_TARGET_GLES2 + .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + #endif .addSource(rs.get("generic.glsl")) .addSource(rs.get("Flat.vert")); frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") @@ -76,6 +79,7 @@ template Flat::Flat(const Flags flags): _fla .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") #endif .addSource(rs.get("generic.glsl")) .addSource(rs.get("Flat.frag")); @@ -101,6 +105,8 @@ template Flat::Flat(const Flags flags): _fla bindFragmentDataLocation(ColorOutput, "color"); bindFragmentDataLocation(ObjectIdOutput, "objectId"); } + if(flags >= Flag::InstancedObjectId) + bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif } #endif @@ -195,6 +201,7 @@ Debug& operator<<(Debug& debug, const FlatFlag value) { _c(TextureTransformation) #ifndef MAGNUM_TARGET_GLES2 _c(ObjectId) + _c(InstancedObjectId) #endif #undef _c /* LCOV_EXCL_STOP */ @@ -210,6 +217,7 @@ Debug& operator<<(Debug& debug, const FlatFlags value) { FlatFlag::VertexColor, FlatFlag::TextureTransformation, #ifndef MAGNUM_TARGET_GLES2 + FlatFlag::InstancedObjectId, /* Superset of ObjectId */ FlatFlag::ObjectId #endif }); diff --git a/src/Magnum/Shaders/Flat.frag b/src/Magnum/Shaders/Flat.frag index 71579c511..623216fe7 100644 --- a/src/Magnum/Shaders/Flat.frag +++ b/src/Magnum/Shaders/Flat.frag @@ -72,6 +72,10 @@ in mediump vec2 interpolatedTextureCoordinates; in lowp vec4 interpolatedVertexColor; #endif +#ifdef INSTANCED_OBJECT_ID +flat in highp uint interpolatedInstanceObjectId; +#endif + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) @@ -104,6 +108,10 @@ void main() { #endif #ifdef OBJECT_ID - fragmentObjectId = objectId; + fragmentObjectId = + #ifdef INSTANCED_OBJECT_ID + interpolatedInstanceObjectId + + #endif + objectId; #endif } diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index 4568f5460..ab4618bdc 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -43,7 +43,8 @@ namespace Implementation { VertexColor = 1 << 2, TextureTransformation = 1 << 3, #ifndef MAGNUM_TARGET_GLES2 - ObjectId = 1 << 4 + ObjectId = 1 << 4, + InstancedObjectId = (1 << 5)|ObjectId #endif }; typedef Containers::EnumSet FlatFlags; @@ -115,6 +116,11 @@ on framebuffers with integer attachments. @snippet MagnumShaders.cpp Flat-usage-object-id +If you have a batch of meshes with different object IDs, enable +@ref Flag::InstancedObjectId and supply per-vertex IDs to the @ref ObjectId +attribute. The output will contain a sum of the per-vertex ID and ID coming +from @ref setObjectId(). + @requires_gles30 Object ID output requires integer buffer attachments, which are not available in OpenGL ES 2.0 or WebGL 1.0. @@ -160,6 +166,20 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab */ typedef typename Generic::Color4 Color4; + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since_latest + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gles30 Object ID output requires integer buffer + * attachments, which are not available in OpenGL ES 2.0 or WebGL + * 1.0. + */ + typedef typename Generic::ObjectId ObjectId; + #endif + enum: UnsignedInt { /** * Color shader output. Present always, expects three- or @@ -234,7 +254,20 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab * WebGL 1.0. * @m_since{2019,10} */ - ObjectId = 1 << 4 + ObjectId = 1 << 4, + + /** + * Instanced object ID. Retrieves a per-instance / per-vertex + * object ID from the @ref ObjectId attribute, outputting a sum of + * the per-vertex ID and ID coming from @ref setObjectId(). + * Implicitly enables @ref Flag::ObjectId. See + * @ref Shaders-Flat-usage-object-id for more information. + * @requires_gles30 Object ID output requires integer buffer + * attachments, which are not available in OpenGL ES 2.0 or + * WebGL 1.0. + * @m_since_latest + */ + InstancedObjectId = (1 << 5)|ObjectId #endif }; @@ -346,7 +379,8 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab * Expects that the shader was created with @ref Flag::ObjectId * enabled. Value set here is written to the @ref ObjectIdOutput, see * @ref Shaders-Flat-usage-object-id for more information. Default is - * @cpp 0 @ce. + * @cpp 0 @ce. If @ref Flag::InstancedObjectId is enabled as well, this + * value is combined with ID coming from the @ref ObjectId attribute. * @requires_gles30 Object ID output requires integer buffer * attachments, which are not available in OpenGL ES 2.0 or WebGL * 1.0. diff --git a/src/Magnum/Shaders/Flat.vert b/src/Magnum/Shaders/Flat.vert index 851e72325..a2779d889 100644 --- a/src/Magnum/Shaders/Flat.vert +++ b/src/Magnum/Shaders/Flat.vert @@ -87,6 +87,15 @@ in lowp vec4 vertexColor; out lowp vec4 interpolatedVertexColor; #endif +#ifdef INSTANCED_OBJECT_ID +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = OBJECT_ID_ATTRIBUTE_LOCATION) +#endif +in highp uint instanceObjectId; + +flat out highp uint interpolatedInstanceObjectId; +#endif + void main() { #ifdef TWO_DIMENSIONS gl_Position.xywz = vec4(transformationProjectionMatrix*vec3(position, 1.0), 0.0); @@ -111,4 +120,9 @@ void main() { /* Vertex colors, if enabled */ interpolatedVertexColor = vertexColor; #endif + + #ifdef INSTANCED_OBJECT_ID + /* Instanced object ID, if enabled */ + interpolatedInstanceObjectId = instanceObjectId; + #endif } diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index fe3d2e5ce..5caeff18b 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -101,6 +101,9 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount)) + #ifndef MAGNUM_TARGET_GLES2 + .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + #endif .addSource(rs.get("generic.glsl")) .addSource(rs.get("Phong.vert")); frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") @@ -111,6 +114,7 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") #endif .addSource(Utility::formatString( "#define LIGHT_COUNT {}\n" @@ -146,6 +150,8 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l bindFragmentDataLocation(ColorOutput, "color"); bindFragmentDataLocation(ObjectIdOutput, "objectId"); } + if(flags >= Flag::InstancedObjectId) + bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif } #endif @@ -355,6 +361,7 @@ Debug& operator<<(Debug& debug, const Phong::Flag value) { _c(VertexColor) _c(TextureTransformation) #ifndef MAGNUM_TARGET_GLES2 + _c(InstancedObjectId) _c(ObjectId) #endif #undef _c @@ -374,6 +381,7 @@ Debug& operator<<(Debug& debug, const Phong::Flags value) { Phong::Flag::VertexColor, Phong::Flag::TextureTransformation, #ifndef MAGNUM_TARGET_GLES2 + Phong::Flag::InstancedObjectId, /* Superset of ObjectId */ Phong::Flag::ObjectId #endif }); diff --git a/src/Magnum/Shaders/Phong.frag b/src/Magnum/Shaders/Phong.frag index 51472a03d..39ff82d47 100644 --- a/src/Magnum/Shaders/Phong.frag +++ b/src/Magnum/Shaders/Phong.frag @@ -153,6 +153,10 @@ in mediump vec2 interpolatedTextureCoordinates; in lowp vec4 interpolatedVertexColor; #endif +#ifdef INSTANCED_OBJECT_ID +flat in highp uint interpolatedInstanceObjectId; +#endif + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) @@ -229,6 +233,10 @@ void main() { #endif #ifdef OBJECT_ID - fragmentObjectId = objectId; + fragmentObjectId = + #ifdef INSTANCED_OBJECT_ID + interpolatedInstanceObjectId + + #endif + objectId; #endif } diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index 134b3670f..ff1537a77 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -98,10 +98,14 @@ diffuse part and then separate the alpha like this: The shader supports writing object ID to the framebuffer for object picking or other annotation purposes. Enable it using @ref Flag::ObjectId and set up an -integer buffer attached to the @ref ObjectIdOutput attachment. The -functionality is practically the same as in the @ref Flat shader, see its -@ref Shaders-Flat-usage-object-id documentation for more information and usage -example. +integer buffer attached to the @ref ObjectIdOutput attachment. If you have a +batch of meshes with different object IDs, enable @ref Flag::InstancedObjectId +and supply per-vertex IDs to the @ref ObjectId attribute. The output will +contain a sum of the per-vertex ID and ID coming from @ref setObjectId(). + +The functionality is practically the same as in the @ref Flat shader, see +@ref Shaders-Flat-usage-object-id "its documentation" for more information and +usage example. @requires_gles30 Object ID output requires integer buffer attachments, which are not available in OpenGL ES 2.0 or WebGL 1.0. @@ -175,6 +179,20 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { */ typedef Generic3D::Color4 Color4; + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since_latest + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gles30 Object ID output requires integer buffer + * attachments, which are not available in OpenGL ES 2.0 or WebGL + * 1.0. + */ + typedef Generic3D::ObjectId ObjectId; + #endif + enum: UnsignedInt { /** * Color shader output. @ref shaders-generic "Generic output", @@ -205,7 +223,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * * @see @ref Flags, @ref flags() */ - enum class Flag: UnsignedByte { + enum class Flag: UnsignedShort { /** * Multiply ambient color with a texture. * @see @ref setAmbientColor(), @ref bindAmbientTexture() @@ -271,7 +289,20 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * WebGL 1.0. * @m_since{2019,10} */ - ObjectId = 1 << 7 + ObjectId = 1 << 7, + + /** + * Instanced object ID. Retrieves a per-instance / per-vertex + * object ID from the @ref ObjectId attribute, outputting a sum of + * the per-vertex ID and ID coming from @ref setObjectId(). + * Implicitly enables @ref Flag::ObjectId. See + * @ref Shaders-Phong-usage-object-id for more information. + * @requires_gles30 Object ID output requires integer buffer + * attachments, which are not available in OpenGL ES 2.0 or + * WebGL 1.0. + * @m_since_latest + */ + InstancedObjectId = (1 << 8)|ObjectId #endif }; diff --git a/src/Magnum/Shaders/Phong.vert b/src/Magnum/Shaders/Phong.vert index 269402458..6e86a4513 100644 --- a/src/Magnum/Shaders/Phong.vert +++ b/src/Magnum/Shaders/Phong.vert @@ -113,6 +113,15 @@ in lowp vec4 vertexColor; out lowp vec4 interpolatedVertexColor; #endif +#ifdef INSTANCED_OBJECT_ID +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = OBJECT_ID_ATTRIBUTE_LOCATION) +#endif +in highp uint instanceObjectId; + +flat out highp uint interpolatedInstanceObjectId; +#endif + #if LIGHT_COUNT out mediump vec3 transformedNormal; #ifdef NORMAL_TEXTURE @@ -160,4 +169,9 @@ void main() { /* Vertex colors, if enabled */ interpolatedVertexColor = vertexColor; #endif + + #ifdef INSTANCED_OBJECT_ID + /* Instanced object ID, if enabled */ + interpolatedInstanceObjectId = instanceObjectId; + #endif } diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index b6d85e6f3..8f6917db6 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -143,6 +143,7 @@ constexpr struct { {"vertex colors + textured", Flat2D::Flag::VertexColor|Flat2D::Flag::Textured}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", Flat2D::Flag::ObjectId}, + {"instanced object ID", Flat2D::Flag::InstancedObjectId}, {"object ID + alpha mask + textured", Flat2D::Flag::ObjectId|Flat2D::Flag::AlphaMask|Flat2D::Flag::Textured} #endif }; @@ -182,6 +183,23 @@ const struct { Flat2D::Flag::Textured|Flat2D::Flag::AlphaMask, 1.0f} }; +#ifndef MAGNUM_TARGET_GLES2 +constexpr struct { + const char* name; + Flat2D::Flags flags; + UnsignedInt uniformId; + UnsignedInt instanceCount; + UnsignedInt expected; +} RenderObjectIdData[] { + {"", /* Verify that it can hold 16 bits at least */ + Flat2D::Flag::ObjectId, 48526, 0, 48526}, + {"instanced, first instance", + Flat2D::Flag::InstancedObjectId, 13524, 1, 24526}, + {"instanced, second instance", + Flat2D::Flag::InstancedObjectId, 13524, 2, 62347} +}; +#endif + FlatGLTest::FlatGLTest() { addInstancedTests({ &FlatGLTest::construct<2>, @@ -236,8 +254,9 @@ FlatGLTest::FlatGLTest() { &FlatGLTest::renderAlphaTeardown); #ifndef MAGNUM_TARGET_GLES2 - addTests({&FlatGLTest::renderObjectId2D, - &FlatGLTest::renderObjectId3D}, + addInstancedTests({&FlatGLTest::renderObjectId2D, + &FlatGLTest::renderObjectId3D}, + Containers::arraySize(RenderObjectIdData), &FlatGLTest::renderObjectIdSetup, &FlatGLTest::renderObjectIdTeardown); #endif @@ -975,14 +994,23 @@ void FlatGLTest::renderObjectIdTeardown() { } void FlatGLTest::renderObjectId2D() { + auto&& data = RenderObjectIdData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32)); - Flat2D{Flat3D::Flag::ObjectId} + if(data.instanceCount) circle + .setInstanceCount(data.instanceCount) + .addVertexBufferInstanced( + GL::Buffer{Containers::arrayView({11002u, 48823u})}, + 1, 0, Flat2D::ObjectId{}); + + Flat2D{data.flags} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) - .setObjectId(47523) + .setObjectId(data.uniformId) .draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1014,23 +1042,32 @@ void FlatGLTest::renderObjectId2D() { MAGNUM_VERIFY_NO_GL_ERROR(); /* Outside of the object, cleared to 27 */ CORRADE_COMPARE(image.pixels()[10][10], 27); - /* Inside of the object. Verify that it can hold 16 bits at least. */ - CORRADE_COMPARE(image.pixels()[40][46], 47523); + /* Inside of the object */ + CORRADE_COMPARE(image.pixels()[40][46], data.expected); } void FlatGLTest::renderObjectId3D() { + auto&& data = RenderObjectIdData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Flat3D{Flat3D::Flag::ObjectId} + if(data.instanceCount) sphere + .setInstanceCount(data.instanceCount) + .addVertexBufferInstanced( + GL::Buffer{Containers::arrayView({11002u, 48823u})}, + 1, 0, Flat2D::ObjectId{}); + + Flat3D{data.flags} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* Matrix4::translation(Vector3::zAxis(-2.15f))* Matrix4::rotationY(-15.0_degf)* Matrix4::rotationX(15.0_degf)) - .setObjectId(48526) + .setObjectId(data.uniformId) .draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1065,8 +1102,8 @@ void FlatGLTest::renderObjectId3D() { MAGNUM_VERIFY_NO_GL_ERROR(); /* Outside of the object, cleared to 27 */ CORRADE_COMPARE(image.pixels()[10][10], 27); - /* Inside of the object. Verify that it can hold 16 bits at least. */ - CORRADE_COMPARE(image.pixels()[40][46], 48526); + /* Inside of the object */ + CORRADE_COMPARE(image.pixels()[40][46], data.expected); } #endif diff --git a/src/Magnum/Shaders/Test/FlatTest.cpp b/src/Magnum/Shaders/Test/FlatTest.cpp index 96bee372f..39d29ec96 100644 --- a/src/Magnum/Shaders/Test/FlatTest.cpp +++ b/src/Magnum/Shaders/Test/FlatTest.cpp @@ -39,6 +39,9 @@ struct FlatTest: TestSuite::Tester { void debugFlag(); void debugFlags(); + #ifndef MAGNUM_TARGET_GLES2 + void debugFlagsInstancedObjectId(); + #endif }; FlatTest::FlatTest() { @@ -49,7 +52,11 @@ FlatTest::FlatTest() { &FlatTest::constructCopy<3>, &FlatTest::debugFlag, - &FlatTest::debugFlags}); + &FlatTest::debugFlags, + #ifndef MAGNUM_TARGET_GLES2 + &FlatTest::debugFlagsInstancedObjectId + #endif + }); } template void FlatTest::constructNoCreate() { @@ -87,6 +94,17 @@ void FlatTest::debugFlags() { CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::Textured|Shaders::Flat::Flag::AlphaMask Shaders::Flat::Flags{}\n"); } +#ifndef MAGNUM_TARGET_GLES2 +void FlatTest::debugFlagsInstancedObjectId() { + std::ostringstream out; + + /* InstancedObjectId is a superset of ObjectId so only one should be + *printed */ + Debug{&out} << (Flat3D::Flag::ObjectId|Flat3D::Flag::InstancedObjectId); + CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::InstancedObjectId\n"); +} +#endif + }}}} CORRADE_TEST_MAIN(Magnum::Shaders::Test::FlatTest) diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index d2764172c..b17082d06 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -151,6 +151,7 @@ constexpr struct { {"vertex colors + diffuse texture", Phong::Flag::VertexColor|Phong::Flag::DiffuseTexture, 1}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", Phong::Flag::ObjectId, 1}, + {"instanced object ID", Phong::Flag::InstancedObjectId, 1}, {"object ID + alpha mask + specular texture", Phong::Flag::ObjectId|Phong::Flag::AlphaMask|Phong::Flag::SpecularTexture, 1}, #endif {"five lights", {}, 5}, @@ -266,6 +267,23 @@ const struct { 0xffffffff_rgbaf, 0x9999ff00_rgbaf} }; +#ifndef MAGNUM_TARGET_GLES2 +constexpr struct { + const char* name; + Phong::Flags flags; + UnsignedInt uniformId; + UnsignedInt instanceCount; + UnsignedInt expected; +} RenderObjectIdData[] { + {"", /* Verify that it can hold 16 bits at least */ + Phong::Flag::ObjectId, 48526, 0, 48526}, + {"instanced, first instance", + Phong::Flag::InstancedObjectId, 13524, 1, 24526}, + {"instanced, second instance", + Phong::Flag::InstancedObjectId, 13524, 2, 62347} +}; +#endif + PhongGLTest::PhongGLTest() { addInstancedTests({&PhongGLTest::construct}, Containers::arraySize(ConstructData)); @@ -322,7 +340,8 @@ PhongGLTest::PhongGLTest() { &PhongGLTest::renderAlphaTeardown); #ifndef MAGNUM_TARGET_GLES2 - addTests({&PhongGLTest::renderObjectId}, + addInstancedTests({&PhongGLTest::renderObjectId}, + Containers::arraySize(RenderObjectIdData), &PhongGLTest::renderObjectIdSetup, &PhongGLTest::renderObjectIdTeardown); #endif @@ -1158,11 +1177,20 @@ void PhongGLTest::renderObjectIdTeardown() { } void PhongGLTest::renderObjectId() { + auto&& data = RenderObjectIdData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Phong{Phong::Flag::ObjectId, 2} + if(data.instanceCount) sphere + .setInstanceCount(data.instanceCount) + .addVertexBufferInstanced( + GL::Buffer{Containers::arrayView({11002u, 48823u})}, + 1, 0, Phong::ObjectId{}); + + Phong{data.flags, 2} .setLightColors({0x993366_rgbf, 0x669933_rgbf}) .setLightPositions({{-3.0f, -3.0f, 0.0f}, { 3.0f, -3.0f, 0.0f}}) @@ -1171,7 +1199,7 @@ void PhongGLTest::renderObjectId() { .setSpecularColor(0x6666ff_rgbf) .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f))) .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)) - .setObjectId(48526) + .setObjectId(data.uniformId) .draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1205,8 +1233,8 @@ void PhongGLTest::renderObjectId() { MAGNUM_VERIFY_NO_GL_ERROR(); /* Outside of the object, cleared to 27 */ CORRADE_COMPARE(image.pixels()[10][10], 27); - /* Inside of the object. Verify that it can hold 16 bits at least. */ - CORRADE_COMPARE(image.pixels()[40][46], 48526); + /* Inside of the object */ + CORRADE_COMPARE(image.pixels()[40][46], data.expected); } #endif diff --git a/src/Magnum/Shaders/Test/PhongTest.cpp b/src/Magnum/Shaders/Test/PhongTest.cpp index 2eb7057de..4a8a7af54 100644 --- a/src/Magnum/Shaders/Test/PhongTest.cpp +++ b/src/Magnum/Shaders/Test/PhongTest.cpp @@ -39,6 +39,9 @@ struct PhongTest: TestSuite::Tester { void debugFlag(); void debugFlags(); + #ifndef MAGNUM_TARGET_GLES2 + void debugFlagsInstancedObjectId(); + #endif }; PhongTest::PhongTest() { @@ -46,7 +49,11 @@ PhongTest::PhongTest() { &PhongTest::constructCopy, &PhongTest::debugFlag, - &PhongTest::debugFlags}); + &PhongTest::debugFlags, + #ifndef MAGNUM_TARGET_GLES2 + &PhongTest::debugFlagsInstancedObjectId + #endif + }); } void PhongTest::constructNoCreate() { @@ -77,6 +84,17 @@ void PhongTest::debugFlags() { CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::DiffuseTexture|Shaders::Phong::Flag::SpecularTexture Shaders::Phong::Flags{}\n"); } +#ifndef MAGNUM_TARGET_GLES2 +void PhongTest::debugFlagsInstancedObjectId() { + std::ostringstream out; + + /* InstancedObjectId is a superset of ObjectId so only one should be + *printed */ + Debug{&out} << (Phong::Flag::ObjectId|Phong::Flag::InstancedObjectId); + CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::InstancedObjectId\n"); +} +#endif + }}}} CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongTest)