From 5617cb519935709da4cad55a4c040bc9c816ec0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 12 Aug 2019 20:42:25 +0200 Subject: [PATCH] Shaders: vertex color support in Phong and Flat. --- doc/changelog.dox | 1 + src/Magnum/Shaders/Flat.cpp | 11 +- src/Magnum/Shaders/Flat.frag | 7 + src/Magnum/Shaders/Flat.h | 33 ++++- src/Magnum/Shaders/Flat2D.vert | 14 ++ src/Magnum/Shaders/Flat3D.vert | 14 ++ src/Magnum/Shaders/Phong.cpp | 20 ++- src/Magnum/Shaders/Phong.frag | 7 + src/Magnum/Shaders/Phong.h | 45 +++++-- src/Magnum/Shaders/Phong.vert | 14 ++ src/Magnum/Shaders/Test/CMakeLists.txt | 5 +- src/Magnum/Shaders/Test/FlatGLTest.cpp | 123 +++++++++++++++++- .../Test/FlatTestFiles/vertexColor2D.tga | Bin 0 -> 19218 bytes .../Test/FlatTestFiles/vertexColor3D.tga | Bin 0 -> 19218 bytes src/Magnum/Shaders/Test/PhongGLTest.cpp | 72 ++++++++++ .../Test/PhongTestFiles/vertexColor.tga | Bin 0 -> 19218 bytes src/Magnum/Shaders/VertexColor.h | 5 + 17 files changed, 347 insertions(+), 24 deletions(-) create mode 100644 src/Magnum/Shaders/Test/FlatTestFiles/vertexColor2D.tga create mode 100644 src/Magnum/Shaders/Test/FlatTestFiles/vertexColor3D.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/vertexColor.tga diff --git a/doc/changelog.dox b/doc/changelog.dox index bf83773c6..943d14824 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -231,6 +231,7 @@ See also: - Normal texture support in @ref Shaders::Phong - Added @ref Shaders::Generic3D::Tangent generic vertex attribute definition - Object ID output in @ref Shaders::Flat and @ref Shaders::Phong +- Vertex color support in @ref Shaders::Flat and @ref Shaders::Phong @subsubsection changelog-latest-new-text Text library diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/Flat.cpp index ce0855174..74ee895aa 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/Flat.cpp @@ -64,10 +64,12 @@ template Flat::Flat(const Flags flags): _fla GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") + .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") + .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") #endif @@ -86,7 +88,10 @@ template Flat::Flat(const Flags flags): _fla #endif { bindAttributeLocation(Position::Location, "position"); - if(flags & Flag::Textured) bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + if(flags & Flag::Textured) + bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + if(flags & Flag::VertexColor) + bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ #ifndef MAGNUM_TARGET_GLES2 if(flags & Flag::ObjectId) { bindFragmentDataLocation(ColorOutput, "color"); @@ -120,7 +125,7 @@ template Flat::Flat(const Flags flags): _fla /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES setTransformationProjectionMatrix({}); - setColor(Color4{1.0f}); + setColor(Magnum::Color4{1.0f}); if(flags & Flag::AlphaMask) setAlphaMask(0.5f); /* Object ID is zero by default */ #endif @@ -160,6 +165,7 @@ Debug& operator<<(Debug& debug, const FlatFlag value) { #define _c(v) case FlatFlag::v: return debug << "Shaders::Flat::Flag::" #v; _c(Textured) _c(AlphaMask) + _c(VertexColor) #ifndef MAGNUM_TARGET_GLES2 _c(ObjectId) #endif @@ -174,6 +180,7 @@ Debug& operator<<(Debug& debug, const FlatFlags value) { return Containers::enumSetDebugOutput(debug, value, "Shaders::Flat::Flags{}", { FlatFlag::Textured, FlatFlag::AlphaMask, + FlatFlag::VertexColor, #ifndef MAGNUM_TARGET_GLES2 FlatFlag::ObjectId #endif diff --git a/src/Magnum/Shaders/Flat.frag b/src/Magnum/Shaders/Flat.frag index 61a576970..ae2f759e9 100644 --- a/src/Magnum/Shaders/Flat.frag +++ b/src/Magnum/Shaders/Flat.frag @@ -68,6 +68,10 @@ uniform highp uint objectId; /* defaults to zero */ in mediump vec2 interpolatedTextureCoordinates; #endif +#ifdef VERTEX_COLOR +in lowp vec4 interpolatedVertexColor; +#endif + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) @@ -87,6 +91,9 @@ void main() { #ifdef TEXTURED texture(textureData, interpolatedTextureCoordinates)* #endif + #ifdef VERTEX_COLOR + interpolatedVertexColor* + #endif color; #ifdef ALPHA_MASK diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index 9d82dd7cc..9eb66ee8d 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -43,8 +43,9 @@ namespace Implementation { enum class FlatFlag: UnsignedByte { Textured = 1 << 0, AlphaMask = 1 << 1, + VertexColor = 1 << 2, #ifndef MAGNUM_TARGET_GLES2 - ObjectId = 1 << 2 + ObjectId = 1 << 3 #endif }; typedef Containers::EnumSet FlatFlags; @@ -71,6 +72,8 @@ For coloring the texture based on intensity you can use the @ref Vector shader. The 3D version of this shader is equivalent to @ref Phong with zero lights, however this implementation is much simpler and thus likely also faster. See @ref Shaders-Phong-zero-lights "its documentation" for more information. +Conversely, enabling @ref Flag::VertexColor and using a default color with no +texturing makes this shader equivalent to @ref VertexColor. @section Shaders-Flat-usage Example usage @@ -139,6 +142,24 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab */ typedef typename Generic::TextureCoordinates TextureCoordinates; + /** + * @brief Three-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use + * either this or the @ref Color4 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef typename Generic::Color3 Color3; + + /** + * @brief Four-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use + * either this or the @ref Color3 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef typename Generic::Color4 Color4; + enum: UnsignedInt { /** * Color shader output. Present always, expects three- or @@ -187,6 +208,12 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab */ AlphaMask = 1 << 1, + /** + * Multiply diffuse color with a vertex color. Requires either + * the @ref Color3 or @ref Color4 attribute to be present. + */ + VertexColor = 1 << 2, + #ifndef MAGNUM_TARGET_GLES2 /** * Enable object ID output. See @ref Shaders-Flat-usage-object-id @@ -195,7 +222,7 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab * attachments, which are not available in OpenGL ES 2.0 or * WebGL 1.0. */ - ObjectId = 1 << 2 + ObjectId = 1 << 3 #endif }; @@ -265,7 +292,7 @@ template class MAGNUM_SHADERS_EXPORT Flat: public GL::Ab * texture. * @see @ref bindTexture() */ - Flat& setColor(const Color4& color){ + Flat& setColor(const Magnum::Color4& color) { setUniform(_colorUniform, color); return *this; } diff --git a/src/Magnum/Shaders/Flat2D.vert b/src/Magnum/Shaders/Flat2D.vert index 6a6cc9ed0..f8c8a1bc1 100644 --- a/src/Magnum/Shaders/Flat2D.vert +++ b/src/Magnum/Shaders/Flat2D.vert @@ -51,6 +51,15 @@ in mediump vec2 textureCoordinates; out mediump vec2 interpolatedTextureCoordinates; #endif +#ifdef VERTEX_COLOR +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = COLOR_ATTRIBUTE_LOCATION) +#endif +in lowp vec4 vertexColor; + +out lowp vec4 interpolatedVertexColor; +#endif + void main() { gl_Position.xywz = vec4(transformationProjectionMatrix*vec3(position, 1.0), 0.0); @@ -58,4 +67,9 @@ void main() { /* Texture coordinates, if needed */ interpolatedTextureCoordinates = textureCoordinates; #endif + + #ifdef VERTEX_COLOR + /* Vertex colors, if enabled */ + interpolatedVertexColor = vertexColor; + #endif } diff --git a/src/Magnum/Shaders/Flat3D.vert b/src/Magnum/Shaders/Flat3D.vert index c79a1897c..eda843c6b 100644 --- a/src/Magnum/Shaders/Flat3D.vert +++ b/src/Magnum/Shaders/Flat3D.vert @@ -51,6 +51,15 @@ in mediump vec2 textureCoordinates; out mediump vec2 interpolatedTextureCoordinates; #endif +#ifdef VERTEX_COLOR +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = COLOR_ATTRIBUTE_LOCATION) +#endif +in lowp vec4 vertexColor; + +out lowp vec4 interpolatedVertexColor; +#endif + void main() { gl_Position = transformationProjectionMatrix*position; @@ -58,4 +67,9 @@ void main() { /* Texture coordinates, if needed */ interpolatedTextureCoordinates = textureCoordinates; #endif + + #ifdef VERTEX_COLOR + /* Vertex colors, if enabled */ + interpolatedVertexColor = vertexColor; + #endif } diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index 148042a14..94f05e138 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -92,6 +92,7 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l vert.addSource(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture) ? "#define TEXTURED\n" : "") .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") + .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount)) .addSource(rs.get("generic.glsl")) .addSource(rs.get("Phong.vert")); @@ -99,6 +100,7 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") + .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") #ifndef MAGNUM_TARGET_GLES2 .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") @@ -128,6 +130,8 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l bindAttributeLocation(Normal::Location, "normal"); if((flags & Flag::NormalTexture) && lightCount) bindAttributeLocation(Tangent::Location, "tangent"); + if(flags & Flag::VertexColor) + bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture)) bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); #ifndef MAGNUM_TARGET_GLES2 @@ -177,17 +181,17 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES /* Default to fully opaque white so we can see the textures */ - if(flags & Flag::AmbientTexture) setAmbientColor(Color4{1.0f}); - else setAmbientColor(Color4{0.0f}); + if(flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f}); + else setAmbientColor(Magnum::Color4{0.0f}); setTransformationMatrix({}); setProjectionMatrix({}); if(lightCount) { - setDiffuseColor(Color4{1.0f}); - setSpecularColor(Color4{1.0f}); + setDiffuseColor(Magnum::Color4{1.0f}); + setSpecularColor(Magnum::Color4{1.0f}); setShininess(80.0f); if(flags & Flag::AlphaMask) setAlphaMask(0.5f); /* Object ID is zero by default */ - setLightColors(Containers::Array{Containers::DirectInit, lightCount, Color4{1.0f}}); + setLightColors(Containers::Array{Containers::DirectInit, lightCount, Magnum::Color4{1.0f}}); /* Light position is zero by default */ setNormalMatrix({}); } @@ -259,14 +263,14 @@ Phong& Phong::setLightPosition(UnsignedInt id, const Vector3& position) { return *this; } -Phong& Phong::setLightColors(const Containers::ArrayView colors) { +Phong& Phong::setLightColors(const Containers::ArrayView colors) { CORRADE_ASSERT(_lightCount == colors.size(), "Shaders::Phong::setLightColors(): expected" << _lightCount << "items but got" << colors.size(), *this); if(_lightCount) setUniform(_lightColorsUniform, colors); return *this; } -Phong& Phong::setLightColor(UnsignedInt id, const Color4& color) { +Phong& Phong::setLightColor(UnsignedInt id, const Magnum::Color4& color) { CORRADE_ASSERT(id < _lightCount, "Shaders::Phong::setLightColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); setUniform(_lightColorsUniform + id, color); @@ -282,6 +286,7 @@ Debug& operator<<(Debug& debug, const Phong::Flag value) { _c(SpecularTexture) _c(NormalTexture) _c(AlphaMask) + _c(VertexColor) #ifndef MAGNUM_TARGET_GLES2 _c(ObjectId) #endif @@ -299,6 +304,7 @@ Debug& operator<<(Debug& debug, const Phong::Flags value) { Phong::Flag::SpecularTexture, Phong::Flag::NormalTexture, Phong::Flag::AlphaMask, + Phong::Flag::VertexColor, #ifndef MAGNUM_TARGET_GLES2 Phong::Flag::ObjectId #endif diff --git a/src/Magnum/Shaders/Phong.frag b/src/Magnum/Shaders/Phong.frag index 84e3233f5..a89b52b4d 100644 --- a/src/Magnum/Shaders/Phong.frag +++ b/src/Magnum/Shaders/Phong.frag @@ -149,6 +149,10 @@ in highp vec3 cameraDirection; in mediump vec2 interpolatedTextureCoords; #endif +#ifdef VERTEX_COLOR +in lowp vec4 interpolatedVertexColor; +#endif + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) @@ -174,6 +178,9 @@ void main() { #ifdef DIFFUSE_TEXTURE texture(diffuseTexture, interpolatedTextureCoords)* #endif + #ifdef VERTEX_COLOR + interpolatedVertexColor* + #endif diffuseColor; lowp const vec4 finalSpecularColor = #ifdef SPECULAR_TEXTURE diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index cdeb7da8b..d7ca7a1ff 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -115,6 +115,7 @@ Creating this shader with zero lights makes its output equivalent to the (if @ref Flag::AmbientTexture is enabled) are taken into account, which correspond to @ref Flat::setColor() and @ref Flat::bindTexture(). This is useful to reduce complexity in apps that render models with pre-baked lights. +In addition, enabling @ref Flag::VertexColor and using a default ambient color with no texturing makes this shader equivalent to @ref VertexColor. @see @ref shaders */ @@ -155,6 +156,24 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { */ typedef Generic3D::TextureCoordinates TextureCoordinates; + /** + * @brief Three-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use + * either this or the @ref Color4 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef Generic3D::Color3 Color3; + + /** + * @brief Four-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use + * either this or the @ref Color3 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef Generic3D::Color4 Color4; + enum: UnsignedInt { /** * Color shader output. @ref shaders-generic "Generic output", @@ -221,6 +240,12 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { */ AlphaMask = 1 << 3, + /** + * Multiply diffuse color with a vertex color. Requires either + * the @ref Color3 or @ref Color4 attribute to be present. + */ + VertexColor = 1 << 5, + #ifndef MAGNUM_TARGET_GLES2 /** * Enable object ID output. See @ref Shaders-Phong-usage-object-id @@ -229,7 +254,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * attachments, which are not available in OpenGL ES 2.0 or * WebGL 1.0. */ - ObjectId = 1 << 5 + ObjectId = 1 << 6 #endif }; @@ -286,7 +311,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * ambient texture, otherwise default value is @cpp 0x00000000_rgbaf @ce. * @see @ref bindAmbientTexture() */ - Phong& setAmbientColor(const Color4& color) { + Phong& setAmbientColor(const Magnum::Color4& color) { setUniform(_ambientColorUniform, color); return *this; } @@ -319,7 +344,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * to the output in that case. * @see @ref bindDiffuseTexture() */ - Phong& setDiffuseColor(const Color4& color) { + Phong& setDiffuseColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_diffuseColorUniform, color); return *this; } @@ -368,7 +393,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * output in that case. * @see @ref bindSpecularTexture() */ - Phong& setSpecularColor(const Color4& color) { + Phong& setSpecularColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_specularColorUniform, color); return *this; } @@ -550,10 +575,10 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * Initial values are @cpp 0xffffffff_rgbaf @ce. Expects that the size * of the @p colors array is the same as @ref lightCount(). */ - Phong& setLightColors(Containers::ArrayView colors); + Phong& setLightColors(Containers::ArrayView colors); /** @overload */ - Phong& setLightColors(std::initializer_list colors) { + Phong& setLightColors(std::initializer_list colors) { return setLightColors({colors.begin(), colors.size()}); } @@ -563,9 +588,9 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * * Unlike @ref setLightColors() updates just a single light color. * Expects that @p id is less than @ref lightCount(). - * @see @ref setLightColor(const Color4&) + * @see @ref setLightColor(const Magnum::Color4&) */ - Phong& setLightColor(UnsignedInt id, const Color4& color); + Phong& setLightColor(UnsignedInt id, const Magnum::Color4& color); /** * @brief Set light color @@ -573,9 +598,9 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { * * Convenience alternative to @ref setLightColors() when there is just * one light. - * @see @ref setLightColor(UnsignedInt, const Color4&) + * @see @ref setLightColor(UnsignedInt, const Magnum::Color4&) */ - Phong& setLightColor(const Color4& color) { + Phong& setLightColor(const Magnum::Color4& color) { return setLightColors({&color, 1}); } diff --git a/src/Magnum/Shaders/Phong.vert b/src/Magnum/Shaders/Phong.vert index e57662ec0..84bbfa5e3 100644 --- a/src/Magnum/Shaders/Phong.vert +++ b/src/Magnum/Shaders/Phong.vert @@ -93,6 +93,15 @@ in mediump vec2 textureCoords; out mediump vec2 interpolatedTextureCoords; #endif +#ifdef VERTEX_COLOR +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = COLOR_ATTRIBUTE_LOCATION) +#endif +in lowp vec4 vertexColor; + +out lowp vec4 interpolatedVertexColor; +#endif + #if LIGHT_COUNT out mediump vec3 transformedNormal; #ifdef NORMAL_TEXTURE @@ -129,4 +138,9 @@ void main() { /* Texture coordinates, if needed */ interpolatedTextureCoords = textureCoords; #endif + + #ifdef VERTEX_COLOR + /* Vertex colors, if enabled */ + interpolatedVertexColor = vertexColor; + #endif } diff --git a/src/Magnum/Shaders/Test/CMakeLists.txt b/src/Magnum/Shaders/Test/CMakeLists.txt index 91fc643bc..8bcfc27b1 100644 --- a/src/Magnum/Shaders/Test/CMakeLists.txt +++ b/src/Magnum/Shaders/Test/CMakeLists.txt @@ -94,7 +94,9 @@ if(BUILD_GL_TESTS) FlatTestFiles/textured2D-alpha.tga FlatTestFiles/textured3D-alpha.tga FlatTestFiles/textured2D-alpha-mask0.5.tga - FlatTestFiles/textured3D-alpha-mask0.5.tga) + FlatTestFiles/textured3D-alpha-mask0.5.tga + FlatTestFiles/vertexColor2D.tga + FlatTestFiles/vertexColor3D.tga) if(NOT BUILD_PLUGINS_STATIC) target_include_directories(ShadersFlatGLTest PRIVATE $) else() @@ -140,6 +142,7 @@ if(BUILD_GL_TESTS) PhongTestFiles/textured-normal.tga PhongTestFiles/textured-specular.tga PhongTestFiles/textured.tga + PhongTestFiles/vertexColor.tga # For zero lights test (equivalency to Flat3D) FlatTestFiles/textured3D-alpha-mask0.5.tga) diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index b0d1502b1..c4a91c841 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -80,6 +80,9 @@ struct FlatGLTest: GL::OpenGLTester { void renderTextured2D(); void renderTextured3D(); + template void renderVertexColor2D(); + template void renderVertexColor3D(); + void renderAlphaSetup(); void renderAlphaTeardown(); @@ -127,6 +130,8 @@ constexpr struct { {"textured", Flat2D::Flag::Textured}, {"alpha mask", Flat2D::Flag::AlphaMask}, {"alpha mask + textured", Flat2D::Flag::AlphaMask|Flat2D::Flag::Textured}, + {"vertex colors", Flat2D::Flag::VertexColor}, + {"vertex colors + textured", Flat2D::Flag::VertexColor|Flat2D::Flag::Textured}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", Flat2D::Flag::ObjectId}, {"object ID + alpha mask + textured", Flat2D::Flag::ObjectId|Flat2D::Flag::AlphaMask|Flat2D::Flag::Textured} @@ -182,7 +187,11 @@ FlatGLTest::FlatGLTest() { &FlatGLTest::renderSinglePixelTextured2D, &FlatGLTest::renderSinglePixelTextured3D, &FlatGLTest::renderTextured2D, - &FlatGLTest::renderTextured3D}, + &FlatGLTest::renderTextured3D, + &FlatGLTest::renderVertexColor2D, + &FlatGLTest::renderVertexColor2D, + &FlatGLTest::renderVertexColor3D, + &FlatGLTest::renderVertexColor3D}, &FlatGLTest::renderSetup, &FlatGLTest::renderTeardown); @@ -603,6 +612,118 @@ void FlatGLTest::renderTextured3D() { (DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold})); } +template void FlatGLTest::renderVertexColor2D() { + setTestCaseTemplateName(T::Size == 3 ? "Color3" : "Color4"); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + Trade::MeshData2D circleData = Primitives::circle2DSolid(32, + Primitives::CircleTextureCoords::Generate); + + /* Highlight a quarter */ + Containers::Array colorData{Containers::DirectInit, circleData.positions(0).size(), 0x999999_rgbf}; + for(std::size_t i = 8; i != 16; ++i) + colorData[i + 1] = 0xffff99_rgbf*1.5f; + + GL::Buffer colors; + colors.setData(colorData); + GL::Mesh circle = MeshTools::compile(circleData); + circle.addVertexBuffer(colors, 0, GL::Attribute{}); + + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D texture; + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/diffuse-texture.tga")) && (image = importer->image2D(0))); + texture.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + + Flat2D shader{Flat2D::Flag::Textured|Flat2D::Flag::VertexColor}; + shader.setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) + .setColor(0x9999ff_rgbf) + .bindTexture(texture); + circle.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + /* SwiftShader has minor rounding errors. ARM Mali slightly more */ + const Float maxThreshold = 1.334f, meanThreshold = 0.015f; + #else + /* WebGL 1 doesn't have 8bit renderbuffer storage, so it's worse */ + const Float maxThreshold = 1.334f, meanThreshold = 0.013f; + #endif + 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(SHADERS_TEST_DIR, "FlatTestFiles/vertexColor2D.tga"), + (DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold})); +} + +template void FlatGLTest::renderVertexColor3D() { + setTestCaseTemplateName(T::Size == 3 ? "Color3" : "Color4"); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + Trade::MeshData3D sphereData = Primitives::uvSphereSolid(16, 32, + Primitives::UVSphereTextureCoords::Generate); + + /* Highlight the middle rings */ + Containers::Array colorData{Containers::DirectInit, sphereData.positions(0).size(), 0x999999_rgbf}; + for(std::size_t i = 6*33; i != 9*33; ++i) + colorData[i + 1] = 0xffff99_rgbf*1.5f; + + GL::Buffer colors; + colors.setData(colorData); + GL::Mesh sphere = MeshTools::compile(sphereData); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D texture; + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/diffuse-texture.tga")) && (image = importer->image2D(0))); + texture.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + + Flat3D shader{Flat3D::Flag::Textured|Flat3D::Flag::VertexColor}; + shader.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)) + .setColor(0x9999ff_rgbf) + .bindTexture(texture); + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + /* SwiftShader has some minor differences on the edges */ + const Float maxThreshold = 76.67f, meanThreshold = 0.072f; + #else + /* WebGL 1 doesn't have 8bit renderbuffer storage, so it's worse */ + const Float maxThreshold = 76.67f, meanThreshold = 0.072f; + #endif + 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(SHADERS_TEST_DIR, "FlatTestFiles/vertexColor3D.tga"), + (DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold})); +} + void FlatGLTest::renderAlphaSetup() { renderSetup(); if(RenderAlphaData[testCaseInstanceId()].blending) diff --git a/src/Magnum/Shaders/Test/FlatTestFiles/vertexColor2D.tga b/src/Magnum/Shaders/Test/FlatTestFiles/vertexColor2D.tga new file mode 100644 index 0000000000000000000000000000000000000000..c857c9b7a385ff9ef50ad844d51e294d0bae2c4f GIT binary patch literal 19218 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 F{{VYVruF~; literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/FlatTestFiles/vertexColor3D.tga b/src/Magnum/Shaders/Test/FlatTestFiles/vertexColor3D.tga new file mode 100644 index 0000000000000000000000000000000000000000..db357fc7464ebe2391968ee3ec83d7928a977675 GIT binary patch literal 19218 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 P$4`DZ@WX+B9S8moeS{eN literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index 76e2cd299..b0c96dcce 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -81,6 +81,8 @@ struct PhongGLTest: GL::OpenGLTester { void renderTextured(); void renderTexturedNormal(); + template void renderVertexColor(); + void renderShininess(); void renderAlphaSetup(); @@ -137,6 +139,8 @@ constexpr struct { {"ambient + diffuse + specular + normal texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture|Phong::Flag::NormalTexture, 1}, {"alpha mask", Phong::Flag::AlphaMask, 1}, {"alpha mask + diffuse texture", Phong::Flag::AlphaMask|Phong::Flag::DiffuseTexture, 1}, + {"vertex colors", Phong::Flag::VertexColor, 1}, + {"vertex colors + diffuse texture", Phong::Flag::VertexColor|Phong::Flag::DiffuseTexture, 1}, #ifndef MAGNUM_TARGET_GLES2 {"object ID", Phong::Flag::ObjectId, 1}, {"object ID + alpha mask + specular texture", Phong::Flag::ObjectId|Phong::Flag::AlphaMask|Phong::Flag::SpecularTexture, 1}, @@ -286,6 +290,11 @@ PhongGLTest::PhongGLTest() { &PhongGLTest::renderSetup, &PhongGLTest::renderTeardown); + addTests({&PhongGLTest::renderVertexColor, + &PhongGLTest::renderVertexColor}, + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + addInstancedTests({&PhongGLTest::renderShininess}, Containers::arraySize(RenderShininessData), &PhongGLTest::renderSetup, @@ -817,6 +826,69 @@ void PhongGLTest::renderTexturedNormal() { (DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold})); } +template void PhongGLTest::renderVertexColor() { + setTestCaseTemplateName(T::Size == 3 ? "Color3" : "Color4"); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + Trade::MeshData3D sphereData = Primitives::uvSphereSolid(16, 32, + Primitives::UVSphereTextureCoords::Generate); + + /* Highlight the middle rings */ + Containers::Array colorData{Containers::DirectInit, sphereData.positions(0).size(), 0x999999_rgbf}; + for(std::size_t i = 6*33; i != 9*33; ++i) + colorData[i + 1] = 0xffff99_rgbf*1.5f; + + GL::Buffer colors; + colors.setData(colorData); + GL::Mesh sphere = MeshTools::compile(sphereData); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D diffuse; + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/diffuse-texture.tga")) && (image = importer->image2D(0))); + diffuse.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + + Phong shader{Phong::Flag::DiffuseTexture|Phong::Flag::VertexColor, 2}; + shader.setLightPositions({{-3.0f, -3.0f, 0.0f}, + { 3.0f, -3.0f, 0.0f}}) + .setTransformationMatrix( + Matrix4::translation(Vector3::zAxis(-2.15f))* + Matrix4::rotationY(-15.0_degf)* + Matrix4::rotationX(15.0_degf)) + /** @todo use normalMatrix() instead */ + .setNormalMatrix((Matrix4::rotationY(-15.0_degf)* + Matrix4::rotationX(15.0_degf)).rotationScaling()) + .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)) + .setDiffuseColor(0x9999ff_rgbf) + .bindDiffuseTexture(diffuse); + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + /* SwiftShader has some minor differences on the edges */ + const Float maxThreshold = 105.4f, meanThreshold = 0.075f; + #else + /* WebGL 1 doesn't have 8bit renderbuffer storage, so it's worse */ + const Float maxThreshold = 105.4f, meanThreshold = 0.075f; + #endif + 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(SHADERS_TEST_DIR, "PhongTestFiles/vertexColor.tga"), + (DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold})); +} + void PhongGLTest::renderShininess() { auto&& data = RenderShininessData[testCaseInstanceId()]; setTestCaseDescription(data.name); diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/vertexColor.tga b/src/Magnum/Shaders/Test/PhongTestFiles/vertexColor.tga new file mode 100644 index 0000000000000000000000000000000000000000..1f044cab8688a0cf4329b2d1c588db822ef15694 GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/VertexColor.h b/src/Magnum/Shaders/VertexColor.h index 1fb6c9367..c6edeed30 100644 --- a/src/Magnum/Shaders/VertexColor.h +++ b/src/Magnum/Shaders/VertexColor.h @@ -49,6 +49,11 @@ configure the shader. @image html shaders-vertexcolor.png width=256px +This shader is equivalent to @ref Flat with @ref Flat::Flag::VertexColor +enabled; the 3D version of this shader is equivalent to @ref Phong with +@ref Phong::Flag::VertexColor enabled. In both cases this implementation is +much simpler and thus likely also faster. + @section Shaders-VertexColor-example Example usage Common mesh setup. The shader accepts either three- or four-component color