From 87764900a4a0dda60a89f9d71bd447cf2ab728cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 3 Aug 2019 23:11:53 +0200 Subject: [PATCH] Shaders: rendering tests for Phong shader. --- src/Magnum/Shaders/Test/CMakeLists.txt | 76 +- src/Magnum/Shaders/Test/PhongGLTest.cpp | 638 +++- .../Shaders/Test/PhongTestFiles/colored.tga | Bin 0 -> 19218 bytes .../Shaders/Test/PhongTestFiles/defaults.tga | Bin 0 -> 19218 bytes .../shininess-black-specular.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/shininess0.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/shininess10.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/shininess80.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/textured-ambient.tga | Bin 0 -> 19218 bytes .../textured-diffuse-alpha-mask0.5.tga | Bin 0 -> 19218 bytes .../PhongTestFiles/textured-diffuse-alpha.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/textured-diffuse.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/textured-normal.tga | Bin 0 -> 19218 bytes .../Test/PhongTestFiles/textured-specular.tga | Bin 0 -> 19218 bytes .../Shaders/Test/PhongTestFiles/textured.tga | Bin 0 -> 19218 bytes .../Shaders/Test/TestFiles/alpha-mask1.0.tga | Bin 0 -> 19218 bytes .../Shaders/Test/TestFiles/alpha-texture.tga | Bin 0 -> 65554 bytes .../Test/TestFiles/ambient-texture.tga | Bin 0 -> 49170 bytes .../Shaders/Test/TestFiles/checkerboard.svg | 3165 +++++++++++++++++ .../Test/TestFiles/diffuse-alpha-texture.tga | Bin 0 -> 65554 bytes .../Test/TestFiles/diffuse-texture.tga | Bin 0 -> 49170 bytes .../Shaders/Test/TestFiles/normal-texture.tga | Bin 0 -> 49170 bytes .../Test/TestFiles/specular-texture.tga | Bin 0 -> 49170 bytes src/Magnum/Shaders/Test/configure.h.cmake | 28 + 24 files changed, 3905 insertions(+), 2 deletions(-) create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/colored.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/defaults.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/shininess-black-specular.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/shininess0.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/shininess10.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/shininess80.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-ambient.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse-alpha-mask0.5.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse-alpha.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-normal.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured-specular.tga create mode 100644 src/Magnum/Shaders/Test/PhongTestFiles/textured.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/alpha-mask1.0.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/alpha-texture.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/ambient-texture.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/checkerboard.svg create mode 100644 src/Magnum/Shaders/Test/TestFiles/diffuse-alpha-texture.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/diffuse-texture.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/normal-texture.tga create mode 100644 src/Magnum/Shaders/Test/TestFiles/specular-texture.tga create mode 100644 src/Magnum/Shaders/Test/configure.h.cmake diff --git a/src/Magnum/Shaders/Test/CMakeLists.txt b/src/Magnum/Shaders/Test/CMakeLists.txt index 962694552..3e468f9a2 100644 --- a/src/Magnum/Shaders/Test/CMakeLists.txt +++ b/src/Magnum/Shaders/Test/CMakeLists.txt @@ -40,10 +40,84 @@ set_target_properties( PROPERTIES FOLDER "Magnum/Shaders/Test") if(BUILD_GL_TESTS) + # Otherwise CMake complains that Corrade::PluginManager is not found, wtf + find_package(Corrade REQUIRED PluginManager) + + if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(SHADERS_TEST_DIR ".") + else() + set(SHADERS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + # CMake before 3.8 has broken $ expressions for iOS (see + # https://gitlab.kitware.com/cmake/cmake/merge_requests/404) and since + # Corrade doesn't support dynamic plugins on iOS, this sorta works around + # that. Should be revisited when updating Travis to newer Xcode (current + # has CMake 3.6). + if(NOT BUILD_PLUGINS_STATIC) + if(WITH_ANYIMAGEIMPORTER) + set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $) + endif() + if(WITH_TGAIMPORTER) + set(TGAIMPORTER_PLUGIN_FILENAME $) + endif() + + # First replace ${} variables, then $<> generator expressions + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) + file(GENERATE OUTPUT $/configure.h + INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) + else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + endif() + corrade_add_test(ShadersDistanceFieldVectorGLTest DistanceFieldVectorGLTest.cpp LIBRARIES MagnumShaders MagnumOpenGLTester) corrade_add_test(ShadersFlatGLTest FlatGLTest.cpp LIBRARIES MagnumShadersTestLib MagnumOpenGLTester) corrade_add_test(ShadersMeshVisualizerGLTest MeshVisualizerGLTest.cpp LIBRARIES MagnumShaders MagnumOpenGLTester) - corrade_add_test(ShadersPhongGLTest PhongGLTest.cpp LIBRARIES MagnumShadersTestLib MagnumOpenGLTester) + + corrade_add_test(ShadersPhongGLTest PhongGLTest.cpp + LIBRARIES + MagnumDebugTools + MagnumMeshTools + MagnumPrimitives + MagnumShadersTestLib + MagnumOpenGLTester + FILES + TestFiles/alpha-texture.tga + TestFiles/ambient-texture.tga + TestFiles/diffuse-alpha-texture.tga + TestFiles/diffuse-texture.tga + TestFiles/normal-texture.tga + TestFiles/specular-texture.tga + TestFiles/alpha-mask1.0.tga + + PhongTestFiles/colored.tga + PhongTestFiles/defaults.tga + PhongTestFiles/shininess-black-specular.tga + PhongTestFiles/shininess0.tga + PhongTestFiles/shininess10.tga + PhongTestFiles/shininess80.tga + PhongTestFiles/textured-ambient.tga + PhongTestFiles/textured-diffuse-alpha.tga + PhongTestFiles/textured-diffuse-alpha-mask0.5.tga + PhongTestFiles/textured-diffuse-alpha.tga + PhongTestFiles/textured-diffuse.tga + PhongTestFiles/textured-normal.tga + PhongTestFiles/textured-specular.tga + PhongTestFiles/textured.tga) + if(NOT BUILD_PLUGINS_STATIC) + target_include_directories(ShadersPhongGLTest PRIVATE $) + else() + target_include_directories(ShadersPhongGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + if(WITH_ANYIMAGEIMPORTER) + target_link_libraries(ShadersPhongGLTest PRIVATE AnyImageImporter) + endif() + if(WITH_TGAIMPORTER) + target_link_libraries(ShadersPhongGLTest PRIVATE TgaImporter) + endif() + endif() + corrade_add_test(ShadersVectorGLTest VectorGLTest.cpp LIBRARIES MagnumShaders MagnumOpenGLTester) corrade_add_test(ShadersVertexColorGLTest VertexColorGLTest.cpp LIBRARIES MagnumShaders MagnumOpenGLTester) diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index b2966582e..3d3d6358b 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -24,14 +24,34 @@ */ #include +#include +#include +#include #include +#include -#include "Magnum/PixelFormat.h" +#include "Magnum/Image.h" #include "Magnum/ImageView.h" +#include "Magnum/PixelFormat.h" +#include "Magnum/DebugTools/CompareImage.h" +#include "Magnum/GL/Framebuffer.h" +#include "Magnum/GL/Mesh.h" #include "Magnum/GL/OpenGLTester.h" +#include "Magnum/GL/Renderer.h" +#include "Magnum/GL/Renderbuffer.h" +#include "Magnum/GL/RenderbufferFormat.h" #include "Magnum/GL/Texture.h" #include "Magnum/GL/TextureFormat.h" +#include "Magnum/MeshTools/Compile.h" +#include "Magnum/MeshTools/Transform.h" +#include "Magnum/Primitives/Plane.h" +#include "Magnum/Primitives/UVSphere.h" #include "Magnum/Shaders/Phong.h" +#include "Magnum/Trade/AbstractImporter.h" +#include "Magnum/Trade/MeshData3D.h" +#include "Magnum/Trade/ImageData.h" + +#include "configure.h" namespace Magnum { namespace Shaders { namespace Test { namespace { @@ -50,6 +70,29 @@ struct PhongGLTest: GL::OpenGLTester { void setWrongLightCount(); void setWrongLightId(); + + void renderSetup(); + void renderTeardown(); + + void renderDefaults(); + void renderColored(); + void renderSinglePixelTextured(); + + void renderTextured(); + void renderTexturedNormal(); + + void renderShininess(); + + void renderAlphaSetup(); + void renderAlphaTeardown(); + + void renderAlpha(); + + private: + PluginManager::Manager _manager{"nonexistent"}; + + GL::Renderbuffer _color{NoCreate}; + GL::Framebuffer _framebuffer{NoCreate}; }; constexpr struct { @@ -72,6 +115,108 @@ constexpr struct { {"five lights", {}, 5} }; +using namespace Math::Literals; + +const struct { + const char* name; + Deg rotation; + Color4 lightColor1, lightColor2; + Float lightPosition1, lightPosition2; +} RenderColoredData[]{ + {"", {}, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f}, + {"flip lights", {}, 0x669933_rgbf, 0x993366_rgbf, 3.0f, -3.0f}, + {"rotated", 45.0_degf, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f} +}; + +constexpr struct { + const char* name; + bool multiBind; +} RenderSinglePixelTexturedData[]{ + {"", false}, + {"multi bind", true} +}; + +constexpr struct { + const char* name; + const char* expected; + Phong::Flags flags; +} RenderTexturedData[]{ + {"all", "textured.tga", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture}, + {"ambient", "textured-ambient.tga", Phong::Flag::AmbientTexture}, + {"diffuse", "textured-diffuse.tga", Phong::Flag::DiffuseTexture}, + {"specular", "textured-specular.tga", Phong::Flag::SpecularTexture} +}; + +/* MSVC 2015 doesn't like constexpr here due to the angles */ +const struct { + const char* name; + Deg rotation; +} RenderTexturedNormalData[]{ + {"", {}}, + {"rotated 90°", 90.0_degf}, + {"rotated -90°", -90.0_degf} +}; + +const struct { + const char* name; + const char* expected; + Float shininess; + Color4 specular; +} RenderShininessData[] { + {"80", "shininess80.tga", 80.0f, 0xffffff_rgbf}, + {"10", "shininess10.tga", 10.0f, 0xffffff_rgbf}, + {"0", "shininess0.tga", 0.0f, 0xffffff_rgbf}, + {"0.001", "shininess0.tga", 0.001f, 0xffffff_rgbf}, + {"black specular", "shininess-black-specular.tga", 80.0f, 0x000000_rgbf} +}; + +const struct { + const char* name; + const char* expected; + bool blending; + Phong::Flags flags; + Float threshold; + const char* ambientTexture; + const char* diffuseTexture; + Color4 ambientColor; + Color4 diffuseColor; +} RenderAlphaData[] { + /* All those deliberately have a non-white diffuse in order to match the + expected data from textured() */ + {"none, separate", "PhongTestFiles/textured-diffuse.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + "alpha-texture.tga", "diffuse-texture.tga", + 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, + {"none, combined", "PhongTestFiles/textured-diffuse.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", + 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, + {"blending, separate", "PhongTestFiles/textured-diffuse-alpha.tga", true, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + "alpha-texture.tga", "diffuse-texture.tga", + 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, + {"blending, combined", "PhongTestFiles/textured-diffuse-alpha.tga", true, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", + 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, + {"masking 0.0, separate", "PhongTestFiles/textured-diffuse.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.0f, + "alpha-texture.tga", "diffuse-texture.tga", + 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, + {"masking 0.5, separate", "PhongTestFiles/textured-diffuse-alpha-mask0.5.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.5f, + "alpha-texture.tga", "diffuse-texture.tga", + 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, + {"masking 0.5, combined", "PhongTestFiles/textured-diffuse-alpha-mask0.5.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.5f, + "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", + 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, + {"masking 1.0, separate", "TestFiles/alpha-mask1.0.tga", false, + Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 1.0f, + "alpha-texture.tga", "diffuse-texture.tga", + 0xffffffff_rgbaf, 0x9999ff00_rgbaf} +}; + PhongGLTest::PhongGLTest() { addInstancedTests({&PhongGLTest::construct}, Containers::arraySize(ConstructData)); @@ -85,6 +230,49 @@ PhongGLTest::PhongGLTest() { &PhongGLTest::setWrongLightCount, &PhongGLTest::setWrongLightId}); + + addTests({&PhongGLTest::renderDefaults}, + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderColored}, + Containers::arraySize(RenderColoredData), + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderSinglePixelTextured}, + Containers::arraySize(RenderSinglePixelTexturedData), + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderTextured}, + Containers::arraySize(RenderTexturedData), + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderTexturedNormal}, + Containers::arraySize(RenderTexturedNormalData), + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderShininess}, + Containers::arraySize(RenderShininessData), + &PhongGLTest::renderSetup, + &PhongGLTest::renderTeardown); + + addInstancedTests({&PhongGLTest::renderAlpha}, + Containers::arraySize(RenderAlphaData), + &PhongGLTest::renderAlphaSetup, + &PhongGLTest::renderAlphaTeardown); + + /* Load the plugins directly from the build tree. Otherwise they're either + static and already loaded or not present in the build tree */ + #ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_manager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + #ifdef TGAIMPORTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_manager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif } void PhongGLTest::construct() { @@ -228,6 +416,454 @@ void PhongGLTest::setWrongLightId() { "Shaders::Phong::setLightPosition(): light ID 3 is out of bounds for 3 lights\n"); } +constexpr Vector2i RenderSize{80, 80}; + +void PhongGLTest::renderSetup() { + /* Pick a color that's directly representable on RGBA4 as well to reduce + artifacts */ + GL::Renderer::setClearColor(0x111111_rgbf); + GL::Renderer::enable(GL::Renderer::Feature::FaceCulling); + + _color = GL::Renderbuffer{}; + _color.setStorage( + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + GL::RenderbufferFormat::RGBA8, + #else + GL::RenderbufferFormat::RGBA4, + #endif + RenderSize); + _framebuffer = GL::Framebuffer{{{}, RenderSize}}; + _framebuffer + .attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, _color) + .clear(GL::FramebufferClear::Color) + .bind(); +} + +void PhongGLTest::renderTeardown() { + _color = GL::Renderbuffer{NoCreate}; + _framebuffer = GL::Framebuffer{NoCreate}; +} + +void PhongGLTest::renderDefaults() { + /* The light is at the center by default, so we scale the sphere to half + and move the vertices back a bit to avoid a fully-black render but + still have the thing in the default [-1; 1] cube */ + Trade::MeshData3D meshData = Primitives::uvSphereSolid(16, 32); + Matrix4 transformation = + Matrix4::translation(Vector3::zAxis(-1.0f))*Matrix4::scaling(Vector3(1.0f, 1.0f, 0.25f)); + MeshTools::transformPointsInPlace(transformation, meshData.positions(0)); + /** @todo use Matrix4::normalMatrix() */ + MeshTools::transformVectorsInPlace(transformation.inverted().transposed(), meshData.normals(0)); + GL::Mesh sphere = MeshTools::compile(meshData); + + Phong shader; + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + 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/defaults.tga"), + (DebugTools::CompareImageToFile{_manager, 0.0f, 0.0f})); +} + +void PhongGLTest::renderColored() { + auto&& data = RenderColoredData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); + + Phong shader{{}, 2}; + shader.setLightColors({data.lightColor1, data.lightColor2}) + .setLightPositions({{data.lightPosition1, -3.0f, 0.0f}, + {data.lightPosition2, -3.0f, 0.0f}}) + .setAmbientColor(0x330033_rgbf) + .setDiffuseColor(0xccffcc_rgbf) + .setSpecularColor(0x6666ff_rgbf) + .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f))* + Matrix4::rotationY(data.rotation)) + .setNormalMatrix(Matrix4::rotationY(data.rotation).rotationScaling()) + .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)); + + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + 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/colored.tga"), + (DebugTools::CompareImageToFile{_manager, 0.0f, 0.0f})); +} + +constexpr GL::TextureFormat TextureFormatRGB = + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + GL::TextureFormat::RGB8 + #else + GL::TextureFormat::RGB + #endif + ; +constexpr GL::TextureFormat TextureFormatRGBA = + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + GL::TextureFormat::RGBA8 + #else + GL::TextureFormat::RGBA + #endif + ; + +void PhongGLTest::renderSinglePixelTextured() { + auto&& data = RenderSinglePixelTexturedData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, + Primitives::UVSphereTextureCoords::Generate)); + + const Color4ub ambientData[]{ 0x330033_rgb }; + ImageView2D ambientImage{PixelFormat::RGBA8Unorm, Vector2i{1}, ambientData}; + GL::Texture2D ambient; + ambient.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGBA, Vector2i{1}) + .setSubImage(0, {}, ambientImage); + + const Color4ub diffuseData[]{ 0xccffcc_rgb }; + ImageView2D diffuseImage{PixelFormat::RGBA8Unorm, Vector2i{1}, diffuseData}; + GL::Texture2D diffuse; + diffuse.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGBA, Vector2i{1}) + .setSubImage(0, {}, diffuseImage); + + const Color4ub specularData[]{ 0x6666ff_rgb }; + ImageView2D specularImage{PixelFormat::RGBA8Unorm, Vector2i{1}, specularData}; + GL::Texture2D specular; + specular.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGBA, Vector2i{1}) + .setSubImage(0, {}, specularImage); + + Phong shader{Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 2}; + shader.setLightColors({0x993366_rgbf, 0x669933_rgbf}) + .setLightPositions({{-3.0f, -3.0f, 0.0f}, + { 3.0f, -3.0f, 0.0f}}) + .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f))) + .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)); + + if(data.multiBind) + shader.bindTextures(&ambient, &diffuse, &specular, nullptr); + else shader + .bindAmbientTexture(ambient) + .bindDiffuseTexture(diffuse) + .bindSpecularTexture(specular); + + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + 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/colored.tga"), + (DebugTools::CompareImageToFile{_manager, 0.0f, 0.0f})); +} + +void PhongGLTest::renderTextured() { + auto&& data = RenderTexturedData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, + Primitives::UVSphereTextureCoords::Generate)); + + Phong shader{data.flags, 2}; + + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D ambient; + if(data.flags & Phong::Flag::AmbientTexture) { + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/ambient-texture.tga")) && (image = importer->image2D(0))); + ambient.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + shader + .bindAmbientTexture(ambient) + /* Colorized. Case without a color (where it should be white) is + tested in renderSinglePixelTextured() */ + .setAmbientColor(0xff9999_rgbf); + } + + /* If no diffuse texture is present, dial down the default diffuse color + so ambient/specular is visible */ + GL::Texture2D diffuse; + if(data.flags & Phong::Flag::DiffuseTexture) { + 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); + shader + .bindDiffuseTexture(diffuse) + /* Colorized. Case without a color (where it should be white) is + tested in renderSinglePixelTextured() */ + .setDiffuseColor(0x9999ff_rgbf); + } else shader.setDiffuseColor(0x333333_rgbf); + + GL::Texture2D specular; + if(data.flags & Phong::Flag::SpecularTexture) { + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/specular-texture.tga")) && (image = importer->image2D(0))); + specular.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + shader + .bindSpecularTexture(specular) + /* Colorized. Case without a color (where it should be white) is + tested in renderSinglePixelTextured() */ + .setSpecularColor(0x99ff99_rgbf); + } + + /* Using default (white) light colors to have the texture data visible + better */ + 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)); + + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + CORRADE_COMPARE_WITH( + /* Dropping the alpha channel, as it's always 1.0 */ + Containers::arrayCast(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}).pixels()), + Utility::Directory::join({SHADERS_TEST_DIR, "PhongTestFiles", data.expected}), + (DebugTools::CompareImageToFile{_manager, 0.0f, 0.0f})); +} + +void PhongGLTest::renderTexturedNormal() { + auto&& data = RenderTexturedNormalData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D normal; + Containers::Optional image; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(SHADERS_TEST_DIR, "TestFiles/normal-texture.tga")) && (image = importer->image2D(0))); + normal.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGB, image->size()) + .setSubImage(0, {}, *image); + + GL::Mesh plane = MeshTools::compile(Primitives::planeSolid( Primitives::PlaneTextureCoords::Generate)); + + /* Add hardcoded tangents */ + /** @todo remove once MeshData is sane */ + GL::Buffer tangents; + tangents.setData(Containers::Array{Containers::DirectInit, 4, Vector3::xAxis()}); + plane.addVertexBuffer(std::move(tangents), 0, Shaders::Phong::Tangent{}); + + /* Rotating the view a few times (together with light positions). If the + tangent transformation in the shader is correct, it should result in + exactly the same images. */ + Phong shader{Phong::Flag::NormalTexture, 2}; + shader.setLightPositions({ + Matrix4::rotationZ(data.rotation).transformPoint({-3.0f, -3.0f, 0.0f}), + Matrix4::rotationZ(data.rotation).transformPoint({ 3.0f, -3.0f, 0.0f})}) + .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.35f))* + Matrix4::rotationZ(data.rotation)* + Matrix4::rotationY(-15.0_degf)* + Matrix4::rotationX(15.0_degf)) + /** @todo use normalMatrix() instead */ + .setNormalMatrix((Matrix4::rotationZ(data.rotation)* + Matrix4::rotationY(-15.0_degf)* + Matrix4::rotationX(15.0_degf)).rotationScaling()) + .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)) + .setDiffuseColor(0x999999_rgbf) + .bindNormalTexture(normal); + + plane.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Image2D actual = _framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); + Containers::StridedArrayView2D pixels = + /* Dropping the alpha channel, as it's always 1.0 */ + Containers::arrayCast(actual.pixels()); + + /* Rotate pixels back to upright position so we can compare with the 0° + file and ensure the tangent calculation is transformation invariant */ + if(data.rotation == -90.0_degf) + pixels = pixels.flipped<0>().transposed<0, 1>(); + else if(data.rotation == 90.0_degf) + pixels = pixels.flipped<1>().transposed<0, 1>(); + else CORRADE_COMPARE(data.rotation, 0.0_degf); + + /* One pixel in the center didn't survive the transformation. But that's + okay */ + CORRADE_COMPARE_WITH(pixels, + Utility::Directory::join(SHADERS_TEST_DIR, "PhongTestFiles/textured-normal.tga"), + (DebugTools::CompareImageToFile{_manager, 1.0f, 0.00016f})); +} + +void PhongGLTest::renderShininess() { + auto&& data = RenderShininessData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); + + Phong shader; + shader.setLightPosition({-3.0f, -3.0f, 0.0f}) + .setDiffuseColor(0xff3333_rgbf) + .setSpecularColor(data.specular) + .setShininess(data.shininess) + .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f))) + .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)); + + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + 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", data.expected}), + (DebugTools::CompareImageToFile{_manager, 0.0f, 0.0f})); +} + +void PhongGLTest::renderAlphaSetup() { + renderSetup(); + if(RenderAlphaData[testCaseInstanceId()].blending) + GL::Renderer::enable(GL::Renderer::Feature::Blending); + GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::SourceAlpha, GL::Renderer::BlendFunction::OneMinusSourceAlpha); + GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add); +} + +void PhongGLTest::renderAlphaTeardown() { + if(RenderAlphaData[testCaseInstanceId()].blending) + GL::Renderer::disable(GL::Renderer::Feature::Blending); + renderTeardown(); +} + +void PhongGLTest::renderAlpha() { + auto&& data = RenderAlphaData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) || + !(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("AnyImageImporter / TgaImageImporter plugins not found."); + + Containers::Optional image; + Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); + CORRADE_VERIFY(importer); + + GL::Texture2D ambient; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join({SHADERS_TEST_DIR, "TestFiles", data.ambientTexture})) && (image = importer->image2D(0))); + ambient.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge) + .setStorage(1, TextureFormatRGBA, image->size()) + .setSubImage(0, {}, *image); + + GL::Texture2D diffuse; + CORRADE_VERIFY(importer->openFile(Utility::Directory::join({SHADERS_TEST_DIR, "TestFiles", data.diffuseTexture})) && (image = importer->image2D(0))); + diffuse.setMinificationFilter(GL::SamplerFilter::Linear) + .setMagnificationFilter(GL::SamplerFilter::Linear) + .setWrapping(GL::SamplerWrapping::ClampToEdge); + + /* In some instances the diffuse texture is just three-component, handle + that properly */ + if(image->format() == PixelFormat::RGBA8Unorm) + diffuse.setStorage(1, TextureFormatRGBA, image->size()); + else { + CORRADE_COMPARE(image->format(), PixelFormat::RGB8Unorm); + diffuse.setStorage(1, TextureFormatRGB, image->size()); + } + diffuse.setSubImage(0, {}, *image); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, + Primitives::UVSphereTextureCoords::Generate)); + + Phong shader{data.flags, 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)) + .setAmbientColor(data.ambientColor) + .setDiffuseColor(data.diffuseColor) + .setSpecularColor(0xffffff00_rgbaf) + .bindTextures(&ambient, &diffuse, nullptr, nullptr); + + if(data.flags & Phong::Flag::AlphaMask) + shader.setAlphaMask(data.threshold); + + /* For proper Z order draw back faces first and then front faces */ + GL::Renderer::setFaceCullingMode(GL::Renderer::PolygonFacing::Front); + sphere.draw(shader); + GL::Renderer::setFaceCullingMode(GL::Renderer::PolygonFacing::Back); + sphere.draw(shader); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + /* In some cases (separate vs combined alpha) there are off-by-one errors. + That's okay, as we have only 8bit texture precision. */ + 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, data.expected), + (DebugTools::CompareImageToFile{_manager, 1.34f, 0.1f})); +} + }}}} CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongGLTest) diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/colored.tga b/src/Magnum/Shaders/Test/PhongTestFiles/colored.tga new file mode 100644 index 0000000000000000000000000000000000000000..6d99eeb91282a36421d1637578008ed86cbbfbc8 GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/shininess-black-specular.tga b/src/Magnum/Shaders/Test/PhongTestFiles/shininess-black-specular.tga new file mode 100644 index 0000000000000000000000000000000000000000..1a439c90ff489ad8821fba31a31fb5f2fbfbda54 GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/shininess0.tga b/src/Magnum/Shaders/Test/PhongTestFiles/shininess0.tga new file mode 100644 index 0000000000000000000000000000000000000000..704c51993cacadf3d16e888c5a960b10364b43bc GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured-ambient.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured-ambient.tga new file mode 100644 index 0000000000000000000000000000000000000000..b67b086f4e920bd4060ea1e796d2ad89816c34e3 GIT binary patch literal 19218 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 H;R*a3P14?F literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse-alpha.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse-alpha.tga new file mode 100644 index 0000000000000000000000000000000000000000..c541bb420bdd8a0247a0cd308b6b9dee70820252 GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured-diffuse.tga new file mode 100644 index 0000000000000000000000000000000000000000..1b0ed212b9fdcae1d04ea78a8493dad7c278c0c3 GIT binary patch literal 19218 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 YD$E!?`&C?i^T^FFaPtfN|M>#{2VAr6Z2$lO literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured-normal.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured-normal.tga new file mode 100644 index 0000000000000000000000000000000000000000..679a3b3ce79dc59fe7409e36f6514ff9bf016e4d GIT binary patch literal 19218 zcmeI%N3)ex76#y3{SSK9zs3Ix|1FS*4<81{vuoEbSWcZfwSWKqZ@>Nan{U2>Yy0-?UwrWeT>q+m zKt6r?w71}|S+i#0!i9$p9r|y>`{}2je*E#rTefTw{8wLn6?L|4+xGeApMUt_hs&2Q z-@JJC&Y>(Sn3H zcJJQ37+~5B8#Y*TF!)`#{<954B7YC90bhH&viZAU!dTq=1hJkWF!i?TZL4^#jOOeX~`l02n#e2XQ6 z4I}hFtDmeNq^L7s)~s3FJ9OyK;lqb7Uc4BM!r+0AKKiI|yr^bE5`6aAX9B~puR5nq zo3?D(vS-hpEn2ilFd9I4kiY;eEg$8efJJU11K>m%o%8rffq&vy4}@V8porR+C2>1{980 zw9IC4{9_m>dB=C66~nxF^MnMiO5&JE!ongR6cI=#ts%04bs+K7^lGtP98-7 zF1dglMzx@2K~6fOLfhhAA;%PyI;zm9G+CdeO{8Xafmad0kEd9?#FcJIrNm|<$*7;V z#X}1cFc^K2E7aj?fGAua3*3*=5mN-F(YyfuM7YUE=#@t{`>euAi8jZ z5Ri=#1H&6nf@1L!PT2GUnX+Ko#ijy)NVL%D)Wd94U~(cVDIPpf++2_NSu@1VV16LG_*VeYfEw+gw7_!n)c>F2a z7>sbj8!=+U$dM!Aav#ueb`S_HV)MzOp$G(Nu5F|R6?OwaP#pC03F>&*05qZkw>jla zWEiM%u3t#BE*9^&apU+<$@Q0r?Wm?oP>s!Wx*Na_>Ey|i$BrF4Y0@NBS|yn}b?THU zQ;bo`G4}ZJW5a|keiVt5Y3VDAkzh^Ga?qfZd-a&*48j0EU>n{T2`#ABBTb<8wOG8! zw^!68he)7^2?a(AkCiW!_P%xN7WG{f7(>hwM5us}2K<;@!!8&= zpe>X^2&Q0?EFV z7hkzu@a)R);8;OBHOgB88DLF4G{u97h>E^C`GIyOA_qk%Q#;K9yoinGSx;Y>dEyy;!_p+JdH-M zsxL^s>Q7Qo4NPuS3Va5;nv5B1+6V(4OZhYs6&49m8U|z-!`l>BsK88tc*Q9gazH1K z}d!j%IAY0SHXH5ZUifdfgV)9yYQSl9#-Ez6O^>2vMcwY>6H)pdm7#3O72qBwwFp~7_A z0chozKlyGQmP0JLO|ibSZ~FA?nolaQC@ey?qXA6lE0TROgWxF= ztwGZXg?_^b2c3d1NRcNct)FuZljeGOCgR$ci$F%2PQ+RVX~05iL8~za28zOa^X5%J zg#FV`KLKlZG4Qjk{msi)ime`z^SJ=nzymL6{Lc@M9z6mC{0uPH-ATd0l|`VVrenxS z4YfpY7Uc5G58$}KI1{z)g7E9tud5a2B0*G^wJB2-f>-2s?%aXb`u4hUFrc_mN}9+UjG?AU1pN>xRtQo5^;k-Yvp5&w!FlJz zcWrCXpn>ZOHvE#~mpZpr_f->_-G+UWB-`Fu%QwcSlv<{3a>= zU29Fpj9?1ED>aBhH2@_Pr^zGedp1at4+J*eYP z3W6*R1;$S3MLzjR`Q*tHvK;9Mv}x0(e7u6`+O?}c=tQDWbE#s5f#8MCS0rFcz%~k$8tBs$J)B@7`EbQoR>K>xX8H8hn!u`QKFP|` z68Rt1&pYqDQ$AjQ*5R#f+qMlGHXJZu0MESp?z>Ew8?w3$J0Pr%f9lgk-QaN1G61CX z#e-U;p&$b#3z)=PvoNN_c@%l5fubqfhd?5_h)Q#BVYDpvIK*4&(6?{jzgIv01nb?q zw^C3(UTlNhzJ2>vty*>H&;gPC`}cqS_1E8c zDa8ga`vL1M;2=|+TQrm-;?f#XT;zevQdlK7_^9*A8%}UCRqxlRDWcQrQ9XobJU9VofhzqQ90dRRlXuIgtqe9XM^R$3V4X21AOfQK~CJiw0Afv&IB}nY3 zLW@*|0u~LQeCw;Fh-*zS@u~cx4*&Vr3>q}Z4MBMU%_+b~ z>MHoKduuy2Stj~SRuYBh1xyR$@unhyLvcVjSuXgbZ^{>pMC5<2MyAj3qep#^@<^kp zob}dy8(66=HftimD-@Nlub**Xq>dd053Kb81i>pOi;ARTuogCGK?vrgDZB){`fSkqje!jsO{7eJYKk=dzJ zCpiL|^Uhv!O7TQyVvt|h=39G7b0>w96dajIECItV7z1#UxfCI>36gb z5O2w95uJb}_YKCmWxb`ie8CA083U_A5=@zRF$oCmJSdH_5J_0;d!-ODo`y}cJ7{Qk ze24*F{rLBaK$L=Az<>xCQeSasDW{M1ame9}VSv5Zo?DE>gQU=-oho5dJWv7KQps2Q zmXB95VpYuI@hB|SSEOJ6Iq0iT9`h-Y?W;#T(2;|0lW|Z8CjX^Hi;(g|r7>`Ef&oUl zGuXv+@Ug_<%DXl~lyNE>$q&kV4yI%ir`bJcG5aYdW$G)ZY>j8eMlXTbjGgp|6X!(a zSh^%gM#T?(^>CWvsfMG1K&Auk?xaCt9#(Zv~9r>++~=R)o`ipftR~5 zrXLl)@`Jjq5#Gwgi&&r}m*7R^QBT~EaZU@^y%jT<4o5s|FemfNWg!t%Mk{E9AhGK- zqcSA+z=STUF~6k%L<_K{sb^VZd|HsnjYOax z8G$-#I(qOUWl&@a5>m3D1J)JS&)R&5aLckp$&itjm93^tJHQ?NAZu%Q=*~#OhDAI% zo8*+hq?l~QhOhafRf@&ZOsEirG4Z3zbckeVJRtZ8?VcmGiHiieV5F4|!=&TeU;Uis zEPML&sjtGba>;m^S)R&Yq{V)=d+^`^@-^@;R0F*A$TB@D3`J-WTDWANe}ky zg$i#u2S2GQKCN#BS8-1{CCiSyBmg+1_H{(kG?y{%qA6S| zCr^Tg6WK>lkd4=Ayv_hg+bb+V2Pxj3H!w!@Bsj?4l9;#seX1aYLmOez!-u8em05lc z;zO1L?d`YUmTvwQ_WK6Ne%pET%{O_HlkLdN;qr$@& zMjGZfKtVcx4Wleq3!7@7nPM31h>CN(vI3H2fg-PgMzuwWuo{6JaHZiDKc~@@#}v|b z?b=0@{CuYe6}EGs5~m|ooJ5y~{4AS57Kxi4pNK>SU^cj9y|PAnkfD#lE)4-+(saDEteF z0ca`)5QG6Q@&#<7_;un6eD>CF3Uu%Sf&ofl$u2%+u_=~iY%!z7;G`=5*g^n#D;Gp! zWjb2Kbj+hdg9l8+b7^?-k2H&bDR|~&Fj|1Ahs}ISOz2cdIvN0!$N>jIzwri;H6@)5 zq=p483k9#{pmERl)hpE?1p!6;ZxKR+rr|Brc2w3>661ZM*IuZwGB%8qFQxfekT8mb zN$_c3i3TizAk~9>(Lw~i?Q$8GKJap2!lnh)%tby3;=u`VjaRAgNecrs#0-wPtgEeD zFe;ehH`gClN{8eEisudB4SZTqFxWHEbV(rqoR^?4yefdI=yqfs=mbU)2dGX(N#vYq zFZrS^0DEcUTwp3ma!`-JxLW=?E4kFL9N(g)j)&sLAOt|WAd^Muh)ENn(<$Ep_bLaF z9{Pf50J?A}m*oOxRFx9&qS4_ZF+pGz7iUfBJ{~!0@j9_aBSeDP{;g0 zEj-T5!Sq}aGI>-&q8M*|V6|aac_?cNhd}LjU?ow%q!tg17I!FE+^?NkK|Mj8gUJfO zYL|c)9N`H@B#HoEQHo@Wtyi%np*1)PUJN6j;^6xPutkd&ty{O2cf28T0F5-4zByz? zjyiFA^w>)SKf;y>eB#pOM}8%d$#q)U3Wj+bHF*HBefsqAzYkmBDsC?UFZMW4R{DcW zo`T6vI)RdXcxG%3F?hJtrJWPh6Ty%s`})5_)22=9*RL-mJv4GdRu)1ayE3Go1;pw9 zQ}`6Tu>BTlRrT^TO*_dyr$HvS5I|y6_?9D z|NJvGC7K1PNeKLt+gH_zcFZ7^aDoSHPy`mii^@fXMn0|J2PoCRI>Z$iXNp|d8Wglt zojP@D)Tr^wE3Y(Z(uCF&WZKj#MGTp!^RFDv;d6_CpDZ>~j}#VjX?TBcR<Z0F#rESCK#_q{d}vf8qnGpFnLVFE=aQohN%xViWs9OTyxGJitx`F>^DHgK@n4&!56dODX9Lq!D=^Z)TmaiTD5D}&glbw`V|dtLFNh# zz=`e@qbxQw2>s_kC}bA_%K{#Tj?hpmUv!t(tfFo^eH0B>8sr$p$?%%u@`C~X;gdol zdAW;7Qi-Vos7_Mb)xs&}z;doR{pCgeY3^{8-7h!P7rML5^*H@qW}NT-7B2Y+exY$z N7OyZ+VW4CN{tbV=hVK9X literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured-specular.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured-specular.tga new file mode 100644 index 0000000000000000000000000000000000000000..70e53bec0480aa5f5383b003443a7ccfd0ac5dbf GIT binary patch literal 19218 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/PhongTestFiles/textured.tga b/src/Magnum/Shaders/Test/PhongTestFiles/textured.tga new file mode 100644 index 0000000000000000000000000000000000000000..1c7d6d153f16b85dd019d36f9adf8c6194cb38b8 GIT binary patch literal 19218 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 Dty$RU literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/alpha-mask1.0.tga b/src/Magnum/Shaders/Test/TestFiles/alpha-mask1.0.tga new file mode 100644 index 0000000000000000000000000000000000000000..8df608ecc38a6bc339c3daea53b7cc28d8f9857e GIT binary patch literal 19218 zcmeIuF%bYD3;?k|9Izp){?#yHfhm!YT0PTr+88ikz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA Oz<>b*1`HVZIB)^Kdi(bP literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/alpha-texture.tga b/src/Magnum/Shaders/Test/TestFiles/alpha-texture.tga new file mode 100644 index 0000000000000000000000000000000000000000..ead141557e28d0dbac3142aa604101890dd4e371 GIT binary patch literal 65554 zcmd_y?W@iQ9LMovk|arzB$*^hk|arzBuSDaNlR-jX{~k4>6p{(vaOjl+uCN$wl+zU zBuSE_Gdnvo_l|?(UXmn9k|eSB_rd;#_k+*s^{XSQ}&ze z`}b#mvM1~}+4mp7{$!8YZ?f+{kp0OXvEO9he-QhVJ!HShzW-qMCwsttlYRdo>`!)| z{U-bVL)o9~9{Wx9{fDtX*AG%Ka%~)ZnEEG-+vVQ zlU--O$-e(+_9wf_ev^IwG3-y)!+w)}|FP^(c8UEa`~KtDpRAkxCj0*5*`KV7{U-bV z6WE{Z9Q#f7{U@?N*%|hm?E6n*f3j2TH`(`}%>HC2*l)7$KZX6tj{C^iAFLO-t#UHqbZiq;I-F-?WUr=`;GK9rR6I^i9j@n?9#+ z+D_kep1$cV`lc`Fo3_z6ncqFA_6pfX`ljFMo6gcVy-nY=iN5JK`X=+cC)IvO_7#28 zFZ4~P>6_lAZ~B_P>1X<;Q}j(M>66`wgZ+f4;$^2_yZS(KFYMb9Zto8@8ALyIDp>O(!zNwkMX$yUm`QD@2ow5(A1_Fe7t=O5Cae=(nZs|?dD61bM#H-|NErc_UCWgc@3uX^i9j@o9xfucd*~oMc=fHzRCQ5pH+LO z>;iq$Qu?M1^i8|yo4VAc` z-?Wgvsg1sAAAM5~ebWN^rgij9`{|pm&^OJeZ(2*=bb!9;Dt*&D`leR;ri1iN*XWz( z(l@oxHyxsHx=!CThrVeIebZt3rW^E4v+0{w(>EQVZ@Nj}G>g8enZD^LebX)arkV7U zwX@&!n!afU{ba}3Z!&LR?djn<*l)7$KaKs#I@xcs??09O$&Rz%WZ!=Z`;*z(vEO9he<=Ht-DkhazW)&RCwsttlYRfe z>`(TP{U-bVgV>+!5&KQ{{Rgr?*<<#b?E4R3f3hd+H`({^&;Ddj*>AG%-;e#tp0VF# r-@h;WlRam@$-aLd_9uJ6ev^Iw-t15IlKm$8{=L|r>=pY>>iz!%zv-ti literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/ambient-texture.tga b/src/Magnum/Shaders/Test/TestFiles/ambient-texture.tga new file mode 100644 index 0000000000000000000000000000000000000000..145fde8c6a519910900ae48ad9f00cfba8193a65 GIT binary patch literal 49170 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/checkerboard.svg b/src/Magnum/Shaders/Test/TestFiles/checkerboard.svg new file mode 100644 index 000000000..fc7d1189f --- /dev/null +++ b/src/Magnum/Shaders/Test/TestFiles/checkerboard.svg @@ -0,0 +1,3165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + 6 + 7 + 8 + 1 + 1 + 2 + 1 + 2 + 3 + 6 + 7 + 8 + 7 + 8 + 8 + + + + + + + + diff --git a/src/Magnum/Shaders/Test/TestFiles/diffuse-alpha-texture.tga b/src/Magnum/Shaders/Test/TestFiles/diffuse-alpha-texture.tga new file mode 100644 index 0000000000000000000000000000000000000000..54ffa06f548430087c716abe06977a9c20bc82fa GIT binary patch literal 65554 zcmc(o3v3fty2shOT2-r6wW=zFstV;IiVzBkGxp5b9zTFM5Rw3S7?Y@Ow3xQ4UtLxsqt=UcWnO#KP%le-Rn~cl$PaS)mV|0s z>9?PJ{LusrWdE($zNcZwgmx*uq?rfzk4FBLgZi0~kY35n%-P3Ld(0o~n;8wbwzir2 zob;LV`^fwtqX#6wT<-zQ{~lbvbm779@X&)}M-DzPrY(N3cXz`BnEw-biFJeXBt4Es z{#7GFOeBk@oUOv#XE0N`M@saL$Odu}vf zPamJFDJdZKf_z3u_}!UPBirBDFiF#X`s7I6*3FaJr}8GvJh*=}@~<3J&67%*TQx8H zVCep7W%7CEQ=!j2%U|y9okv9Pt&sgy2lvlYRhmPddzL@sGem;l?;py^OdGm#>EgJ~ z-qStWcJoH(c$-wu;5?-sH*dEE-mtC;l&wmMc>UMn)x?spd@~ojyo!spbU)D<-{E4D zjWQyiv6?b(Un~h+%X_gJOHr)s`qd}8s~2N6%adcdldVtMB>F;5eo`QBf3>y5Uz}(1 zmldq?m*kuLpI*8^>?78dnt5=)|LHmr`0V)3(Z2%+cT`5S{$K7_$B~kMLLHa7S`n9O z`jPa_inww+xsO;k&Tl71apFjv+LRur4?=9C@q&AHFD>x=*L(Z+ZEC$(H#k>}W9yJs zh6&?w%BXREC1XS)@PKR3g9%3F!8KtGmcazpe;G_5dlx3bSzsK)-VX&Pac+kK6Ue>~ z6O7D*Yg&c`4wHm|9u5;&gLPmMoCU^lxlgOaB;MDn#00K=J0=*J2iLUv1vMt{>_?3W zWZ#WRa26QHwjrGclZ1g@4JMF%7bX~)2iJu4S{)|v>`#XYWPcNr;4CnXEq>hsOc;-S z0VeSO{5mF9zvfSv$h?k4n8;ao4JLnfp1p<%WPcx%c#qwH38V1TV)Cf(>=&3o_TOLv z&)yfK!nrmiAOd6mRZJlJdzir5YceJYta~FSj~r*OU{dba+{Gl$)0=_`jQyK2dE`9v zDJIrI;SMGV1I{!|7=`N%OknK4hzX4Sf5ZgVUYBD6WB;3&z})`=CXoGYOknPpjtSiR zZN=n~v;90Kkp0)RlzTN_m%9aOy;v9KewmoS*#8zLaPRja4fk&y|F9x&8I?A;Ub$a8 zLQ3v2k=Oz1zb>Y3ggNFZgoasnZ$vb|4R~r482Cl(j5=`&% z!zual;gXx`ab2lhJ)CNh4`=S=#@nQNCJfk3v?z`oFsW-RsP$r982jr;;Q1qUdVXmg z%ibW;g{uMge&=Xewn%mE-nFCDda*9#G$a*^Ll{alBn*}H2$M7xr)DT|QNob;D%DTy zC-e4Z)50A+kgck%q}Gdd;offtDIC|lL&GfxT{p4z=~_QH&$QE0xFV_D^GOr6UaSil z3`(W&WA$K4p*(E=lx+E6(G^wL^P%d%+HWo`?9t|2^}0%Gy;v8<;CdRATw}e!<$%^f zr5~&LgY)beTDI7-&wO%tJGEY{YxQgWQYq;c{7W*Kko_%gt>3Vi@mu`Kom`YW-+k*4+U2e^jX0HyQ-Kl1e*P6Yl*^(elB&HK+EzVWHNGbz$w#M?$Ja z;VU?&nxL_`H9oODtB#$}F2z^oahPdgTU*S+IvcfKtPA7uE_z(M)LhXnCAXW}1MdA! z($aT+|4Ca;8ns@m3uCgEgwh_tn_3|Enmbfpi%alkH}hUYYJxYbp7UD0WL{!jxCV=8 zQ5&3bZ=h+<@-Mh8QCA$^eB`P1d7i**CVei?t?9>Hqf4X^`+QaJ843J`R zX$F$BnE@E@2QoIZ18Ek;K>leZv5#06p8Xfo0`tFOp{9abFV=-|cu%CTZ0jB^pG)Nf z_hH8(;c)$$V`ukmqV|Am&_haA9p_nAuJFKoU{nihK%S*}a!<*PAActCgE?3!E$q<) zrRthWYQ0z&?#mjZfrig)WZ4d4uOA%kt&woA^H^(sdSdHC#~CUg*n8_Hq3Bb!J9!o3 zhRi4E@=hq-ncKJtZBl$;47Sh$^FNDFTS=`K>%!Q-HyWt8y1h!Sp4bcS!45}C&qne!#!S&<{cawBn zO#-(Tur?_a*M8DDn$%ofla^ZsKlc%M{a6?Fel$zPd+|VX$;zeAWbn!%$$ny8>!8+2 z%Ia%^GqsFyF3kb*fLz82e; z!_68tyII38hu8FGfvs&;uwBGHVqLiQn=pa#*+C0D|8G z_B~7>gI-MF8B7f(F!mqB1n&LzVglLQF@ZJM^_alD-yux?>^#$miOsL=!33VcZ^Q(~ z{==BS+TS~vz#42fCNTDI#su!oj$rbruYDIL)l3Ecagzy!Yg z{5P1$26|6m5^i7Y|5v-KUUmZ$*dz58CXjs_CNTHfiHW;D{w5|ipRg4Zxc54S3B314 zw0|;EeSdwzEll9vYYQeY_dbdV{ocz+_H91V!r0%13G9pBjEQW(egqTP2mcNxko{Mf zl>0OrF@bxp!%j!}$<$y1_udCF zf%)5enDp1j+cB~Fw68~k#TA(z_QD*%1lC@N_e?#}i2JP^5$N4bF!uLi0^hw;O^U@S zRA+2fR3~LH)k{_aSxj|)yNcLHtPA&k%~bSsHfzkQ=(IsKN%vlf{aN-9?7PZn*0DeC zzY_Oh@z6%&1=%}Dc&|j}$X^_q#zHbLu`Yb~LKP7M+NxBuylT}xWmP#Gi`tSK>Z-+= z@+$N1p^eZFp1n6w;qGZ#sFpV+xGD8xby;@{jQ^5Rb8ok3xs@#}dv#nR=WeuUICG1d z+cw@N)e|ys(sI-$b8gI{*Nb(_eL@8Zc}G+gY2}JZnxYO>MM@qsseLMM*n7917JZ^- ze?r%n)OxWl%;gC7-*g|+@mlDAGlWJwCqR35h;!jJEj}~oa>ORHg^VE8=F3H{-mi_%<4WAu$zmAsAJS^ug zggqas7R>$nX*p_(@84*o*Nb)G*_(xg#03c!OK)gRQZk(D3wRRPoPnh$e>$vI@T(lguCAc;j>Gfh=SoispFa|f$!oRn>QMqjcwO*`Cy7xlE7ae2S(@*W$=sl)k zi;k(-txvU2y|)A2gWa^i`0s}CpIR^0h0jP9OQp;q6entB#mm;ni^bz$UFHt1IDIWQ zp)L4)xMO(sw}%$_r9bS^=B}jHi*;e1MzsGz&RuWQa;w@nuDuPe^)@B9w@t?-wW+vm z;L}g!CDw)vJhVXmo=rx2y;v94ev2gI(i9mC2}OmUsEU^6D~gN_e9@}Cd=bnCijR(H_U|G^`S$8M32h9IYlGA%q$7h_>^ZJu&e%(n8zxpJ{wNdzZ zPC^C)v>dg{2H^Uq){Av*gIY5QiHVHa;?a(hcS>o_d0%NZeg4hc(@Y2$1lX*87>Gfh=nEU6G zkdi0Qhws=T(mcx_)_xlzA>r1S4chb+@aUoPfw|uq5)_IHXLNizXq*#tJa_nvz-^k) zCdC)#U_M%4{^#3hq}PjeVeL1U1Y-l6YiwkRG|%#fdoXwxiVW43_4QnHBb5)#|Jq4V z@_X8qeBC4s%U*03`20!jQ+dNR=%)qV|NSujQ|raLFbB^jq4?Yo{)T}U-ex)AQn*X3St=!Fz|18xLp8eKE1NQj)bwXJIv6r0lbdb^0q34!% zaNO_4bqemY4){*i4h8qgc$-vD$Y6++`h3|?b*5~nFj+PP`4j7d>%rbXBMtC<8%Frv zWg~nSk1;8gF{YL<#*#0|y<{HycBv??T-dHLr9Ttqi;I%|#JX^Oen^U(yYivHnLpHU zS%7i$mE+D5`-pX2J7vS9*ncA%KD9I_xYg7in4i56 zYbPk&=jm~Q))|4`ecn|cKY|IY%cNrhV?XxiuP(qG4Gp*!zs3aS=F2gGd%rg^fid_Z zCh%T-8x#2KPZ}mL2ETy`?A`nn6S(&Oh>69oNx=l3!J&Ts9n83Av2NRoDos0?Q zcW;Qb8P0tb6IX-mE+()pvltV22D$aF*Zwz{ zln-eZVFKCXe*YTlz7F$0G~m7eJ|>LEz5o@@vjCpIqk;L^Yq9o*4I2WO#QU5&OyqL6 z4imWcP(Oc*nY~yW*55R!u>Bg?H-!e|kNWvb?ED!|j~W%;qh=7n{Op}r8#{max386$ zC=@OwCUE@|ef}!i{ju{;80g_p;Rd(_L})*I6D=Kf{&8-H0uz|~DKLSx7wXSnL_>?6 zKkU6`P+|KS86q&AQ}4fzh88=2#^aQs!h2*e|BC?l{UgvrhSdA7qoIu?|MlzF2iDit zMznqq=eNfZ;j+gm4!jqqUTuogr>Dm0QHMz!EZgWkn?CQlIb$#8jTx(0LCV5dT_hGwqud%wEH&#YOU#y19jpev^KnK73 zs1|-NZaK6;eIhS!EM!5of3k0u|4G_!&nQ()QRg@NidRpWWT{`%U$ zilv4?t|@c8O{%Zl-8)Y@x8}*uoeJIm)X{nR%%srgo>fEco(J#;pa&uc``}d^gB=)OWw=R&R`Lk{<-l4XxM_e@cG-28V$=rJN)+$_`x+uz5goLAiI5e6TM!nO_G(Z z+!9#6WYMJT$2`)K^nuC>YuNK+{eoZNvv+f%h0>ZgM|t8fnV)iCP67dXr4stz3aQa6 z^RZ33)!8_k35+ z>}VlmXUtZdJ4xgRbHCZr>6x9VP(c5l5SpIZf7(Z%F9Y7WGrScw&xf#CbWn12yTaGf3u>(#g18eJwGend5g@C_sxoz%&l2^o(IZ6 z19gIQJiiUv*Gy;&J|FHFu0iVO?-w`7?yp`-uNP|vXCdWSoa>46KdYs5^ja^<&j~Ei ztElFFVm)~F6GKE#XN*u)8pE7D_CyEALTX}+u(#n!n^a%M6T?WRCnix4p#MiP0+R)7 z1sZ_T7(qyd_D%w?AL~K}4`^}jlszymls$lZL23^vnLpj9rltn&|8%3{y(uGY^x7{g zE+W46Mc?^@eKSemZhbyepT1-!x3zYrJ|}(jSYMnolWRLjXmnD*Eo>fEbeN{$)T5W>- z*ZoRYn*-TdD~R(~xLmK0qD$5hYr@u0Kz$zq@1fNY=Py;iIdu=@|-{Dm_drcV3;xAL9Po~M+rUzD3#Y{7?e<-K=Z7= zkp06*>8X=FgfZY@=T>sBsq%UHd`XcxuyRG}q?}8N3Ie8#Ws};U)<69-Q8YMFDSK40oZRc_Jf`|t zock?ZC^$#uzD!J2;mdqx=45tlA@|~;J{2u58+iB~ z00VD;SNNUyYs6l#{`*)epKXqRoWJ z&i~a*sKohSf(M5Y0Kb2n2%QI9`+vbiYEGg0iO+w@H}`h;i>PRzJ|d9)-!OSzxk~ko_xXN>N<7p@1hW4-CQ@^HUj5W|`!7*ZLw!Ub z`+s2aymFQ5``XGYlMK6kor%2#iwDeCk&-*c++>7KiuduQFczpcCXZ|Az5 z>;As(caQ)5Xa0<*pW*Lgo_>7a%zFCq82|5{!iVCX!iVCX!iVBn{_+{j@|S;u5YJ^iTu3YS;Nu7CL)$?54wv;4FC>GtQBUw--d?p->>7;<|0QT-Jzui$R| zFV6UG-*A=Hgq&pcQw~_Hr1RyG4_7oUsq?jW<-rYs=%cWnhq(p7Sl;#N=Wa z9)98AU{~wh?9G&TX=!oeaNmJv_F!@`45{X$SGMmO>!3r7p#%tmwl~8?)qa==jF{6X z8T#k0#@ZVqJGS_5TuO-pS1!alo5FjZQ09U_$?*H{zN;ume6zH~Du4L?`|`Xv{Lebm z+8BmZ;}L&A+AueR(15d<`D|(5dm7KY$%vh!#`?dOlYl`J`sS1@`%`0~bEDP9M+N zG6s8O*b8HFDP*~E=gys;)_U0H?0kF+EdCGPeOs=lQOXu$tO0+Z3Wr0b-9dJdOKc3o zl!hF6K2fs%fv`VkY{PlEp_af?>lEt?c22-lS|oRj5Xt5 zzn3&TOC-ylh9u}Dp~%i{rjGvs@~ekmIJEz1miD!))1w33tVd*Huv5*N@o#vBz=uMX z7!t^mQ0VMbw6|3vpdk@A*8kS&lRLI;W<6(5y}9%8t*l36Q??kx3;uAx-+Y8W;3?}3 zwx0@1u+tC)B{Sx~<_>kp1}K5?`Z04Z~XN9IZhxNBKiO8+SJA4Pr(!% z*)@txNy+F!l^bnSVL17POAv4su4bz>a1(nW0>cnA)*G+F32(fqD&AZjZ>+MWCXtCE zZfX6${`%|BKmVLIByzffnSof2T|bJ%n3DN#UH2_qcaG!wI{g26_4sI8g{#F6VkFGg*Tcol!Q#3g+#iIygssQI z!`~UZKWiV{6KkmAKH;aI#7u{hf5@6nl0@7ti<9aEDNNc0^kZ2cDbw*h|2=yuFB14; z?le9H$-nVAyR<#nH~r_z@1Kd54Fv0Uo9_>?j=r2Tz5#=sYLoy$V3XGpqy#1cBjz-& zU{>Tse!qOoRf=-`Lr;EQzJFk5)n;dKK9;xM5C1FEDJYEL5&xAbcsXuY2CeHHUggjg z%+Bh9rE@R3N>KuYK0xS9aLP)W1Kk%QPCw_tV5b`I_^(XCb1~8!u;!J_S%E8ZKnrz zxTPJz&i5j);G18v3rhXVJ706hKlH2N_4)_wK{AuD3q#f?$SH6I^N-on&1Db3fha!9 zNjt4)@OG@YIRM)nXikI0k8I9_Qj{&mSOflmomj_WcB>cs0sG|cht3>)#5jN0+5mRg z7XVT?1uJR0e>j?UzNiy}ood#GKah{xb(ZxmW(x2mQ%X4gY_HD8p9N4*5(A!tE^Z32 zXTH#`3D3$&QfP>>#TaYGKSG`ilignMhgsPFNdMXAw<0Hwf|3}Ghe*TTRkV9Q&w&iL@AR;&ME1aZ4BijW_1>R{puLx)h1G$cizc7X z3h#O}x}g_Z#67tF0LPqTQ8E;=E(779H5VZ}<90>Bx|J3<=X4U|Jl~#wnR_z^9sYRX z6;A9NikNeLU=G)ON?L*?Z2@>VuJhgdrvsdl8)B9{Xy9o$>%>u*0_0;^v@C~9G_=Vi zoczKi2)GItCF4QsYmt)kJBgX~aJb|{cvfZ2-VZvmSlI@(TKd=ZM2)e3<2*<uAL5Q%WREV!awC zwFy!I_XpuFp-o;1Shq2`82-=q`PvKl&;BmdiJNi(g8*&|mUadk57=P95E}KNV-|Uf z)&@)?#zxB0n z#o(&fhC{Cc+$G24Dgm;BWL^y3oX>icwvr+Ao1V8(L^(gJM&{!w*0j{*=^L@y1yCy`=vC6bI z20PVw#6K_B@BHP6{37$ur$k5l$nnEU=BywsG}aj;UnNL6>shhql6De$l^uS5nkZY0 z;RSzK4kYaSm7TA#;~!7?LtAoQp16COoeelmI~29HIwyc+KMFbDZ? z3gqHRrj+4*JM0&q#b+Tg!qx`1Ij}ES(a*(6Lx_Bd$)#%>V|cOs0fr^*L1Z^9xA-&Q z567SJno|5(0EQtv2OYPo*)v~g*UTYXFu54)RO1o<`aRfRE70c;D?hSrV)^&uR9l{u z0K+g$o`IfZR%u!1p+%hah-}IhV|c_LPI%!rYv2-u6R*;P#K_8^R~fzn$ltFKabx|& znuHc{)&tica>&E1M`UBLQ;kRb0dms|%RgS$fBny%e0Wx|(aYbDfY-T42RhhE5!oVc ztNknir-`a^1wx4v#KzaOJHP*4_t zGh*o2S1x`Kh`3RI@Zve{%@}kTxbz8?i3|)w&;WC|<`XA%al0NKjw9p@GEt75MrWS% zoqT9{3ifrHzy8B=hSM?jK{+;*))sLy9OVR;1# z$|EB!G=ol4oJDoy^z@@1VW(vcqE1^%#LbjnpRl|F1?7>E7Mek)DbAuga(envkFe9S z22rOiCE{kvuTNNBfr9eLFvUSsNB-C8M?Jzq%Wn4gpNN|&zdm7k1q#X|!(;rLO>q|0 zk<-(UdW4;p&GMJe5e4Ouk>#J|FWR;0|-Yc1b z&M3Gon;=!trBAFWWFmgEb8UyOuhiYmK`4%d+1u4omY*zLA1}>Il;*`@h)h&s^xwD~ zYj1#_5cpYn5c?OdS+Bj6EXfUhct)8E0vyJL7-%+cmT0Yo>=WkyVqWHwfBs*{H;3S&3|Dg-ukKL>`-f&cJw8QLL}sno@81Q`JP= zSU)_9xbn8-d3a~FOU4l=7J_-^&B$`NP%*u*1FpP{X&Nyx@VcjSoq% z(~yWc>xV;7z|MN`Hp^LL$LxA!H>|UQTmEqT*_7|%EP#TN7^5S@u=v?C-~OJ?=DI3L z3JoDiCW>>BN>1h^=JZ6!4&<*DICI_d2mSVD-(mDufP#`3oo!8RjdiTx!3`so#d)kp zWOKMg!$isY<&D4iI)fN<_kuBoJ`Qd0YFny78Vum7aoIgzV!&A~h>q^QG&niZ6zu%Doe@K}c^=+s$ z#vgXRCArbzf&LU^xDZjC8+~weM8ur+V;F)4j(_5{<+L*&jPRcAm|TvtWN4Ek%kRgq zYZ7(=oDoCEzC=tzO8ytO@^8kV@5=b{QS}tCtRyxthig7?2@Xzs;lrK|NU|V=VW^{_ zpwPxF`=FdMOUYkTAg9MgS1vz$aQ)f+W}i-(5}>9)6R$FzBW!#~L3w0o;#HJ5 z<&mL@SDCH^s3|ZGoGa)Nc3M^mP*b3ZSDDV?GCriBJTf%#D$|t!H3i0ja|Qnk(LUw3 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/normal-texture.tga b/src/Magnum/Shaders/Test/TestFiles/normal-texture.tga new file mode 100644 index 0000000000000000000000000000000000000000..d0fb330e7444b4dfb1f1970f880500e2d25b996e GIT binary patch literal 49170 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�gKx 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/TestFiles/specular-texture.tga b/src/Magnum/Shaders/Test/TestFiles/specular-texture.tga new file mode 100644 index 0000000000000000000000000000000000000000..ee1d79c38c01671e7717e6ecb523f394560f9c89 GIT binary patch literal 49170 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 CU8bD? literal 0 HcmV?d00001 diff --git a/src/Magnum/Shaders/Test/configure.h.cmake b/src/Magnum/Shaders/Test/configure.h.cmake new file mode 100644 index 000000000..5a4b889b9 --- /dev/null +++ b/src/Magnum/Shaders/Test/configure.h.cmake @@ -0,0 +1,28 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#cmakedefine ANYIMAGEIMPORTER_PLUGIN_FILENAME "${ANYIMAGEIMPORTER_PLUGIN_FILENAME}" +#cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}" +#define SHADERS_TEST_DIR "${SHADERS_TEST_DIR}"