Reflector::Reflector(Object3D* parent, SceneGraph::DrawableGroup3D* group): Object3D(parent), SceneGraph::Drawable3D(*this, group) { CubeMapResourceManager& resourceManager = CubeMapResourceManager::instance(); /* Sphere mesh */ if(!(_sphere = resourceManager.get<GL::Mesh>("sphere"))) { Trade::MeshData3D sphereData = Primitives::uvSphereSolid(16, 32, Primitives::UVSphereTextureCoords::Generate); GL::Buffer* buffer = new GL::Buffer; buffer->setData(MeshTools::interleave(sphereData.positions(0), sphereData.textureCoords2D(0)), GL::BufferUsage::StaticDraw); Containers::Array<char> indexData; MeshIndexType indexType; UnsignedInt indexStart, indexEnd; std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(sphereData.indices()); GL::Buffer* indexBuffer = new GL::Buffer; indexBuffer->setData(indexData, GL::BufferUsage::StaticDraw); GL::Mesh* mesh = new GL::Mesh; mesh->setPrimitive(sphereData.primitive()) .setCount(sphereData.indices().size()) .addVertexBuffer(*buffer, 0, ReflectorShader::Position{}, ReflectorShader::TextureCoords{}) .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); resourceManager.set("sphere-buffer", buffer, ResourceDataState::Final, ResourcePolicy::Resident) .set("sphere-index-buffer", indexBuffer, ResourceDataState::Final, ResourcePolicy::Resident) .set(_sphere.key(), mesh, ResourceDataState::Final, ResourcePolicy::Resident); } /* Tarnish texture */ if(!(_tarnishTexture = resourceManager.get<GL::Texture2D>("tarnish-texture"))) { Resource<Trade::AbstractImporter> importer = resourceManager.get<Trade::AbstractImporter>("jpeg-importer"); Utility::Resource rs("data"); importer->openData(rs.getRaw("tarnish.jpg")); Containers::Optional<Trade::ImageData2D> image = importer->image2D(0); CORRADE_INTERNAL_ASSERT(image); auto texture = new GL::Texture2D; texture->setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Linear) .setMinificationFilter(GL::SamplerFilter::Linear, GL::SamplerMipmap::Linear) .setStorage(Math::log2(image->size().min())+1, GL::TextureFormat::RGB8, image->size()) .setSubImage(0, {}, *image) .generateMipmap(); resourceManager.set<GL::Texture2D>(_tarnishTexture.key(), texture, ResourceDataState::Final, ResourcePolicy::Resident); } /* Reflector shader */ if(!(_shader = resourceManager.get<GL::AbstractShaderProgram, ReflectorShader>("reflector-shader"))) resourceManager.set<GL::AbstractShaderProgram>(_shader.key(), new ReflectorShader, ResourceDataState::Final, ResourcePolicy::Resident); /* Texture (created in CubeMap class) */ _texture = resourceManager.get<GL::CubeMapTexture>("texture"); }
AreaLightsExample::AreaLightsExample(const Arguments& arguments): Platform::Application{arguments, NoCreate} { /* Try to create multisampled context, but be nice and fall back if not available. Enable only 2x MSAA if we have enough DPI. */ { const Vector2 dpiScaling = this->dpiScaling({}); Configuration conf; conf.setTitle("Magnum Area Lights Example") .setSize(conf.size(), dpiScaling); GLConfiguration glConf; glConf.setSampleCount(dpiScaling.max() < 2.0f ? 8 : 2); if(!tryCreate(conf, glConf)) create(conf, glConf.setSampleCount(0)); } /* Make it all DARK, eanble face culling so one-sided lights are properly visualized */ GL::Renderer::enable(GL::Renderer::Feature::FaceCulling); GL::Renderer::setClearColor(0x000000_rgbf); /* Setup the plane mesh, which will be used for both the floor and light visualization */ _vertices = GL::Buffer{}; _vertices.setData(LightVertices, GL::BufferUsage::StaticDraw); _plane = GL::Mesh{}; _plane.setPrimitive(GL::MeshPrimitive::TriangleFan) .addVertexBuffer(_vertices, 0, Shaders::Generic3D::Position{}, Shaders::Generic3D::Normal{}) .setCount(Containers::arraySize(LightVertices)); /* Setup project and floor plane tranformation matrix */ _projection = Matrix4::perspectiveProjection(60.0_degf, 4.0f/3.0f, 0.1f, 50.0f); _transformation = Matrix4::rotationX(-90.0_degf)*Matrix4::scaling(Vector3{25.0f}); /* Load LTC matrix and BRDF textures */ PluginManager::Manager<Trade::AbstractImporter> manager; Containers::Pointer<Trade::AbstractImporter> importer = manager.loadAndInstantiate("DdsImporter"); if(!importer) std::exit(1); const Utility::Resource rs{"arealights-data"}; if(!importer->openData(rs.getRaw("ltc_amp.dds"))) std::exit(2); /* Set texture data and parameters */ Containers::Optional<Trade::ImageData2D> image = importer->image2D(0); CORRADE_INTERNAL_ASSERT(image); _ltcAmp = GL::Texture2D{}; _ltcAmp.setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Linear) .setMinificationFilter(GL::SamplerFilter::Linear) .setStorage(1, GL::TextureFormat::RG32F, image->size()) .setSubImage(0, {}, *image); if(!importer->openData(rs.getRaw("ltc_mat.dds"))) std::exit(2); /* Set texture data and parameters */ image = importer->image2D(0); CORRADE_INTERNAL_ASSERT(image); _ltcMat = GL::Texture2D{}; _ltcMat.setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Linear) .setMinificationFilter(GL::SamplerFilter::Linear) .setStorage(1, GL::TextureFormat::RGBA32F, image->size()) .setSubImage(0, {}, *image); /* Compile shaders */ _areaLightShader = AreaLightShader{}; _flatShader = Shaders::Flat3D{}; /* Create the UI */ _ui.emplace(Vector2{windowSize()}/dpiScaling(), windowSize(), framebufferSize(), Ui::mcssDarkStyleConfiguration(), "ƒ₀"); Interconnect::connect(*_ui, &Ui::UserInterface::inputWidgetFocused, *this, &AreaLightsExample::startTextInput); Interconnect::connect(*_ui, &Ui::UserInterface::inputWidgetBlurred, *this, &AreaLightsExample::stopTextInput); /* Base UI plane */ _baseUiPlane.emplace(*_ui); Interconnect::connect(_baseUiPlane->metalness, &Ui::Input::valueChanged, *this, &AreaLightsExample::enableApplyButton); Interconnect::connect(_baseUiPlane->roughness, &Ui::Input::valueChanged, *this, &AreaLightsExample::enableApplyButton); Interconnect::connect(_baseUiPlane->f0, &Ui::Input::valueChanged, *this, &AreaLightsExample::enableApplyButton); Interconnect::connect(_baseUiPlane->apply, &Ui::Button::tapped, *this, &AreaLightsExample::apply); Interconnect::connect(_baseUiPlane->reset, &Ui::Button::tapped, *this, &AreaLightsExample::reset); /* Apply the default values */ apply(); }
CubeMap::CubeMap(const std::string& prefix, Object3D* parent, SceneGraph::DrawableGroup3D* group): Object3D(parent), SceneGraph::Drawable3D(*this, group) { CubeMapResourceManager& resourceManager = CubeMapResourceManager::instance(); /* Cube mesh */ if(!(_cube = resourceManager.get<GL::Mesh>("cube"))) { Trade::MeshData3D cubeData = Primitives::cubeSolid(); MeshTools::flipFaceWinding(cubeData.indices()); GL::Buffer* buffer = new GL::Buffer; buffer->setData(MeshTools::interleave(cubeData.positions(0)), GL::BufferUsage::StaticDraw); Containers::Array<char> indexData; MeshIndexType indexType; UnsignedInt indexStart, indexEnd; std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(cubeData.indices()); GL::Buffer* indexBuffer = new GL::Buffer; indexBuffer->setData(indexData, GL::BufferUsage::StaticDraw); GL::Mesh* mesh = new GL::Mesh; mesh->setPrimitive(cubeData.primitive()) .setCount(cubeData.indices().size()) .addVertexBuffer(*buffer, 0, CubeMapShader::Position{}) .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); resourceManager.set("cube-buffer", buffer, ResourceDataState::Final, ResourcePolicy::Resident) .set("cube-index-buffer", indexBuffer, ResourceDataState::Final, ResourcePolicy::Resident) .set(_cube.key(), mesh, ResourceDataState::Final, ResourcePolicy::Resident); } /* Cube map texture */ if(!(_texture = resourceManager.get<GL::CubeMapTexture>("texture"))) { GL::CubeMapTexture* cubeMap = new GL::CubeMapTexture; cubeMap->setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Linear) .setMinificationFilter(GL::SamplerFilter::Linear, GL::SamplerMipmap::Linear); Resource<Trade::AbstractImporter> importer = resourceManager.get<Trade::AbstractImporter>("jpeg-importer"); /* Configure texture storage using size of first image */ importer->openFile(prefix + "+x.jpg"); Containers::Optional<Trade::ImageData2D> image = importer->image2D(0); CORRADE_INTERNAL_ASSERT(image); Vector2i size = image->size(); cubeMap->setStorage(Math::log2(size.min())+1, GL::TextureFormat::RGB8, size) .setSubImage(GL::CubeMapCoordinate::PositiveX, 0, {}, *image); importer->openFile(prefix + "-x.jpg"); CORRADE_INTERNAL_ASSERT_OUTPUT(image = importer->image2D(0)); cubeMap->setSubImage(GL::CubeMapCoordinate::NegativeX, 0, {}, *image); importer->openFile(prefix + "+y.jpg"); CORRADE_INTERNAL_ASSERT_OUTPUT(image = importer->image2D(0)); cubeMap->setSubImage(GL::CubeMapCoordinate::PositiveY, 0, {}, *image); importer->openFile(prefix + "-y.jpg"); CORRADE_INTERNAL_ASSERT_OUTPUT(image = importer->image2D(0)); cubeMap->setSubImage(GL::CubeMapCoordinate::NegativeY, 0, {}, *image); importer->openFile(prefix + "+z.jpg"); CORRADE_INTERNAL_ASSERT_OUTPUT(image = importer->image2D(0)); cubeMap->setSubImage(GL::CubeMapCoordinate::PositiveZ, 0, {}, *image); importer->openFile(prefix + "-z.jpg"); CORRADE_INTERNAL_ASSERT_OUTPUT(image = importer->image2D(0)); cubeMap->setSubImage(GL::CubeMapCoordinate::NegativeZ, 0, {}, *image); cubeMap->generateMipmap(); resourceManager.set(_texture.key(), cubeMap, ResourceDataState::Final, ResourcePolicy::Manual); } /* Shader */ if(!(_shader = resourceManager.get<GL::AbstractShaderProgram, CubeMapShader>("shader"))) resourceManager.set<GL::AbstractShaderProgram>(_shader.key(), new CubeMapShader, ResourceDataState::Final, ResourcePolicy::Manual); }