void FramebufferGLTest::attachRenderbufferMultisample() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::framebuffer_object>()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) CORRADE_SKIP("Required extension is not available."); #endif Renderbuffer color; #ifndef MAGNUM_TARGET_GLES2 color.setStorageMultisample(Renderbuffer::maxSamples(), RenderbufferFormat::RGBA8, Vector2i(128)); #else color.setStorageMultisample(Renderbuffer::maxSamples(), RenderbufferFormat::RGBA4, Vector2i(128)); #endif #ifdef MAGNUM_TARGET_GLES2 MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::packed_depth_stencil); #endif Renderbuffer depthStencil; depthStencil.setStorageMultisample(Renderbuffer::maxSamples(), RenderbufferFormat::Depth24Stencil8, Vector2i(128)); Framebuffer framebuffer({{}, Vector2i(128)}); framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), color) #ifndef MAGNUM_TARGET_GLES2 .attachRenderbuffer(Framebuffer::BufferAttachment::DepthStencil, depthStencil); #else .attachRenderbuffer(Framebuffer::BufferAttachment::Depth, depthStencil)
void MagnumFontConverterTest::exportFont() { /* Remove previously created files */ Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf")); Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga")); /* Open font */ FreeTypeFont font; CORRADE_VERIFY(font.openFile(Utility::Directory::join(FREETYPEFONT_TEST_DIR, "Oxygen.ttf"), 16.0f)); /* Create fake cache */ MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); GlyphCache cache(TextureFormat::R8, Vector2i(1536), Vector2i(256), Vector2i(24)); cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}}); cache.insert(font.glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}}); /* Convert the file */ MagnumFontConverter converter; converter.exportFontToFile(font, cache, Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font"), "Wave"); /* Verify font parameters */ /** @todo This might behave differently elsewhere due to unspecified order of glyphs in cache */ CORRADE_COMPARE_AS(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf"), Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), TestSuite::Compare::File); /* Verify font image, no need to test image contents, as the image is garbage anyway */ Trade::TgaImporter importer; CORRADE_VERIFY(importer.openFile(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga"))); std::optional<Trade::ImageData2D> image = importer.image2D(0); CORRADE_VERIFY(image); CORRADE_COMPARE(image->size(), Vector2i(256)); CORRADE_COMPARE(image->format(), ImageFormat::Red); CORRADE_COMPARE(image->type(), ImageType::UnsignedByte); }
GlyphCache::GlyphCache(const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding): _size(originalSize), _padding(padding) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); #endif /** @todo Is there any better way to select proper sized/unsized format on ES2? */ #ifndef MAGNUM_TARGET_GLES2 const TextureFormat internalFormat = TextureFormat::R8; #else TextureFormat internalFormat; if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>()) { internalFormat = Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_storage>() ? TextureFormat::R8 : TextureFormat::Red; } else internalFormat = TextureFormat::Luminance; #endif initialize(internalFormat, size); }
CubeMapExample::CubeMapExample(const Arguments& arguments): Platform::Application(arguments, Configuration().setTitle("Magnum Cube Map Example")) { MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::invalidate_subdata); Renderer::setFeature(Renderer::Feature::DepthTest, true); Renderer::setFeature(Renderer::Feature::FaceCulling, true); /* Set up perspective camera */ (cameraObject = new Object3D(&scene)) ->translate(Vector3::zAxis(3.0f)); (camera = new SceneGraph::Camera3D(*cameraObject)) ->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend) .setPerspective(Deg(55.0f), 1.0f, 0.001f, 100.0f) .setViewport(defaultFramebuffer.viewport().size()); /* Load TGA importer plugin */ PluginManager::Manager<Trade::AbstractImporter> manager(MAGNUM_PLUGINS_IMPORTER_DIR); if(!(manager.load("JpegImporter") & PluginManager::LoadState::Loaded)) std::exit(1); resourceManager.set<Trade::AbstractImporter>("jpeg-importer", manager.instance("JpegImporter").release(), ResourceDataState::Final, ResourcePolicy::Manual); /* Add objects to scene */ (new CubeMap(arguments.argc == 2 ? arguments.argv[1] : "", &scene, &drawables)) ->scale(Vector3(20.0f)); (new Reflector(&scene, &drawables)) ->scale(Vector3(0.5f)) .translate(Vector3::xAxis(-0.5f)); (new Reflector(&scene, &drawables)) ->scale(Vector3(0.3f)) .rotate(Deg(37.0f), Vector3::xAxis()) .translate(Vector3::xAxis(0.3f)); /* We don't need the importer anymore */ resourceManager.free<Trade::AbstractImporter>(); }
MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { #ifndef MAGNUM_TARGET_GLES if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4); #elif defined(MAGNUM_TARGET_GLES2) if(flags & Flag::Wireframe) MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives); #endif Utility::Resource rs("MagnumShaders"); #ifndef MAGNUM_TARGET_GLES const Version v = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL210}); #else const Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); #endif Shader vert(v, Shader::Type::Vertex); vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("MeshVisualizer.vert")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); vert.compile(); attachShader(vert); #ifndef MAGNUM_TARGET_GLES if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { Shader geom(v, Shader::Type::Geometry); geom.addSource(rs.get("compatibility.glsl")) .addSource(rs.get("MeshVisualizer.geom")); CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile()); geom.compile(); attachShader(geom); } #endif Shader frag(v, Shader::Type::Fragment); frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("MeshVisualizer.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); frag.compile(); attachShader(frag); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || Context::current()->version() == Version::GL210) #else if(!Context::current()->isVersionSupported(Version::GLES300)) #endif { bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isVersionSupported(Version::GL310)) #endif { bindAttributeLocation(VertexIndex::Location, "vertexIndex"); } } CORRADE_INTERNAL_ASSERT_OUTPUT(link()); link(); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) #endif { transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); colorUniform = uniformLocation("color"); if(flags & Flag::Wireframe) { wireframeColorUniform = uniformLocation("wireframeColor"); wireframeWidthUniform = uniformLocation("wireframeWidth"); smoothnessUniform = uniformLocation("smoothness"); if(!(flags & Flag::NoGeometryShader)) viewportSizeUniform = uniformLocation("viewportSize"); } } /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES setColor(Color3<>(1.0f)); if(flags & Flag::Wireframe) { setWireframeColor(Color3<>(0.0f)); setWireframeWidth(1.0f); setSmoothness(2.0f); } #endif }
MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { #ifndef MAGNUM_TARGET_GLES if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4); } #elif defined(MAGNUM_TARGET_GLES2) if(flags & Flag::Wireframe) MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives); #endif Utility::Resource rs("MagnumShaders"); #ifndef MAGNUM_TARGET_GLES const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210}); CORRADE_INTERNAL_ASSERT_OUTPUT(flags & Flag::NoGeometryShader || version >= Version::GL320); #else const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); #endif Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment); vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") #ifdef MAGNUM_TARGET_WEBGL .addSource("#define SUBSCRIPTING_WORKAROUND\n") #elif defined(MAGNUM_TARGET_GLES2) .addSource(Context::current()->detectedDriver() & Context::DetectedDriver::ProbablyAngle ? "#define SUBSCRIPTING_WORKAROUND\n" : "") #endif .addSource(rs.get("generic.glsl")) .addSource(rs.get("MeshVisualizer.vert")); frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(rs.get("MeshVisualizer.frag")); #ifndef MAGNUM_TARGET_GLES std::optional<Shader> geom; if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry); geom->addSource(rs.get("MeshVisualizer.geom")); } #endif #ifndef MAGNUM_TARGET_GLES if(geom) Shader::compile({vert, *geom, frag}); else #endif Shader::compile({vert, frag}); attachShaders({vert, frag}); #ifndef MAGNUM_TARGET_GLES if(geom) attachShader(*geom); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version)) #else if(!Context::current()->isVersionSupported(Version::GLES300)) #endif { bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isVersionSupported(Version::GL310)) #endif { bindAttributeLocation(VertexIndex::Location, "vertexIndex"); } } CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version)) #endif { transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); colorUniform = uniformLocation("color"); if(flags & Flag::Wireframe) { wireframeColorUniform = uniformLocation("wireframeColor"); wireframeWidthUniform = uniformLocation("wireframeWidth"); smoothnessUniform = uniformLocation("smoothness"); if(!(flags & Flag::NoGeometryShader)) viewportSizeUniform = uniformLocation("viewportSize"); } } /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES setColor(Color3(1.0f)); if(flags & Flag::Wireframe) { setWireframeColor(Color3(0.0f)); setWireframeWidth(1.0f); setSmoothness(2.0f); } #endif }
Camera::Camera(Object3D* parent): Object3D(parent), SceneGraph::Camera3D(*this), _blurred(true), multisampleFramebuffer({{}, defaultFramebuffer.viewport().size()/8}), framebuffer1(multisampleFramebuffer.viewport()), framebuffer2(multisampleFramebuffer.viewport()), blurShaderHorizontal(Shaders::Blur::Direction::Horizontal), blurShaderVertical(Shaders::Blur::Direction::Vertical) { /* Get full screen triangle */ fullScreenTriangleBuffer = SceneResourceManager::instance().get<Buffer>("fullscreentriangle"); fullScreenTriangle = SceneResourceManager::instance().get<Mesh>("fullscreentriangle"); setPerspective(Deg(35.0f), 1.0f, 0.001f, 100.0f); setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend); SceneGraph::Camera3D::setViewport(defaultFramebuffer.viewport().size()); /* Decide about multisampling on ES2 */ #ifdef MAGNUM_TARGET_GLES2 if(Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() || Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) { _multisample = true; } else { Debug() << "Neither" << Extensions::GL::ANGLE::framebuffer_multisample::string() << "nor" << Extensions::GL::NV::framebuffer_multisample::string() << "is supported, expect ugly blur :-)"; _multisample = false; } #else _multisample = true; #endif /* Configure depth buffer */ RenderbufferFormat depthFormat = RenderbufferFormat::DepthComponent24; #ifdef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported<Extensions::GL::OES::depth24>()) { Debug() << Extensions::GL::OES::depth24::string() << "not supported, fallback to 16bit depth buffer"; depthFormat = RenderbufferFormat::DepthComponent16; } #endif depth.setStorage(depthFormat, multisampleFramebuffer.viewport().size()); framebuffer1.attachRenderbuffer(Framebuffer::BufferAttachment::Depth, depth); framebuffer2.attachRenderbuffer(Framebuffer::BufferAttachment::Depth, depth); /* Configure multisample framebuffer */ if(_multisample) { #ifdef MAGNUM_TARGET_GLES MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::rgb8_rgba8); #endif multisampleColor.setStorageMultisample(16, RenderbufferFormat::RGBA8, multisampleFramebuffer.viewport().size()); multsampleDepth.setStorageMultisample(16, depthFormat, multisampleFramebuffer.viewport().size()); multisampleFramebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), multisampleColor); multisampleFramebuffer.attachRenderbuffer(Framebuffer::BufferAttachment::Depth, multsampleDepth); CORRADE_INTERNAL_ASSERT(multisampleFramebuffer.checkStatus(FramebufferTarget::ReadDraw) == Framebuffer::Status::Complete); } /* Configure textures */ TextureFormat internalFormat = TextureFormat::RGB8; #ifdef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::OES::required_internalformat>()) internalFormat = TextureFormat::RGB; #endif texture1.setStorage(1, internalFormat, multisampleFramebuffer.viewport().size()) .setMagnificationFilter(Sampler::Filter::Linear) .setMinificationFilter(Sampler::Filter::Nearest) .setWrapping(Sampler::Wrapping::ClampToEdge); texture2.setStorage(1, internalFormat, multisampleFramebuffer.viewport().size()) .setMagnificationFilter(Sampler::Filter::Linear) .setMinificationFilter(Sampler::Filter::Nearest) .setWrapping(Sampler::Wrapping::ClampToEdge); framebuffer1.attachTexture(Framebuffer::ColorAttachment(0), texture1, 0); framebuffer2.attachTexture(Framebuffer::ColorAttachment(0), texture2, 0); /* Verify that everything is sane */ CORRADE_INTERNAL_ASSERT(framebuffer1.checkStatus(FramebufferTarget::ReadDraw) == Framebuffer::Status::Complete); CORRADE_INTERNAL_ASSERT(framebuffer2.checkStatus(FramebufferTarget::ReadDraw) == Framebuffer::Status::Complete); }
namespace Magnum { namespace Text { namespace Test { class MagnumFontConverterGLTest: public Magnum::Test::AbstractOpenGLTester { public: explicit MagnumFontConverterGLTest(); void exportFont(); }; MagnumFontConverterGLTest::MagnumFontConverterGLTest() { addTests({&MagnumFontConverterGLTest::exportFont}); } void MagnumFontConverterGLTest::exportFont() { /* Remove previously created files */ Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf")); Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga")); /* Fake font with fake cache */ class FakeFont: public Text::AbstractFont { public: explicit FakeFont(): _opened(false) {} private: void doClose() { _opened = false; } bool doIsOpened() const { return _opened; } std::pair<Float, Float> doOpenFile(const std::string&, Float) { _opened = true; return {16.0f, 39.7333f}; } Features doFeatures() const { return {}; } std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; } UnsignedInt doGlyphId(const char32_t character) { switch(character) { case 'W': return 2; case 'e': return 1; } return 0; } Vector2 doGlyphAdvance(const UnsignedInt glyph) { switch(glyph) { case 0: return {8, 0}; case 1: return {12, 0}; case 2: return {23, 0}; } CORRADE_ASSERT_UNREACHABLE(); } bool _opened; } font; font.openFile({}, {}); /* Create fake cache */ MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); GlyphCache cache(TextureFormat::R8, Vector2i(1536), Vector2i(256), Vector2i(24)); cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}}); cache.insert(font.glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}}); /* Convert the file */ MagnumFontConverter converter; converter.exportFontToFile(font, cache, Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font"), "Wave"); /* Verify font parameters */ /** @todo This might behave differently elsewhere due to unspecified order of glyphs in cache */ CORRADE_COMPARE_AS(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf"), Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), TestSuite::Compare::File); /* Verify font image, no need to test image contents, as the image is garbage anyway */ Trade::TgaImporter importer; CORRADE_VERIFY(importer.openFile(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga"))); std::optional<Trade::ImageData2D> image = importer.image2D(0); CORRADE_VERIFY(image); CORRADE_COMPARE(image->size(), Vector2i(256)); CORRADE_COMPARE(image->format(), ColorFormat::Red); CORRADE_COMPARE(image->type(), ColorType::UnsignedByte); } }}}