diff --git a/examples/actor_animation/Main.cc b/examples/actor_animation/Main.cc index 10e18d0da..c204dc88e 100644 --- a/examples/actor_animation/Main.cc +++ b/examples/actor_animation/Main.cc @@ -156,10 +156,11 @@ void buildScene(ScenePtr _scene, std::vector &_visuals, ////////////////////////////////////////////////// CameraPtr createCamera(const std::string &_engineName, + const std::map& _params, std::vector &_visuals, common::SkeletonPtr &_skel) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -187,6 +188,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -201,7 +208,14 @@ int main(int _argc, char** _argv) std::cout << "Starting engine [" << engineName << "]" << std::endl; try { - CameraPtr camera = createCamera(engineName, visuals, skel); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params, visuals, skel); if (camera) { cameras.push_back(camera); diff --git a/examples/camera_tracking/Main.cc b/examples/camera_tracking/Main.cc index 2df2c5862..6aee947af 100644 --- a/examples/camera_tracking/Main.cc +++ b/examples/camera_tracking/Main.cc @@ -95,10 +95,11 @@ NodePtr createMainNode(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -126,6 +127,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -138,7 +145,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/custom_scene_viewer/ManualSceneDemo.cc b/examples/custom_scene_viewer/ManualSceneDemo.cc index 0b4c122bc..2f2bdeb57 100644 --- a/examples/custom_scene_viewer/ManualSceneDemo.cc +++ b/examples/custom_scene_viewer/ManualSceneDemo.cc @@ -91,9 +91,10 @@ unsigned int ManualSceneDemo::CameraCount() const } ////////////////////////////////////////////////// -void ManualSceneDemo::AddCamera(const std::string &_engineName) +void ManualSceneDemo::AddCamera(const std::string &_engineName, + const std::map& _params) { - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -191,6 +192,19 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + + std::map params; + if (ogreEngineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + common::Console::SetVerbosity(4); //! [add scenes] ManualSceneDemoPtr sceneDemo(new ManualSceneDemo); @@ -208,7 +222,7 @@ int main(int _argc, char** _argv) sceneDemo->AddScene(SceneBuilderPtr(new ShadowSceneBuilder(4))); sceneDemo->AddScene(SceneBuilderPtr(new ShadowSceneBuilder(5))); //! [add scenes] - sceneDemo->AddCamera(ogreEngineName); + sceneDemo->AddCamera(ogreEngineName, params); sceneDemo->AddCamera("optix"); sceneDemo->Run(); return 0; diff --git a/examples/custom_scene_viewer/ManualSceneDemo.hh b/examples/custom_scene_viewer/ManualSceneDemo.hh index 57942d90c..99a316864 100644 --- a/examples/custom_scene_viewer/ManualSceneDemo.hh +++ b/examples/custom_scene_viewer/ManualSceneDemo.hh @@ -17,6 +17,7 @@ #ifndef IGNITION_RENDERING_EXAMPLES_CUSTOM_SCENE_VIEWER_MANUALSCENEDEMO_HH_ #define IGNITION_RENDERING_EXAMPLES_CUSTOM_SCENE_VIEWER_MANUALSCENEDEMO_HH_ +#include #include #include #include "TestTypes.hh" @@ -46,7 +47,8 @@ namespace ignition public: virtual unsigned int CameraCount() const; - public: virtual void AddCamera(const std::string &_engineName); + public: virtual void AddCamera(const std::string &_engineName, + const std::map& _params = {}); public: virtual void PrevCamera(); diff --git a/examples/depth_camera/Main.cc b/examples/depth_camera/Main.cc index 6064a84ac..d0ef5a9d5 100644 --- a/examples/depth_camera/Main.cc +++ b/examples/depth_camera/Main.cc @@ -154,17 +154,18 @@ int main(int _argc, char** _argv) engineName = _argv[1]; } - bool useMetalRenderSystem{false}; - if (_argc > 2 && std::string(_argv[2]).compare("metal") == 0) + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) { - useMetalRenderSystem = true; + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); } common::Console::SetVerbosity(4); try { std::map params; - if (engineName.compare("ogre2") == 0 && useMetalRenderSystem) + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) { params["metal"] = "1"; } diff --git a/examples/heightmap/Main.cc b/examples/heightmap/Main.cc index 027ac1be5..ac7306d3d 100644 --- a/examples/heightmap/Main.cc +++ b/examples/heightmap/Main.cc @@ -192,10 +192,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -227,13 +228,26 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + engineNames.push_back(ogreEngineName); for (auto engineName : engineNames) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/lidar_visual/Main.cc b/examples/lidar_visual/Main.cc index 71e3eebff..7765f45cc 100644 --- a/examples/lidar_visual/Main.cc +++ b/examples/lidar_visual/Main.cc @@ -240,10 +240,11 @@ LidarVisualPtr createLidar(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -271,6 +272,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -284,7 +291,14 @@ int main(int _argc, char** _argv) std::cout << "Starting engine [" << engineName << "]" << std::endl; try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/mesh_viewer/Main.cc b/examples/mesh_viewer/Main.cc index d0d40fa22..dc102dba4 100644 --- a/examples/mesh_viewer/Main.cc +++ b/examples/mesh_viewer/Main.cc @@ -100,10 +100,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -131,6 +132,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -142,7 +149,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/mouse_picking/Main.cc b/examples/mouse_picking/Main.cc index 1d0749b7a..b5fc9c192 100644 --- a/examples/mouse_picking/Main.cc +++ b/examples/mouse_picking/Main.cc @@ -104,10 +104,11 @@ void buildScene(ScenePtr _scene) root->AddChild(camera); } -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -134,6 +135,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -145,7 +152,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/ogre2_demo/Main.cc b/examples/ogre2_demo/Main.cc index e92f2283f..8f942dc2a 100644 --- a/examples/ogre2_demo/Main.cc +++ b/examples/ogre2_demo/Main.cc @@ -274,10 +274,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -316,12 +317,25 @@ int main(int _argc, char** _argv) std::vector engineNames; std::vector cameras; + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + engineNames.push_back("ogre2"); for (auto engineName : engineNames) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/particles_demo/Main.cc b/examples/particles_demo/Main.cc index 0652ccbb1..4a12f32ec 100644 --- a/examples/particles_demo/Main.cc +++ b/examples/particles_demo/Main.cc @@ -136,10 +136,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -167,6 +168,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -177,7 +184,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/render_pass/Main.cc b/examples/render_pass/Main.cc index 1ed9463f8..3a63aa30d 100644 --- a/examples/render_pass/Main.cc +++ b/examples/render_pass/Main.cc @@ -137,10 +137,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -184,6 +185,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -194,7 +201,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/segmentation_camera/Main.cc b/examples/segmentation_camera/Main.cc index d679bf40c..2847b507a 100644 --- a/examples/segmentation_camera/Main.cc +++ b/examples/segmentation_camera/Main.cc @@ -118,10 +118,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -149,10 +150,23 @@ int main(int _argc, char** _argv) engineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { run(camera); diff --git a/examples/simple_demo/Main.cc b/examples/simple_demo/Main.cc index 17279a024..489d9533e 100644 --- a/examples/simple_demo/Main.cc +++ b/examples/simple_demo/Main.cc @@ -186,10 +186,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -217,6 +218,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -228,7 +235,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/thermal_camera/Main.cc b/examples/thermal_camera/Main.cc index f48c23eab..aee8e61d1 100644 --- a/examples/thermal_camera/Main.cc +++ b/examples/thermal_camera/Main.cc @@ -106,10 +106,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -137,6 +138,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -147,7 +154,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/transform_control/Main.cc b/examples/transform_control/Main.cc index e2102ba0d..aef627d4d 100644 --- a/examples/transform_control/Main.cc +++ b/examples/transform_control/Main.cc @@ -89,10 +89,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { ignwarn << "Engine '" << _engineName @@ -120,6 +121,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -131,7 +138,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/examples/view_control/Main.cc b/examples/view_control/Main.cc index 7c2a2070e..478e7ceb4 100644 --- a/examples/view_control/Main.cc +++ b/examples/view_control/Main.cc @@ -135,10 +135,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -166,6 +167,12 @@ int main(int _argc, char** _argv) ogreEngineName = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -176,7 +183,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) cameras.push_back(camera); } diff --git a/examples/visualization_demo/Main.cc b/examples/visualization_demo/Main.cc index b4cfc2f4f..ab709c4a5 100644 --- a/examples/visualization_demo/Main.cc +++ b/examples/visualization_demo/Main.cc @@ -216,10 +216,11 @@ void buildScene(ScenePtr _scene) } ////////////////////////////////////////////////// -CameraPtr createCamera(const std::string &_engineName) +CameraPtr createCamera(const std::string &_engineName, + const std::map& _params) { // create and populate scene - RenderEngine *engine = rendering::engine(_engineName); + RenderEngine *engine = rendering::engine(_engineName, _params); if (!engine) { std::cout << "Engine '" << _engineName @@ -247,6 +248,12 @@ int main(int _argc, char** _argv) engine = _argv[1]; } + GraphicsAPI graphicsApi = GraphicsAPI::OPENGL; + if (_argc > 2) + { + graphicsApi = GraphicsAPIUtils::Set(std::string(_argv[2])); + } + common::Console::SetVerbosity(4); std::vector engineNames; std::vector cameras; @@ -258,7 +265,14 @@ int main(int _argc, char** _argv) { try { - CameraPtr camera = createCamera(engineName); + std::map params; + if (engineName.compare("ogre2") == 0 + && graphicsApi == GraphicsAPI::METAL) + { + params["metal"] = "1"; + } + + CameraPtr camera = createCamera(engineName, params); if (camera) { cameras.push_back(camera); diff --git a/include/ignition/rendering/GraphicsAPI.hh b/include/ignition/rendering/GraphicsAPI.hh new file mode 100644 index 000000000..505e4019d --- /dev/null +++ b/include/ignition/rendering/GraphicsAPI.hh @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef IGNITION_RENDERING_GRAPHICSAPI_HH_ +#define IGNITION_RENDERING_GRAPHICSAPI_HH_ + +#include +#include "ignition/rendering/config.hh" +#include "ignition/rendering/Export.hh" + +namespace ignition +{ + namespace rendering + { + inline namespace IGNITION_RENDERING_VERSION_NAMESPACE { + + /// \brief The graphics API used by the render engine + enum class IGNITION_RENDERING_VISIBLE GraphicsAPI : uint16_t + { + /// \internal + /// \brief Indicator used to create an iterator over the + /// enum. Do not use this. + GRAPHICS_API_BEGIN = 0, + + /// \brief Unknown graphics interface + UNKNOWN = GRAPHICS_API_BEGIN, + + /// \brief OpenGL graphics interface + OPENGL = 1, + + /// \brief Direct3D11 graphics interface + DIRECT3D11 = 2, + + /// \brief Vulkan graphics interface + VULKAN = 3, + + /// \brief Metal graphics interface + METAL = 4, + + /// \internal + /// \brief Indicator used to create an iterator over the + /// enum. Do not use this. + GRAPHICS_API_END + }; + + /// \brief Utils to convert GraphicsAPI to and from strings + class IGNITION_RENDERING_VISIBLE GraphicsAPIUtils + { + /// \brief Convert enum value to string. + /// \param[in] _e Enum value to convert. + /// \return String representation of the enum. An empty string is + /// returned if _e is invalid, or the names for the enum have not been + /// set. + public: static std::string Str(GraphicsAPI _e); + + /// \brief Set an enum from a string. This function requires a valid + /// string, and an array of names for the enum must exist. + /// The string is not case sensitive. + /// \param[in] _str String value to convert to enum value. + /// \return GraphicsAPI enum + public: static GraphicsAPI Set(const std::string &_str); + }; + } + } +} +#endif diff --git a/ogre2/src/Ogre2RenderEngine.cc b/ogre2/src/Ogre2RenderEngine.cc index 6c08bed91..76a2c6bf9 100644 --- a/ogre2/src/Ogre2RenderEngine.cc +++ b/ogre2/src/Ogre2RenderEngine.cc @@ -34,6 +34,7 @@ #include +#include "ignition/rendering/GraphicsAPI.hh" #include "ignition/rendering/RenderEngineManager.hh" #include "ignition/rendering/ogre2/Ogre2Includes.hh" #include "ignition/rendering/ogre2/Ogre2RenderEngine.hh" @@ -52,6 +53,9 @@ class ignition::rendering::Ogre2RenderEnginePrivate public: GLXFBConfig* dummyFBConfigs = nullptr; #endif + /// \brief The graphics API to use + public: ignition::rendering::GraphicsAPI graphicsAPI{GraphicsAPI::OPENGL}; + /// \brief A list of supported fsaa levels public: std::vector fsaaLevels; @@ -302,6 +306,15 @@ bool Ogre2RenderEngine::LoadImpl( if (it != _params.end()) std::istringstream(it->second) >> this->winID; + it = _params.find("metal"); + if (it != _params.end()) + { + bool useMetal; + std::istringstream(it->second) >> useMetal; + if(useMetal) + this->dataPtr->graphicsAPI = GraphicsAPI::METAL; + } + try { this->LoadAttempt(); @@ -339,7 +352,8 @@ bool Ogre2RenderEngine::InitImpl() void Ogre2RenderEngine::LoadAttempt() { this->CreateLogger(); - if (!this->useCurrentGLContext) + if (!this->useCurrentGLContext && + this->dataPtr->graphicsAPI == GraphicsAPI::OPENGL) this->CreateContext(); this->CreateRoot(); this->CreateOverlay(); @@ -489,6 +503,12 @@ void Ogre2RenderEngine::LoadPlugins() p = common::joinPaths(path, "Plugin_ParticleFX"); plugins.push_back(p); + if (this->dataPtr->graphicsAPI == GraphicsAPI::METAL) + { + p = common::joinPaths(path, "RenderSystem_Metal"); + plugins.push_back(p); + } + for (piter = plugins.begin(); piter != plugins.end(); ++piter) { // check if plugin library exists @@ -534,6 +554,11 @@ void Ogre2RenderEngine::CreateRenderSystem() const Ogre::RenderSystemList *rsList; rsList = &(this->ogreRoot->getAvailableRenderers()); + std::string targetRenderSysName("OpenGL 3+ Rendering Subsystem"); + if (this->dataPtr->graphicsAPI == GraphicsAPI::METAL) + { + targetRenderSysName = "Metal Rendering Subsystem"; + } int c = 0; @@ -551,11 +576,11 @@ void Ogre2RenderEngine::CreateRenderSystem() // (it thinks the while loop is empty), so we must put the whole while // statement on one line and add NOLINT at the end so that cpplint doesn't // complain about the line being too long - while (renderSys && renderSys->getName().compare("OpenGL 3+ Rendering Subsystem") != 0); // NOLINT + while (renderSys && renderSys->getName().compare(targetRenderSysName) != 0); // NOLINT if (renderSys == nullptr) { - ignerr << "unable to find OpenGL rendering system. OGRE is probably " + ignerr << "unable to find " << targetRenderSysName << ". OGRE is probably " "installed incorrectly. Double check the OGRE cmake output, " "and make sure OpenGL is enabled." << std::endl; } @@ -663,6 +688,18 @@ void Ogre2RenderEngine::RegisterHlms() Ogre::ResourceGroupManager::getSingleton().addResourceLocation( terraGLSLMaterialFolder, "FileSystem", "General"); + if (this->dataPtr->graphicsAPI == GraphicsAPI::METAL) + { + Ogre::String commonMetalMaterialFolder = common::joinPaths( + rootHlmsFolder, "2.0", "scripts", "materials", "Common", "Metal"); + Ogre::ResourceGroupManager::getSingleton().addResourceLocation( + commonMetalMaterialFolder, "FileSystem", "General"); + Ogre::String terraMetalMaterialFolder = common::joinPaths( + rootHlmsFolder, "2.0", "scripts", "materials", "Terra", "Metal"); + Ogre::ResourceGroupManager::getSingleton().addResourceLocation( + terraMetalMaterialFolder, "FileSystem", "General"); + } + // The following code is taken from the registerHlms() function in ogre2 // samples framework if (rootHlmsFolder.empty()) @@ -814,6 +851,10 @@ void Ogre2RenderEngine::CreateResources() std::make_pair(p, "General")); archNames.push_back( std::make_pair(p + "/materials/programs", "General")); + archNames.push_back( + std::make_pair(p + "/materials/programs/GLSL", "General")); + archNames.push_back( + std::make_pair(p + "/materials/programs/Metal", "General")); archNames.push_back( std::make_pair(p + "/materials/scripts", "General")); archNames.push_back( diff --git a/ogre2/src/media/2.0/scripts/materials/Terra/Metal/GpuNormalMapper_ps.metal b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/GpuNormalMapper_ps.metal new file mode 100644 index 000000000..c496cac85 --- /dev/null +++ b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/GpuNormalMapper_ps.metal @@ -0,0 +1,95 @@ +// Our terrain has the following pattern: +// +// 1N 10 11 +// o-o-o +// |/|/| +// 0N o-+-o 01 +// |/|/| +// o-o-o +// NN N0 N1 +// +// We need to calculate the normal of the vertex in +// the center '+', which is shared by 6 triangles. + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ + float2 heightMapResolution; + float3 vScale; +}; + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + + texture2d heightMap [[texture(0)]], + + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + int2 iCoord = int2( inPs.uv0 * p.heightMapResolution ); + + int3 xN01; + xN01.x = max( iCoord.x - 1, 0 ); + xN01.y = iCoord.x; + xN01.z = min( iCoord.x + 1, int(p.heightMapResolution.x) ); + int3 yN01; + yN01.x = max( iCoord.y - 1, 0 ); + yN01.y = iCoord.y; + yN01.z = min( iCoord.y + 1, int(p.heightMapResolution.y) ); + + //Watch out! It's heightXY, but heightMap.read uses YX. + float heightNN = heightMap.read( ushort2( xN01.x, yN01.x ) ).x * p.vScale.y; + float heightN0 = heightMap.read( ushort2( xN01.y, yN01.x ) ).x * p.vScale.y; + //float heightN1 = heightMap.read( ushort2( xN01.z, yN01.x ) ).x * p.vScale.y; + + float height0N = heightMap.read( ushort2( xN01.x, yN01.y ) ).x * p.vScale.y; + float height00 = heightMap.read( ushort2( xN01.y, yN01.y ) ).x * p.vScale.y; + float height01 = heightMap.read( ushort2( xN01.z, yN01.y ) ).x * p.vScale.y; + + //float height1N = heightMap.read( ushort2( xN01.x, yN01.z ) ).x * p.vScale.y; + float height10 = heightMap.read( ushort2( xN01.y, yN01.z ) ).x * p.vScale.y; + float height11 = heightMap.read( ushort2( xN01.z, yN01.z ) ).x * p.vScale.y; + + float3 vNN = float3( -p.vScale.x, heightNN, -p.vScale.z ); + float3 vN0 = float3( -p.vScale.x, heightN0, 0 ); + //float3 vN1 = float3( -p.vScale.x, heightN1, p.vScale.z ); + + float3 v0N = float3( 0, height0N, -p.vScale.z ); + float3 v00 = float3( 0, height00, 0 ); + float3 v01 = float3( 0, height01, p.vScale.z ); + + //float3 v1N = float3( p.vScale.x, height1N, -p.vScale.z ); + float3 v10 = float3( p.vScale.x, height10, 0 ); + float3 v11 = float3( p.vScale.x, height11, p.vScale.z ); + + float3 vNormal = float3( 0, 0, 0 ); + + vNormal += cross( (v01 - v00), (v11 - v00) ); + vNormal += cross( (v11 - v00), (v10 - v00) ); + vNormal += cross( (v10 - v00), (v0N - v00) ); + vNormal += cross( (v0N - v00), (vNN - v00) ); + vNormal += cross( (vNN - v00), (vN0 - v00) ); + vNormal += cross( (vN0 - v00), (v01 - v00) ); + +// vNormal += cross( (v01 - v00), (v11 - v00) ); +// vNormal += cross( (v11 - v00), (v10 - v00) ); +// vNormal += cross( (v10 - v00), (v1N - v00) ); +// vNormal += cross( (v1N - v00), (v0N - v00) ); +// vNormal += cross( (v0N - v00), (vNN - v00) ); +// vNormal += cross( (vNN - v00), (vN0 - v00) ); +// vNormal += cross( (vN0 - v00), (vN1 - v00) ); +// vNormal += cross( (vN1 - v00), (v01 - v00) ); + + vNormal = normalize( vNormal ); + + //return vNormal.zx; + return float4( vNormal.zyx * 0.5f + 0.5f, 1.0f ); +} diff --git a/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraGaussianBlur_cs.metal b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraGaussianBlur_cs.metal new file mode 100644 index 000000000..8d0955379 --- /dev/null +++ b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraGaussianBlur_cs.metal @@ -0,0 +1,24 @@ +//Based on GPUOpen's samples SeparableFilter11 +//https://github.com/GPUOpen-LibrariesAndSDKs/SeparableFilter11 +//For better understanding, read "Efficient Compute Shader Programming" from Bill Bilodeau +//http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps + +//TL;DR: +// * Each thread works on 4 pixels at a time (for VLIW hardware, i.e. Radeon HD 5000 & 6000 series). +// * 256 pixels per threadgroup. Each threadgroup works on 2 rows of 128 pixels each. +// That means 32x2 threads = 64. 64 threads x 4 pixels per thread = 256 + +@piece( data_type )float3@end +@piece( lds_data_type )float3@end +@piece( lds_definition ) + threadgroup float3 g_f3LDS[ 2 ] [ @value( samples_per_threadgroup ) ] +@end + +@piece( image_sample ) + return inputImage.sample( inputSampler, f2SamplePosition, level(0) ).xyz; +@end + +@piece( image_store ) + @foreach( 4, iPixel ) + outputImage.write( float4( outColour[ @iPixel ], 1.0 ), uint2( i2Center + @iPixel * i2Inc ), 0 );@end +@end diff --git a/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraShadowGenerator.metal b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraShadowGenerator.metal new file mode 100644 index 000000000..1f5ad0d83 --- /dev/null +++ b/ogre2/src/media/2.0/scripts/materials/Terra/Metal/TerraShadowGenerator.metal @@ -0,0 +1,113 @@ +#include +using namespace metal; + +//in uvec3 gl_NumWorkGroups; +//in uvec3 gl_WorkGroupID; +//in uvec3 gl_LocalInvocationID; +//in uvec3 gl_GlobalInvocationID; +//in uint gl_LocalInvocationIndex; + +struct Params +{ + //Bresenham algorithm uniforms + float2 delta; + + int2 xyStep; //(y0 < y1) ? 1 : -1; + int isSteep; + + //Rendering uniforms + float heightDelta; +}; + +struct PerGroupData +{ + int iterations; + float deltaErrorStart; + float padding0; + float padding1; +}; + +float2 calcShadow( int2 xyPos, float2 prevHeight, + texture2d shadowMap, + texture2d heightMap, + constant Params &p ); + +float2 calcShadow( int2 xyPos, float2 prevHeight, + texture2d shadowMap, + texture2d heightMap, + constant Params &p ) +{ + prevHeight.x -= p.heightDelta; + prevHeight.y = prevHeight.y * 0.985 - p.heightDelta; //Used for the penumbra region + + float currHeight = heightMap.read( uint2( xyPos ), 0 ).x; + + float shadowValue = smoothstep( prevHeight.y, prevHeight.x, currHeight + 0.001 ); + prevHeight.x = currHeight >= prevHeight.x ? currHeight : prevHeight.x; + prevHeight.y = currHeight >= prevHeight.y ? currHeight : prevHeight.y; + + //We store shadow's height in 10 bits, but the actual heightmap is in 16 bits. + //If we have a height of 0.9775, it will translate to 999.98 rounding to 1000 + //Thus when sampling, the objects on top of the terrain will be shadowed by the + //terrain at that spot. Thus we subtract 1 from the height, and add 1 to + //invHeightLength for a smooth gradient (which also prevents div. by zero). + float2 roundedHeight = floor( saturate( prevHeight.xy ) * 1023.0 + 0.5 ) - 1.0; + float invHeightLength = 1.0 / (roundedHeight.x - roundedHeight.y + 1); //+1 Avoids div. by zero + roundedHeight.y *= 0.000977517; + + shadowMap.write( float4( shadowValue, roundedHeight.y, invHeightLength, 1.0 ), uint2( xyPos ) ); + + return prevHeight; +} + +kernel void main_metal +( + constant int4 *startXY [[buffer(CONST_SLOT_START+0)]] + , constant PerGroupData *perGroupData [[buffer(CONST_SLOT_START+1)]] + + , texture2d shadowMap [[texture(UAV_SLOT_START+0)]] + , texture2d heightMap [[texture(0)]] + + , constant Params &p [[buffer(PARAMETER_SLOT)]] + + , uint3 gl_GlobalInvocationID [[thread_position_in_grid]] + , uint3 gl_WorkGroupID [[threadgroup_position_in_grid]] +) +{ + float2 prevHeight = float2( 0.0, 0.0 ); + float error = p.delta.x * 0.5 + perGroupData[gl_WorkGroupID.x].deltaErrorStart; + + int x, y; + if( gl_GlobalInvocationID.x < 4096u ) + { + x = startXY[gl_GlobalInvocationID.x].x; + y = startXY[gl_GlobalInvocationID.x].y; + } + else + { + //Due to alignment nightmares, instead of doing startXY[8192]; + //we perform startXY[4096] and store the values in .zw instead of .xy + //It only gets used if the picture is very big. This branch is coherent as + //long as 4096 is multiple of threads_per_group_x. + x = startXY[gl_GlobalInvocationID.x - 4096u].z; + y = startXY[gl_GlobalInvocationID.x - 4096u].w; + } + + int numIterations = perGroupData[gl_WorkGroupID.x].iterations; + for( int i=0; i +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ + float near; + float far; + float min; + float max; + float4 texResolution; +}; + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d inputTexture [[texture(0)]], + sampler inputSampler [[sampler(0)]], + constant Params ¶ms [[buffer(PARAMETER_SLOT)]] +) +{ + float tolerance = 1e-6; + + // Note: We use texelFetch because p.a contains an uint32 and sampling + // (even w/ point filtering) causes p.a to loss information (e.g. + // values close to 0 get rounded to 0) + // + // See https://github.com/ignitionrobotics/ign-rendering/issues/332 + // float4 p = texelFetch(inputTexture, int2(inPs.uv0 * params.texResolution.xy), 0); + // TODO - establish Metal equivalent - use standard sampler as interim approx. + float4 p = inputTexture.sample(inputSampler, inPs.uv0); + + float3 point = p.xyz; + + // Clamp again in case render passes changed depth values + // to be outside of min/max range + + // clamp xyz + if (!isinf(point.x) && length(point) > params.far - tolerance) + { + if (isinf(params.max)) + { + point = float3(params.max); + } + else + { + point.x = params.max; + } + } + else if (point.x < params.near + tolerance) + { + if (isinf(params.min)) + { + point = float3(params.min); + } + else + { + point.x = params.min; + } + } + + float4 fragColor(point, p.a); + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/depth_camera_final_vs.metal b/ogre2/src/media/materials/programs/Metal/depth_camera_final_vs.metal new file mode 100644 index 000000000..15e7048c1 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/depth_camera_final_vs.metal @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; + float3 normal [[attribute(VES_NORMAL)]]; + float2 uv0 [[attribute(VES_TEXTURE_COORDINATES0)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float2 uv0; +}; + +struct Params +{ + float4x4 worldViewProj; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + outVs.uv0 = input.uv0; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/depth_camera_fs.metal b/ogre2/src/media/materials/programs/Metal/depth_camera_fs.metal new file mode 100644 index 000000000..0e5de2275 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/depth_camera_fs.metal @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: depth_camera_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float2 projectionParams; + float near; + float far; + float min; + float max; + float3 backgroundColor; + + float particleStddev; + float particleScatterRatio; + // rnd is a random number in the range of [0-1] + float rnd; +}; + +float packFloat(float4 color) +{ + int rgba = (int(color.x * 255.0) << 24) + + (int(color.y * 255.0) << 16) + + (int(color.z * 255.0) << 8) + + int(color.w * 255.0); + return as_type(rgba); +} + +// see gaussian_noise_fs.metal for documentation on the rand and gaussrand +// functions + +#define PI 3.14159265358979323846264 + +float rand(float2 co) +{ + float r = fract(sin(dot(co.xy, float2(12.9898,78.233))) * 43758.5453); + if(r == 0.0) + return 0.000000000001; + else + return r; +} + +float4 gaussrand(float2 co, float3 offsets, float mean, float stddev) +{ + float U, V, R, Z; + U = rand(co + float2(offsets.x, offsets.x)); + V = rand(co + float2(offsets.y, offsets.y)); + R = rand(co + float2(offsets.z, offsets.z)); + if(R < 0.5) + Z = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V); + else + Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V); + Z = Z * stddev + mean; + return float4(Z, Z, Z, 0.0); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d depthTexture [[texture(0)]], + texture2d colorTexture [[texture(1)]], + texture2d particleTexture [[texture(2)]], + texture2d particleDepthTexture [[texture(3)]], + sampler depthSampler [[sampler(0)]], + sampler colorSampler [[sampler(1)]], + sampler particleSampler [[sampler(2)]], + sampler particleDepthSampler [[sampler(3)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + float tolerance = 1e-6; + + // get linear depth + float fDepth = depthTexture.sample(depthSampler, inPs.uv0).x; + float d = p.projectionParams.y / (fDepth - p.projectionParams.x); + + // reconstruct 3d viewspace pos from depth + float3 viewSpacePos = inPs.cameraDir * d; + + // convert to z up + float3 point = float3(-viewSpacePos.z, -viewSpacePos.x, viewSpacePos.y); + + // color + float4 color = colorTexture.sample(colorSampler, inPs.uv0); + + // particle mask - color and depth + float4 particle = particleTexture.sample(particleSampler, inPs.uv0); + float particleDepth = particleDepthTexture.sample(particleDepthSampler, inPs.uv0).x; + float pd = p.projectionParams.y / (particleDepth - p.projectionParams.x); + + // return particle depth if it can be seen by the camera and not obstructed + // by other objects in the camera view + if (particle.x > 0 && pd < d) + { + // apply scatter effect so that only some of the smoke pixels are visible + float r = rand(inPs.uv0 + float2(p.rnd, p.rnd)); + if (r < p.particleScatterRatio) + { + // set point to 3d pos of particle pixel + float3 particleViewSpacePos = inPs.cameraDir * pd; + float3 particlePoint = float3( + -particleViewSpacePos.z, + -particleViewSpacePos.x, + particleViewSpacePos.y); + + float rr = rand(inPs.uv0 + float2(p.rnd, p.rnd)) - 0.5; + + // apply gaussian noise to particle point cloud data + // With large particles, the range returned are all from the first large + // particle. So add noise with some mean values so that all the points are + // shifted further out. This gives depth readings beyond the first few + // particles and avoid too many early returns + float3 noise = gaussrand(inPs.uv0, float3(p.rnd, p.rnd, p.rnd), + p.particleStddev, rr*rr*p.particleStddev*0.5).xyz; + float noiseLength = length(noise); + float particlePointLength = length(particlePoint); + float newLength = particlePointLength + noiseLength; + float3 newPoint = particlePoint * (newLength / particlePointLength); + + // make sure we do not produce depth values larger than depth of first + // non-particle obstacle, e.g. a box behind particle should still return + // a hit + float pointLength = length(point); + if (newLength < pointLength) + point = newPoint; + } + } + + // clamp xyz and set rgb to background color + if (length(point) > p.far - tolerance) + { + if (isinf(p.max)) + { + point = float3(p.max); + } + else + { + point.x = p.max; + } + // clamp to background color only if it is not a particle pixel + // this is because point.x may have been set to background depth value + // due to the scatter effect. We should still render particles in the color + // image + if (particle.x < 1e-6) + { + color = float4(p.backgroundColor, 1.0); + } + } + else if (point.x < p.near + tolerance) + { + if (isinf(p.min)) + { + point = float3(p.min); + } + else + { + point.x = p.min; + } + + // clamp to background color only if it is not a particle pixel + if (particle.x < 1e-6) + { + color = float4(p.backgroundColor, 1.0); + } + } + + // gamma correct - using same method as: + // https://bitbucket.org/sinbad/ogre/src/v2-1/Samples/Media/Hlms/Pbs/GLSL/PixelShader_ps.glsl#lines-513 + color = sqrt(color); + + float rgba = packFloat(color); + float4 fragColor(point, rgba); + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/depth_camera_vs.metal b/ogre2/src/media/materials/programs/Metal/depth_camera_vs.metal new file mode 100644 index 000000000..d5182beb8 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/depth_camera_vs.metal @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; + float3 normal [[attribute(VES_NORMAL)]]; + float2 uv0 [[attribute(VES_TEXTURE_COORDINATES0)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float4x4 worldViewProj; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + outVs.uv0 = input.uv0; + + // normal is used in fragment shader to reconstruct + // viewspace pos from depth buffer data + // see the `quad_normals` and `camera_far_corners_view_space` + // param descriptions in + // https://ogrecave.github.io/ogre/api/2.1/compositor.html + outVs.cameraDir = input.normal; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/gaussian_noise_depth_fs.metal b/ogre2/src/media/materials/programs/Metal/gaussian_noise_depth_fs.metal new file mode 100644 index 000000000..09a3d749d --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gaussian_noise_depth_fs.metal @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2019 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: gaussian_noise_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ + // Random values sampled on the CPU, which we'll use as offsets into our 2-D + // pseudo-random sampler here. + float3 offsets; + // Mean of the Gaussian distribution that we want to sample from. + float mean; + // Standard deviation of the Gaussian distribution that we want to sample from. + float stddev; +}; + +#define PI 3.14159265358979323846264 + +float rand(float2 co) +{ + // This one-liner can be found in many places, including: + // http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl + // I can't find any explanation for it, but experimentally it does seem to + // produce approximately uniformly distributed values in the interval [0,1]. + float r = fract(sin(dot(co.xy, float2(12.9898,78.233))) * 43758.5453); + + // Make sure that we don't return 0.0 + if(r == 0.0) + return 0.000000000001; + else + return r; +} + +float4 gaussrand(float2 co, float3 offsets, float mean, float stddev) +{ + // Box-Muller method for sampling from the normal distribution + // http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_from_normal_distribution + // This method requires 2 uniform random inputs and produces 2 + // Gaussian random outputs. We'll take a 3rd random variable and use it to + // switch between the two outputs. + + float U, V, R, Z; + // Add in the CPU-supplied random offsets to generate the 3 random values that + // we'll use. + U = rand(co + float2(offsets.x, offsets.x)); + V = rand(co + float2(offsets.y, offsets.y)); + R = rand(co + float2(offsets.z, offsets.z)); + // Switch between the two random outputs. + if(R < 0.5) + Z = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V); + else + Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V); + + // Apply the stddev and mean. + Z = Z * stddev + mean; + + // Return it as a vec4, to be added to the input ("true") color. + return float4(Z, Z, Z, 0.0); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d RT [[texture(0)]], + sampler rtSampler [[sampler(0)]], + // constant float3 &offsets [[buffer(PARAMETER_SLOT)]], + // constant float &mean [[buffer(PARAMETER_SLOT)]], + // constant float &stddev [[buffer(PARAMETER_SLOT)]] + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // Add the sampled noise to the input color and clamp the result to a valid + // range. + // note that an exponent is added to sampled noise, i.e. pow(noise, x), + // which produces more consistent result with ogre1.x + float z = gaussrand(inPs.uv0.xy, p.offsets, p.mean, p.stddev).x; + float n = pow(abs(z), 2.1); + if (z < 0) + n = -n; + + float4 texColor = RT.sample(rtSampler, inPs.uv0.xy); + float4 fragColor = clamp(texColor + float4(n, n, n, 0.0), 0.0, 1.0); + + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/gaussian_noise_fs.metal b/ogre2/src/media/materials/programs/Metal/gaussian_noise_fs.metal new file mode 100644 index 000000000..cf1f61362 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gaussian_noise_fs.metal @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: gaussian_noise_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ + // Random values sampled on the CPU, which we'll use as offsets into our 2-D + // pseudo-random sampler here. + float3 offsets; + // Mean of the Gaussian distribution that we want to sample from. + float mean; + // Standard deviation of the Gaussian distribution that we want to sample from. + float stddev; +}; + +#define PI 3.14159265358979323846264 + +float rand(float2 co) +{ + // This one-liner can be found in many places, including: + // http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl + // I can't find any explanation for it, but experimentally it does seem to + // produce approximately uniformly distributed values in the interval [0,1]. + float r = fract(sin(dot(co.xy, float2(12.9898,78.233))) * 43758.5453); + + // Make sure that we don't return 0.0 + if(r == 0.0) + return 0.000000000001; + else + return r; +} + +float4 gaussrand(float2 co, float3 offsets, float mean, float stddev) +{ + // Box-Muller method for sampling from the normal distribution + // http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_from_normal_distribution + // This method requires 2 uniform random inputs and produces 2 + // Gaussian random outputs. We'll take a 3rd random variable and use it to + // switch between the two outputs. + + float U, V, R, Z; + // Add in the CPU-supplied random offsets to generate the 3 random values that + // we'll use. + U = rand(co + float2(offsets.x, offsets.x)); + V = rand(co + float2(offsets.y, offsets.y)); + R = rand(co + float2(offsets.z, offsets.z)); + // Switch between the two random outputs. + if(R < 0.5) + Z = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V); + else + Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V); + + // Apply the stddev and mean. + Z = Z * stddev + mean; + + // Return it as a vec4, to be added to the input ("true") color. + return float4(Z, Z, Z, 0.0); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d RT [[texture(0)]], + sampler rtSampler [[sampler(0)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // Add the sampled noise to the input color and clamp the result to a valid + // range. + // note that an exponent is added to sampled noise, i.e. pow(noise, x), + // which produces more consistent result with ogre1.x + float z = gaussrand(inPs.uv0.xy, p.offsets, p.mean, p.stddev).x; + float n = pow(abs(z), 2.1); + if (z < 0) + n = -n; + + float4 texColor = RT.sample(rtSampler, inPs.uv0.xy); + float4 fragColor = clamp(texColor + float4(n, n, n, 0.0), 0.0, 1.0); + + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/gaussian_noise_vs.metal b/ogre2/src/media/materials/programs/Metal/gaussian_noise_vs.metal new file mode 100644 index 000000000..dc492ac88 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gaussian_noise_vs.metal @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// Simple vertex shader; just setting things up for the real work to be done in +// gaussian_noise_fs.metal. + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; + float2 uv0 [[attribute(VES_TEXTURE_COORDINATES0)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float2 uv0; +}; + +struct Params +{ + float4x4 worldViewProj; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + outVs.uv0 = input.uv0; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_fs.metal b/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_fs.metal new file mode 100644 index 000000000..3159e8e56 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_fs.metal @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: gpu_rays_1st_pass_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float2 projectionParams; + float near; + float far; + float min; + float max; + float particleStddev; + float particleScatterRatio; + // rnd is a random number in the range of [0-1] + float rnd; +}; + +// see gaussian_noise_fs.metal for documentation on the rand and gaussrand +// functions + +#define PI 3.14159265358979323846264 + +float rand(float2 co) +{ + float r = fract(sin(dot(co.xy, float2(12.9898,78.233))) * 43758.5453); + if(r == 0.0) + return 0.000000000001; + else + return r; +} + +float4 gaussrand(float2 co, float3 offsets, float mean, float stddev) +{ + float U, V, R, Z; + U = rand(co + float2(offsets.x, offsets.x)); + V = rand(co + float2(offsets.y, offsets.y)); + R = rand(co + float2(offsets.z, offsets.z)); + if(R < 0.5) + Z = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V); + else + Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V); + Z = Z * stddev + mean; + return float4(Z, Z, Z, 0.0); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d depthTexture [[texture(0)]], + texture2d colorTexture [[texture(1)]], + texture2d particleDepthTexture [[texture(2)]], + texture2d particleTexture [[texture(3)]], + sampler depthSampler [[sampler(0)]], + sampler colorSampler [[sampler(1)]], + sampler particleDepthSampler [[sampler(2)]], + sampler particleSampler [[sampler(3)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // get linear depth + float fDepth = depthTexture.sample(depthSampler, inPs.uv0).x; + float d = p.projectionParams.y / (fDepth - p.projectionParams.x); + + // get retro + float retro = colorTexture.sample(colorSampler, inPs.uv0).x * 2000.0; + + // reconstruct 3d viewspace pos from depth + float3 viewSpacePos = inPs.cameraDir * d; + + // get length of 3d point, i.e.range + float l = length(viewSpacePos); + + // particle mask - color and depth + float4 particle = particleTexture.sample(particleSampler, inPs.uv0); + float particleDepth = particleDepthTexture.sample(particleDepthSampler, inPs.uv0).x; + float pd = p.projectionParams.y / (particleDepth - p.projectionParams.x); + + // check if need to apply scatter effect + if (particle.x > 0.0 && pd < d) + { + // apply scatter effect so that only some of the smoke pixels are visible + float r = rand(inPs.uv0 + float2(p.rnd, p.rnd)); + if (r < p.particleScatterRatio) + { + float3 point = inPs.cameraDir * pd; + + float rr = rand(inPs.uv0 + float2(p.rnd, p.rnd)) - 0.5; + + // apply gaussian noise to particle range data + // With large particles, the range returned are all from the first large + // particle. So add noise with some mean values so that all the points are + // shifted further out. This gives depth readings beyond the first few + // particles and avoid too many early returns + float3 noise = gaussrand(inPs.uv0, float3(p.rnd, p.rnd, p.rnd), + p.particleStddev, rr*rr*p.particleStddev*0.5).xyz; + float noiseLength = length(noise); + + // apply gaussian noise to particle depth data + float newLength = length(point) + noiseLength; + + // make sure we do not produce values larger than the range of the first + // non-particle obstacle, e.g. a box behind particle should still return + // a hit + if (newLength < l) + l = newLength; + } + } + + if (l > p.far) + l = p.max; + else if (l < p.near) + l = p.min; + + float4 fragColor(l, retro, 0.0, 1.0); + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_vs.metal b/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_vs.metal new file mode 100644 index 000000000..d5182beb8 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gpu_rays_1st_pass_vs.metal @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; + float3 normal [[attribute(VES_NORMAL)]]; + float2 uv0 [[attribute(VES_TEXTURE_COORDINATES0)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float4x4 worldViewProj; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + outVs.uv0 = input.uv0; + + // normal is used in fragment shader to reconstruct + // viewspace pos from depth buffer data + // see the `quad_normals` and `camera_far_corners_view_space` + // param descriptions in + // https://ogrecave.github.io/ogre/api/2.1/compositor.html + outVs.cameraDir = input.normal; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/gpu_rays_2nd_pass_fs.metal b/ogre2/src/media/materials/programs/Metal/gpu_rays_2nd_pass_fs.metal new file mode 100644 index 000000000..9a1c3c48c --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/gpu_rays_2nd_pass_fs.metal @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: gpu_rays_2nd_pass_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ +}; + +float2 getRange(float2 uv, texture2d tex, sampler texSampler) +{ + float2 range = tex.sample(texSampler, uv).xy; + return range; +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d cubeUVTex [[texture(0)]], + texture2d tex0 [[texture(1)]], + texture2d tex1 [[texture(2)]], + texture2d tex2 [[texture(3)]], + texture2d tex3 [[texture(4)]], + texture2d tex4 [[texture(5)]], + texture2d tex5 [[texture(6)]], + sampler cubeUVTexSampler [[sampler(0)]], + sampler tex0Sampler [[sampler(1)]], + sampler tex1Sampler [[sampler(2)]], + sampler tex2Sampler [[sampler(3)]], + sampler tex3Sampler [[sampler(4)]], + sampler tex4Sampler [[sampler(5)]], + sampler tex5Sampler [[sampler(6)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // get face index and uv coorodate data + float3 data = cubeUVTex.sample(cubeUVTexSampler, inPs.uv0).xyz; + + // which face to sample range data from + float faceIdx = data.z; + + // uv coordinates on texture that stores the range data + float2 uv = data.xy; + + float2 d; + d.x = 0; + d.y = 0; + if (faceIdx == 0) + d = getRange(uv, tex0, tex0Sampler); + else if (faceIdx == 1) + d = getRange(uv, tex1, tex1Sampler); + else if (faceIdx == 2) + d = getRange(uv, tex2, tex2Sampler); + else if (faceIdx == 3) + d = getRange(uv, tex3, tex3Sampler); + else if (faceIdx == 4) + d = getRange(uv, tex4, tex4Sampler); + else if (faceIdx == 5) + d = getRange(uv, tex5, tex5Sampler); + + float range = d.x; + float retro = d.y; + + float4 fragColor(range, retro, 0, 1.0); + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/heat_signature_fs.metal b/ogre2/src/media/materials/programs/Metal/heat_signature_fs.metal new file mode 100644 index 000000000..cb541bd01 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/heat_signature_fs.metal @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: thermal_camera_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; +}; + +struct Params +{ + // The minimum and maximum temprature values (in Kelvin) that the + // heat signature texture should be normalized to + // (users can override these defaults) + float minTemp = 0.0; + float maxTemp = 100.0; + + int bitDepth; + float resolution; +}; + +// map a temperature from the [min, max] range to the user defined +// [minTemp, maxTemp] range +float mapNormalized( + float num, + float minTemp, + float maxTemp, + float resolution, + int bitDepth) +{ + float mappedKelvin = ((maxTemp - minTemp) * num) + minTemp; + return mappedKelvin / (((1 << bitDepth) - 1.0) * resolution); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d renderTexture [[texture(0)]], + sampler renderTextureSampler [[sampler(0)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + float heat = renderTexture.sample(renderTextureSampler, inPs.uv0.xy).x; + + // set g, b, a to 0. This will be used by thermal_camera_fs.glsl to determine + // if a particular fragment is a heat source or not + float normalisedHeat = mapNormalized( + heat, p.minTemp, p.maxTemp, p.resolution, p.bitDepth); + + float4 fragColor(normalisedHeat, 0, 0, 0.0); + return fragColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/plain_color_fs.metal b/ogre2/src/media/materials/programs/Metal/plain_color_fs.metal new file mode 100644 index 000000000..082e9facf --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/plain_color_fs.metal @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct PS_INPUT +{ +}; + +struct Params +{ + float4 inColor; +}; + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + return p.inColor; +} diff --git a/ogre2/src/media/materials/programs/Metal/plain_color_vs.metal b/ogre2/src/media/materials/programs/Metal/plain_color_vs.metal new file mode 100644 index 000000000..6b0ee7be8 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/plain_color_vs.metal @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float gl_ClipDistance [[clip_distance]] [1]; +}; + +struct Params +{ + float4x4 worldViewProj; + float4x4 worldView; + float ignMinClipDistance; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + + if( p.ignMinClipDistance > 0.0f ) + { + // Frustum is rectangular; but the minimum lidar distance is spherical, + // so we can't rely on near plane to clip geometry that is too close, + // we have to do it by hand + float3 viewSpacePos = (p.worldView * input.position).xyz; + outVs.gl_ClipDistance[0] = length( viewSpacePos.xyz ) - p.ignMinClipDistance; + } + else + { + outVs.gl_ClipDistance[0] = 1.0f; + } + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/point_fs.metal b/ogre2/src/media/materials/programs/Metal/point_fs.metal new file mode 100644 index 000000000..4fa9088a9 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/point_fs.metal @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct PS_INPUT +{ +}; + +struct Params +{ + float4 color; +}; + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + return p.color; +} diff --git a/ogre2/src/media/materials/programs/Metal/point_vs.metal b/ogre2/src/media/materials/programs/Metal/point_vs.metal new file mode 100644 index 000000000..192e21930 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/point_vs.metal @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float gl_PointSize [[point_size]]; +}; + +struct Params +{ + float4x4 worldViewProj; + float size; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position = ( p.worldViewProj * input.position ).xyzw; + outVs.gl_PointSize = p.size; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/selection_buffer_fs.metal b/ogre2/src/media/materials/programs/Metal/selection_buffer_fs.metal new file mode 100644 index 000000000..5620d1c12 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/selection_buffer_fs.metal @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float2 projectionParams; + float far; + float inf; +}; + +float packFloat(float4 color) +{ + int rgba = (int(color.x * 255.0) << 24) + + (int(color.y * 255.0) << 16) + + (int(color.z * 255.0) << 8) + + int(color.w * 255.0); + return as_type(rgba); +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d colorTexture [[texture(0)]], + texture2d depthTexture [[texture(1)]], + sampler colorSampler [[sampler(0)]], + sampler depthSampler [[sampler(1)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // get linear depth + float fDepth = depthTexture.sample(depthSampler, inPs.uv0).x; + + float d = p.projectionParams.y / (fDepth - p.projectionParams.x); + + // reconstruct 3d viewspace pos from depth + float3 viewSpacePos = inPs.cameraDir * d; + + // convert to z up + float3 point = float3(-viewSpacePos.z, -viewSpacePos.x, viewSpacePos.y); + + // set to inf if point is at far clip plane + if (point.x > p.far - 1e-4) + point = float3(p.inf); + + // color + float4 color = colorTexture.sample(colorSampler, inPs.uv0); + + float rgba = packFloat(color); + + return float4(point.xyz, rgba); +} diff --git a/ogre2/src/media/materials/programs/Metal/skybox_fs.metal b/ogre2/src/media/materials/programs/Metal/skybox_fs.metal new file mode 100644 index 000000000..84e8d9970 --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/skybox_fs.metal @@ -0,0 +1,22 @@ +// The code in this file is adapted from OGRE Samples. The OGRE's license and +// copyright header is included in skybox.material. +// See: ogre-next/Samples/2.0/scripts/materials/Common/Metal/SkyCubemap_ps.metal + +#include +using namespace metal; + +struct PS_INPUT +{ + float3 cameraDir; +}; + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texturecube skyCubemap [[texture(0)]], + sampler samplerState [[sampler(0)]] +) +{ + //Cubemaps are left-handed + return skyCubemap.sample( samplerState, float3( inPs.cameraDir.xy, -inPs.cameraDir.z ) ).xyzw; +} diff --git a/ogre2/src/media/materials/programs/Metal/skybox_vs.metal b/ogre2/src/media/materials/programs/Metal/skybox_vs.metal new file mode 100644 index 000000000..83aca118d --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/skybox_vs.metal @@ -0,0 +1,40 @@ +// The code in this file is adapted from OGRE Samples. The OGRE's license and +// copyright header is included in skybox.material. +// See: ogre-next/Samples/2.0/scripts/materials/Common/Metal/QuadCameraDirNoUV_vs.metal + +#include +using namespace metal; + +struct VS_INPUT +{ + float4 position [[attribute(VES_POSITION)]]; + float3 normal [[attribute(VES_NORMAL)]]; +}; + +struct PS_INPUT +{ + float4 gl_Position [[position]]; + float3 cameraDir; +}; + +struct Params +{ + float2 rsDepthRange; + float4x4 worldViewProj; +}; + +vertex PS_INPUT main_metal +( + VS_INPUT input [[stage_in]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + PS_INPUT outVs; + + outVs.gl_Position.xy= ( p.worldViewProj * float4( input.position.xy, 0.0f, 1.0f ) ).xy; + outVs.gl_Position.z = p.rsDepthRange.y; + outVs.gl_Position.w = 1.0f; + outVs.cameraDir = input.normal; + + return outVs; +} diff --git a/ogre2/src/media/materials/programs/Metal/thermal_camera_fs.metal b/ogre2/src/media/materials/programs/Metal/thermal_camera_fs.metal new file mode 100644 index 000000000..9f6c4d3ae --- /dev/null +++ b/ogre2/src/media/materials/programs/Metal/thermal_camera_fs.metal @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2019 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// For details and documentation see: thermal_camera_fs.glsl + +#include +using namespace metal; + +struct PS_INPUT +{ + float2 uv0; + float3 cameraDir; +}; + +struct Params +{ + float2 projectionParams; + float near; + float far; + float min; + float max; + float range; + float resolution; + float heatSourceTempRange; + float ambient; + int rgbToTemp; + int bitDepth; +}; + +float getDepth( + float2 uv, + texture2d depthTexture, + sampler depthSampler, + float2 projectionParams) +{ + float fDepth = depthTexture.sample(depthSampler, uv).x; + float linearDepth = projectionParams.y / (fDepth - projectionParams.x); + return linearDepth; +} + +fragment float4 main_metal +( + PS_INPUT inPs [[stage_in]], + texture2d depthTexture [[texture(0)]], + texture2d colorTexture [[texture(1)]], + sampler depthSampler [[sampler(0)]], + sampler colorSampler [[sampler(1)]], + constant Params &p [[buffer(PARAMETER_SLOT)]] +) +{ + // temperature defaults to ambient + float temp = p.ambient; + float heatRange = p.range; + int bitMaxValue = (1 << p.bitDepth) - 1; + + // dNorm value is between [0, 1]. It is used to for varying temperature + // value of a fragment. + // When dNorm = 1, temp = temp + heatRange*0.5. + // When dNorm = 0, temp = temp - heatRange*0.5. + float dNorm = 0.5; + + // check for heat source + // heat source are objects with uniform temperature or heat signature + // The custom heat source / signature shaders stores heat data in + // a vec4 of [heat, 0, 0, 0] so we test to see if it is a heat + // source by checking gba == 0. This is more of a hack but the idea is to + // avoid having to render an extra pass to create a mask of heat source + // objects + float4 rgba = colorTexture.sample(colorSampler, inPs.uv0).rgba; + bool isHeatSource = (rgba.g == 0.0 && rgba.b == 0.0 && rgba.a == 0.0); + float heat = rgba.r; + + if (isHeatSource) + { + // heat is normalized so convert back to work in kelvin + // for 16 bit camera and 0.01 resolution: + // ((1 << bitDepth) - 1) * resolution = 655.35 + temp = heat * bitMaxValue * p.resolution; + + // set temperature variation for heat source + heatRange = p.heatSourceTempRange; + } + else + { + // other non-heat source objects are assigned ambient temperature + temp = p.ambient; + } + + // add temperature variation, either as a function of color or depth + if (p.rgbToTemp == 1) + { + if (!isHeatSource) + { + // convert to grayscale: darker = warmer + // (https://docs.opencv.org/3.4/de/d25/imgproc_color_conversions.html) + float gray = rgba.r * 0.299 + rgba.g * 0.587 + rgba.b*0.114; + dNorm = 1.0 - gray; + } + } + else + { + // get depth + float d = getDepth(inPs.uv0, depthTexture, depthSampler, p.projectionParams); + // reconstruct 3d viewspace pos from depth + float3 viewSpacePos = inPs.cameraDir * d; + d = -viewSpacePos.z; + dNorm = (d-p.near) / (p.far-p.near); + } + + // simulate temp variations + float delta = (1.0 - dNorm) * heatRange; + temp = temp - heatRange / 2.0 + delta; + clamp(temp, p.min, p.max); + + // apply resolution factor + temp /= p.resolution; + // normalize + float denorm = float(bitMaxValue); + temp /= denorm; + + float4 fragColor(temp, 0, 0, 1.0); + return fragColor; +} diff --git a/ogre2/src/media/materials/scripts/depth_camera.material b/ogre2/src/media/materials/scripts/depth_camera.material index 8d097fdd1..4c9613d2f 100644 --- a/ogre2/src/media/materials/scripts/depth_camera.material +++ b/ogre2/src/media/materials/scripts/depth_camera.material @@ -15,7 +15,8 @@ * */ -vertex_program DepthCameraVS glsl +// GLSL shaders +vertex_program DepthCameraVS_GLSL glsl { source depth_camera_vs.glsl default_params @@ -24,7 +25,7 @@ vertex_program DepthCameraVS glsl } } -fragment_program DepthCameraFS glsl +fragment_program DepthCameraFS_GLSL glsl { source depth_camera_fs.glsl @@ -37,6 +38,35 @@ fragment_program DepthCameraFS glsl } } +// Metal shaders +vertex_program DepthCameraVS_Metal metal +{ + source depth_camera_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program DepthCameraFS_Metal metal +{ + source depth_camera_fs.metal + shader_reflection_pair_hint DepthCameraVS_Metal +} + +// Unified shaders +vertex_program DepthCameraVS unified +{ + delegate DepthCameraVS_GLSL + delegate DepthCameraVS_Metal +} + +fragment_program DepthCameraFS unified +{ + delegate DepthCameraFS_GLSL + delegate DepthCameraFS_Metal +} + material DepthCamera { technique @@ -69,8 +99,8 @@ material DepthCamera } } - -vertex_program DepthCameraFinalVS glsl +// GLSL shaders +vertex_program DepthCameraFinalVS_GLSL glsl { source depth_camera_final_vs.glsl default_params @@ -79,7 +109,7 @@ vertex_program DepthCameraFinalVS glsl } } -fragment_program DepthCameraFinalFS glsl +fragment_program DepthCameraFinalFS_GLSL glsl { source depth_camera_final_fs.glsl @@ -91,6 +121,35 @@ fragment_program DepthCameraFinalFS glsl } } +// Metal shaders +vertex_program DepthCameraFinalVS_Metal metal +{ + source depth_camera_final_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program DepthCameraFinalFS_Metal metal +{ + source depth_camera_final_fs.metal + shader_reflection_pair_hint DepthCameraFinalVS_Metal +} + +// Unified shaders +vertex_program DepthCameraFinalVS unified +{ + delegate DepthCameraFinalVS_GLSL + delegate DepthCameraFinalVS_Metal +} + +fragment_program DepthCameraFinalFS unified +{ + delegate DepthCameraFinalFS_GLSL + delegate DepthCameraFinalFS_Metal +} + material DepthCameraFinal { technique diff --git a/ogre2/src/media/materials/scripts/gaussian_noise.material b/ogre2/src/media/materials/scripts/gaussian_noise.material index 21aa00242..2d0cc2f80 100644 --- a/ogre2/src/media/materials/scripts/gaussian_noise.material +++ b/ogre2/src/media/materials/scripts/gaussian_noise.material @@ -15,7 +15,8 @@ * */ -vertex_program GaussianNoiseVS glsl +// GLSL shaders +vertex_program GaussianNoiseVS_GLSL glsl { source gaussian_noise_vs.glsl default_params @@ -24,7 +25,7 @@ vertex_program GaussianNoiseVS glsl } } -fragment_program GaussianNoiseFS glsl +fragment_program GaussianNoiseFS_GLSL glsl { source gaussian_noise_fs.glsl default_params @@ -36,6 +37,35 @@ fragment_program GaussianNoiseFS glsl } } +// Metal shaders +vertex_program GaussianNoiseVS_Metal metal +{ + source gaussian_noise_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program GaussianNoiseFS_Metal metal +{ + source gaussian_noise_fs.metal + shader_reflection_pair_hint GaussianNoiseVS_Metal +} + +// Unified shaders +vertex_program GaussianNoiseVS unified +{ + delegate GaussianNoiseVS_GLSL + delegate GaussianNoiseVS_Metal +} + +fragment_program GaussianNoiseFS unified +{ + delegate GaussianNoiseFS_GLSL + delegate GaussianNoiseFS_Metal +} + material GaussianNoise { technique @@ -59,8 +89,8 @@ material GaussianNoise } } - -fragment_program GaussianNoiseDepthFS glsl +// GLSL shaders +fragment_program GaussianNoiseDepthFS_GLSL glsl { source gaussian_noise_depth_fs.glsl default_params @@ -72,6 +102,20 @@ fragment_program GaussianNoiseDepthFS glsl } } +// Metal shaders +fragment_program GaussianNoiseDepthFS_Metal metal +{ + source gaussian_noise_depth_fs.metal + shader_reflection_pair_hint GaussianNoiseVS_Metal +} + +// Unified shaders +fragment_program GaussianNoiseDepthFS unified +{ + delegate GaussianNoiseDepthFS_GLSL + delegate GaussianNoiseDepthFS_Metal +} + material GaussianNoiseDepth { technique diff --git a/ogre2/src/media/materials/scripts/gpu_rays.material b/ogre2/src/media/materials/scripts/gpu_rays.material index 2341df7e4..0d50ca9c5 100644 --- a/ogre2/src/media/materials/scripts/gpu_rays.material +++ b/ogre2/src/media/materials/scripts/gpu_rays.material @@ -15,7 +15,8 @@ * */ -vertex_program GpuRaysScan1stVS glsl +// GLSL shaders +vertex_program GpuRaysScan1stVS_GLSL glsl { source gpu_rays_1st_pass_vs.glsl default_params @@ -24,7 +25,7 @@ vertex_program GpuRaysScan1stVS glsl } } -fragment_program GpuRaysScan1stFS glsl +fragment_program GpuRaysScan1stFS_GLSL glsl { source gpu_rays_1st_pass_fs.glsl @@ -37,6 +38,35 @@ fragment_program GpuRaysScan1stFS glsl } } +// Metal shaders +vertex_program GpuRaysScan1stVS_Metal metal +{ + source gpu_rays_1st_pass_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program GpuRaysScan1stFS_Metal metal +{ + source gpu_rays_1st_pass_fs.metal + shader_reflection_pair_hint GpuRaysScan1stVS_Metal +} + +// Unified shaders +vertex_program GpuRaysScan1stVS unified +{ + delegate GpuRaysScan1stVS_GLSL + delegate GpuRaysScan1stVS_Metal +} + +fragment_program GpuRaysScan1stFS unified +{ + delegate GpuRaysScan1stFS_GLSL + delegate GpuRaysScan1stFS_Metal +} + material GpuRaysScan1st { technique @@ -69,7 +99,8 @@ material GpuRaysScan1st } } -fragment_program GpuRaysScan2ndFS glsl +// GLSL shaders +fragment_program GpuRaysScan2ndFS_GLSL glsl { source gpu_rays_2nd_pass_fs.glsl @@ -85,6 +116,20 @@ fragment_program GpuRaysScan2ndFS glsl } } +// Metal shaders +fragment_program GpuRaysScan2ndFS_Metal metal +{ + source gpu_rays_2nd_pass_fs.metal + shader_reflection_pair_hint Ogre/Compositor/Quad_vs +} + +// Unified shaders +fragment_program GpuRaysScan2ndFS unified +{ + delegate GpuRaysScan2ndFS_GLSL + delegate GpuRaysScan2ndFS_Metal +} + material GpuRaysScan2nd { technique @@ -125,7 +170,8 @@ material GpuRaysScan2nd } } -vertex_program laser_retro_vs glsl +// GLSL shaders +vertex_program laser_retro_vs_GLSL glsl { source plain_color_vs.glsl num_clip_distances 1 @@ -138,7 +184,7 @@ vertex_program laser_retro_vs glsl } } -fragment_program laser_retro_fs glsl +fragment_program laser_retro_fs_GLSL glsl { source plain_color_fs.glsl @@ -148,6 +194,39 @@ fragment_program laser_retro_fs glsl } } +// Metal shaders +vertex_program laser_retro_vs_Metal metal +{ + source plain_color_vs.metal + num_clip_distances 1 + + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto worldView worldview_matrix + param_named ignMinClipDistance float 0.0 + } +} + +fragment_program laser_retro_fs_Metal metal +{ + source plain_color_fs.metal + shader_reflection_pair_hint laser_retro_vs_Metal +} + +// Unified shaders +vertex_program laser_retro_vs unified +{ + delegate laser_retro_vs_GLSL + delegate laser_retro_vs_Metal +} + +fragment_program laser_retro_fs unified +{ + delegate laser_retro_fs_GLSL + delegate laser_retro_fs_Metal +} + material LaserRetroSource { // Material has one technique diff --git a/ogre2/src/media/materials/scripts/picker.material b/ogre2/src/media/materials/scripts/picker.material index 2fec2bde3..a849b51b0 100644 --- a/ogre2/src/media/materials/scripts/picker.material +++ b/ogre2/src/media/materials/scripts/picker.material @@ -1,4 +1,5 @@ -vertex_program plaincolor_vs glsl +// GLSL shaders +vertex_program plaincolor_vs_GLSL glsl { source plain_color_vs.glsl num_clip_distances 1 @@ -11,7 +12,7 @@ vertex_program plaincolor_vs glsl } } -fragment_program plaincolor_fs glsl +fragment_program plaincolor_fs_GLSL glsl { source plain_color_fs.glsl @@ -21,6 +22,39 @@ fragment_program plaincolor_fs glsl } } +// Metal shaders +vertex_program plaincolor_vs_Metal metal +{ + source plain_color_vs.metal + num_clip_distances 1 + + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto worldView worldview_matrix + param_named ignMinClipDistance float 0.0 + } +} + +fragment_program plaincolor_fs_Metal metal +{ + source plain_color_fs.metal + shader_reflection_pair_hint plaincolor_vs_Metal +} + +// Unified shaders +vertex_program plaincolor_vs unified +{ + delegate plaincolor_vs_GLSL + delegate plaincolor_vs_Metal +} + +fragment_program plaincolor_fs unified +{ + delegate plaincolor_fs_GLSL + delegate plaincolor_fs_Metal +} + material ign-rendering/plain_color { // Material has one technique diff --git a/ogre2/src/media/materials/scripts/point_cloud_point.material b/ogre2/src/media/materials/scripts/point_cloud_point.material index 1745ab795..d2d81a1e4 100644 --- a/ogre2/src/media/materials/scripts/point_cloud_point.material +++ b/ogre2/src/media/materials/scripts/point_cloud_point.material @@ -15,7 +15,8 @@ * */ -vertex_program PointCloudVS glsl +// GLSL shaders +vertex_program PointCloudVS_GLSL glsl { source point_vs.glsl @@ -26,7 +27,7 @@ vertex_program PointCloudVS glsl } } -fragment_program PointCloudFS glsl +fragment_program PointCloudFS_GLSL glsl { source point_fs.glsl default_params @@ -35,6 +36,37 @@ fragment_program PointCloudFS glsl } } +// Metal shaders +vertex_program PointCloudVS_Metal metal +{ + source point_vs.metal + + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + param_named size float 1.0 + } +} + +fragment_program PointCloudFS_Metal metal +{ + source point_fs.metal + shader_reflection_pair_hint PointCloudVS_Metal +} + +// Unified shaders +vertex_program PointCloudVS unified +{ + delegate PointCloudVS_GLSL + delegate PointCloudVS_Metal +} + +fragment_program PointCloudFS unified +{ + delegate PointCloudFS_GLSL + delegate PointCloudFS_Metal +} + material PointCloudPoint { technique diff --git a/ogre2/src/media/materials/scripts/selection_buffer.material b/ogre2/src/media/materials/scripts/selection_buffer.material index 62c3137d2..18649f55d 100644 --- a/ogre2/src/media/materials/scripts/selection_buffer.material +++ b/ogre2/src/media/materials/scripts/selection_buffer.material @@ -15,7 +15,8 @@ * */ -vertex_program selection_buffer_vs glsl +// GLSL shaders +vertex_program selection_buffer_vs_GLSL glsl { // reuse depth camera vertex shader source depth_camera_vs.glsl @@ -25,7 +26,7 @@ vertex_program selection_buffer_vs glsl } } -fragment_program selection_buffer_fs glsl +fragment_program selection_buffer_fs_GLSL glsl { source selection_buffer_fs.glsl default_params @@ -35,6 +36,36 @@ fragment_program selection_buffer_fs glsl } } +// Metal shaders +vertex_program selection_buffer_vs_Metal metal +{ + // reuse depth camera vertex shader + source depth_camera_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program selection_buffer_fs_Metal metal +{ + source selection_buffer_fs.metal + shader_reflection_pair_hint selection_buffer_vs_Metal +} + +// Unified shaders +vertex_program selection_buffer_vs unified +{ + delegate selection_buffer_vs_GLSL + delegate selection_buffer_vs_Metal +} + +fragment_program selection_buffer_fs unified +{ + delegate selection_buffer_fs_GLSL + delegate selection_buffer_fs_Metal +} + material SelectionBuffer { // Material has one technique diff --git a/ogre2/src/media/materials/scripts/skybox.material b/ogre2/src/media/materials/scripts/skybox.material index 22aebf8f7..416a2c83a 100644 --- a/ogre2/src/media/materials/scripts/skybox.material +++ b/ogre2/src/media/materials/scripts/skybox.material @@ -29,7 +29,7 @@ THE SOFTWARE. // GLSL shaders -vertex_program SkyBox_vs glsl +vertex_program SkyBox_vs_GLSL glsl { source skybox_vs.glsl default_params @@ -38,7 +38,7 @@ vertex_program SkyBox_vs glsl } } -fragment_program SkyBox_fs glsl +fragment_program SkyBox_fs_GLSL glsl { source skybox_fs.glsl default_params @@ -47,6 +47,35 @@ fragment_program SkyBox_fs glsl } } +// Metal shaders +vertex_program SkyBox_vs_Metal metal +{ + source skybox_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program SkyBox_fs_Metal metal +{ + source skybox_fs.metal + shader_reflection_pair_hint SkyBox_vs_Metal +} + +// Unified shaders +vertex_program SkyBox_vs unified +{ + delegate SkyBox_vs_GLSL + delegate SkyBox_vs_Metal +} + +fragment_program SkyBox_fs unified +{ + delegate SkyBox_fs_GLSL + delegate SkyBox_fs_Metal +} + // Material definition material SkyBox { diff --git a/ogre2/src/media/materials/scripts/thermal.material b/ogre2/src/media/materials/scripts/thermal.material index 840c07e70..c6be0f2e1 100644 --- a/ogre2/src/media/materials/scripts/thermal.material +++ b/ogre2/src/media/materials/scripts/thermal.material @@ -15,7 +15,8 @@ * */ -vertex_program ThermalCameraVS glsl +// GLSL shaders +vertex_program ThermalCameraVS_GLSL glsl { source depth_camera_vs.glsl default_params @@ -24,7 +25,7 @@ vertex_program ThermalCameraVS glsl } } -fragment_program ThermalCameraFS glsl +fragment_program ThermalCameraFS_GLSL glsl { source thermal_camera_fs.glsl @@ -35,6 +36,35 @@ fragment_program ThermalCameraFS glsl } } +// Metal shaders +vertex_program ThermalCameraVS_Metal metal +{ + source depth_camera_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program ThermalCameraFS_Metal metal +{ + source thermal_camera_fs.metal + shader_reflection_pair_hint ThermalCameraVS_Metal +} + +// Unified shaders +vertex_program ThermalCameraVS unified +{ + delegate ThermalCameraVS_GLSL + delegate ThermalCameraVS_Metal +} + +fragment_program ThermalCameraFS unified +{ + delegate ThermalCameraFS_GLSL + delegate ThermalCameraFS_Metal +} + material ThermalCamera { technique @@ -57,7 +87,8 @@ material ThermalCamera } } -vertex_program heat_source_vs glsl +// GLSL shaders +vertex_program heat_source_vs_GLSL glsl { source plain_color_vs.glsl num_clip_distances 1 @@ -70,7 +101,7 @@ vertex_program heat_source_vs glsl } } -fragment_program heat_source_fs glsl +fragment_program heat_source_fs_GLSL glsl { source plain_color_fs.glsl @@ -80,6 +111,39 @@ fragment_program heat_source_fs glsl } } +// Metal shaders +vertex_program heat_source_vs_Metal metal +{ + source plain_color_vs.metal + num_clip_distances 1 + + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto worldView worldview_matrix + param_named ignMinClipDistance float 0.0 + } +} + +fragment_program heat_source_fs_Metal metal +{ + source plain_color_fs.metal + shader_reflection_pair_hint ThermalCameraVS_Metal +} + +// Unified shaders +vertex_program heat_source_vs unified +{ + delegate heat_source_vs_GLSL + delegate heat_source_vs_Metal +} + +fragment_program heat_source_fs unified +{ + delegate heat_source_fs_GLSL + delegate heat_source_fs_Metal +} + material ThermalHeatSource { // Material has one technique @@ -103,7 +167,8 @@ material ThermalHeatSource } // copied from gaussian_noise.material -vertex_program HeatSignatureVS glsl +// GLSL shaders +vertex_program HeatSignatureVS_GLSL glsl { source gaussian_noise_vs.glsl default_params @@ -112,7 +177,7 @@ vertex_program HeatSignatureVS glsl } } -fragment_program HeatSignatureFS glsl +fragment_program HeatSignatureFS_GLSL glsl { source heat_signature_fs.glsl default_params @@ -121,6 +186,35 @@ fragment_program HeatSignatureFS glsl } } +// Metal shaders +vertex_program HeatSignatureVS_Metal metal +{ + source gaussian_noise_vs.metal + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + } +} + +fragment_program HeatSignatureFS_Metal metal +{ + source heat_signature_fs.metal + shader_reflection_pair_hint HeatSignatureVS_Metal +} + +// Unified shaders +vertex_program HeatSignatureVS unified +{ + delegate HeatSignatureVS_GLSL + delegate HeatSignatureVS_Metal +} + +fragment_program HeatSignatureFS unified +{ + delegate HeatSignatureFS_GLSL + delegate HeatSignatureFS_Metal +} + material ThermalHeatSignature { technique diff --git a/src/GraphicsAPI.cc b/src/GraphicsAPI.cc new file mode 100644 index 000000000..5ecad1c32 --- /dev/null +++ b/src/GraphicsAPI.cc @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "ignition/rendering/config.hh" +#include "ignition/rendering/GraphicsAPI.hh" +#include + +#include +#include + +using namespace ignition; +using namespace rendering; + +////////////////////////////////////////////////// +IGN_ENUM(graphicsAPIIface, GraphicsAPI, + GraphicsAPI::GRAPHICS_API_BEGIN, + GraphicsAPI::GRAPHICS_API_END, + "UNKNOWN", "OPENGL", "DIRECT3D11", "VULKAN", "METAL") + +////////////////////////////////////////////////// +std::string GraphicsAPIUtils::Str(GraphicsAPI _e) +{ + return graphicsAPIIface.Str(_e); +} + +////////////////////////////////////////////////// +GraphicsAPI GraphicsAPIUtils::Set(const std::string &_str) +{ + // Convert to upper case + std::string str(_str); + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + + // Set the enum + GraphicsAPI e{GraphicsAPI::UNKNOWN}; + graphicsAPIIface.Set(e, str); + return e; +}