From ce84c10139ca73c50af16ed3dc1dcbbdb5498858 Mon Sep 17 00:00:00 2001 From: ahcorde Date: Fri, 19 Mar 2021 23:18:57 +0100 Subject: [PATCH] Ogre 2.2 Signed-off-by: ahcorde --- CMakeLists.txt | 2 +- .../ignition/rendering/ogre2/Ogre2Camera.hh | 1 + .../rendering/ogre2/Ogre2Conversions.hh | 4 +- .../ignition/rendering/ogre2/Ogre2Includes.hh | 58 +- .../ignition/rendering/ogre2/Ogre2Material.hh | 2 +- .../rendering/ogre2/Ogre2MaterialSwitcher.hh | 10 +- .../rendering/ogre2/Ogre2RenderEngine.hh | 9 + .../rendering/ogre2/Ogre2RenderTarget.hh | 10 +- .../ogre2/Ogre2RenderTargetMaterial.hh | 24 +- .../ignition/rendering/ogre2/Ogre2Scene.hh | 2 + .../ignition/rendering/ogre2/Ogre2Storage.hh | 1 + ogre2/src/Ogre2Conversions.cc | 29 +- ogre2/src/Ogre2DepthCamera.cc | 217 ++--- ogre2/src/Ogre2DynamicRenderable.cc | 2 + ogre2/src/Ogre2GaussianNoisePass.cc | 2 +- ogre2/src/Ogre2Geometry.cc | 1 - ogre2/src/Ogre2GpuRays.cc | 357 +++++--- ogre2/src/Ogre2Material.cc | 81 +- ogre2/src/Ogre2MaterialSwitcher.cc | 8 +- ogre2/src/Ogre2Mesh.cc | 1 + ogre2/src/Ogre2RenderTarget.cc | 239 +++--- ogre2/src/Ogre2RenderTargetMaterial.cc | 20 +- ogre2/src/Ogre2Scene.cc | 7 +- ogre2/src/Ogre2SelectionBuffer.cc | 134 +-- ogre2/src/Ogre2ThermalCamera.cc | 152 ++-- ogre2/src/Ogre2Visual.cc | 1 - .../Compositors/GaussianNoise.compositor | 41 - .../Compositors/PbsMaterials.compositor | 67 -- .../Hlms/Common/Any/Cubemap_piece_all.any | 42 +- .../Common/Any/DualParaboloid_piece_ps.any | 17 + .../Any/ReverseDepthHelpers_piece_ps.any | 10 + .../Hlms/Common/Any/ShadowCaster_piece_ps.any | 8 +- .../Hlms/Common/Any/ShadowCaster_piece_vs.any | 22 +- .../Common/Any/UnpackHelpers_piece_all.any | 7 + .../GLSL/CrossPlatformSettings_piece_all.glsl | 110 ++- .../Hlms/Common/GLSL/Matrix_piece_all.glsl | 38 +- .../GLSL/UavCrossPlatform_piece_all.glsl | 21 + .../CrossPlatformSettings_piece_all.glsl | 88 ++ .../Hlms/Common/GLSLES/Matrix_piece_all.glsl | 53 ++ .../GLSLES/QuaternionCode_piece_all.glsl | 55 ++ .../GLSLES/RenderDepthOnly_piece_ps.glsl | 3 + .../HLSL/CrossPlatformSettings_piece_all.hlsl | 98 +++ .../Hlms/Common/HLSL/Matrix_piece_all.hlsl | 35 + .../Common/HLSL/QuaternionCode_piece_all.hlsl | 55 ++ .../Common/HLSL/RenderDepthOnly_piece_ps.hlsl | 31 + .../HLSL/UavCrossPlatform_piece_all.hlsl | 21 + .../CrossPlatformSettings_piece_all.metal | 102 ++- .../Hlms/Common/Metal/Matrix_piece_all.metal | 15 +- .../Metal/RenderDepthOnly_piece_ps.metal | 2 +- .../Metal/UavCrossPlatform_piece_all.metal | 21 + .../Pbs/Any/200.TextureRegisters_piece_vs.any | 30 + .../Hlms/Pbs/Any/AmbientLighting_piece_ps.any | 90 ++ .../Hlms/Pbs/Any/AreaLights_LTC_piece_ps.any | 333 +++++++ .../Hlms/Pbs/Any/AreaLights_piece_ps.any | 285 +++--- .../ForwardPlus_DecalsCubemaps_piece_ps.any | 273 ++++++ .../Pbs/Any/IrradianceField_piece_all.any | 30 + .../Hlms/Pbs/Any/IrradianceField_piece_ps.any | 202 +++++ .../Pbs/Any/IrradianceVolume_piece_ps.any | 79 ++ .../Hlms/Pbs/Any/LightProfiles_piece_ps.any | 55 ++ .../Hlms/Pbs/Any/Main/200.BRDFs_piece_ps.any | 264 ++++++ .../Pbs/Any/Main/200.BlendModes_piece_ps.any | 108 +++ .../Main/200.DetailMaps_piece_ps.any} | 0 .../Pbs/Any/Main/200.ForwardPlus_piece_ps.any | 273 ++++++ .../Pbs/Any/Main/200.Textures_piece_ps.any | 33 + .../Main/500.Structs_piece_vs_piece_ps.any | 439 ++++++++++ .../Pbs/Any/Main/800.PixelShader_piece_ps.any | 809 ++++++++++++++++++ .../Any/Main/800.VertexShader_piece_vs.any | 288 +++++++ .../Pbs/Any/PlanarReflections_piece_all.any | 4 - .../Pbs/Any/PlanarReflections_piece_ps.any | 34 +- .../Hlms/Pbs/Any/Refractions_piece_ps.any | 63 ++ .../Hlms/Pbs/Any/ShadowMapping_piece_ps.any | 169 ++-- .../Hlms/Pbs/Any/ShadowMapping_piece_vs.any | 8 +- .../src/media/Hlms/Pbs/Any/Vct_piece_all.any | 35 + ogre2/src/media/Hlms/Pbs/Any/Vct_piece_ps.any | 455 ++++++++++ .../Hlms/Pbs/GLSL/Forward3D_piece_ps.glsl | 232 +---- .../media/Hlms/Pbs/GLSL/PixelShader_ps.glsl | 583 ++----------- .../media/Hlms/Pbs/GLSL/VertexShader_vs.glsl | 168 +--- .../Pbs/{GLSL => GLSLES}/BRDFs_piece_ps.glsl | 5 +- .../{GLSL => GLSLES}/BlendModes_piece_ps.glsl | 0 .../DetailMaps_piece_ps.glsl} | 0 .../Hlms/Pbs/GLSLES/Forward3D_piece_ps.glsl | 261 ++++++ .../IrradianceVolume_piece_ps.glsl | 0 .../media/Hlms/Pbs/GLSLES/PixelShader_ps.glsl | 624 ++++++++++++++ .../Structs_piece_vs_piece_ps.glsl | 11 +- .../{GLSL => GLSLES}/Textures_piece_ps.glsl | 79 +- .../Hlms/Pbs/GLSLES/VertexShader_vs.glsl | 294 +++++++ .../Hlms/Pbs/HLSL/Forward3D_piece_ps.hlsl | 17 + .../media/Hlms/Pbs/HLSL/PixelShader_ps.hlsl | 188 ++++ .../Hlms/Pbs/HLSL/Textures_piece_ps.hlsl | 11 + .../media/Hlms/Pbs/HLSL/VertexShader_vs.hlsl | 75 ++ .../media/Hlms/Pbs/Metal/BRDFs_piece_ps.metal | 242 ------ .../Hlms/Pbs/Metal/BlendModes_piece_ps.metal | 105 --- .../Hlms/Pbs/Metal/Forward3D_piece_ps.metal | 220 +---- .../Pbs/Metal/IrradianceVolume_piece_ps.metal | 75 -- .../media/Hlms/Pbs/Metal/PixelShader_ps.metal | 548 ++---------- .../Pbs/Metal/Structs_piece_vs_piece_ps.metal | 252 ------ .../Hlms/Pbs/Metal/Textures_piece_ps.metal | 197 +---- .../Hlms/Pbs/Metal/VertexShader_vs.metal | 177 +--- .../Hlms/Unlit/GLSL/BlendModes_piece_ps.glsl | 17 +- .../media/Hlms/Unlit/GLSL/PixelShader_ps.glsl | 4 +- .../Unlit/GLSL/Structs_piece_vs_piece_ps.glsl | 2 +- .../Hlms/Unlit/GLSL/VertexShader_vs.glsl | 4 +- .../Unlit/GLSLES/BlendModes_piece_ps.glsl | 137 +++ .../Hlms/Unlit/GLSLES/PixelShader_ps.glsl | 97 +++ .../GLSLES/Structs_piece_vs_piece_ps.glsl | 66 ++ .../Hlms/Unlit/GLSLES/VertexShader_vs.glsl | 113 +++ .../Hlms/Unlit/HLSL/BlendModes_piece_ps.hlsl | 127 +++ .../media/Hlms/Unlit/HLSL/PixelShader_ps.hlsl | 101 +++ .../Unlit/HLSL/Structs_piece_vs_piece_ps.hlsl | 76 ++ .../Hlms/Unlit/HLSL/VertexShader_vs.hlsl | 101 +++ .../Unlit/Metal/BlendModes_piece_ps.metal | 15 +- .../Hlms/Unlit/Metal/PixelShader_ps.metal | 9 +- .../Hlms/Unlit/Metal/VertexShader_vs.metal | 7 +- 113 files changed, 8257 insertions(+), 3678 deletions(-) delete mode 100644 ogre2/src/media/2.0/scripts/Compositors/GaussianNoise.compositor delete mode 100644 ogre2/src/media/2.0/scripts/Compositors/PbsMaterials.compositor create mode 100644 ogre2/src/media/Hlms/Common/Any/DualParaboloid_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Common/Any/ReverseDepthHelpers_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Common/Any/UnpackHelpers_piece_all.any create mode 100644 ogre2/src/media/Hlms/Common/GLSL/UavCrossPlatform_piece_all.glsl create mode 100644 ogre2/src/media/Hlms/Common/GLSLES/CrossPlatformSettings_piece_all.glsl create mode 100644 ogre2/src/media/Hlms/Common/GLSLES/Matrix_piece_all.glsl create mode 100644 ogre2/src/media/Hlms/Common/GLSLES/QuaternionCode_piece_all.glsl create mode 100644 ogre2/src/media/Hlms/Common/GLSLES/RenderDepthOnly_piece_ps.glsl create mode 100644 ogre2/src/media/Hlms/Common/HLSL/CrossPlatformSettings_piece_all.hlsl create mode 100644 ogre2/src/media/Hlms/Common/HLSL/Matrix_piece_all.hlsl create mode 100644 ogre2/src/media/Hlms/Common/HLSL/QuaternionCode_piece_all.hlsl create mode 100644 ogre2/src/media/Hlms/Common/HLSL/RenderDepthOnly_piece_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Common/HLSL/UavCrossPlatform_piece_all.hlsl create mode 100644 ogre2/src/media/Hlms/Common/Metal/UavCrossPlatform_piece_all.metal create mode 100644 ogre2/src/media/Hlms/Pbs/Any/200.TextureRegisters_piece_vs.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/AmbientLighting_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/AreaLights_LTC_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/ForwardPlus_DecalsCubemaps_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_all.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/IrradianceVolume_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/LightProfiles_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/200.BRDFs_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/200.BlendModes_piece_ps.any rename ogre2/src/media/Hlms/Pbs/{GLSL/DetailMaps_piece_ps.glsl => Any/Main/200.DetailMaps_piece_ps.any} (100%) create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/200.ForwardPlus_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/200.Textures_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/500.Structs_piece_vs_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/800.PixelShader_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Main/800.VertexShader_piece_vs.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Refractions_piece_ps.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Vct_piece_all.any create mode 100644 ogre2/src/media/Hlms/Pbs/Any/Vct_piece_ps.any rename ogre2/src/media/Hlms/Pbs/{GLSL => GLSLES}/BRDFs_piece_ps.glsl (96%) rename ogre2/src/media/Hlms/Pbs/{GLSL => GLSLES}/BlendModes_piece_ps.glsl (100%) rename ogre2/src/media/Hlms/Pbs/{Metal/DetailMaps_piece_ps.metal => GLSLES/DetailMaps_piece_ps.glsl} (100%) create mode 100644 ogre2/src/media/Hlms/Pbs/GLSLES/Forward3D_piece_ps.glsl rename ogre2/src/media/Hlms/Pbs/{GLSL => GLSLES}/IrradianceVolume_piece_ps.glsl (100%) create mode 100644 ogre2/src/media/Hlms/Pbs/GLSLES/PixelShader_ps.glsl rename ogre2/src/media/Hlms/Pbs/{GLSL => GLSLES}/Structs_piece_vs_piece_ps.glsl (95%) rename ogre2/src/media/Hlms/Pbs/{GLSL => GLSLES}/Textures_piece_ps.glsl (56%) create mode 100644 ogre2/src/media/Hlms/Pbs/GLSLES/VertexShader_vs.glsl create mode 100644 ogre2/src/media/Hlms/Pbs/HLSL/Forward3D_piece_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Pbs/HLSL/PixelShader_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Pbs/HLSL/Textures_piece_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Pbs/HLSL/VertexShader_vs.hlsl delete mode 100644 ogre2/src/media/Hlms/Pbs/Metal/BRDFs_piece_ps.metal delete mode 100644 ogre2/src/media/Hlms/Pbs/Metal/BlendModes_piece_ps.metal delete mode 100644 ogre2/src/media/Hlms/Pbs/Metal/IrradianceVolume_piece_ps.metal delete mode 100644 ogre2/src/media/Hlms/Pbs/Metal/Structs_piece_vs_piece_ps.metal create mode 100644 ogre2/src/media/Hlms/Unlit/GLSLES/BlendModes_piece_ps.glsl create mode 100644 ogre2/src/media/Hlms/Unlit/GLSLES/PixelShader_ps.glsl create mode 100644 ogre2/src/media/Hlms/Unlit/GLSLES/Structs_piece_vs_piece_ps.glsl create mode 100644 ogre2/src/media/Hlms/Unlit/GLSLES/VertexShader_vs.glsl create mode 100644 ogre2/src/media/Hlms/Unlit/HLSL/BlendModes_piece_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Unlit/HLSL/PixelShader_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Unlit/HLSL/Structs_piece_vs_piece_ps.hlsl create mode 100644 ogre2/src/media/Hlms/Unlit/HLSL/VertexShader_vs.hlsl diff --git a/CMakeLists.txt b/CMakeLists.txt index d3e4f245b..7ec90d15b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ endif() #-------------------------------------- # Find OGRE2 -ign_find_package(IgnOGRE2 VERSION 2.1.0 +ign_find_package(IgnOGRE2 VERSION 2.2.0 COMPONENTS HlmsPbs HlmsUnlit Overlay REQUIRED_BY ogre2 PRIVATE_FOR ogre2) diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh index 0f891dcdc..eff16dcaf 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh @@ -21,6 +21,7 @@ #include "ignition/rendering/base/BaseCamera.hh" #include "ignition/rendering/ogre2/Ogre2RenderTypes.hh" +#include "ignition/rendering/ogre2/Ogre2Includes.hh" #include "ignition/rendering/ogre2/Ogre2Sensor.hh" namespace Ogre diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh index d4326a1c9..8724141b4 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh @@ -96,10 +96,10 @@ namespace ignition /// \brief Ign-rendering PixelFormat to Ogre PixelFormat /// \param[in] _v Ign-rendering PixelFormat /// return Ogre PixelFormat - public: static Ogre::PixelFormat Convert(PixelFormat _format); + public: static Ogre::PixelFormatGpu Convert(PixelFormat _format); /// \brief A list of ogre pixel formats - private: static const Ogre::PixelFormat ogrePixelFormats[PF_COUNT]; + private: static const Ogre::PixelFormatGpu ogrePixelFormats[PF_COUNT]; }; /// \} } diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh index 1a0bc41fa..cbc981493 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh @@ -27,54 +27,62 @@ // This prevents some deprecation #warning messages on OSX 10.9 #pragma clang diagnostic ignored "-W#warnings" +#include + #include #include -#include -#include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include +#include +#include #include #include #include -#include -#include #include -#include #include -#include -#include +#include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include +#include +#include #include #include #include -#include #include #include #include #include #include #include +#include +#include +#include -#include -#include #include #include diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh index b7d6d90ef..224d2a274 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh @@ -232,7 +232,7 @@ namespace ignition /// \brief Get a pointer to the ogre texture by name /// \return Ogre texture - protected: virtual Ogre::TexturePtr Texture(const std::string &_name); + protected: virtual Ogre::TextureGpu *Texture(const std::string &_name); /// \brief Updates the material transparency in the engine, /// based on transparency and diffuse alpha values diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh index de8471190..be58b53eb 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh @@ -38,7 +38,7 @@ namespace ignition /// \brief Helper class to assign unique colors to renderables class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2MaterialSwitcher : - public Ogre::RenderTargetListener + public Ogre::Camera::Listener { /// \brief Constructor public: explicit Ogre2MaterialSwitcher(Ogre2ScenePtr _scene); @@ -57,14 +57,14 @@ namespace ignition /// \brief Ogre's pre render update callback /// \param[in] _evt Ogre render target event containing information about /// the source render target. - public: virtual void preRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt); + public: virtual void cameraPreRenderScene( + Ogre::Camera *_cam) override; /// \brief Ogre's post render update callback /// \param[in] _evt Ogre render target event containing information about /// the source render target. - public: virtual void postRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt); + public: virtual void cameraPostRenderScene ( + Ogre::Camera * _cam) override; /// \brief Current unique color value private: ignition::math::Color currentColor; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh index 677548f98..b484a1a32 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh @@ -138,6 +138,9 @@ namespace ignition /// \brief Create GL context private: void CreateContext(); + /// \brief Register Hlms + private: void registerHlms(); + /// \brief Create ogre root private: void CreateRoot(); @@ -192,6 +195,12 @@ namespace ignition /// \brief Dummy window Id needed for linux platform private: uint64_t dummyWindowId = 0u; + /// \brief Ogre Window + private: Ogre::Window * window; + + /// \brief return the ogre window + public: Ogre::Window *getWindow(){ return this->window; } + /// \brief True to use the current opengl context private: bool useCurrentGLContext = false; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh index 1433b8646..7a29c24c1 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh @@ -106,7 +106,7 @@ namespace ignition public: void SetMaterial(MaterialPtr _material); /// \brief Get a pointer to the ogre render target - public: virtual Ogre::RenderTarget *RenderTarget() const = 0; + public: virtual Ogre::TextureGpu *RenderTarget() const = 0; /// \brief Get visibility mask for the viewport associated with this /// render target @@ -239,7 +239,7 @@ namespace ignition public: virtual unsigned int GLId() const override; // Documentation inherited. - public: virtual Ogre::RenderTarget *RenderTarget() const override; + public: virtual Ogre::TextureGpu *RenderTarget() const override; // Documentation inherited. protected: virtual void RebuildTarget() override; @@ -251,7 +251,7 @@ namespace ignition protected: virtual void BuildTarget(); /// \brief Pointer to the internal ogre render texture object - protected: Ogre::Texture *ogreTexture = nullptr; + protected: Ogre::TextureGpu *ogreTexture = nullptr; /// \brief Make scene our friend so it can create a ogre2 render texture private: friend class Ogre2Scene; @@ -271,7 +271,7 @@ namespace ignition public: virtual void Destroy() override; // Documentation inherited. - public: virtual Ogre::RenderTarget *RenderTarget() const override; + public: virtual Ogre::TextureGpu *RenderTarget() const override; // Documentation inherited. protected: virtual void RebuildTarget() override; @@ -280,7 +280,7 @@ namespace ignition protected: virtual void BuildTarget(); /// \brief Pointer to the internal ogre render target object - protected: Ogre::RenderTarget *ogreRenderWindow = nullptr; + protected: Ogre::TextureGpu *ogreRenderWindow = nullptr; /// \brief Make scene our friend so it can create a ogre2 render window private: friend class Ogre2Scene; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh index 4f5eb1369..66349b707 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh @@ -42,7 +42,7 @@ namespace ignition /// handleSchemeNotFound which returns the first supported technique on the /// material provided to this class's constructor. class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2RenderTargetMaterial : - public Ogre::RenderTargetListener, + public Ogre::Camera::Listener, public Ogre::MaterialManager::Listener { /// \brief constructor @@ -50,22 +50,20 @@ namespace ignition /// \param[in] _renderTarget the RenderTarget this should apply to /// \param[in] _material the material to apply to all renderables public: Ogre2RenderTargetMaterial(Ogre::SceneManager *_scene, - Ogre::RenderTarget *_renderTarget, Ogre::Material *_material); + Ogre::Camera *renderTexture, Ogre::Material *_material); /// \brief destructor public: ~Ogre2RenderTargetMaterial(); - /// \brief Callback when a render target is about to be rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void preRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camera is about to be rendered + /// \param[in] _cam Ogre camera. + private: virtual void cameraPreRenderScene( + Ogre::Camera *_cam) override; - /// \brief Callback when a render target is finisned being rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void postRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camera is finisned being rendered + /// \param[in] _evt Ogre camera + private: virtual void cameraPostRenderScene( + Ogre::Camera *_evt) override; /// \brief Ogre callback that assigned same material to all renderables /// when the requested scheme is not found @@ -86,7 +84,7 @@ namespace ignition private: Ogre::SceneManager *scene = nullptr; /// \brief render target that should see a uniform material - private: Ogre::RenderTarget *renderTarget = nullptr; + private: Ogre::Camera *renderCamera = nullptr; /// \brief material that should be applied to all objects private: Ogre::Material *material = nullptr; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh index 64ecc0386..a4ac638f1 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh @@ -26,6 +26,8 @@ #include "ignition/rendering/ogre2/Export.hh" +// #include "Compositor/OgreCompositorManager2.h" + namespace Ogre { class Root; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Storage.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Storage.hh index b37291179..6a9661985 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Storage.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Storage.hh @@ -23,6 +23,7 @@ #include "ignition/rendering/ogre2/Ogre2Light.hh" #include "ignition/rendering/ogre2/Ogre2Mesh.hh" +#include "ignition/rendering/ogre2/Ogre2Geometry.hh" #include "ignition/rendering/ogre2/Ogre2Node.hh" #include "ignition/rendering/ogre2/Ogre2Sensor.hh" #include "ignition/rendering/ogre2/Ogre2Scene.hh" diff --git a/ogre2/src/Ogre2Conversions.cc b/ogre2/src/Ogre2Conversions.cc index 6ba9e2a7e..7fc16c12b 100644 --- a/ogre2/src/Ogre2Conversions.cc +++ b/ogre2/src/Ogre2Conversions.cc @@ -20,32 +20,32 @@ using namespace ignition; using namespace rendering; ////////////////////////////////////////////////// -const Ogre::PixelFormat Ogre2Conversions::ogrePixelFormats[PF_COUNT] = +const Ogre::PixelFormatGpu Ogre2Conversions::ogrePixelFormats[PF_COUNT] = { // UKNOWN - Ogre::PF_UNKNOWN, + Ogre::PFG_UNKNOWN, // L8 - Ogre::PF_L8, + Ogre::PFG_R8_UNORM, // R8G8B8 - Ogre::PF_BYTE_RGB, + Ogre::PFG_RGB8_UNORM, // B8G8R8 - Ogre::PF_BYTE_BGR, + Ogre::PFG_BGR8_UNORM, // BAYER_RGGB8 - Ogre::PF_BYTE_RGB, + Ogre::PFG_RGB8_UNORM, // BAYER_BGGR8 - Ogre::PF_BYTE_RGB, + Ogre::PFG_RGB8_UNORM, // BAYER_GBGR8 - Ogre::PF_BYTE_RGB, + Ogre::PFG_RGB8_UNORM, // BAYER_GRGB8 - Ogre::PF_BYTE_RGB, + Ogre::PFG_RGB8_UNORM, // PF_FLOAT32_R - Ogre::PF_FLOAT32_R, + Ogre::PFG_R32_FLOAT, // PF_FLOAT32_RGBA - Ogre::PF_FLOAT32_RGBA, + Ogre::PFG_RGBA32_FLOAT, // PF_FLOAT32_RGB - Ogre::PF_FLOAT32_RGB, + Ogre::PFG_RGB32_FLOAT, // PF_L16 - Ogre::PF_L16 + Ogre::PFG_R16_UNORM }; ////////////////////////////////////////////////// @@ -97,7 +97,7 @@ math::Angle Ogre2Conversions::Convert(const Ogre::Radian &_angle) } ////////////////////////////////////////////////// -Ogre::PixelFormat Ogre2Conversions::Convert(PixelFormat _format) +Ogre::PixelFormatGpu Ogre2Conversions::Convert(PixelFormat _format) { return Ogre2Conversions::ogrePixelFormats[_format]; } @@ -119,4 +119,3 @@ Ogre::Matrix4 Ogre2Conversions::Convert(const math::Matrix4d &_m) _m(2, 0), _m(2, 1), _m(2, 2), _m(2, 3), _m(3, 0), _m(3, 1), _m(3, 2), _m(3, 3)); } - diff --git a/ogre2/src/Ogre2DepthCamera.cc b/ogre2/src/Ogre2DepthCamera.cc index 5f4b12b4a..1aac5d83a 100644 --- a/ogre2/src/Ogre2DepthCamera.cc +++ b/ogre2/src/Ogre2DepthCamera.cc @@ -102,7 +102,7 @@ class ignition::rendering::Ogre2DepthCameraPrivate public: Ogre::CompositorWorkspace *ogreCompositorWorkspace = nullptr; /// \brief Output texture with depth and color data - public: Ogre::TexturePtr ogreDepthTexture; + public: Ogre::TextureGpu * ogreDepthTexture; /// \brief Dummy render texture for the depth data public: RenderTexturePtr depthTexture; @@ -229,7 +229,7 @@ void Ogre2DepthGaussianNoisePass::CreateRenderPass() static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = materialName; - passQuad->addQuadTextureSource(0, "rt_input", 0); + passQuad->addQuadTextureSource(0, "rt_input"); } nodeDef->mapOutputChannel(0, "rt_output"); nodeDef->mapOutputChannel(1, "rt_input"); @@ -293,8 +293,9 @@ void Ogre2DepthCamera::Destroy() // remove depth texture, material, compositor if (this->dataPtr->ogreDepthTexture) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->ogreDepthTexture->getName()); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->ogreDepthTexture); + this->dataPtr->ogreDepthTexture = nullptr; } if (this->dataPtr->ogreCompositorWorkspace) { @@ -412,10 +413,9 @@ void Ogre2DepthCamera::CreateDepthTexture() // The other params are used to clamp the range output // Use the 'real' clip distance here so depth can be // linearized correctly - double projectionA = farPlane / - (farPlane - nearPlane); - double projectionB = (-farPlane * nearPlane) / - (farPlane - nearPlane); + Ogre::Vector2 projectionAB = this->ogreCamera->getProjectionParamsAB(); + double projectionA = projectionAB.x; + double projectionB = projectionAB.y; projectionB /= farPlane; psParams->setNamedConstant("projectionParams", Ogre::Vector2(projectionA, projectionB)); @@ -479,7 +479,7 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::TextureUnitState *texUnit = mat->getTechnique(0u)->getPass(0u)->getTextureUnitState(0u); texUnit->setTextureName(backgroundMaterial->EnvironmentMap(), - Ogre::TEX_TYPE_CUBE_MAP); + Ogre::TextureTypes::TypeCube); } // Create depth camera compositor @@ -585,119 +585,124 @@ void Ogre2DepthCamera::CreateDepthTexture() ogreCompMgr->addNodeDefinition(baseNodeDefName); Ogre::TextureDefinitionBase::TextureDefinition *rt0TexDef = baseNodeDef->addTextureDefinition("rt0"); - rt0TexDef->textureType = Ogre::TEX_TYPE_2D; + rt0TexDef->textureType = Ogre::TextureTypes::Type2D; rt0TexDef->width = 0; rt0TexDef->height = 0; - rt0TexDef->depth = 1; + rt0TexDef->depthOrSlices = 1; rt0TexDef->numMipmaps = 0; rt0TexDef->widthFactor = 1; rt0TexDef->heightFactor = 1; - rt0TexDef->formatList = {Ogre::PF_FLOAT32_RGBA}; - rt0TexDef->fsaa = 0; - rt0TexDef->uav = false; - rt0TexDef->automipmaps = false; - rt0TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + rt0TexDef->format = Ogre::PFG_RGBA32_FLOAT; + rt0TexDef->textureFlags |= !Ogre::TextureFlags::Uav; rt0TexDef->depthBufferId = Ogre::DepthBuffer::POOL_INVALID; - rt0TexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - rt0TexDef->fsaaExplicitResolve = false; + rt0TexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + rt0TexDef->fsaa = "0"; + + Ogre::RenderTargetViewDef *rtv0 = baseNodeDef->addRenderTextureView("rt0"); + rtv0->setForTextureDefinition("rt0", rt0TexDef); Ogre::TextureDefinitionBase::TextureDefinition *rt1TexDef = baseNodeDef->addTextureDefinition("rt1"); - rt1TexDef->textureType = Ogre::TEX_TYPE_2D; + rt1TexDef->textureType = Ogre::TextureTypes::Type2D; rt1TexDef->width = 0; rt1TexDef->height = 0; - rt1TexDef->depth = 1; + rt1TexDef->depthOrSlices = 1; rt1TexDef->numMipmaps = 0; rt1TexDef->widthFactor = 1; rt1TexDef->heightFactor = 1; - rt1TexDef->formatList = {Ogre::PF_FLOAT32_RGBA}; - rt1TexDef->fsaa = 0; - rt1TexDef->uav = false; - rt1TexDef->automipmaps = false; - rt1TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + rt1TexDef->format = Ogre::PFG_RGBA32_FLOAT; + rt1TexDef->textureFlags |= !Ogre::TextureFlags::Uav; rt1TexDef->depthBufferId = Ogre::DepthBuffer::POOL_INVALID; - rt1TexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - rt1TexDef->fsaaExplicitResolve = false; + rt1TexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + rt1TexDef->fsaa = "0"; + + Ogre::RenderTargetViewDef *rtv1 = baseNodeDef->addRenderTextureView("rt1"); + rtv1->setForTextureDefinition("rt1", rt1TexDef); Ogre::TextureDefinitionBase::TextureDefinition *depthTexDef = baseNodeDef->addTextureDefinition("depthTexture"); - depthTexDef->textureType = Ogre::TEX_TYPE_2D; + depthTexDef->textureType = Ogre::TextureTypes::Type2D; depthTexDef->width = 0; depthTexDef->height = 0; - depthTexDef->depth = 1; + depthTexDef->depthOrSlices = 1; depthTexDef->numMipmaps = 0; depthTexDef->widthFactor = 1; depthTexDef->heightFactor = 1; - depthTexDef->formatList = {Ogre::PF_D32_FLOAT}; - depthTexDef->fsaa = 0; - depthTexDef->uav = false; - depthTexDef->automipmaps = false; - depthTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + depthTexDef->format = Ogre::PFG_D32_FLOAT; + depthTexDef->textureFlags |= !Ogre::TextureFlags::Uav; depthTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - depthTexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - depthTexDef->fsaaExplicitResolve = false; + depthTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + depthTexDef->fsaa = "0"; + + Ogre::RenderTargetViewDef *rtvDepth = + baseNodeDef->addRenderTextureView("depthTexture"); + rtvDepth->setForTextureDefinition("depthTexture", depthTexDef ); Ogre::TextureDefinitionBase::TextureDefinition *colorTexDef = baseNodeDef->addTextureDefinition("colorTexture"); - colorTexDef->textureType = Ogre::TEX_TYPE_2D; + colorTexDef->textureType = Ogre::TextureTypes::Type2D; colorTexDef->width = 0; colorTexDef->height = 0; - colorTexDef->depth = 1; + colorTexDef->depthOrSlices = 1; colorTexDef->numMipmaps = 0; colorTexDef->widthFactor = 1; colorTexDef->heightFactor = 1; - colorTexDef->formatList = {Ogre::PF_R8G8B8}; - colorTexDef->fsaa = 0; - colorTexDef->uav = false; - colorTexDef->automipmaps = false; + colorTexDef->format = Ogre::PFG_RGB8_UNORM; // Enable gamma write to avoid discretization in the color values // Note we are using low level materials in quad pass so also had to perform // gamma correction in the fragment shaders (depth_camera_fs.glsl) - colorTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolTrue; + colorTexDef->textureFlags |= !Ogre::TextureFlags::Uav; colorTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - colorTexDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + colorTexDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; colorTexDef->preferDepthTexture = true; - colorTexDef->fsaaExplicitResolve = false; + colorTexDef->fsaa = "0"; + + Ogre::RenderTargetViewDef *rtvColor = + baseNodeDef->addRenderTextureView("colorTexture"); + rtvColor->setForTextureDefinition("colorTexture", colorTexDef); Ogre::TextureDefinitionBase::TextureDefinition *particleTexDef = baseNodeDef->addTextureDefinition("particleTexture"); - particleTexDef->textureType = Ogre::TEX_TYPE_2D; + particleTexDef->textureType = Ogre::TextureTypes::Type2D; particleTexDef->width = 0; particleTexDef->height = 0; - particleTexDef->depth = 1; + particleTexDef->depthOrSlices = 1; particleTexDef->numMipmaps = 0; particleTexDef->widthFactor = 0.5; particleTexDef->heightFactor = 0.5; - particleTexDef->formatList = {Ogre::PF_L8}; - particleTexDef->fsaa = 0; - particleTexDef->uav = false; - particleTexDef->automipmaps = false; - particleTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + particleTexDef->format = Ogre::PFG_R8_UNORM; + particleTexDef->textureFlags |= !Ogre::TextureFlags::Uav; particleTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - particleTexDef->depthBufferFormat = Ogre::PF_UNKNOWN; + particleTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; particleTexDef->preferDepthTexture = false; - particleTexDef->fsaaExplicitResolve = false; + particleTexDef->fsaa = "0"; + + Ogre::RenderTargetViewDef *rtvParticleTexture = + baseNodeDef->addRenderTextureView("particleTexture"); + rtvParticleTexture->setForTextureDefinition( + "particleTexture", particleTexDef); Ogre::TextureDefinitionBase::TextureDefinition *particleDepthTexDef = baseNodeDef->addTextureDefinition("particleDepthTexture"); - particleDepthTexDef->textureType = Ogre::TEX_TYPE_2D; + particleDepthTexDef->textureType = Ogre::TextureTypes::Type2D; particleDepthTexDef->width = 0; particleDepthTexDef->height = 0; - particleDepthTexDef->depth = 1; + particleDepthTexDef->depthOrSlices = 1; particleDepthTexDef->numMipmaps = 0; particleDepthTexDef->widthFactor = 0.5; particleDepthTexDef->heightFactor = 0.5; - particleDepthTexDef->formatList = {Ogre::PF_D32_FLOAT}; - particleDepthTexDef->fsaa = 0; - particleDepthTexDef->uav = false; - particleDepthTexDef->automipmaps = false; - particleDepthTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + particleDepthTexDef->format = Ogre::PFG_D32_FLOAT; particleDepthTexDef->depthBufferId = Ogre::DepthBuffer::POOL_NON_SHAREABLE; - particleDepthTexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - particleDepthTexDef->fsaaExplicitResolve = false; + particleDepthTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + particleDepthTexDef->fsaa = "0"; + particleDepthTexDef->textureFlags |= !Ogre::TextureFlags::Uav; - baseNodeDef->setNumTargetPass(5); + Ogre::RenderTargetViewDef *rtvparticleDepthTex = + baseNodeDef->addRenderTextureView("particleDepthTexture"); + rtvparticleDepthTex->setForTextureDefinition( + "particleDepthTexture", particleDepthTexDef); + baseNodeDef->setNumTargetPass(5); Ogre::CompositorTargetDef *colorTargetDef = baseNodeDef->addTargetPass("colorTexture"); @@ -710,8 +715,8 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue( - Ogre2Conversions::Convert(this->Scene()->BackgroundColor())); + passClear->setAllClearColours(Ogre::ColourValue( + Ogre2Conversions::Convert(this->Scene()->BackgroundColor()))); if (validBackground) { @@ -747,8 +752,10 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( depthTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); + passClear->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); // scene pass Ogre::CompositorPassSceneDef *passScene = @@ -767,7 +774,7 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( particleTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue::Black; + passClear->setAllClearColours(Ogre::ColourValue::Black); // scene pass Ogre::CompositorPassSceneDef *passScene = @@ -785,8 +792,10 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( particleDepthTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); + passClear->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); // scene pass Ogre::CompositorPassSceneDef *passScene = @@ -805,18 +814,18 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( inTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); + passClear->setAllClearColours(Ogre::ColourValue(this->FarClipPlane(), + this->FarClipPlane(), this->FarClipPlane())); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = this->dataPtr->depthMaterial->getName(); - passQuad->addQuadTextureSource(0, "depthTexture", 0); - passQuad->addQuadTextureSource(1, "colorTexture", 0); - passQuad->addQuadTextureSource(2, "particleTexture", 0); - passQuad->addQuadTextureSource(3, "particleDepthTexture", 0); + passQuad->addQuadTextureSource(0, "depthTexture"); + passQuad->addQuadTextureSource(1, "colorTexture"); + passQuad->addQuadTextureSource(2, "particleTexture"); + passQuad->addQuadTextureSource(3, "particleDepthTexture"); passQuad->mFrustumCorners = Ogre::CompositorPassQuadDef::VIEW_SPACE_CORNERS; } @@ -867,15 +876,18 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorPassClearDef *passClear = static_cast( outputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); + passClear->setAllClearColours( + Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( outputTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = this->dataPtr->depthFinalMaterial->getName(); - passQuad->addQuadTextureSource(0, "rt_input", 0); + passQuad->addQuadTextureSource(0, "rt_input"); } finalNodeDef->mapOutputChannel(0, "rt_output"); @@ -902,21 +914,32 @@ void Ogre2DepthCamera::CreateDepthTexture() << " for " << this->Name(); } + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); // create render texture - these textures pack the range data this->dataPtr->ogreDepthTexture = - Ogre::TextureManager::getSingleton().createManual( - this->Name() + "_depth", "General", Ogre::TEX_TYPE_2D, - this->ImageWidth(), this->ImageHeight(), 1, 0, - Ogre::PF_FLOAT32_RGBA, Ogre::TU_RENDERTARGET, - 0, false, 0, Ogre::BLANKSTRING, false, true); + textureMgr->createOrRetrieveTexture( + this->Name() + "_depth", + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->dataPtr->ogreDepthTexture->setResolution( + this->ImageWidth(), this->ImageHeight()); + this->dataPtr->ogreDepthTexture->setNumMipmaps(1u); + this->dataPtr->ogreDepthTexture->setPixelFormat( + Ogre::PFG_RGBA32_FLOAT); - Ogre::RenderTarget *rt = - this->dataPtr->ogreDepthTexture->getBuffer()->getRenderTarget(); + this->dataPtr->ogreDepthTexture->scheduleTransitionTo( + Ogre::GpuResidency::Resident); // create compositor worksspace this->dataPtr->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - rt, this->ogreCamera, wsDefName, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + this->dataPtr->ogreDepthTexture, + this->ogreCamera, + wsDefName, + false); } ////////////////////////////////////////////////// @@ -955,22 +978,21 @@ void Ogre2DepthCamera::PostRender() unsigned int height = this->ImageHeight(); PixelFormat format = PF_FLOAT32_RGBA; - Ogre::PixelFormat imageFormat = Ogre2Conversions::Convert(format); + Ogre::PixelFormatGpu imageFormat = Ogre2Conversions::Convert(format); - size_t size = Ogre::PixelUtil::getMemorySize(width, height, 1, imageFormat); int len = width * height; unsigned int channelCount = PixelUtil::ChannelCount(format); + Ogre::Image2 image; + image.convertFromTexture(this->dataPtr->ogreDepthTexture, 0u, 0u); + float * depthBufferTmp = static_cast(image.getRawBuffer()); if (!this->dataPtr->depthBuffer) { this->dataPtr->depthBuffer = new float[len * channelCount]; } - Ogre::PixelBox dstBox(width, height, - 1, imageFormat, this->dataPtr->depthBuffer); - // blit data from gpu to cpu - auto rt = this->dataPtr->ogreDepthTexture->getBuffer()->getRenderTarget(); - rt->copyContentsToMemory(dstBox, Ogre::RenderTarget::FB_AUTO); + memcpy(this->dataPtr->depthBuffer, depthBufferTmp, + len * channelCount * sizeof(float)); if (!this->dataPtr->depthImage) { @@ -997,7 +1019,8 @@ void Ogre2DepthCamera::PostRender() // point cloud data if (this->dataPtr->newRgbPointCloud.ConnectionCount() > 0u) { - memcpy(this->dataPtr->pointCloudImage, this->dataPtr->depthBuffer, size); + memcpy(this->dataPtr->pointCloudImage, + this->dataPtr->depthBuffer, len * channelCount * sizeof(float)); this->dataPtr->newRgbPointCloud( this->dataPtr->pointCloudImage, width, height, channelCount, "PF_FLOAT32_RGBA"); diff --git a/ogre2/src/Ogre2DynamicRenderable.cc b/ogre2/src/Ogre2DynamicRenderable.cc index f6590e13d..2c9f9f599 100644 --- a/ogre2/src/Ogre2DynamicRenderable.cc +++ b/ogre2/src/Ogre2DynamicRenderable.cc @@ -32,6 +32,8 @@ #include "ignition/rendering/ogre2/Ogre2RenderEngine.hh" #include "ignition/rendering/ogre2/Ogre2Scene.hh" +#include "Vao/OgreVaoManager.h" + /// \brief Private implementation class ignition::rendering::Ogre2DynamicRenderablePrivate { diff --git a/ogre2/src/Ogre2GaussianNoisePass.cc b/ogre2/src/Ogre2GaussianNoisePass.cc index d85003401..f766fc8c7 100644 --- a/ogre2/src/Ogre2GaussianNoisePass.cc +++ b/ogre2/src/Ogre2GaussianNoisePass.cc @@ -162,7 +162,7 @@ void Ogre2GaussianNoisePass::CreateRenderPass() static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = materialName; - passQuad->addQuadTextureSource(0, "rt_input", 0); + passQuad->addQuadTextureSource(0, "rt_input"); } nodeDef->mapOutputChannel(0, "rt_output"); nodeDef->mapOutputChannel(1, "rt_input"); diff --git a/ogre2/src/Ogre2Geometry.cc b/ogre2/src/Ogre2Geometry.cc index 007b1f7e4..759fe3b97 100644 --- a/ogre2/src/Ogre2Geometry.cc +++ b/ogre2/src/Ogre2Geometry.cc @@ -16,7 +16,6 @@ */ #include "ignition/rendering/ogre2/Ogre2Geometry.hh" -#include "ignition/rendering/ogre2/Ogre2Scene.hh" #include "ignition/rendering/ogre2/Ogre2Visual.hh" using namespace ignition; diff --git a/ogre2/src/Ogre2GpuRays.cc b/ogre2/src/Ogre2GpuRays.cc index 0d19589fa..d7b6c75fc 100644 --- a/ogre2/src/Ogre2GpuRays.cc +++ b/ogre2/src/Ogre2GpuRays.cc @@ -42,7 +42,7 @@ inline namespace IGNITION_RENDERING_VERSION_NAMESPACE { // /// \brief Helper class for switching the ogre item's material to laser retro /// source material when a thermal camera is being rendered. -class Ogre2LaserRetroMaterialSwitcher : public Ogre::RenderTargetListener +class Ogre2LaserRetroMaterialSwitcher : public Ogre::Camera::Listener { /// \brief constructor /// \param[in] _scene the scene manager responsible for rendering @@ -51,17 +51,15 @@ class Ogre2LaserRetroMaterialSwitcher : public Ogre::RenderTargetListener /// \brief destructor public: ~Ogre2LaserRetroMaterialSwitcher() = default; - /// \brief Callback when a render target is about to be rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void preRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camera is about to be rendered + /// \param[in] _evt Ogre camera which is about to render + private: virtual void cameraPreRenderScene( + Ogre::Camera *_cam) override; - /// \brief Callback when a render target is finisned being rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void postRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camera is finisned being rendered + /// \param[in] _evt Ogre camera which has already rendered + private: virtual void cameraPostRenderScene( + Ogre::Camera *_cam) override; /// \brief Scene manager private: Ogre2ScenePtr scene = nullptr; @@ -112,7 +110,7 @@ class ignition::rendering::Ogre2GpuRaysPrivate public: Ogre::Camera *cubeCam[6]; /// \brief Texture packed with cubemap face and uv data - public: Ogre::TexturePtr cubeUVTexture; + public: Ogre::TextureGpu *cubeUVTexture = nullptr; /// \brief Set of cubemap faces that are needed to generate the final /// range data @@ -137,10 +135,10 @@ class ignition::rendering::Ogre2GpuRaysPrivate public: Ogre::CompositorWorkspace *ogreCompositorWorkspace2nd = nullptr; /// \brief An array of first pass textures. One for each cubemap camera. - public: Ogre::TexturePtr firstPassTextures[6]; + public: Ogre::TextureGpu * firstPassTextures[6]; /// \brief Second pass texture. - public: Ogre::TexturePtr secondPassTexture; + public: Ogre::TextureGpu * secondPassTexture = nullptr; /// \brief Pointer to the ogre camera public: Ogre::Camera *ogreCamera = nullptr; @@ -191,8 +189,8 @@ Ogre2LaserRetroMaterialSwitcher::Ogre2LaserRetroMaterialSwitcher( } ////////////////////////////////////////////////// -void Ogre2LaserRetroMaterialSwitcher::preRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2LaserRetroMaterialSwitcher::cameraPreRenderScene( + Ogre::Camera * /*_cam*/) { // swap item to use v1 shader material // Note: keep an eye out for performance impact on switching materials @@ -281,8 +279,8 @@ void Ogre2LaserRetroMaterialSwitcher::preRenderTargetUpdate( } ////////////////////////////////////////////////// -void Ogre2LaserRetroMaterialSwitcher::postRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2LaserRetroMaterialSwitcher::cameraPostRenderScene( + Ogre::Camera * /*_cam*/) { // restore item to use hlms material for (auto it : this->datablockMap) @@ -341,15 +339,15 @@ void Ogre2GpuRays::Destroy() this->dataPtr->gpuRaysScan = nullptr; } + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); if (this->dataPtr->cubeUVTexture) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->cubeUVTexture->getName()); - this->dataPtr->cubeUVTexture.reset(); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->cubeUVTexture); + this->dataPtr->cubeUVTexture = nullptr; } - auto engine = Ogre2RenderEngine::Instance(); - auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); // remove 1st pass textures, material, compositors @@ -357,9 +355,9 @@ void Ogre2GpuRays::Destroy() { if (this->dataPtr->firstPassTextures[i]) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->firstPassTextures[i]->getName()); - this->dataPtr->firstPassTextures[i].reset(); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->firstPassTextures[i]); + this->dataPtr->firstPassTextures[i] = nullptr; } if (this->dataPtr->ogreCompositorWorkspace1st[i]) { @@ -387,9 +385,9 @@ void Ogre2GpuRays::Destroy() // remove 2nd pass texture, material, compositor if (this->dataPtr->secondPassTexture) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->secondPassTexture->getName()); - this->dataPtr->secondPassTexture.reset(); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->secondPassTexture); + this->dataPtr->secondPassTexture = nullptr; } if (this->dataPtr->matSecondPass) @@ -424,7 +422,7 @@ void Ogre2GpuRays::CreateRenderTexture() void Ogre2GpuRays::CreateCamera() { // Create ogre camera object - Ogre::SceneManager *ogreSceneManager = this->scene->OgreSceneManager(); + Ogre::SceneManager *ogreSceneManager = this->scene->OgreSceneManager(); if (ogreSceneManager == nullptr) { ignerr << "Scene manager cannot be obtained" << std::endl; @@ -533,24 +531,40 @@ void Ogre2GpuRays::CreateSampleTexture() // G: v coordinate on the cubemap face // B: cubemap face index // this texture is passed to the 2nd pass fragment shader + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); std::string texName = this->Name() + "_samplerTex"; this->dataPtr->cubeUVTexture = - Ogre::TextureManager::getSingleton().createManual( - texName, - "General", - Ogre::TEX_TYPE_2D, - this->dataPtr->w2nd, - this->dataPtr->h2nd, - 0, - Ogre::PF_FLOAT32_RGB); - Ogre::v1::HardwarePixelBufferSharedPtr pixelBuffer = - this->dataPtr->cubeUVTexture->getBuffer(); - // fill the texture - pixelBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL); - const Ogre::PixelBox &pixelBox = pixelBuffer->getCurrentLock(); - float *pDest = static_cast(pixelBox.data); + textureMgr->createOrRetrieveTexture( + texName, + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::ManualTexture, + Ogre::TextureTypes::Type2D, + Ogre::BLANKSTRING, + 0u); + + this->dataPtr->cubeUVTexture->setTextureType(Ogre::TextureTypes::Type2D); + this->dataPtr->cubeUVTexture->setResolution( + this->dataPtr->w2nd, this->dataPtr->h2nd); + this->dataPtr->cubeUVTexture->setNumMipmaps(1u); + this->dataPtr->cubeUVTexture->setPixelFormat(Ogre::PFG_RGB32_FLOAT); + + const Ogre::uint32 rowAlignment = 1u; + const size_t dataSize = Ogre::PixelFormatGpuUtils::getSizeBytes( + this->dataPtr->cubeUVTexture->getWidth(), + this->dataPtr->cubeUVTexture->getHeight(), + this->dataPtr->cubeUVTexture->getDepth(), + this->dataPtr->cubeUVTexture->getNumSlices(), + this->dataPtr->cubeUVTexture->getPixelFormat(), + rowAlignment); + + const size_t bytesPerRow = this->dataPtr->cubeUVTexture->_getSysRamCopyBytesPerRow( 0 ); + float *pDest = reinterpret_cast( + OGRE_MALLOC_SIMD(dataSize, Ogre::MEMCATEGORY_RESOURCE)); double v = vmin; + int index = 0; for (unsigned int i = 0; i < this->dataPtr->h2nd; ++i) { double h = min; @@ -568,18 +582,51 @@ void Ogre2GpuRays::CreateSampleTexture() // igndbg << "p(" << pitch << ") y(" << yaw << "): " << dir << " | " // << uv << " | " << faceIdx << std::endl; // u - *pDest++ = uv.X(); + pDest[index++] = uv.X(); // v - *pDest++ = uv.Y(); + pDest[index++] = uv.Y(); // face - *pDest++ = faceIdx; + pDest[index++] = faceIdx; - h += hStep; + h += hStep; } v += vStep; } - - pixelBuffer->unlock(); + this->dataPtr->cubeUVTexture->_transitionTo( + Ogre::GpuResidency::Resident, + reinterpret_cast(pDest) ); + this->dataPtr->cubeUVTexture->_setNextResidencyStatus( + Ogre::GpuResidency::Resident); + //We have to upload the data via a StagingTexture, which acts as an intermediate stash + //memory that is both visible to CPU and GPU. + Ogre::StagingTexture *stagingTexture = textureMgr->getStagingTexture( + this->dataPtr->cubeUVTexture->getWidth(), + this->dataPtr->cubeUVTexture->getHeight(), + this->dataPtr->cubeUVTexture->getDepth(), + this->dataPtr->cubeUVTexture->getNumSlices(), + this->dataPtr->cubeUVTexture->getPixelFormat() ); + stagingTexture->startMapRegion(); + //Map region of the staging texture. This function can be called from any thread after + //startMapRegion has already been called. + Ogre::TextureBox texBox = stagingTexture->mapRegion( + this->dataPtr->cubeUVTexture->getWidth(), + this->dataPtr->cubeUVTexture->getHeight(), + this->dataPtr->cubeUVTexture->getDepth(), + this->dataPtr->cubeUVTexture->getNumSlices(), + this->dataPtr->cubeUVTexture->getPixelFormat()); + + texBox.copyFrom( + pDest, + this->dataPtr->cubeUVTexture->getWidth(), + this->dataPtr->cubeUVTexture->getHeight(), + bytesPerRow); + stagingTexture->stopMapRegion(); + stagingTexture->upload(texBox, this->dataPtr->cubeUVTexture, 0, 0, 0, true); + //Tell the TextureGpuManager we're done with this StagingTexture. Otherwise it will leak. + textureMgr->removeStagingTexture(stagingTexture); + stagingTexture = 0; + //Do not free the pointer if texture's paging strategy is GpuPageOutStrategy::AlwaysKeepSystemRamCopy + this->dataPtr->cubeUVTexture->notifyDataIsReady(); } ///////////////////////////////////////////////////////// @@ -600,10 +647,9 @@ void Ogre2GpuRays::Setup1stPass() // Set the uniform variables (see gpu_rays_1st_pass_fs.glsl). // The projectParams is used to linearize depth buffer data // The other params are used to clamp the range output - double projectionA = this->FarClipPlane() / - (this->FarClipPlane() - this->NearClipPlane()); - double projectionB = (-this->FarClipPlane() * this->NearClipPlane()) / - (this->FarClipPlane() - this->NearClipPlane()); + Ogre::Vector2 projectionAB = this->dataPtr->ogreCamera->getProjectionParamsAB(); + double projectionA = projectionAB.x; + double projectionB = projectionAB.y; projectionB /= this->FarClipPlane(); psParams->setNamedConstant("projectionParams", Ogre::Vector2(projectionA, projectionB)); @@ -632,7 +678,7 @@ void Ogre2GpuRays::Setup1stPass() // compositor_node GpuRays1stPass // { // in 0 rt_input - // texture depthTexture target_width target_height PF_D32_FLOAT + // texture depthTexture target_width target_height PFG_D32_FLOAT // texture colorTexture target_width target_height PF_R8G8B8 // texture particleTexture target_width target_height PF_L8 // texture particleDepthTexture target_width target_height PF_D32_FLOAT @@ -687,78 +733,81 @@ void Ogre2GpuRays::Setup1stPass() Ogre::TextureDefinitionBase::TEXTURE_INPUT); Ogre::TextureDefinitionBase::TextureDefinition *depthTexDef = nodeDef->addTextureDefinition("depthTexture"); - depthTexDef->textureType = Ogre::TEX_TYPE_2D; + depthTexDef->textureType = Ogre::TextureTypes::Type2D; depthTexDef->width = 0; depthTexDef->height = 0; - depthTexDef->depth = 1; + depthTexDef->depthOrSlices = 1; depthTexDef->numMipmaps = 0; depthTexDef->widthFactor = 1; depthTexDef->heightFactor = 1; - depthTexDef->formatList = {Ogre::PF_D32_FLOAT}; - depthTexDef->fsaa = 0; - depthTexDef->uav = false; - depthTexDef->automipmaps = false; - depthTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + depthTexDef->fsaa = "0"; + depthTexDef->format = Ogre::PFG_D32_FLOAT; + depthTexDef->textureFlags |= !Ogre::TextureFlags::Uav; depthTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; + depthTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; - depthTexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - depthTexDef->fsaaExplicitResolve = false; + Ogre::RenderTargetViewDef *rtv = nodeDef->addRenderTextureView("depthTexture"); + rtv->setForTextureDefinition("depthTexture", depthTexDef); Ogre::TextureDefinitionBase::TextureDefinition *colorTexDef = nodeDef->addTextureDefinition("colorTexture"); - colorTexDef->textureType = Ogre::TEX_TYPE_2D; + colorTexDef->textureType = Ogre::TextureTypes::Type2D; colorTexDef->width = 0; colorTexDef->height = 0; - colorTexDef->depth = 1; - colorTexDef->numMipmaps = 0; + colorTexDef->depthOrSlices = 1; colorTexDef->widthFactor = 1; colorTexDef->heightFactor = 1; - colorTexDef->formatList = {Ogre::PF_R8G8B8}; - colorTexDef->fsaa = 0; - colorTexDef->uav = false; - colorTexDef->automipmaps = false; - colorTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + colorTexDef->format = Ogre::PFG_RGB8_UNORM; + colorTexDef->fsaa = "0"; + depthTexDef->textureFlags |= !Ogre::TextureFlags::Uav; colorTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - colorTexDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + colorTexDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; colorTexDef->preferDepthTexture = true; - colorTexDef->fsaaExplicitResolve = false; + + Ogre::RenderTargetViewDef *rtv2 = nodeDef->addRenderTextureView("colorTexture"); + rtv2->setForTextureDefinition("colorTexture", colorTexDef); Ogre::TextureDefinitionBase::TextureDefinition *particleDepthTexDef = nodeDef->addTextureDefinition("particleDepthTexture"); - particleDepthTexDef->textureType = Ogre::TEX_TYPE_2D; + particleDepthTexDef->textureType = Ogre::TextureTypes::Type2D; particleDepthTexDef->width = 0; particleDepthTexDef->height = 0; - particleDepthTexDef->depth = 1; + particleDepthTexDef->depthOrSlices = 1; particleDepthTexDef->numMipmaps = 0; particleDepthTexDef->widthFactor = 0.5; particleDepthTexDef->heightFactor = 0.5; - particleDepthTexDef->formatList = {Ogre::PF_D32_FLOAT}; - particleDepthTexDef->fsaa = 0; - particleDepthTexDef->uav = false; - particleDepthTexDef->automipmaps = false; - particleDepthTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + particleDepthTexDef->format = Ogre::PFG_D32_FLOAT; + particleDepthTexDef->fsaa = "0"; particleDepthTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; + particleDepthTexDef->textureFlags |= !Ogre::TextureFlags::Uav; + + Ogre::RenderTargetViewDef *rtvparticleDepthTex = + nodeDef->addRenderTextureView("particleDepthTexture"); + rtvparticleDepthTex->setForTextureDefinition( + "particleDepthTexture", particleDepthTexDef); Ogre::TextureDefinitionBase::TextureDefinition *particleTexDef = nodeDef->addTextureDefinition("particleTexture"); - particleTexDef->textureType = Ogre::TEX_TYPE_2D; + particleTexDef->textureType = Ogre::TextureTypes::Type2D; particleTexDef->width = 0; particleTexDef->height = 0; - particleTexDef->depth = 1; + particleTexDef->depthOrSlices = 1; particleTexDef->numMipmaps = 0; particleTexDef->widthFactor = 0.5; particleTexDef->heightFactor = 0.5; - particleTexDef->formatList = {Ogre::PF_R8G8B8}; - particleTexDef->fsaa = 0; - particleTexDef->uav = false; - particleTexDef->automipmaps = false; - particleTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + particleTexDef->format = Ogre::PFG_RGB8_UNORM; + particleTexDef->fsaa = "0"; + particleTexDef->textureFlags |= !Ogre::TextureFlags::Uav; particleTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - particleTexDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + particleTexDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; particleTexDef->preferDepthTexture = true; - particleTexDef->fsaaExplicitResolve = false; - nodeDef->setNumTargetPass(3); + Ogre::RenderTargetViewDef *rtvParticleTexture = + nodeDef->addRenderTextureView("particleTexture"); + rtvParticleTexture->setForTextureDefinition( + "particleTexture", particleTexDef); + + nodeDef->setNumTargetPass(4); Ogre::CompositorTargetDef *colorTargetDef = nodeDef->addTargetPass("colorTexture"); @@ -768,7 +817,7 @@ void Ogre2GpuRays::Setup1stPass() Ogre::CompositorPassClearDef *passClear = static_cast( colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(0, 0, 0); + passClear->setAllClearColours(Ogre::ColourValue(0, 0, 0)); // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( @@ -778,6 +827,28 @@ void Ogre2GpuRays::Setup1stPass() ~Ogre2ParticleEmitter::kParticleVisibilityFlags; } + Ogre::CompositorTargetDef *depthTargetDef = + nodeDef->addTargetPass("depthTexture"); + depthTargetDef->setNumPasses(2); + { + // clear pass + Ogre::CompositorPassClearDef *passClear = + static_cast( + depthTargetDef->addPass(Ogre::PASS_CLEAR)); + passClear->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); + + // scene pass + Ogre::CompositorPassSceneDef *passScene = + static_cast( + depthTargetDef->addPass(Ogre::PASS_SCENE)); + // depth texute does not contain particles + passScene->mVisibilityMask = IGN_VISIBILITY_ALL + & ~Ogre2ParticleEmitter::kParticleVisibilityFlags; + } + Ogre::CompositorTargetDef *particleTargetDef = nodeDef->addTargetPass("particleTexture"); particleTargetDef->setNumPasses(2); @@ -786,7 +857,7 @@ void Ogre2GpuRays::Setup1stPass() Ogre::CompositorPassClearDef *passClear = static_cast( particleTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue::Black; + passClear->setAllClearColours(Ogre::ColourValue::Black); // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( @@ -805,16 +876,16 @@ void Ogre2GpuRays::Setup1stPass() Ogre::CompositorPassClearDef *passClear = static_cast( inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->dataMaxVal, 0, 1.0); + passClear->setAllClearColours(Ogre::ColourValue(this->dataMaxVal, 0, 1.0)); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = this->dataPtr->matFirstPass->getName(); - passQuad->addQuadTextureSource(0, "depthTexture", 0); - passQuad->addQuadTextureSource(1, "colorTexture", 0); - passQuad->addQuadTextureSource(2, "particleDepthTexture", 0); - passQuad->addQuadTextureSource(3, "particleTexture", 0); + passQuad->addQuadTextureSource(0, "depthTexture"); + passQuad->addQuadTextureSource(1, "colorTexture"); + passQuad->addQuadTextureSource(2, "particleDepthTexture"); + passQuad->addQuadTextureSource(3, "particleTexture"); passQuad->mFrustumCorners = Ogre::CompositorPassQuadDef::VIEW_SPACE_CORNERS; } @@ -862,21 +933,33 @@ void Ogre2GpuRays::Setup1stPass() // create render texture - these textures pack the range data // that will be used in the 2nd pass + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); std::stringstream texName; texName << this->Name() << "_first_pass_" << i; this->dataPtr->firstPassTextures[i] = - Ogre::TextureManager::getSingleton().createManual( - texName.str(), "General", Ogre::TEX_TYPE_2D, - this->dataPtr->w1st, this->dataPtr->h1st, 1, 0, - Ogre::PF_FLOAT32_RGB, Ogre::TU_RENDERTARGET, - 0, false, 0, Ogre::BLANKSTRING, false, true); - - Ogre::RenderTarget *rt = - this->dataPtr->firstPassTextures[i]->getBuffer()->getRenderTarget(); + textureMgr->createOrRetrieveTexture( + texName.str(), + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->dataPtr->firstPassTextures[i]->setResolution( + this->dataPtr->w1st, this->dataPtr->h1st); + this->dataPtr->firstPassTextures[i]->setNumMipmaps(1u); + this->dataPtr->firstPassTextures[i]->setPixelFormat( + Ogre::PFG_RGB32_FLOAT); + + this->dataPtr->firstPassTextures[i]->scheduleTransitionTo( + Ogre::GpuResidency::Resident); + // create compositor worksspace this->dataPtr->ogreCompositorWorkspace1st[i] = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - rt, this->dataPtr->cubeCam[i], wsDefName, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + this->dataPtr->firstPassTextures[i], + this->dataPtr->cubeCam[i], + wsDefName, + false); // add laser retro material switcher to render target listener // so we can switch to use laser retro material when the camera is being @@ -887,11 +970,11 @@ void Ogre2GpuRays::Setup1stPass() for (auto c : channelsTex) { - if (c.textures[0]->getSrcFormat() == Ogre::PF_R8G8B8) + if (c->getPixelFormat() == Ogre::PFG_RGB8_UNORM) { this->dataPtr->laserRetroMaterialSwitcher[i].reset( new Ogre2LaserRetroMaterialSwitcher(this->scene)); - c.target->addListener( + this->dataPtr->cubeCam[i]->addListener( this->dataPtr->laserRetroMaterialSwitcher[i].get()); break; } @@ -904,14 +987,25 @@ void Ogre2GpuRays::Setup2ndPass() { // Create second pass RTT, which stores the final range data output // see PostRender on how we retrieve data from this texture + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); + this->dataPtr->secondPassTexture = - Ogre::TextureManager::getSingleton().createManual( + textureMgr->createOrRetrieveTexture( this->Name() + "_second_pass", - "General", - Ogre::TEX_TYPE_2D, - this->dataPtr->w2nd, this->dataPtr->h2nd, 0, - Ogre::PF_FLOAT32_RGB, - Ogre::TU_RENDERTARGET); + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->dataPtr->secondPassTexture->setResolution( + this->dataPtr->w2nd, this->dataPtr->h2nd); + this->dataPtr->secondPassTexture->setNumMipmaps(1u); + this->dataPtr->secondPassTexture->setPixelFormat( + Ogre::PFG_RGB32_FLOAT); + + this->dataPtr->secondPassTexture->scheduleTransitionTo( + Ogre::GpuResidency::Resident); // Create second pass material // The GpuRaysScan2nd material is defined in script (gpu_rays.material). @@ -942,8 +1036,6 @@ void Ogre2GpuRays::Setup2ndPass() } // create 2nd pass compositor - auto engine = Ogre2RenderEngine::Instance(); - auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); // Same as 1st pass. We need to programmatically create the compositor in @@ -987,7 +1079,7 @@ void Ogre2GpuRays::Setup2ndPass() Ogre::CompositorPassClearDef *passClear = static_cast( inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->dataMaxVal, 0, 1.0); + passClear->setAllClearColours(Ogre::ColourValue(this->dataMaxVal, 0, 1.0)); // quad pass - sample from cubemap textures Ogre::CompositorPassQuadDef *passQuad = static_cast( @@ -1009,11 +1101,13 @@ void Ogre2GpuRays::Setup2ndPass() } // create the compositor workspace - Ogre::RenderTarget *rt = - this->dataPtr->secondPassTexture->getBuffer()->getRenderTarget(); this->dataPtr->ogreCompositorWorkspace2nd = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - rt, this->dataPtr->ogreCamera, wsDefName, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + this->dataPtr->secondPassTexture, + this->dataPtr->ogreCamera, + wsDefName, + false); } ///////////////////////////////////////////////////////// @@ -1066,27 +1160,25 @@ void Ogre2GpuRays::PostRender() unsigned int width = this->dataPtr->w2nd; unsigned int height = this->dataPtr->h2nd; - size_t size = Ogre::PixelUtil::getMemorySize( - width, height, 1, Ogre::PF_FLOAT32_RGB); int len = width * height * this->Channels(); if (!this->dataPtr->gpuRaysBuffer) { this->dataPtr->gpuRaysBuffer = new float[len]; } - Ogre::PixelBox dstBox(width, height, - 1, Ogre::PF_FLOAT32_RGB, this->dataPtr->gpuRaysBuffer); // blit data from gpu to cpu - auto rt = this->dataPtr->secondPassTexture->getBuffer()->getRenderTarget(); - rt->copyContentsToMemory(dstBox, Ogre::RenderTarget::FB_FRONT); + Ogre::Image2 image; + image.convertFromTexture(this->dataPtr->secondPassTexture, 0u, 0u); + float * bufferTmp = static_cast(image.getRawBuffer()); + memcpy(this->dataPtr->gpuRaysBuffer, bufferTmp, len * sizeof(float)); if (!this->dataPtr->gpuRaysScan) { this->dataPtr->gpuRaysScan = new float[len]; } - memcpy(this->dataPtr->gpuRaysScan, this->dataPtr->gpuRaysBuffer, size); + memcpy(this->dataPtr->gpuRaysScan, this->dataPtr->gpuRaysBuffer, len * sizeof(float)); this->dataPtr->newGpuRaysFrame(this->dataPtr->gpuRaysScan, width, height, this->Channels(), "PF_FLOAT32_RGB"); @@ -1117,10 +1209,7 @@ void Ogre2GpuRays::Copy(float *_dataDest) unsigned int width = this->dataPtr->w2nd; unsigned int height = this->dataPtr->h2nd; - size_t size = Ogre::PixelUtil::getMemorySize( - width, height, 1, Ogre::PF_FLOAT32_RGB); - - memcpy(_dataDest, this->dataPtr->gpuRaysScan, size); + memcpy(_dataDest, this->dataPtr->gpuRaysScan, width * height * 3 * sizeof(float)); } ///////////////////////////////////////////////// diff --git a/ogre2/src/Ogre2Material.cc b/ogre2/src/Ogre2Material.cc index 3a7bac172..d76650075 100644 --- a/ogre2/src/Ogre2Material.cc +++ b/ogre2/src/Ogre2Material.cc @@ -157,17 +157,16 @@ void Ogre2Material::SetAlphaFromTexture(bool _enabled, double _alpha, bool _twoSided) { BaseMaterial::SetAlphaFromTexture(_enabled, _alpha, _twoSided); - Ogre::HlmsBlendblock block; if (_enabled) { this->ogreDatablock->setAlphaTest(Ogre::CMPF_GREATER_EQUAL); + Ogre::HlmsBlendblock block; block.setBlendType(Ogre::SBT_TRANSPARENT_ALPHA); this->ogreDatablock->setBlendblock(block); } else { this->ogreDatablock->setAlphaTest(Ogre::CMPF_ALWAYS_PASS); - this->ogreDatablock->setBlendblock(block); } this->ogreDatablock->setAlphaTestThreshold(_alpha); this->ogreDatablock->setTwoSidedLighting(_twoSided); @@ -176,7 +175,9 @@ void Ogre2Material::SetAlphaFromTexture(bool _enabled, ////////////////////////////////////////////////// float Ogre2Material::RenderOrder() const { - return this->renderOrder; + Ogre::HlmsMacroblock macroblock( + *this->ogreDatablock->getMacroblock()); + return macroblock.mDepthBiasConstant; } ////////////////////////////////////////////////// @@ -230,7 +231,7 @@ void Ogre2Material::SetTexture(const std::string &_name) void Ogre2Material::ClearTexture() { this->textureName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_DIFFUSE, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_DIFFUSE, this->textureName); } ////////////////////////////////////////////////// @@ -262,7 +263,7 @@ void Ogre2Material::SetNormalMap(const std::string &_name) void Ogre2Material::ClearNormalMap() { this->normalMapName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_NORMAL, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_NORMAL, this->normalMapName); } ////////////////////////////////////////////////// @@ -294,7 +295,7 @@ void Ogre2Material::SetRoughnessMap(const std::string &_name) void Ogre2Material::ClearRoughnessMap() { this->roughnessMapName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_ROUGHNESS, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_ROUGHNESS, this->roughnessMapName); } ////////////////////////////////////////////////// @@ -326,7 +327,7 @@ void Ogre2Material::SetMetalnessMap(const std::string &_name) void Ogre2Material::ClearMetalnessMap() { this->metalnessMapName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_METALLIC, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_METALLIC, this->metalnessMapName); } ////////////////////////////////////////////////// @@ -358,7 +359,7 @@ void Ogre2Material::SetEnvironmentMap(const std::string &_name) void Ogre2Material::ClearEnvironmentMap() { this->environmentMapName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_REFLECTION, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_REFLECTION, this->environmentMapName); } ////////////////////////////////////////////////// @@ -390,7 +391,7 @@ void Ogre2Material::SetEmissiveMap(const std::string &_name) void Ogre2Material::ClearEmissiveMap() { this->emissiveMapName = ""; - this->ogreDatablock->setTexture(Ogre::PBSM_EMISSIVE, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_EMISSIVE, this->emissiveMapName); } ////////////////////////////////////////////////// @@ -440,7 +441,7 @@ void Ogre2Material::ClearLightMap() { this->lightMapName = ""; this->lightMapUvSet = 0u; - this->ogreDatablock->setTexture(Ogre::PBSM_DETAIL0, 0, Ogre::TexturePtr()); + this->ogreDatablock->setTexture(Ogre::PBSM_DETAIL0, this->lightMapName); } ////////////////////////////////////////////////// @@ -529,42 +530,39 @@ void Ogre2Material::SetTextureMapImpl(const std::string &_texture, } } - Ogre::HlmsTextureManager *hlmsTextureManager = - this->ogreHlmsPbs->getHlmsManager()->getTextureManager(); - Ogre::HlmsTextureManager::TextureLocation texLocation = - hlmsTextureManager->createOrRetrieveTexture(baseName, - this->ogreDatablock->suggestMapTypeBasedOnTextureType(_type)); - + // Ogre::HlmsSamplerblock samplerblock( *datablock->getSamplerblock( Ogre::PBSM_ROUGHNESS ) ); Ogre::HlmsSamplerblock samplerBlockRef; samplerBlockRef.mU = Ogre::TAM_WRAP; samplerBlockRef.mV = Ogre::TAM_WRAP; samplerBlockRef.mW = Ogre::TAM_WRAP; - this->ogreDatablock->setTexture(_type, texLocation.xIdx, texLocation.texture, - &samplerBlockRef); + this->ogreDatablock->setTexture(_type, baseName, &samplerBlockRef); + // TODO(ahcorde) // disable alpha from texture if texture does not have an alpha channel // otherwise this becomes a transparent material - if (_type == Ogre::PBSM_DIFFUSE) - { - if (this->TextureAlphaEnabled() && !texLocation.texture->hasAlpha()) - { - this->SetAlphaFromTexture(false, this->AlphaThreshold(), - this->TwoSidedEnabled()); - } - } + // if (_type == Ogre::PBSM_DIFFUSE) + // { + // if (this->TextureAlphaEnabled() && !texture->hasAlpha()) + // { + // this->SetAlphaFromTexture(false, this->AlphaThreshold(), + // this->TwoSidedEnabled()); + // } + // } } ////////////////////////////////////////////////// -Ogre::TexturePtr Ogre2Material::Texture(const std::string &_name) +Ogre::TextureGpu* Ogre2Material::Texture(const std::string &_name) { - Ogre::HlmsTextureManager *hlmsTextureManager = - this->ogreHlmsPbs->getHlmsManager()->getTextureManager(); - Ogre::HlmsTextureManager::TextureLocation texLocation = - hlmsTextureManager->createOrRetrieveTexture(_name, - Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE); + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = + root->getRenderSystem()->getTextureGpuManager(); + Ogre::TextureGpu *texture = textureMgr->createOrRetrieveTexture(_name, + Ogre::GpuPageOutStrategy::Discard, + Ogre::TextureFlags::ManualTexture, + Ogre::TextureTypes::Type2D); - return texLocation.texture; + return texture; } ////////////////////////////////////////////////// @@ -669,13 +667,16 @@ void Ogre2Material::FillUnlitDatablock(Ogre::HlmsUnlitDatablock *_datablock) if (!this->textureName.empty()) { std::string baseName = common::basename(this->textureName); - Ogre::HlmsTextureManager *hlmsTextureManager = - this->ogreHlmsPbs->getHlmsManager()->getTextureManager(); - Ogre::HlmsTextureManager::TextureLocation texLocation = - hlmsTextureManager->createOrRetrieveTexture(baseName, - this->ogreDatablock->suggestMapTypeBasedOnTextureType( - Ogre::PBSM_DIFFUSE)); - _datablock->setTexture(0, texLocation.xIdx, texLocation.texture); + + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = + root->getRenderSystem()->getTextureGpuManager(); + Ogre::TextureGpu *texture = textureMgr->createOrRetrieveTexture(baseName, + Ogre::GpuPageOutStrategy::Discard, + Ogre::TextureFlags::ManualTexture, + Ogre::TextureTypes::Type2D); + + _datablock->setTexture(0, texture); } auto samplerblock = this->ogreDatablock->getSamplerblock(Ogre::PBSM_DIFFUSE); diff --git a/ogre2/src/Ogre2MaterialSwitcher.cc b/ogre2/src/Ogre2MaterialSwitcher.cc index 9bddc5ad1..0e51b5305 100644 --- a/ogre2/src/Ogre2MaterialSwitcher.cc +++ b/ogre2/src/Ogre2MaterialSwitcher.cc @@ -63,8 +63,8 @@ Ogre2MaterialSwitcher::~Ogre2MaterialSwitcher() } //////////////////////////////////////////////// -void Ogre2MaterialSwitcher::preRenderTargetUpdate( - const Ogre::RenderTargetEvent &/*_evt*/) +void Ogre2MaterialSwitcher::cameraPreRenderScene( + Ogre::Camera * /*_evt*/) { // swap item to use v1 shader material // Note: keep an eye out for performance impact on switching materials @@ -104,8 +104,8 @@ void Ogre2MaterialSwitcher::preRenderTargetUpdate( } ///////////////////////////////////////////////// -void Ogre2MaterialSwitcher::postRenderTargetUpdate( - const Ogre::RenderTargetEvent &/*_evt*/) +void Ogre2MaterialSwitcher::cameraPostRenderScene( + Ogre::Camera * /*_evt*/) { // restore item to use hlms material auto itor = this->scene->OgreSceneManager()->getMovableObjectIterator( diff --git a/ogre2/src/Ogre2Mesh.cc b/ogre2/src/Ogre2Mesh.cc index eaf7e8e7b..60bf28e70 100644 --- a/ogre2/src/Ogre2Mesh.cc +++ b/ogre2/src/Ogre2Mesh.cc @@ -33,6 +33,7 @@ #include "ignition/rendering/ogre2/Ogre2Material.hh" #include "ignition/rendering/ogre2/Ogre2Storage.hh" +#include "Animation/OgreSkeletonInstance.h" /// brief Private implementation of the Ogre2Mesh class class ignition::rendering::Ogre2MeshPrivate diff --git a/ogre2/src/Ogre2RenderTarget.cc b/ogre2/src/Ogre2RenderTarget.cc index 91c1247bb..785190c05 100644 --- a/ogre2/src/Ogre2RenderTarget.cc +++ b/ogre2/src/Ogre2RenderTarget.cc @@ -15,16 +15,6 @@ * */ -// leave this out of OgreIncludes as it conflicts with other files requiring -// gl.h -#ifdef _MSC_VER -#pragma warning(push, 0) -#endif -#include -#ifdef _MSC_VER -#pragma warning(pop) -#endif - #include #include "ignition/rendering/Material.hh" @@ -66,7 +56,8 @@ class Ogre2RenderTargetCompositorListener : Ogre::CompositorPassScene *scenePass = static_cast(_pass); IGN_ASSERT(scenePass != nullptr, "Unable to get scene pass"); - Ogre::Viewport *vp = scenePass->getViewport(); + Ogre::Viewport *vp = scenePass->getCamera()->getLastViewport(); + if (vp == nullptr) return; // make sure we do not alter the reserved visibility flags uint32_t f = this->ogreRenderTarget->VisibilityMask() | ~Ogre::VisibilityFlags::RESERVED_VISIBILITY_FLAGS; @@ -156,39 +147,36 @@ void Ogre2RenderTarget::BuildCompositor() // Input texture Ogre::TextureDefinitionBase::TextureDefinition *rt0TexDef = nodeDef->addTextureDefinition("rt0"); - rt0TexDef->textureType = Ogre::TEX_TYPE_2D; + rt0TexDef->textureType = Ogre::TextureTypes::Type2D; rt0TexDef->width = 0; rt0TexDef->height = 0; - rt0TexDef->depth = 1; + rt0TexDef->depthOrSlices = 1; rt0TexDef->numMipmaps = 0; rt0TexDef->widthFactor = 1; rt0TexDef->heightFactor = 1; - rt0TexDef->formatList = {Ogre::PF_R8G8B8}; - rt0TexDef->fsaa = 0; - rt0TexDef->uav = false; - rt0TexDef->automipmaps = false; - rt0TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolTrue; + rt0TexDef->format = Ogre::PFG_RGBA8_UNORM; + rt0TexDef->textureFlags |= !Ogre::TextureFlags::Uav; rt0TexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - rt0TexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - rt0TexDef->fsaaExplicitResolve = false; + rt0TexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + + Ogre::RenderTargetViewDef *rtv = nodeDef->addRenderTextureView("rt0"); + rtv->setForTextureDefinition("rt0", rt0TexDef); Ogre::TextureDefinitionBase::TextureDefinition *rt1TexDef = nodeDef->addTextureDefinition("rt1"); - rt1TexDef->textureType = Ogre::TEX_TYPE_2D; + rt1TexDef->textureType = Ogre::TextureTypes::Type2D; rt1TexDef->width = 0; rt1TexDef->height = 0; - rt1TexDef->depth = 1; - rt1TexDef->numMipmaps = 0; + rt1TexDef->depthOrSlices = 1; rt1TexDef->widthFactor = 1; rt1TexDef->heightFactor = 1; - rt1TexDef->formatList = {Ogre::PF_R8G8B8}; - rt1TexDef->fsaa = 0; - rt1TexDef->uav = false; - rt1TexDef->automipmaps = false; - rt1TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolTrue; + rt1TexDef->format = Ogre::PFG_RGBA8_UNORM; + rt1TexDef->textureFlags |= !Ogre::TextureFlags::Uav; rt1TexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - rt1TexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - rt1TexDef->fsaaExplicitResolve = false; + rt1TexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + + Ogre::RenderTargetViewDef *rtv2 = nodeDef->addRenderTextureView("rt1"); + rtv2->setForTextureDefinition("rt1", rt1TexDef); nodeDef->setNumTargetPass(2); Ogre::CompositorTargetDef *rt0TargetDef = @@ -203,7 +191,7 @@ void Ogre2RenderTarget::BuildCompositor() Ogre::CompositorPassClearDef *passClear = static_cast( rt0TargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = this->ogreBackgroundColor; + passClear->setAllClearColours(this->ogreBackgroundColor); if (validBackground) { @@ -248,7 +236,7 @@ void Ogre2RenderTarget::BuildCompositor() static_cast( outTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = "Ogre/Copy/4xFP32"; - passQuad->addQuadTextureSource(0, "rtN", 0); + passQuad->addQuadTextureSource(0, "rtN"); // scene pass Ogre::CompositorPassSceneDef *passScene = @@ -269,12 +257,15 @@ void Ogre2RenderTarget::BuildCompositor() this->UpdateShadowNode(); this->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - this->RenderTarget(), this->ogreCamera, - this->ogreCompositorWorkspaceDefName, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + this->RenderTarget(), + this->ogreCamera, + this->ogreCompositorWorkspaceDefName, + true); this->dataPtr->rtListener = new Ogre2RenderTargetCompositorListener(this); - this->ogreCompositorWorkspace->setListener(this->dataPtr->rtListener); + this->ogreCompositorWorkspace->addListener(this->dataPtr->rtListener); } ////////////////////////////////////////////////// @@ -286,7 +277,7 @@ void Ogre2RenderTarget::DestroyCompositor() auto engine = Ogre2RenderEngine::Instance(); auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); - this->ogreCompositorWorkspace->setListener(nullptr); + this->ogreCompositorWorkspace->addListener(nullptr); ogreCompMgr->removeWorkspace(this->ogreCompositorWorkspace); ogreCompMgr->removeWorkspaceDefinition(this->ogreCompositorWorkspaceDefName); ogreCompMgr->removeNodeDefinition(this->ogreCompositorWorkspaceDefName + @@ -309,6 +300,12 @@ void Ogre2RenderTarget::RebuildCompositor() ////////////////////////////////////////////////// void Ogre2RenderTarget::Copy(Image &_image) const { + Ogre::TextureGpu * texture = this->RenderTarget(); + + if (texture == nullptr){ + return; + } + // TODO(anyone) handle Bayer conversions // TODO(anyone) handle ogre version differences @@ -318,10 +315,21 @@ void Ogre2RenderTarget::Copy(Image &_image) const return; } - void *data = _image.Data(); - Ogre::PixelFormat imageFormat = Ogre2Conversions::Convert(_image.Format()); - Ogre::PixelBox ogrePixelBox(this->width, this->height, 1, imageFormat, data); - this->RenderTarget()->copyContentsToMemory(ogrePixelBox); + Ogre::Image2 image2; + image2.convertFromTexture(texture, 0u, 0u); + + auto dataImage = static_cast(_image.Data()); + auto dataImage2 = static_cast(image2.getRawBuffer()); + + for (int row = 0; row < texture->getHeight(); ++row) + { + for (int column = 0; column < texture->getWidth(); ++column) + { + dataImage[row*texture->getWidth() * 3 + column * 3] = dataImage2[row * texture->getWidth() * 4 + column * 4]; + dataImage[row*texture->getWidth() * 3 + column * 3 + 1] = dataImage2[row * texture->getWidth() * 4 + column * 4 + 1]; + dataImage[row*texture->getWidth() * 3 + column * 3 + 2] = dataImage2[row * texture->getWidth() * 4 + column * 4 + 2]; + } + } } ////////////////////////////////////////////////// @@ -450,8 +458,8 @@ void Ogre2RenderTarget::UpdateBackgroundColor() auto nodeSeq = this->ogreCompositorWorkspace->getNodeSequence(); auto pass = nodeSeq[0]->_getPasses()[0]->getDefinition(); auto clearPass = dynamic_cast(pass); - const_cast(clearPass)->mColourValue = - this->ogreBackgroundColor; + const_cast(clearPass)->setAllClearColours( + this->ogreBackgroundColor); this->colorDirty = false; } @@ -485,7 +493,7 @@ void Ogre2RenderTarget::UpdateBackgroundMaterial() Ogre::TextureUnitState *texUnit = mat->getTechnique(0u)->getPass(0u)->getTextureUnitState(0u); texUnit->setTextureName(this->backgroundMaterial->EnvironmentMap(), - Ogre::TEX_TYPE_CUBE_MAP); + Ogre::TextureTypes::TypeCube); } this->backgroundMaterialDirty = false; @@ -814,17 +822,19 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( for (size_t i = 0; i < numTextures; ++i) { const Ogre::ShadowNodeHelper::Resolution &atlasRes = atlasResolutions[i]; + Ogre::String texName = "atlas" + Ogre::StringConverter::toString(i); Ogre::TextureDefinitionBase::TextureDefinition *texDef = - shadowNodeDef->addTextureDefinition( - "atlas" + Ogre::StringConverter::toString(i)); + shadowNodeDef->addTextureDefinition(texName); texDef->width = std::max(atlasRes.x, 1u); texDef->height = std::max(atlasRes.y, 1u); - texDef->formatList.push_back(Ogre::PF_D32_FLOAT); + texDef->format = Ogre::PFG_D32_FLOAT; texDef->depthBufferId = Ogre::DepthBuffer::POOL_NON_SHAREABLE; - texDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + texDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; texDef->preferDepthTexture = false; - texDef->fsaa = false; + texDef->fsaa = "0"; + Ogre::RenderTargetViewDef *rtv = shadowNodeDef->addRenderTextureView(texName); + rtv->setForTextureDefinition(texName, texDef); } // Define the cubemap needed by point lights @@ -833,15 +843,17 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( Ogre::TextureDefinitionBase::TextureDefinition *texDef = shadowNodeDef->addTextureDefinition("tmpCubemap"); - texDef->width = pointLightCubemapResolution; - texDef->height = pointLightCubemapResolution; - texDef->depth = 6u; - texDef->textureType = Ogre::TEX_TYPE_CUBE_MAP; - texDef->formatList.push_back(Ogre::PF_FLOAT32_R); + texDef->width = pointLightCubemapResolution; + texDef->height = pointLightCubemapResolution; + texDef->depthOrSlices = 6u; + texDef->textureType = Ogre::TextureTypes::TypeCube; + texDef->format = Ogre::PFG_R16_UNORM; texDef->depthBufferId = 1u; - texDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + texDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; texDef->preferDepthTexture = false; - texDef->fsaa = false; + texDef->fsaa = "0"; + Ogre::RenderTargetViewDef *rtv = shadowNodeDef->addRenderTextureView( "tmpCubemap" ); + rtv->setForTextureDefinition( "tmpCubemap", texDef ); } } @@ -879,7 +891,7 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( Ogre::ShadowTextureDefinition *shadowTexDef = shadowNodeDef->addShadowTextureDefinition(lightIdx, j, texName, - 0, uvOffset, uvLength, 0); + uvOffset, uvLength, 0); shadowTexDef->shadowMapTechnique = shadowParam.technique; shadowTexDef->pssmLambda = pssmLambda; shadowTexDef->splitPadding = splitPadding; @@ -906,8 +918,8 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( Ogre::CompositorPassDef *passDef = targetDef->addPass(Ogre::PASS_CLEAR); Ogre::CompositorPassClearDef *passClear = static_cast(passDef); - passClear->mColourValue = Ogre::ColourValue::White; - passClear->mDepthValue = 1.0f; + passClear->setAllClearColours(Ogre::ColourValue::White); + passClear->mClearDepth = 1.0f; } // Pass scene for directional and spot lights first @@ -961,25 +973,16 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( targetDef->setShadowMapSupportedLightTypes( shadowParam.supportedLightTypes & pointMask); { - // Clear pass - Ogre::CompositorPassDef *passDef = - targetDef->addPass(Ogre::PASS_CLEAR); - Ogre::CompositorPassClearDef *passClear = - static_cast(passDef); - passClear->mColourValue = Ogre::ColourValue::White; - passClear->mDepthValue = 1.0f; - passClear->mShadowMapIdx = shadowMapIdx; - } - - { - // Scene pass - Ogre::CompositorPassDef *passDef = - targetDef->addPass(Ogre::PASS_SCENE); - Ogre::CompositorPassSceneDef *passScene = - static_cast(passDef); - passScene->mCameraCubemapReorient = true; - passScene->mShadowMapIdx = shadowMapIdx; - passScene->mIncludeOverlays = false; + //Scene pass + Ogre::CompositorPassDef *passDef = targetDef->addPass(Ogre::PASS_SCENE); + Ogre::CompositorPassSceneDef *passScene = + static_cast(passDef); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue(0.0f, 0.0f, 0.0f, 0.0f)); + passScene->mClearDepth = 1.0f; + passScene->mCameraCubemapReorient = true; + passScene->mShadowMapIdx = shadowMapIdx; + passScene->mIncludeOverlays = false; } } @@ -995,7 +998,7 @@ void Ogre2RenderTarget::CreateShadowNodeWithSettings( static_cast(passDef); passQuad->mMaterialIsHlms = false; passQuad->mMaterialName = "Ogre/DPSM/CubeToDpsm"; - passQuad->addQuadTextureSource(0, "tmpCubemap", 0); + passQuad->addQuadTextureSource(0, "tmpCubemap"); passQuad->mShadowMapIdx = shadowMapIdx; } const size_t numSplits = shadowParam.technique == @@ -1033,9 +1036,8 @@ void Ogre2RenderTarget::RebuildMaterial() Ogre::MaterialPtr matPtr = ogreMaterial->Material(); Ogre::SceneManager *sceneMgr = this->scene->OgreSceneManager(); - Ogre::RenderTarget *target = this->RenderTarget(); this->materialApplicator.reset(new Ogre2RenderTargetMaterial( - sceneMgr, target, matPtr.get())); + sceneMgr, this->ogreCamera, matPtr.get())); } } @@ -1058,12 +1060,11 @@ void Ogre2RenderTexture::Destroy() } ////////////////////////////////////////////////// -Ogre::RenderTarget *Ogre2RenderTexture::RenderTarget() const +Ogre::TextureGpu *Ogre2RenderTexture::RenderTarget() const { - return this->ogreTexture->getBuffer()->getRenderTarget(); + return this->ogreTexture; } - ////////////////////////////////////////////////// void Ogre2RenderTexture::RebuildTarget() { @@ -1077,13 +1078,16 @@ void Ogre2RenderTexture::DestroyTarget() if (nullptr == this->ogreTexture) return; - auto &manager = Ogre::TextureManager::getSingleton(); - manager.unload(this->ogreTexture->getName()); - manager.remove(this->ogreTexture->getName()); + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); + Ogre::CompositorManager2 *compositorManager = root->getCompositorManager2(); + compositorManager->removeAllWorkspaces(); + this->ogreCompositorWorkspace = 0; + + compositorManager->removeAllNodeDefinitions(); + compositorManager->removeAllWorkspaceDefinitions(); - // TODO(anyone) there is memory leak when a render texture is destroyed. - // The RenderSystem::_cleanupDepthBuffers method used in ogre1 does not - // seem to work in ogre2 + Ogre::TextureGpuManager *textureManager = root->getRenderSystem()->getTextureGpuManager(); + textureManager->destroyTexture(this->ogreTexture); this->ogreTexture = nullptr; } @@ -1091,9 +1095,6 @@ void Ogre2RenderTexture::DestroyTarget() ////////////////////////////////////////////////// void Ogre2RenderTexture::BuildTarget() { - Ogre::TextureManager &manager = Ogre::TextureManager::getSingleton(); - Ogre::PixelFormat ogreFormat = Ogre2Conversions::Convert(this->format); - // check if target fsaa is supported unsigned int fsaa = 0; std::vector fsaaLevels = @@ -1116,10 +1117,24 @@ void Ogre2RenderTexture::BuildTarget() } } - // Ogre 2 PBS expects gamma correction to be enabled - this->ogreTexture = (manager.createManual(this->name, "General", - Ogre::TEX_TYPE_2D, this->width, this->height, 0, ogreFormat, - Ogre::TU_RENDERTARGET, 0, true, fsaa)).get(); + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); + this->ogreTexture = textureMgr->createOrRetrieveTexture( + this->name, + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->ogreTexture->setResolution(this->width, this->height); + this->ogreTexture->setNumMipmaps(1u); + this->ogreTexture->setPixelFormat(Ogre::PFG_RGBA8_UNORM); + + this->ogreTexture->scheduleTransitionTo( + Ogre::GpuResidency::Resident); + + engine->getWindow()->reposition(0, 0); + } ////////////////////////////////////////////////// @@ -1128,9 +1143,9 @@ unsigned int Ogre2RenderTexture::GLId() const if (!this->ogreTexture) return 0; - GLuint texId; - this->ogreTexture->getCustomAttribute("GLID", &texId); - + unsigned int texId; + auto engine = Ogre2RenderEngine::Instance(); + this->ogreTexture->getCustomAttribute("msFinalTextureBuffer", &texId); return static_cast(texId); } @@ -1159,7 +1174,7 @@ Ogre2RenderWindow::~Ogre2RenderWindow() } ////////////////////////////////////////////////// -Ogre::RenderTarget *Ogre2RenderWindow::RenderTarget() const +Ogre::TextureGpu *Ogre2RenderWindow::RenderTarget() const { return this->ogreRenderWindow; } @@ -1179,9 +1194,10 @@ void Ogre2RenderWindow::RebuildTarget() if (!this->ogreRenderWindow) this->BuildTarget(); - Ogre::RenderWindow *window = - dynamic_cast(this->ogreRenderWindow); - window->resize(this->width, this->height); + Ogre::Window *window = + dynamic_cast(this->ogreRenderWindow); + window->requestResolution(this->width, this->height); + window->getTexture()->setResolution(this->width, this->height); window->windowMovedOrResized(); } @@ -1189,12 +1205,11 @@ void Ogre2RenderWindow::RebuildTarget() void Ogre2RenderWindow::BuildTarget() { auto engine = Ogre2RenderEngine::Instance(); - std::string renderTargetName = - engine->CreateRenderWindow(this->handle, - this->width, - this->height, - this->ratio, - this->antiAliasing); - this->ogreRenderWindow = - engine->OgreRoot()->getRenderTarget(renderTargetName); + engine->CreateRenderWindow(this->handle, + this->width, + this->height, + this->ratio, + this->antiAliasing); + + this->ogreRenderWindow = engine->getWindow()->getTexture(); } diff --git a/ogre2/src/Ogre2RenderTargetMaterial.cc b/ogre2/src/Ogre2RenderTargetMaterial.cc index cfcd8c515..24ce838d3 100644 --- a/ogre2/src/Ogre2RenderTargetMaterial.cc +++ b/ogre2/src/Ogre2RenderTargetMaterial.cc @@ -22,32 +22,34 @@ using namespace ignition::rendering; ////////////////////////////////////////////////// Ogre2RenderTargetMaterial::Ogre2RenderTargetMaterial( - Ogre::SceneManager *_scene, Ogre::RenderTarget *_renderTarget, + Ogre::SceneManager *_scene, Ogre::Camera *renderCamera, Ogre::Material *_material): - scene(_scene), renderTarget(_renderTarget), material(_material) + scene(_scene), renderCamera(renderCamera), material(_material) { // Pick a name that's unlikely to collide with a real material scheme this->schemeName = "__ignition__rendering__Ogre2RenderTargetMaterial"; - this->renderTarget->getViewport(0)->setMaterialScheme(this->schemeName); - this->renderTarget->addListener(this); + Ogre::Viewport* renderViewport = + _scene->getCurrentViewport0(); + renderViewport->setMaterialScheme(this->schemeName); + this->renderCamera->addListener(this); } ////////////////////////////////////////////////// Ogre2RenderTargetMaterial::~Ogre2RenderTargetMaterial() { - this->renderTarget->removeListener(this); + this->renderCamera->removeListener(this); } ////////////////////////////////////////////////// -void Ogre2RenderTargetMaterial::preRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2RenderTargetMaterial::cameraPreRenderScene( + Ogre::Camera * /*_evt*/) { Ogre::MaterialManager::getSingleton().addListener(this); } ////////////////////////////////////////////////// -void Ogre2RenderTargetMaterial::postRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2RenderTargetMaterial::cameraPostRenderScene( + Ogre::Camera * /*_evt*/) { Ogre::MaterialManager::getSingleton().removeListener(this); } diff --git a/ogre2/src/Ogre2Scene.cc b/ogre2/src/Ogre2Scene.cc index 5c4619bdf..13d9819df 100644 --- a/ogre2/src/Ogre2Scene.cc +++ b/ogre2/src/Ogre2Scene.cc @@ -503,8 +503,6 @@ void Ogre2Scene::CreateContext() { Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); - Ogre::InstancingThreadedCullingMethod threadedCullingMethod = - Ogre::INSTANCING_CULLING_SINGLETHREAD; // getNumLogicalCores() may return 0 if couldn't detect const size_t numThreads = std::max( 1, Ogre::PlatformInformation::getNumLogicalCores()); @@ -515,8 +513,7 @@ void Ogre2Scene::CreateContext() // threadedCullingMethod = Ogre::INSTANCING_CULLING_THREADED; // Create the SceneManager, in this case a generic one this->ogreSceneManager = root->createSceneManager(Ogre::ST_GENERIC, - numThreads, - threadedCullingMethod); + numThreads); this->ogreSceneManager->addRenderQueueListener( Ogre2RenderEngine::Instance()->OverlaySystem()); @@ -532,7 +529,7 @@ void Ogre2Scene::CreateContext() // enable forward plus to support multiple lights // this is required for non-shadow-casting point lights and // spot lights to work - this->ogreSceneManager->setForwardClustered(true, 16, 8, 24, 96, 1, 500); + this->ogreSceneManager->setForwardClustered(true, 16, 8, 24, 96, 0, 0, 1, 500); } ////////////////////////////////////////////////// diff --git a/ogre2/src/Ogre2SelectionBuffer.cc b/ogre2/src/Ogre2SelectionBuffer.cc index a3aec839a..644b7c589 100644 --- a/ogre2/src/Ogre2SelectionBuffer.cc +++ b/ogre2/src/Ogre2SelectionBuffer.cc @@ -51,22 +51,12 @@ class ignition::rendering::Ogre2SelectionBufferPrivate /// \brief Selection buffer's render to texture camera public: Ogre::Camera *selectionCamera = nullptr; - /// \brief Ogre texture - public: Ogre::TexturePtr texture; - /// \brief Ogre render texture - // public: Ogre2RenderTexturePtr renderTexture; - public: Ogre::RenderTexture *renderTexture = nullptr; + public: Ogre::TextureGpu *renderTexture = nullptr; /// \brief Ogre's compositor workspace - the main interface to render /// into a render target or render texture. public: Ogre::CompositorWorkspace *ogreCompositorWorkspace = nullptr; - - /// \brief Render texture data buffer - public: uint8_t *buffer = nullptr; - - /// \brief Ogre pixel box that contains description of the data buffer - public: Ogre::PixelBox *pixelBox = nullptr; }; ///////////////////////////////////////////////// @@ -88,6 +78,12 @@ Ogre2SelectionBuffer::Ogre2SelectionBuffer(const std::string &_cameraName, this->dataPtr->selectionCamera = this->dataPtr->sceneMgr->createCamera(_cameraName + "_selection_buffer"); + this->dataPtr->selectionCamera->setFOVy(this->dataPtr->camera->getFOVy()); + this->dataPtr->selectionCamera->setNearClipDistance(this->dataPtr->camera->getNearClipDistance()); + this->dataPtr->selectionCamera->setFarClipDistance(this->dataPtr->camera->getFarClipDistance()); + this->dataPtr->selectionCamera->detachFromParent(); + this->dataPtr->sceneMgr->getRootSceneNode()->attachObject(this->dataPtr->selectionCamera); + this->dataPtr->materialSwitcher.reset( new Ogre2MaterialSwitcher(this->dataPtr->scene)); this->CreateRTTBuffer(); @@ -115,50 +111,44 @@ void Ogre2SelectionBuffer::Update() auto engine = Ogre2RenderEngine::Instance(); engine->OgreRoot()->renderOneFrame(); this->dataPtr->ogreCompositorWorkspace->setEnabled(false); - - this->dataPtr->renderTexture->copyContentsToMemory(*this->dataPtr->pixelBox, - Ogre::RenderTarget::FB_FRONT); } ///////////////////////////////////////////////// void Ogre2SelectionBuffer::DeleteRTTBuffer() { - auto &manager = Ogre::TextureManager::getSingleton(); - manager.unload(this->dataPtr->texture->getName()); - manager.remove(this->dataPtr->texture->getName()); - - if (this->dataPtr->buffer) - { - delete [] this->dataPtr->buffer; - this->dataPtr->buffer = nullptr; - } - if (this->dataPtr->pixelBox) - delete this->dataPtr->pixelBox; + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->renderTexture); + this->dataPtr->renderTexture = nullptr; } ///////////////////////////////////////////////// void Ogre2SelectionBuffer::CreateRTTBuffer() { - // create a 1x1 pixel buffer - unsigned int width = 1; - unsigned int height = 1; - Ogre::PixelFormat format = Ogre::PF_R8G8B8; - this->dataPtr->texture = Ogre::TextureManager::getSingleton().createManual( - "SelectionPassTex", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, width, height, 0, Ogre::PF_R8G8B8, - Ogre::TU_RENDERTARGET); + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); this->dataPtr->renderTexture = - this->dataPtr->texture->getBuffer()->getRenderTarget(); - this->dataPtr->renderTexture->addListener( + textureMgr->createOrRetrieveTexture("SelectionPassTex", + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D ); + this->dataPtr->renderTexture->setResolution(engine->getWindow()->getTexture()->getWidth(), + engine->getWindow()->getTexture()->getHeight()); + this->dataPtr->renderTexture->setNumMipmaps(1u); + this->dataPtr->renderTexture->setPixelFormat(Ogre::PFG_RGBA8_UNORM_SRGB); + + this->dataPtr->renderTexture->scheduleTransitionTo(Ogre::GpuResidency::Resident); + + this->dataPtr->selectionCamera->addListener( this->dataPtr->materialSwitcher.get()); // create compositor workspace for rendering - auto engine = Ogre2RenderEngine::Instance(); - auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); + //Setup the cubemap's compositor. const Ogre::String workspaceName = "SelectionBufferWorkspace" + this->dataPtr->camera->getName(); ogreCompMgr->createBasicWorkspaceDef(workspaceName, @@ -166,20 +156,16 @@ void Ogre2SelectionBuffer::CreateRTTBuffer() this->dataPtr->ogreCompositorWorkspace = ogreCompMgr->addWorkspace(this->dataPtr->scene->OgreSceneManager(), this->dataPtr->renderTexture, - this->dataPtr->selectionCamera, workspaceName, false); + this->dataPtr->selectionCamera, + workspaceName, + false); // set visibility mask to see only items that are selectable auto nodeSeq = this->dataPtr->ogreCompositorWorkspace->getNodeSequence(); - auto pass = nodeSeq[0]->_getPasses()[1]->getDefinition(); + auto pass = nodeSeq[0]->_getPasses()[0]->getDefinition(); auto scenePass = dynamic_cast(pass); const_cast(scenePass)->mVisibilityMask = IGN_VISIBILITY_SELECTABLE; - - // buffer to store render texture data - size_t bufferSize = Ogre::PixelUtil::getMemorySize(width, height, 1, format); - this->dataPtr->buffer = new uint8_t[bufferSize]; - this->dataPtr->pixelBox = new Ogre::PixelBox(width, - height, 1, format, this->dataPtr->buffer); } ///////////////////////////////////////////////// @@ -196,63 +182,35 @@ Ogre::Item *Ogre2SelectionBuffer::OnSelectionClick(const int _x, const int _y) if (!vp) return nullptr; - Ogre::RenderTarget *rt = vp->getTarget(); - - if (!rt) - return nullptr; - - const unsigned int targetWidth = rt->getWidth(); - const unsigned int targetHeight = rt->getHeight(); + const unsigned int targetWidth = vp->getWidth(); + const unsigned int targetHeight = vp->getHeight(); + // TODO (ahcorde): Revisit this part. It's partially working if (_x < 0 || _y < 0 || _x >= static_cast(targetWidth) || _y >= static_cast(targetHeight)) return nullptr; - // 1x1 selection buffer, adapted from rviz - // http://docs.ros.org/indigo/api/rviz/html/c++/selection__manager_8cpp.html - unsigned int width = 1; - unsigned int height = 1; - float x1 = static_cast(_x) / - static_cast(targetWidth - 1) - 0.5f; - float y1 = static_cast(_y) / - static_cast(targetHeight - 1) - 0.5f; - float x2 = static_cast(_x+width) / - static_cast(targetWidth - 1) - 0.5f; - float y2 = static_cast(_y+height) / - static_cast(targetHeight - 1) - 0.5f; - Ogre::Matrix4 scaleMatrix = Ogre::Matrix4::IDENTITY; - Ogre::Matrix4 transMatrix = Ogre::Matrix4::IDENTITY; - scaleMatrix[0][0] = 1.0 / (x2-x1); - scaleMatrix[1][1] = 1.0 / (y2-y1); - transMatrix[0][3] -= x1+x2; - transMatrix[1][3] += y1+y2; this->dataPtr->selectionCamera->setCustomProjectionMatrix(true, - scaleMatrix * transMatrix * this->dataPtr->camera->getProjectionMatrix()); + this->dataPtr->camera->getProjectionMatrix()); this->dataPtr->selectionCamera->setPosition( this->dataPtr->camera->getDerivedPosition()); this->dataPtr->selectionCamera->setOrientation( this->dataPtr->camera->getDerivedOrientation()); - Ogre::Viewport* renderViewport = - this->dataPtr->renderTexture->getViewport(0); - renderViewport->setDimensions(0, 0, width, height); // update render texture this->Update(); - size_t posInStream = 0; - ignition::math::Color::BGRA color(0); - if (!this->dataPtr->buffer) - { - ignerr << "Selection buffer is null." << std::endl; - return nullptr; - } - memcpy(static_cast(&color), this->dataPtr->buffer + posInStream, 4); - ignition::math::Color cv; - cv.SetFromARGB(color); - cv.A(1.0); - const std::string &entName = - this->dataPtr->materialSwitcher->EntityName(cv); + Ogre::Image2 image; + image.convertFromTexture(this->dataPtr->renderTexture, 0, 0); + + Ogre::ColourValue colorValue = image.getColourAt(_x, _y, 0, 0); + ignition::math::Color cv( + colorValue.r, + colorValue.g, + colorValue.b); + cv.A(1.0); + const std::string &entName = this->dataPtr->materialSwitcher->EntityName(cv); if (entName.empty()) { return 0; diff --git a/ogre2/src/Ogre2ThermalCamera.cc b/ogre2/src/Ogre2ThermalCamera.cc index eaac4647e..b197708cd 100644 --- a/ogre2/src/Ogre2ThermalCamera.cc +++ b/ogre2/src/Ogre2ThermalCamera.cc @@ -65,7 +65,7 @@ inline namespace IGNITION_RENDERING_VERSION_NAMESPACE { // /// \brief Helper class for switching the ogre item's material to heat source /// material when a thermal camera is being rendered. -class Ogre2ThermalCameraMaterialSwitcher : public Ogre::RenderTargetListener +class Ogre2ThermalCameraMaterialSwitcher : public Ogre::Camera::Listener { /// \brief constructor /// \param[in] _scene the scene manager responsible for rendering @@ -84,17 +84,15 @@ class Ogre2ThermalCameraMaterialSwitcher : public Ogre::RenderTargetListener /// \param[in] _resolution Temperature linear resolution public: void SetLinearResolution(double _resolution); - /// \brief Callback when a render target is about to be rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void preRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camara is about to be rendered + /// \param[in] _cam Ogre camera pointer which is about to render + private: virtual void cameraPreRenderScene( + Ogre::Camera * _cam) override; - /// \brief Callback when a render target is finisned being rendered - /// \param[in] _evt Ogre render target event containing information about - /// the source render target. - private: virtual void postRenderTargetUpdate( - const Ogre::RenderTargetEvent &_evt) override; + /// \brief Callback when a camera is finisned being rendered + /// \param[in] _cam Ogre camera pointer which has already render + private: virtual void cameraPostRenderScene( + Ogre::Camera * _cam) override; /// \brief Scene manager private: Ogre2ScenePtr scene = nullptr; @@ -147,9 +145,6 @@ class Ogre2ThermalCameraMaterialSwitcher : public Ogre::RenderTargetListener /// \brief Private data for the Ogre2ThermalCamera class class ignition::rendering::Ogre2ThermalCameraPrivate { - /// \brief The thermal buffer - public: unsigned char *thermalBuffer = nullptr; - /// \brief Outgoing thermal data, used by newThermalFrame event. public: uint16_t *thermalImage = nullptr; @@ -169,7 +164,7 @@ class ignition::rendering::Ogre2ThermalCameraPrivate public: Ogre::CompositorWorkspace *ogreCompositorWorkspace; /// \brief Thermal textures. - public: Ogre::TexturePtr ogreThermalTexture; + public: Ogre::TextureGpu * ogreThermalTexture; /// \brief Dummy render texture for the thermal data public: RenderTexturePtr thermalTexture = nullptr; @@ -230,8 +225,8 @@ void Ogre2ThermalCameraMaterialSwitcher::SetLinearResolution(double _resolution) this->resolution = _resolution; } ////////////////////////////////////////////////// -void Ogre2ThermalCameraMaterialSwitcher::preRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2ThermalCameraMaterialSwitcher::cameraPreRenderScene( + Ogre::Camera * /*_cam*/) { // swap item to use v1 shader material // Note: keep an eye out for performance impact on switching materials @@ -414,8 +409,8 @@ void Ogre2ThermalCameraMaterialSwitcher::preRenderTargetUpdate( } ////////////////////////////////////////////////// -void Ogre2ThermalCameraMaterialSwitcher::postRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2ThermalCameraMaterialSwitcher::cameraPostRenderScene( + Ogre::Camera * /*_cam*/) { // restore item to use pbs hlms material for (auto it : this->datablockMap) @@ -455,12 +450,9 @@ void Ogre2ThermalCamera::Init() ////////////////////////////////////////////////// void Ogre2ThermalCamera::Destroy() { - if (this->dataPtr->thermalBuffer) - { - delete [] this->dataPtr->thermalBuffer; - this->dataPtr->thermalBuffer = nullptr; - } + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); if (this->dataPtr->thermalImage) { delete [] this->dataPtr->thermalImage; @@ -470,15 +462,14 @@ void Ogre2ThermalCamera::Destroy() if (!this->ogreCamera) return; - auto engine = Ogre2RenderEngine::Instance(); - auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); // remove thermal texture, material, compositor if (this->dataPtr->ogreThermalTexture) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->ogreThermalTexture->getName()); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->ogreThermalTexture); + this->dataPtr->ogreThermalTexture = nullptr; } if (this->dataPtr->ogreCompositorWorkspace) { @@ -590,15 +581,15 @@ void Ogre2ThermalCamera::CreateThermalTexture() // only support 8 bit and 16 bit formats for now. // default to 16 bit - Ogre::PixelFormat ogrePF; + Ogre::PixelFormatGpu ogrePF; if (this->ImageFormat() == PF_L8) { - ogrePF = Ogre::PF_L8; + ogrePF = Ogre::PFG_R8_UNORM; } else { this->SetImageFormat(PF_L16); - ogrePF = Ogre::PF_L16; + ogrePF = Ogre::PFG_R16_UNORM; } PixelFormat format = this->ImageFormat(); @@ -649,7 +640,7 @@ void Ogre2ThermalCamera::CreateThermalTexture() // compositor_node ThermalCamera // { // in 0 rt_input - // texture depthTexture target_width target_height PF_D32_FLOAT + // texture depthTexture target_width target_height PFG_D32_FLOAT // texture colorTexture target_width target_height PF_R8G8B8A8 // target colorTexture // { @@ -690,42 +681,40 @@ void Ogre2ThermalCamera::CreateThermalTexture() Ogre::TextureDefinitionBase::TEXTURE_INPUT); Ogre::TextureDefinitionBase::TextureDefinition *thermalTexDef = nodeDef->addTextureDefinition("depthTexture"); - thermalTexDef->textureType = Ogre::TEX_TYPE_2D; + thermalTexDef->textureType = Ogre::TextureTypes::Type2D; thermalTexDef->width = 0; thermalTexDef->height = 0; - thermalTexDef->depth = 1; + thermalTexDef->depthOrSlices = 1; thermalTexDef->numMipmaps = 0; thermalTexDef->widthFactor = 1; thermalTexDef->heightFactor = 1; - thermalTexDef->formatList = {Ogre::PF_D32_FLOAT}; - thermalTexDef->fsaa = 0; - thermalTexDef->uav = false; - thermalTexDef->automipmaps = false; - thermalTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + thermalTexDef->format = Ogre::PFG_D32_FLOAT; + thermalTexDef->textureFlags |= !Ogre::TextureFlags::Uav; // set to default pool so that when the colorTexture pass is rendered, its // depth data get populated to depthTexture thermalTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - thermalTexDef->depthBufferFormat = Ogre::PF_UNKNOWN; - thermalTexDef->fsaaExplicitResolve = false; + thermalTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + + Ogre::RenderTargetViewDef *rtv = nodeDef->addRenderTextureView("depthTexture"); + rtv->setForTextureDefinition("depthTexture", thermalTexDef); Ogre::TextureDefinitionBase::TextureDefinition *colorTexDef = nodeDef->addTextureDefinition("colorTexture"); - colorTexDef->textureType = Ogre::TEX_TYPE_2D; + colorTexDef->textureType = Ogre::TextureTypes::Type2D; colorTexDef->width = 0; colorTexDef->height = 0; - colorTexDef->depth = 1; + colorTexDef->depthOrSlices = 1; colorTexDef->numMipmaps = 0; colorTexDef->widthFactor = 1; colorTexDef->heightFactor = 1; - colorTexDef->formatList = {Ogre::PF_R8G8B8A8}; - colorTexDef->fsaa = 0; - colorTexDef->uav = false; - colorTexDef->automipmaps = false; - colorTexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse; + colorTexDef->format = Ogre::PFG_RGBA8_UNORM; + colorTexDef->textureFlags |= !Ogre::TextureFlags::Uav; colorTexDef->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; - colorTexDef->depthBufferFormat = Ogre::PF_D32_FLOAT; + colorTexDef->depthBufferFormat = Ogre::PFG_D32_FLOAT; colorTexDef->preferDepthTexture = true; - colorTexDef->fsaaExplicitResolve = false; + + Ogre::RenderTargetViewDef *rtv2 = nodeDef->addRenderTextureView("colorTexture"); + rtv2->setForTextureDefinition("colorTexture", colorTexDef); nodeDef->setNumTargetPass(2); Ogre::CompositorTargetDef *colorTargetDef = @@ -736,7 +725,7 @@ void Ogre2ThermalCamera::CreateThermalTexture() Ogre::CompositorPassClearDef *passClear = static_cast( colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(0, 0, 0); + passClear->setAllClearColours(Ogre::ColourValue(0, 0, 0)); // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( @@ -755,14 +744,14 @@ void Ogre2ThermalCamera::CreateThermalTexture() Ogre::CompositorPassClearDef *passClear = static_cast( inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->ambient, 0, 1.0); + passClear->setAllClearColours(Ogre::ColourValue(this->ambient, 0, 1.0)); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); passQuad->mMaterialName = this->dataPtr->thermalMaterial->getName(); - passQuad->addQuadTextureSource(0, "depthTexture", 0); - passQuad->addQuadTextureSource(1, "colorTexture", 0); + passQuad->addQuadTextureSource(0, "depthTexture"); + passQuad->addQuadTextureSource(1, "colorTexture"); passQuad->mFrustumCorners = Ogre::CompositorPassQuadDef::VIEW_SPACE_CORNERS; } @@ -780,37 +769,47 @@ void Ogre2ThermalCamera::CreateThermalTexture() << " for " << this->Name(); } + Ogre::TextureGpuManager *textureMgr = ogreRoot->getRenderSystem()->getTextureGpuManager(); // create render texture - these textures pack the thermal data this->dataPtr->ogreThermalTexture = - Ogre::TextureManager::getSingleton().createManual( - this->Name() + "_thermal", "General", Ogre::TEX_TYPE_2D, - this->ImageWidth(), this->ImageHeight(), 1, 0, - ogrePF, Ogre::TU_RENDERTARGET, - 0, false, 0, Ogre::BLANKSTRING, false, true); + textureMgr->createOrRetrieveTexture(this->Name() + "_thermal", + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); - Ogre::RenderTarget *rt = - this->dataPtr->ogreThermalTexture->getBuffer()->getRenderTarget(); + this->dataPtr->ogreThermalTexture->setResolution( + this->ImageWidth(), this->ImageHeight()); + this->dataPtr->ogreThermalTexture->setNumMipmaps(1u); + this->dataPtr->ogreThermalTexture->setPixelFormat( + ogrePF); + + this->dataPtr->ogreThermalTexture->scheduleTransitionTo( + Ogre::GpuResidency::Resident); // create compositor worksspace this->dataPtr->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - rt, this->ogreCamera, wsDefName, false); - - // add thermal material swticher to render target listener + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + this->dataPtr->ogreThermalTexture, + this->ogreCamera, + wsDefName, + false); + + // add thermal material switcher to render target listener // so we can switch to use heat material when the camera is being udpated Ogre::CompositorNode *node = this->dataPtr->ogreCompositorWorkspace->getNodeSequence()[0]; auto channels = node->getLocalTextures(); for (auto c : channels) { - if (c.textures[0]->getSrcFormat() == Ogre::PF_R8G8B8A8) + if (c->getPixelFormat() == Ogre::PFG_RGBA8_UNORM) { this->dataPtr->thermalMaterialSwitcher.reset( new Ogre2ThermalCameraMaterialSwitcher(this->scene, this->Name())); this->dataPtr->thermalMaterialSwitcher->SetFormat(this->ImageFormat()); this->dataPtr->thermalMaterialSwitcher->SetLinearResolution( this->resolution); - c.target->addListener(this->dataPtr->thermalMaterialSwitcher.get()); + this->ogreCamera->addListener(this->dataPtr->thermalMaterialSwitcher.get()); break; } } @@ -842,23 +841,14 @@ void Ogre2ThermalCamera::PostRender() unsigned int width = this->ImageWidth(); unsigned int height = this->ImageHeight(); PixelFormat format = this->ImageFormat(); - Ogre::PixelFormat imageFormat = Ogre2Conversions::Convert(format); int len = width * height; unsigned int channelCount = PixelUtil::ChannelCount(format); unsigned int bytesPerChannel = PixelUtil::BytesPerChannel(format); - if (!this->dataPtr->thermalBuffer) - { - this->dataPtr->thermalBuffer = - new unsigned char[len * channelCount * bytesPerChannel]; - } - Ogre::PixelBox dstBox(width, height, - 1, imageFormat, this->dataPtr->thermalBuffer); - - // blit data from gpu to cpu - auto rt = this->dataPtr->ogreThermalTexture->getBuffer()->getRenderTarget(); - rt->copyContentsToMemory(dstBox, Ogre::RenderTarget::FB_FRONT); + Ogre::Image2 image; + image.convertFromTexture(this->dataPtr->ogreThermalTexture, 0u, 0u); + uint16_t * thermalBuffer = static_cast(image.getRawBuffer()); if (!this->dataPtr->thermalImage) { @@ -877,14 +867,14 @@ void Ogre2ThermalCamera::PostRender() { unsigned int idx = (i * width) + j; this->dataPtr->thermalImage[idx] = static_cast( - this->dataPtr->thermalBuffer[idx]); + thermalBuffer[idx]); } } } else { // fill thermal data - memcpy(this->dataPtr->thermalImage, this->dataPtr->thermalBuffer, + memcpy(this->dataPtr->thermalImage, thermalBuffer, height * width * channelCount * bytesPerChannel); } diff --git a/ogre2/src/Ogre2Visual.cc b/ogre2/src/Ogre2Visual.cc index f6eefeac2..bc29ae457 100644 --- a/ogre2/src/Ogre2Visual.cc +++ b/ogre2/src/Ogre2Visual.cc @@ -23,7 +23,6 @@ #include "ignition/rendering/ogre2/Ogre2RenderTypes.hh" #include "ignition/rendering/ogre2/Ogre2Storage.hh" #include "ignition/rendering/ogre2/Ogre2Visual.hh" -#include "ignition/rendering/ogre2/Ogre2WireBox.hh" #include "ignition/rendering/Utils.hh" using namespace ignition; diff --git a/ogre2/src/media/2.0/scripts/Compositors/GaussianNoise.compositor b/ogre2/src/media/2.0/scripts/Compositors/GaussianNoise.compositor deleted file mode 100644 index 8b02ef146..000000000 --- a/ogre2/src/media/2.0/scripts/Compositors/GaussianNoise.compositor +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - * - */ - -compositor_node GaussianNoiseNode -{ - // render texture input from previous render pass - in 0 rt_input - // render texture output to be passed to next render pass - in 1 rt_output - - // Only one target pass is needed. - // rt_input is used as input to this pass and result is stored - // in rt_output - target rt_output - { - pass render_quad - { - material GaussianNoise - input 0 rt_input - } - } - // pass the result to the next render pass - out 0 rt_output - // pass the rt_input render texture to the next render pass - // where the texture is reused to store its result - out 1 rt_input -} diff --git a/ogre2/src/media/2.0/scripts/Compositors/PbsMaterials.compositor b/ogre2/src/media/2.0/scripts/Compositors/PbsMaterials.compositor deleted file mode 100644 index 634752aad..000000000 --- a/ogre2/src/media/2.0/scripts/Compositors/PbsMaterials.compositor +++ /dev/null @@ -1,67 +0,0 @@ -compositor_node PbsMaterialsRenderingNode -{ - // rt0 - original scene - texture rt0 target_width target_height PF_R8G8B8 - // rt1 - texture to be passed to the next compositor node for - // adding render pass effect. Note: it seems that a clear pass is not needed - // for rt1 - texture rt1 target_width target_height PF_R8G8B8 - - target rt0 - { - - pass clear - { - colour_value 0.0 0.0 0.0 1 - } - - pass render_scene - { - overlays on - shadows PbsMaterialsShadowNode - } - } - - out 0 rt0 - out 1 rt1 -} - -compositor_node FinalComposition -{ - in 0 rt_output - // Take input texture #1 and use the local name "rtN" for reference in this - // scope. Note: A clear pass was removed from this target as it generated - // image artifacts on some machines - in 1 rtN - - target rt_output - { - pass render_quad - { - // Ignore the alpha channel - material Ogre/Copy/4xFP32 - input 0 rtN - } - - pass render_scene - { - lod_update_list off - - // Render Overlays - overlays on - rq_first 254 - rq_last 255 - } - } -} - -// The compositor shadow node will be programmatically constructed -compositor_node_shadow PbsMaterialsShadowNode -{ -} - -workspace PbsMaterialsWorkspace -{ - connect_output FinalComposition 0 - connect PbsMaterialsRenderingNode 0 FinalComposition 1 -} diff --git a/ogre2/src/media/Hlms/Common/Any/Cubemap_piece_all.any b/ogre2/src/media/Hlms/Common/Any/Cubemap_piece_all.any index e8f3dd3e1..b98265b26 100644 --- a/ogre2/src/media/Hlms/Common/Any/Cubemap_piece_all.any +++ b/ogre2/src/media/Hlms/Common/Any/Cubemap_piece_all.any @@ -10,6 +10,7 @@ struct CubemapProbe float4 row2_centerZ; float4 halfSize; float4 cubemapPosLS; + float4 cubemapPosVS; }; @end @@ -25,20 +26,16 @@ struct CubemapProbe \return Parallax-Corrected reflection dir, IN LOCAL SPACE (local to probe's). Unlike the inputs, this vector is LEFT HANDED. + + The w component contains the distance from pos to intersection walking across reflDir */ -@property( syntax == metal )inline @end float3 localCorrect( float3 reflDir, float3 posLS, - CubemapProbe probe ) +INLINE float4 localCorrect( float3 reflDir, float3 posLS, CubemapProbe probe ) { float3 probeShapeHalfSize = probe.halfSize.xyz; - float3x3 viewSpaceToProbeLocal = float3x3( probe.row0_centerX.xyz, - probe.row1_centerY.xyz, - probe.row2_centerZ.xyz ); - - @property( syntax == hlsl ) - float3 reflDirLS = mul( viewSpaceToProbeLocal, reflDir ); - @end @property( syntax != hlsl ) - float3 reflDirLS = reflDir * viewSpaceToProbeLocal; - @end + float3x3 viewSpaceToProbeLocal = buildFloat3x3( probe.row0_centerX.xyz, + probe.row1_centerY.xyz, + probe.row2_centerZ.xyz ); + float3 reflDirLS = mul( reflDir, viewSpaceToProbeLocal ); //Find the ray intersection with box plane float3 invReflDirLS = float3( 1.0, 1.0, 1.0 ) / reflDirLS; @@ -55,8 +52,9 @@ struct CubemapProbe //Make it left-handed. localCorrectedVec.z = -localCorrectedVec.z; - return localCorrectedVec; + return float4( localCorrectedVec, distance ); } + /** Converts a position from view space to probe's local space. \param pos Position of the object where the reflection is going to reflect, in view space @@ -100,10 +98,18 @@ struct CubemapProbe float3 vDiff = ( probe.halfSize.xyz - abs( posLS.xyz ) ) / probe.halfSize.xyz; return min( min( vDiff.x, vDiff.y ), vDiff.z ); } -@end -//float3 main( float3 reflDir : TEXCOORD0, float3 pos : TEXCOORD1 ) : SV_Target0 -//{ -// return localCorrect( reflDir, pos, probe ); -//} -@end +INLINE float getProbeNDF( float3 posLS, float3 probeToAreaCenterOffsetLS, + float3 innerRange, float3 outerRange ) +{ + float3 areaPosLS = posLS.xyz - probeToAreaCenterOffsetLS.xyz; + //float3 areaPosLS = posLS.xyz - float3( 0, 0, -5 ); + float3 dist = abs( areaPosLS.xyz ); + //1e-6f avoids division by zero. + float3 ndf = (dist - innerRange) / (outerRange - innerRange + 1e-6f); + + return max3( ndf.x, ndf.y, ndf.z ); +} + +@end /// DeclParallaxLocalCorrect +@end /// parallax_correct_cubemaps diff --git a/ogre2/src/media/Hlms/Common/Any/DualParaboloid_piece_ps.any b/ogre2/src/media/Hlms/Common/Any/DualParaboloid_piece_ps.any new file mode 100644 index 000000000..024e6f60d --- /dev/null +++ b/ogre2/src/media/Hlms/Common/Any/DualParaboloid_piece_ps.any @@ -0,0 +1,17 @@ + +//#include "SyntaxHighlightingMisc.h" +@piece( DeclDualParaboloidFunc ) + +/// Converts UVW coordinates that would be used for sampling a cubemap, +/// and returns UV coordinates to sample a dual paraboloid in 2D +INLINE float2 mapCubemapToDpm( float3 cubemapDir ) +{ + cubemapDir = normalize( cubemapDir ); + float2 retVal; + retVal.x = (cubemapDir.x / (1.0 + abs( cubemapDir.z ))) * 0.25 + + (cubemapDir.z < 0.0 ? 0.75 : 0.25 ); + retVal.y = (cubemapDir.y / (1.0 + abs( cubemapDir.z ))) * 0.5 + 0.5; + return retVal; +} + +@end /// DeclDualParaboloidFunc diff --git a/ogre2/src/media/Hlms/Common/Any/ReverseDepthHelpers_piece_ps.any b/ogre2/src/media/Hlms/Common/Any/ReverseDepthHelpers_piece_ps.any new file mode 100644 index 000000000..36b490119 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/Any/ReverseDepthHelpers_piece_ps.any @@ -0,0 +1,10 @@ + +@piece( DeclReverseDepthMacros ) + @property( hlms_no_reverse_depth ) + #define OGRE_DEPTH_CMP_GE( a, b ) (a) >= (b) + #define OGRE_DEPTH_DEFAULT_CLEAR 1.0 + @else + #define OGRE_DEPTH_CMP_GE( a, b ) (a) <= (b) + #define OGRE_DEPTH_DEFAULT_CLEAR 0.0 + @end +@end diff --git a/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_ps.any b/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_ps.any index 630292d19..55f774357 100644 --- a/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_ps.any +++ b/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_ps.any @@ -6,7 +6,7 @@ ///-------------------------------------------------------------------------------------- @piece( DeclShadowCasterMacros ) - @property( syntax == glsl ) + @property( syntax == glsl || syntax == glsles ) @property( !hlms_render_depth_only ) @property( GL3+ ) #define outDepth outColour @@ -33,8 +33,12 @@ float distanceToCamera = length( inPs.toCameraWS ); @property( !exponential_shadow_maps ) outDepth = (distanceToCamera - passBuf.depthRange.x) * passBuf.depthRange.y + inPs.constBias; - @end @property( exponential_shadow_maps ) + @else outDepth = (distanceToCamera - passBuf.depthRange.x) * passBuf.depthRange.y; @end + + @property( !hlms_no_reverse_depth ) + outDepth = 1.0 - outDepth; + @end @end @end diff --git a/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_vs.any b/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_vs.any index 988098d96..75671d040 100644 --- a/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_vs.any +++ b/ogre2/src/media/Hlms/Common/Any/ShadowCaster_piece_vs.any @@ -3,24 +3,20 @@ @property( hlms_shadowcaster ) @piece( DoShadowCasterVS ) - @property( syntax == glsl ) - float shadowConstantBias = uintBitsToFloat( instance.worldMaterialIdx[drawId].y ); - @end - @property( syntax == hlsl ) - float shadowConstantBias = asfloat( worldMaterialIdx[input.drawId].y ); - @end - @property( syntax == metal ) - float shadowConstantBias = as_type( worldMaterialIdx[drawId].y ); + @property( hlms_no_reverse_depth || hlms_shadowcaster_point ) + float shadowConstantBias = uintBitsToFloat( worldMaterialIdx[inVs_drawId].y ); + @else + float shadowConstantBias = -uintBitsToFloat( worldMaterialIdx[inVs_drawId].y ); @end @property( !hlms_shadow_uses_depth_texture && !hlms_shadowcaster_point && !exponential_shadow_maps ) //Linear depth - @property( hlms_shadowcaster_directional ) + @property( hlms_shadowcaster_directional || !hlms_no_reverse_depth ) outVs.depth = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y; - @end @property( !hlms_shadowcaster_directional ) + @else outVs.depth = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y; @end - @property( syntax == glsl )outVs.depth = (outVs.depth * 0.5) + 0.5;@end + @property( hlms_no_reverse_depth && (syntax == glsl || syntax == glsles) )outVs.depth = (outVs.depth * 0.5) + 0.5;@end @end @property( hlms_shadowcaster_point ) @@ -34,9 +30,9 @@ //We can't make the depth buffer linear without Z out in the fragment shader; //however we can use a cheap approximation ("pseudo linear depth") //see http://www.yosoygames.com.ar/wp/2014/01/linear-depth-buffer-my-ass/ - @property( hlms_shadowcaster_directional ) + @property( hlms_shadowcaster_directional || !hlms_no_reverse_depth ) outVs_Position.z = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y; - @end @property( !hlms_shadowcaster_directional ) + @else outVs_Position.z = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y * outVs_Position.w; @end @end diff --git a/ogre2/src/media/Hlms/Common/Any/UnpackHelpers_piece_all.any b/ogre2/src/media/Hlms/Common/Any/UnpackHelpers_piece_all.any new file mode 100644 index 000000000..1a11f7900 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/Any/UnpackHelpers_piece_all.any @@ -0,0 +1,7 @@ + +@piece( UnpackHelpers ) + INLINE float2 unpackUshort2ToFloat2( uint value ) + { + return float2( value & 0xFFFFu, value >> 16u ); + } +@end diff --git a/ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl index 466aa3523..fa0587f04 100644 --- a/ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl +++ b/ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl @@ -1,15 +1,33 @@ @piece( SetCrossPlatformSettings ) -@property( GL3+ >= 430 )#version 430 core -@end @property( GL3+ < 430 ) -#version 330 core +@property( GL3+ >= 430 ) + #version 430 core +@else + #version 330 core @end +@insertpiece( CustomGlslExtensions ) + @property( GL_ARB_shading_language_420pack ) #extension GL_ARB_shading_language_420pack: require #define layout_constbuffer(x) layout( std140, x ) +@else + #define layout_constbuffer(x) layout( std140 ) +@end + +@property( hlms_instanced_stereo ) + #extension GL_ARB_shader_viewport_layer_array: require @end + @property( GL_ARB_texture_buffer_range ) - #define bufferFetch texelFetch + #define bufferFetch texelFetch + #define structuredBufferFetch texelFetch +@end + +@property( hlms_amd_trinary_minmax ) + #extension GL_AMD_shader_trinary_minmax: require +@else + #define min3( a, b, c ) min( a, min( b, c ) ) + #define max3( a, b, c ) max( a, max( b, c ) ) @end #define float2 vec2 @@ -24,19 +42,96 @@ #define uint3 uvec3 #define uint4 uvec4 +#define float2x2 mat2 #define float3x3 mat3 #define float4x4 mat4 +#define ogre_float4x3 mat3x4 + +#define ushort uint +#define ushort3 uint3 +#define ushort4 uint4 + +//Short used for read operations. It's an int in GLSL & HLSL. An ushort in Metal +#define rshort int +#define rshort2 int2 +#define rint int +//Short used for write operations. It's an int in GLSL. An ushort in HLSL & Metal +#define wshort2 int2 +#define wshort3 int3 + +#define toFloat3x3( x ) mat3( x ) +#define buildFloat3x3( row0, row1, row2 ) mat3( row0, row1, row2 ) #define mul( x, y ) ((x) * (y)) #define saturate(x) clamp( (x), 0.0, 1.0 ) #define lerp mix +#define rsqrt inversesqrt #define INLINE +#define NO_INTERPOLATION_PREFIX flat +#define NO_INTERPOLATION_SUFFIX #define finalDrawId drawId +#define PARAMS_ARG_DECL +#define PARAMS_ARG + +#define inVs_vertexId gl_VertexID +#define inVs_vertex vertex +#define inVs_blendWeights blendWeights +#define inVs_blendIndices blendIndices +#define inVs_qtangent qtangent + +@property( !hlms_instanced_stereo ) + #define inVs_drawId drawId +@else + #define inVs_drawId (drawId >> 1u) + #define inVs_stereoDrawId drawId +@end + +@foreach( hlms_uv_count, n ) + #define inVs_uv@n uv@n@end #define outVs_Position gl_Position -#define OGRE_SampleLevel( tex, sampler, uv, lod ) textureLod( tex, uv.xy, lod ) +#define outVs_viewportIndex gl_ViewportIndex +#define outVs_clipDistance0 gl_ClipDistance[0] + +#define gl_SampleMaskIn0 gl_SampleMaskIn[0] +#define reversebits bitfieldReverse + +#define outPs_colour0 outColour +#define OGRE_Sample( tex, sampler, uv ) texture( tex, uv ) +#define OGRE_SampleLevel( tex, sampler, uv, lod ) textureLod( tex, uv, lod ) +#define OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) texture( tex, vec3( uv, arrayIdx ) ) #define OGRE_SampleArray2DLevel( tex, sampler, uv, arrayIdx, lod ) textureLod( tex, vec3( uv, arrayIdx ), lod ) +#define OGRE_SampleArrayCubeLevel( tex, sampler, uv, arrayIdx, lod ) textureLod( tex, vec4( uv, arrayIdx ), lod ) +#define OGRE_SampleGrad( tex, sampler, uv, ddx, ddy ) textureGrad( tex, uv, ddx, ddy ) +#define OGRE_SampleArray2DGrad( tex, sampler, uv, arrayIdx, ddx, ddy ) textureGrad( tex, vec3( uv, arrayIdx ), ddx, ddy ) +#define OGRE_ddx( val ) dFdx( val ) +#define OGRE_ddy( val ) dFdy( val ) +#define OGRE_Load2D( tex, iuv, lod ) texelFetch( tex, iuv, lod ) +#define OGRE_LoadArray2D( tex, iuv, arrayIdx, lod ) texelFetch( tex, ivec3( iuv, arrayIdx ), lod ) +#define OGRE_Load2DMS( tex, iuv, subsample ) texelFetch( tex, iuv, subsample ) + +#define OGRE_Load3D( tex, iuv, lod ) texelFetch( tex, ivec3( iuv ), lod ) + +#define bufferFetch1( buffer, idx ) texelFetch( buffer, idx ).x + +#define OGRE_SAMPLER_ARG_DECL( samplerName ) +#define OGRE_SAMPLER_ARG( samplerName ) + +#define OGRE_Texture3D_float4 sampler3D + +#define CONST_BUFFER( bufferName, bindingPoint ) layout_constbuffer(binding = bindingPoint) uniform bufferName +#define CONST_BUFFER_STRUCT_BEGIN( structName, bindingPoint ) layout_constbuffer(binding = bindingPoint) uniform structName +#define CONST_BUFFER_STRUCT_END( variableName ) variableName + +#define FLAT_INTERPOLANT( decl, bindingPoint ) flat decl +#define INTERPOLANT( decl, bindingPoint ) decl + +#define OGRE_OUT_REF( declType, variableName ) out declType variableName +#define OGRE_INOUT_REF( declType, variableName ) inout declType variableName + +#define OGRE_ARRAY_START( type ) type[]( +#define OGRE_ARRAY_END ) @end @property( !GL_ARB_texture_buffer_range || !GL_ARB_shading_language_420pack ) @@ -60,9 +155,6 @@ ivec2 pos = ivec2( mod( pixelIdx, 2048 ), int( uint(pixelIdx) >> 11u ) ); return texelFetch( sampl, pos, 0 ); } - @end - @property( !GL_ARB_shading_language_420pack ) - #define layout_constbuffer(x) layout( std140 ) - @end + @end @end @end diff --git a/ogre2/src/media/Hlms/Common/GLSL/Matrix_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSL/Matrix_piece_all.glsl index 9eda568ab..d75bac90a 100644 --- a/ogre2/src/media/Hlms/Common/GLSL/Matrix_piece_all.glsl +++ b/ogre2/src/media/Hlms/Common/GLSL/Matrix_piece_all.glsl @@ -10,8 +10,8 @@ mat4 UNPACK_MAT4( samplerBuffer matrixBuf, uint pixelIdx ) } @end -@piece( Common_Matrix_DeclUnpackMatrix3x4 ) -mat3x4 UNPACK_MAT3x4( samplerBuffer matrixBuf, uint pixelIdx ) +@piece( Common_Matrix_DeclUnpackMatrix4x3 ) +mat3x4 UNPACK_MAT4x3( samplerBuffer matrixBuf, uint pixelIdx ) { vec4 row0 = texelFetch( matrixBuf, int((pixelIdx) << 2u) ); vec4 row1 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 1u) ); @@ -19,6 +19,19 @@ mat3x4 UNPACK_MAT3x4( samplerBuffer matrixBuf, uint pixelIdx ) return mat3x4( row0, row1, row2 ); } @end + +@piece( Common_Matrix_DeclLoadOgreFloat4x3 ) +ogre_float4x3 loadOgreFloat4x3( samplerBuffer matrixBuf, uint offsetIdx ) +{ + mat3x4 retVal; + retVal[0] = texelFetch( matrixBuf, int(offsetIdx) ); + retVal[1] = texelFetch( matrixBuf, int(offsetIdx + 1u) ); + retVal[2] = texelFetch( matrixBuf, int(offsetIdx + 2u) ); + return retVal; +} + +#define makeOgreFloat4x3( row0, row1, row2 ) mat3x4( row0, row1, row2 ) +@end @end @property( !GL_ARB_texture_buffer_range ) @@ -37,8 +50,8 @@ mat4 UNPACK_MAT4( in sampler2D matrixBuf, in uint pixelIdx ) } @end -@piece( Common_Matrix_DeclUnpackMatrix3x4 ) -mat3x4 UNPACK_MAT3x4( in sampler2D matrixBuf, in uint pixelIdx ) +@piece( Common_Matrix_DeclUnpackMatrix4x3 ) +mat3x4 UNPACK_MAT4x3( in sampler2D matrixBuf, in uint pixelIdx ) { ivec2 pos0 = ivec2(int(((pixelIdx) << 2u) & 2047u), int(((pixelIdx) << 2u) >> 11u)); ivec2 pos1 = ivec2(int((((pixelIdx) << 2u) + 1u) & 2047u), int((((pixelIdx) << 2u) + 1u) >> 11u)); @@ -49,5 +62,22 @@ mat3x4 UNPACK_MAT3x4( in sampler2D matrixBuf, in uint pixelIdx ) return mat3x4( row0, row1, row2 ); } @end + +@piece( Common_Matrix_DeclLoadOgreFloat4x3 ) +ogre_float4x3 loadOgreFloat4x3( samplerBuffer matrixBuf, uint offsetIdx ) +{ + ivec2 pos0 = ivec2(int(offsetIdx & 2047u), int(offsetIdx >> 11u)); + ivec2 pos1 = ivec2(int((offsetIdx + 1u) & 2047u), int((offsetIdx + 1u) >> 11u)); + ivec2 pos2 = ivec2(int((offsetIdx + 2u) & 2047u), int((offsetIdx + 2u) >> 11u)); + + mat3x4 retVal; + retVal[0] = texelFetch( matrixBuf, pos0, 0 ); + retVal[1] = texelFetch( matrixBuf, pos1, 0 ); + retVal[2] = texelFetch( matrixBuf, pos2, 0 ); + return retVal; +} + +#define makeOgreFloat4x3( row0, row1, row2 ) mat3x4( row0, row1, row2 ) +@end @end diff --git a/ogre2/src/media/Hlms/Common/GLSL/UavCrossPlatform_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSL/UavCrossPlatform_piece_all.glsl new file mode 100644 index 000000000..b99afdb4c --- /dev/null +++ b/ogre2/src/media/Hlms/Common/GLSL/UavCrossPlatform_piece_all.glsl @@ -0,0 +1,21 @@ + +@piece( DeclUavCrossPlatform ) + +#define OGRE_imageLoad2D( inImage, iuv ) imageLoad( inImage, int2( iuv ) ) +#define OGRE_imageLoad2DArray( inImage, iuvw ) imageLoad( inImage, int3( iuvw ) ) + +#define OGRE_imageWrite2D1( outImage, iuv, value ) imageStore( outImage, int2( iuv ), float4( value, 0, 0, 0 ) ) +#define OGRE_imageWrite2D2( outImage, iuv, value ) imageStore( outImage, int2( iuv ), float4( value, 0, 0 ) ) +#define OGRE_imageWrite2D4( outImage, iuv, value ) imageStore( outImage, int2( iuv ), value ) + +#define OGRE_imageLoad3D( inImage, iuv ) imageLoad( inImage, int3( iuv ) ) + +#define OGRE_imageWrite3D1( outImage, iuv, value ) imageStore( outImage, int3( iuv ), value ) +#define OGRE_imageWrite3D4( outImage, iuv, value ) imageStore( outImage, int3( iuv ), value ) + +#define OGRE_imageWrite2DArray1( outImage, iuvw, value ) imageStore( outImage, int3( iuvw ), value ) +#define OGRE_imageWrite2DArray4( outImage, iuvw, value ) imageStore( outImage, int3( iuvw ), value ) + +#define __sharedOnlyBarrier memoryBarrierShared();barrier(); + +@end diff --git a/ogre2/src/media/Hlms/Common/GLSLES/CrossPlatformSettings_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSLES/CrossPlatformSettings_piece_all.glsl new file mode 100644 index 000000000..432eea890 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/GLSLES/CrossPlatformSettings_piece_all.glsl @@ -0,0 +1,88 @@ +@piece( SetCrossPlatformSettings ) +@property( 300 <= GLES )#version 300 es +precision highp float; +precision highp isampler2D; +precision highp usampler2D; +precision highp sampler2DShadow; +precision highp sampler2DArray; +@end + +@property( GL_ARB_shading_language_420pack ) + #extension GL_ARB_shading_language_420pack: require + #define layout_constbuffer(x) layout( std140, x ) +@end +@property( GL_ARB_texture_buffer_range ) + #define bufferFetch texelFetch +@end + +#define float2 vec2 +#define float3 vec3 +#define float4 vec4 + +#define int2 ivec2 +#define int3 ivec3 +#define int4 ivec4 + +#define uint2 uvec2 +#define uint3 uvec3 +#define uint4 uvec4 + +#define float2x2 mat2 +#define float3x3 mat3 +#define float4x4 mat4 + +#define ushort uint + +#define toFloat3x3( x ) mat3( x ) +#define buildFloat3x3( row0, row1, row2 ) mat3( row0, row1, row2 ) + +#define mul( x, y ) ((x) * (y)) +#define saturate(x) clamp( (x), 0.0, 1.0 ) +#define lerp mix +#define rsqrt inversesqrt +#define INLINE + +#define finalDrawId drawId +#define PARAMS_ARG_DECL +#define PARAMS_ARG + +#define outVs_Position gl_Position +#define OGRE_Sample( tex, sampler, uv ) texture( tex, uv ) +#define OGRE_SampleLevel( tex, sampler, uv, lod ) textureLod( tex, uv.xy, lod ) +#define OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) texture( tex, vec3( uv, arrayIdx ) ) +#define OGRE_SampleArray2DLevel( tex, sampler, uv, arrayIdx, lod ) textureLod( tex, vec3( uv, arrayIdx ), lod ) +#define OGRE_SampleGrad( tex, sampler, uv, ddx, ddy ) textureGrad( tex, uv, ddx, ddy ) +#define OGRE_SampleArray2DGrad( tex, sampler, uv, arrayIdx, ddx, ddy ) textureGrad( tex, vec3( uv, arrayIdx ), ddx, ddy ) +#define OGRE_ddx( val ) dFdx( val ) +#define OGRE_ddy( val ) dFdy( val ) + +#define bufferFetch1( buffer, idx ) texelFetch( buffer, idx ).x +@end + +@property( GLES < 320) +@piece( SetCompatibilityLayer ) + @property( !GL_ARB_texture_buffer_range ) + #define samplerBuffer sampler2D + #define isamplerBuffer isampler2D + #define usamplerBuffer usampler2D + vec4 bufferFetch( in sampler2D sampl, in int pixelIdx ) + { + ivec2 pos = ivec2( mod( float(pixelIdx), 2048. ), int( uint(pixelIdx) >> 11u ) ); + return texelFetch( sampl, pos, 0 ); + } + ivec4 bufferFetch(in isampler2D sampl, in int pixelIdx) + { + ivec2 pos = ivec2( mod( float(pixelIdx), 2048. ), int( uint(pixelIdx) >> 11u ) ); + return texelFetch( sampl, pos, 0 ); + } + uvec4 bufferFetch( in usampler2D sampl, in int pixelIdx ) + { + ivec2 pos = ivec2( mod( float(pixelIdx), 2048. ), int( uint(pixelIdx) >> 11u ) ); + return texelFetch( sampl, pos, 0 ); + } + @end + @property( !GL_ARB_shading_language_420pack ) + #define layout_constbuffer(x) layout( std140 ) + @end +@end +@end diff --git a/ogre2/src/media/Hlms/Common/GLSLES/Matrix_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSLES/Matrix_piece_all.glsl new file mode 100644 index 000000000..9eda568ab --- /dev/null +++ b/ogre2/src/media/Hlms/Common/GLSLES/Matrix_piece_all.glsl @@ -0,0 +1,53 @@ +@property( GL_ARB_texture_buffer_range ) +@piece( Common_Matrix_DeclUnpackMatrix4x4 ) +mat4 UNPACK_MAT4( samplerBuffer matrixBuf, uint pixelIdx ) +{ + vec4 row0 = texelFetch( matrixBuf, int((pixelIdx) << 2u) ); + vec4 row1 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 1u) ); + vec4 row2 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 2u) ); + vec4 row3 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 3u) ); + return mat4( row0, row1, row2, row3 ); +} +@end + +@piece( Common_Matrix_DeclUnpackMatrix3x4 ) +mat3x4 UNPACK_MAT3x4( samplerBuffer matrixBuf, uint pixelIdx ) +{ + vec4 row0 = texelFetch( matrixBuf, int((pixelIdx) << 2u) ); + vec4 row1 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 1u) ); + vec4 row2 = texelFetch( matrixBuf, int(((pixelIdx) << 2u) + 2u) ); + return mat3x4( row0, row1, row2 ); +} +@end +@end + +@property( !GL_ARB_texture_buffer_range ) +@piece( Common_Matrix_DeclUnpackMatrix4x4 ) +mat4 UNPACK_MAT4( in sampler2D matrixBuf, in uint pixelIdx ) +{ + ivec2 pos0 = ivec2(int(((pixelIdx) << 2u) & 2047u), int(((pixelIdx) << 2u) >> 11u)); + ivec2 pos1 = ivec2(int((((pixelIdx) << 2u) + 1u) & 2047u), int((((pixelIdx) << 2u) + 1u) >> 11u)); + ivec2 pos2 = ivec2(int((((pixelIdx) << 2u) + 2u) & 2047u), int((((pixelIdx) << 2u) + 2u) >> 11u)); + ivec2 pos3 = ivec2(int((((pixelIdx) << 2u) + 3u) & 2047u), int((((pixelIdx) << 2u) + 3u) >> 11u)); + vec4 row0 = texelFetch( matrixBuf, pos0, 0 ); + vec4 row1 = texelFetch( matrixBuf, pos1, 0 ); + vec4 row2 = texelFetch( matrixBuf, pos2, 0 ); + vec4 row3 = texelFetch( matrixBuf, pos3, 0 ); + return mat4( row0, row1, row2, row3 ); +} +@end + +@piece( Common_Matrix_DeclUnpackMatrix3x4 ) +mat3x4 UNPACK_MAT3x4( in sampler2D matrixBuf, in uint pixelIdx ) +{ + ivec2 pos0 = ivec2(int(((pixelIdx) << 2u) & 2047u), int(((pixelIdx) << 2u) >> 11u)); + ivec2 pos1 = ivec2(int((((pixelIdx) << 2u) + 1u) & 2047u), int((((pixelIdx) << 2u) + 1u) >> 11u)); + ivec2 pos2 = ivec2(int((((pixelIdx) << 2u) + 2u) & 2047u), int((((pixelIdx) << 2u) + 2u) >> 11u)); + vec4 row0 = texelFetch( matrixBuf, pos0, 0 ); + vec4 row1 = texelFetch( matrixBuf, pos1, 0 ); + vec4 row2 = texelFetch( matrixBuf, pos2, 0 ); + return mat3x4( row0, row1, row2 ); +} +@end +@end + diff --git a/ogre2/src/media/Hlms/Common/GLSLES/QuaternionCode_piece_all.glsl b/ogre2/src/media/Hlms/Common/GLSLES/QuaternionCode_piece_all.glsl new file mode 100644 index 000000000..b72defabf --- /dev/null +++ b/ogre2/src/media/Hlms/Common/GLSLES/QuaternionCode_piece_all.glsl @@ -0,0 +1,55 @@ +@piece( DeclQuat_xAxis ) +vec3 xAxis( vec4 qQuat ) +{ + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwy = fTy * qQuat.w; + float fTwz = fTz * qQuat.w; + float fTxy = fTy * qQuat.x; + float fTxz = fTz * qQuat.x; + float fTyy = fTy * qQuat.y; + float fTzz = fTz * qQuat.z; + + return vec3( 1.0-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy ); +} +@end + +@piece( DeclQuat_yAxis ) +vec3 yAxis( vec4 qQuat ) +{ + float fTx = 2.0 * qQuat.x; + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwx = fTx * qQuat.w; + float fTwz = fTz * qQuat.w; + float fTxx = fTx * qQuat.x; + float fTxy = fTy * qQuat.x; + float fTyz = fTz * qQuat.y; + float fTzz = fTz * qQuat.z; + + return vec3( fTxy-fTwz, 1.0-(fTxx+fTzz), fTyz+fTwx ); +} +@end + +@piece( DeclQuat_zAxis ) +vec3 zAxis( vec4 qQuat ) +{ + float fTx = 2.0 * qQuat.x; + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwx = fTx * qQuat.w; + float fTwy = fTy * qQuat.w; + float fTxx = fTx * qQuat.x; + float fTxz = fTz * qQuat.x; + float fTyy = fTy * qQuat.y; + float fTyz = fTz * qQuat.y; + + return vec3( fTxz+fTwy, fTyz-fTwx, 1.0-(fTxx+fTyy) ); +} +@end + +@piece( DeclQuat_AllAxis ) +@insertpiece( DeclQuat_xAxis ) +@insertpiece( DeclQuat_yAxis ) +@insertpiece( DeclQuat_zAxis ) +@end diff --git a/ogre2/src/media/Hlms/Common/GLSLES/RenderDepthOnly_piece_ps.glsl b/ogre2/src/media/Hlms/Common/GLSLES/RenderDepthOnly_piece_ps.glsl new file mode 100644 index 000000000..7ba220fcd --- /dev/null +++ b/ogre2/src/media/Hlms/Common/GLSLES/RenderDepthOnly_piece_ps.glsl @@ -0,0 +1,3 @@ +@property( 0 && hlms_render_depth_only && !alpha_test && !hlms_shadows_esm && !macOS) + @set( hlms_disable_stage, 1 ) +@end diff --git a/ogre2/src/media/Hlms/Common/HLSL/CrossPlatformSettings_piece_all.hlsl b/ogre2/src/media/Hlms/Common/HLSL/CrossPlatformSettings_piece_all.hlsl new file mode 100644 index 000000000..f5e17e02d --- /dev/null +++ b/ogre2/src/media/Hlms/Common/HLSL/CrossPlatformSettings_piece_all.hlsl @@ -0,0 +1,98 @@ +@piece( SetCrossPlatformSettings ) +#define ushort uint +#define ushort3 uint3 +#define ushort4 uint4 +#define ogre_float4x3 float4x3 + +//Short used for read operations. It's an int in GLSL & HLSL. An ushort in Metal +#define rshort int +#define rshort2 int2 +#define rint int +//Short used for write operations. It's an int in GLSL. An ushort in HLSL & Metal +#define wshort2 uint2 +#define wshort3 uint3 + +#define toFloat3x3( x ) ((float3x3)(x)) +#define buildFloat3x3( row0, row1, row2 ) transpose( float3x3( row0, row1, row2 ) ) + +#define min3( a, b, c ) min( a, min( b, c ) ) +#define max3( a, b, c ) max( a, max( b, c ) ) + +#define INLINE +#define NO_INTERPOLATION_PREFIX nointerpolation +#define NO_INTERPOLATION_SUFFIX + +#define finalDrawId input.drawId +#define PARAMS_ARG_DECL +#define PARAMS_ARG + +#define floatBitsToUint(x) asuint(x) +#define uintBitsToFloat(x) asfloat(x) +#define floatBitsToInt(x) asint(x) +#define fract frac +#define lessThan( a, b ) (a < b) + +#define inVs_vertexId input.vertexId +#define inVs_vertex input.vertex +#define inVs_blendWeights input.blendWeights +#define inVs_blendIndices input.blendIndices +#define inVs_qtangent input.qtangent +@property( !hlms_instanced_stereo ) + #define inVs_drawId input.drawId +@else + #define inVs_drawId (input.drawId >> 1u) + #define inVs_stereoDrawId input.drawId +@end + +@foreach( hlms_uv_count, n ) + #define inVs_uv@n input.uv@n@end + +#define outVs_Position outVs.gl_Position +#define outVs_viewportIndex outVs.gl_ViewportIndex +#define outVs_clipDistance0 outVs.gl_ClipDistance0.x + +#define gl_SampleMaskIn0 gl_SampleMask +#define interpolateAtSample( interp, subsample ) EvaluateAttributeAtSample( interp, subsample ) +#define findLSB firstbitlow +#define findMSB firstbithigh +#define mod( a, b ) (a - b * floor(a / b)) + +#define outPs_colour0 outPs.colour0 +#define OGRE_Sample( tex, sampler, uv ) tex.Sample( sampler, uv ) +#define OGRE_SampleLevel( tex, sampler, uv, lod ) tex.SampleLevel( sampler, uv, lod ) +#define OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) tex.Sample( sampler, float3( uv, arrayIdx ) ) +#define OGRE_SampleArray2DLevel( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float3( uv, arrayIdx ), lod ) +#define OGRE_SampleArrayCubeLevel( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float4( uv, arrayIdx ), lod ) +#define OGRE_SampleGrad( tex, sampler, uv, ddx, ddy ) tex.SampleGrad( sampler, uv, ddx, ddy ) +#define OGRE_SampleArray2DGrad( tex, sampler, uv, arrayIdx, ddx, ddy ) tex.SampleGrad( sampler, float3( uv, arrayIdx ), ddx, ddy ) +#define OGRE_ddx( val ) ddx( val ) +#define OGRE_ddy( val ) ddy( val ) +#define OGRE_Load2D( tex, iuv, lod ) tex.Load( int3( iuv, lod ) ) +#define OGRE_LoadArray2D( tex, iuv, arrayIdx, lod ) tex.Load( int4( iuv, arrayIdx, lod ) ) +#define OGRE_Load2DMS( tex, iuv, subsample ) tex.Load( iuv, subsample ) + +#define OGRE_Load3D( tex, iuv, lod ) tex.Load( int4( iuv, lod ) ) + +#define bufferFetch( buffer, idx ) buffer.Load( idx ) +#define bufferFetch1( buffer, idx ) buffer.Load( idx ).x + +#define structuredBufferFetch( buffer, idx ) buffer[idx] + +#define OGRE_Texture3D_float4 Texture3D + +#define OGRE_SAMPLER_ARG_DECL( samplerName ) , SamplerState samplerName +#define OGRE_SAMPLER_ARG( samplerName ) , samplerName + +#define CONST_BUFFER( bufferName, bindingPoint ) cbuffer bufferName : register(b##bindingPoint) +#define CONST_BUFFER_STRUCT_BEGIN( structName, bindingPoint ) cbuffer structName : register(b##bindingPoint) { struct _##structName +#define CONST_BUFFER_STRUCT_END( variableName ) variableName; } + +#define FLAT_INTERPOLANT( decl, bindingPoint ) nointerpolation decl : TEXCOORD##bindingPoint +#define INTERPOLANT( decl, bindingPoint ) decl : TEXCOORD##bindingPoint + +#define OGRE_OUT_REF( declType, variableName ) out declType variableName +#define OGRE_INOUT_REF( declType, variableName ) inout declType variableName + +#define OGRE_ARRAY_START( type ) { +#define OGRE_ARRAY_END } +@end diff --git a/ogre2/src/media/Hlms/Common/HLSL/Matrix_piece_all.hlsl b/ogre2/src/media/Hlms/Common/HLSL/Matrix_piece_all.hlsl new file mode 100644 index 000000000..ad78ddc8e --- /dev/null +++ b/ogre2/src/media/Hlms/Common/HLSL/Matrix_piece_all.hlsl @@ -0,0 +1,35 @@ +@piece( Common_Matrix_DeclUnpackMatrix4x4 ) +float4x4 UNPACK_MAT4( Buffer matrixBuf, uint pixelIdx ) +{ + float4 row1 = matrixBuf.Load( int((pixelIdx) << 2u) ); + float4 row2 = matrixBuf.Load( int(((pixelIdx) << 2u) + 1u) ); + float4 row3 = matrixBuf.Load( int(((pixelIdx) << 2u) + 2u) ); + float4 row4 = matrixBuf.Load( int(((pixelIdx) << 2u) + 3u) ); + + return transpose( float4x4( row1, row2, row3, row4 ) ); +} +@end + +@piece( Common_Matrix_DeclUnpackMatrix4x3 ) +float4x3 UNPACK_MAT4x3( Buffer matrixBuf, uint pixelIdx ) +{ + float4 row1 = matrixBuf.Load( int((pixelIdx) << 2u) ); + float4 row2 = matrixBuf.Load( int(((pixelIdx) << 2u) + 1u) ); + float4 row3 = matrixBuf.Load( int(((pixelIdx) << 2u) + 2u) ); + + return transpose( float3x4( row1, row2, row3 ) ); +} +@end + +@piece( Common_Matrix_DeclLoadOgreFloat4x3 ) +ogre_float4x3 loadOgreFloat4x3( Buffer matrixBuf, uint offsetIdx ) +{ + float4 row1 = matrixBuf.Load( int(offsetIdx) ); + float4 row2 = matrixBuf.Load( int(offsetIdx) + 1u ); + float4 row3 = matrixBuf.Load( int(offsetIdx) + 2u ); + + return transpose( float3x4( row1, row2, row3 ) ); +} + +#define makeOgreFloat4x3( row0, row1, row2 ) transpose( float3x4( row0, row1, row2 ) ) +@end diff --git a/ogre2/src/media/Hlms/Common/HLSL/QuaternionCode_piece_all.hlsl b/ogre2/src/media/Hlms/Common/HLSL/QuaternionCode_piece_all.hlsl new file mode 100644 index 000000000..30f01a3e8 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/HLSL/QuaternionCode_piece_all.hlsl @@ -0,0 +1,55 @@ +@piece( DeclQuat_xAxis ) +float3 xAxis( float4 qQuat ) +{ + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwy = fTy * qQuat.w; + float fTwz = fTz * qQuat.w; + float fTxy = fTy * qQuat.x; + float fTxz = fTz * qQuat.x; + float fTyy = fTy * qQuat.y; + float fTzz = fTz * qQuat.z; + + return float3( 1.0-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy ); +} +@end + +@piece( DeclQuat_yAxis ) +float3 yAxis( float4 qQuat ) +{ + float fTx = 2.0 * qQuat.x; + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwx = fTx * qQuat.w; + float fTwz = fTz * qQuat.w; + float fTxx = fTx * qQuat.x; + float fTxy = fTy * qQuat.x; + float fTyz = fTz * qQuat.y; + float fTzz = fTz * qQuat.z; + + return float3( fTxy-fTwz, 1.0-(fTxx+fTzz), fTyz+fTwx ); +} +@end + +@piece( DeclQuat_zAxis ) +float3 zAxis( float4 qQuat ) +{ + float fTx = 2.0 * qQuat.x; + float fTy = 2.0 * qQuat.y; + float fTz = 2.0 * qQuat.z; + float fTwx = fTx * qQuat.w; + float fTwy = fTy * qQuat.w; + float fTxx = fTx * qQuat.x; + float fTxz = fTz * qQuat.x; + float fTyy = fTy * qQuat.y; + float fTyz = fTz * qQuat.y; + + return float3( fTxz+fTwy, fTyz-fTwx, 1.0-(fTxx+fTyy) ); +} +@end + +@piece( DeclQuat_AllAxis ) +@insertpiece( DeclQuat_xAxis ) +@insertpiece( DeclQuat_yAxis ) +@insertpiece( DeclQuat_zAxis ) +@end diff --git a/ogre2/src/media/Hlms/Common/HLSL/RenderDepthOnly_piece_ps.hlsl b/ogre2/src/media/Hlms/Common/HLSL/RenderDepthOnly_piece_ps.hlsl new file mode 100644 index 000000000..41d6ab3f3 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/HLSL/RenderDepthOnly_piece_ps.hlsl @@ -0,0 +1,31 @@ + +@property( !hlms_render_depth_only || (hlms_shadowcaster && (exponential_shadow_maps || hlms_shadowcaster_point)) ) + @piece( output_type )PS_OUTPUT@end +@end @property( !(!hlms_render_depth_only || (hlms_shadowcaster && (exponential_shadow_maps || hlms_shadowcaster_point))) ) + @piece( output_type )void@end +@end + +@property( hlms_render_depth_only && !alpha_test && !hlms_shadows_esm ) + @set( hlms_disable_stage, 1 ) +@end + + +@piece( DeclOutputType ) + struct PS_OUTPUT + { + @property( hlms_render_depth_only || hlms_shadowcaster || !hlms_prepass ) + @property( !hlms_shadowcaster ) + float4 colour0 : SV_Target@counter(rtv_target); + @else + @property( !hlms_render_depth_only ) + float colour0 : SV_Target@counter(rtv_target); + @end + @property( hlms_render_depth_only ) + float colour0 : SV_Depth; + @end + @end + @end + + @insertpiece( ExtraOutputTypes ) + }; +@end diff --git a/ogre2/src/media/Hlms/Common/HLSL/UavCrossPlatform_piece_all.hlsl b/ogre2/src/media/Hlms/Common/HLSL/UavCrossPlatform_piece_all.hlsl new file mode 100644 index 000000000..efc42fef5 --- /dev/null +++ b/ogre2/src/media/Hlms/Common/HLSL/UavCrossPlatform_piece_all.hlsl @@ -0,0 +1,21 @@ + +@piece( DeclUavCrossPlatform ) + +#define OGRE_imageLoad2D( inImage, iuv ) inImage[uint2( iuv )] +#define OGRE_imageLoad2DArray( inImage, iuvw ) inImage[uint3( iuvw )] + +#define OGRE_imageWrite2D1( outImage, iuv, value ) outImage[uint2( iuv )] = value +#define OGRE_imageWrite2D2( outImage, iuv, value ) outImage[uint2( iuv )] = (value).xy +#define OGRE_imageWrite2D4( outImage, iuv, value ) outImage[uint2( iuv )] = value + +#define OGRE_imageLoad3D( inImage, iuv ) inImage[uint3( iuv )] + +#define OGRE_imageWrite3D1( outImage, iuv, value ) outImage[uint3( iuv )] = value.x +#define OGRE_imageWrite3D4( outImage, iuv, value ) outImage[uint3( iuv )] = value + +#define OGRE_imageWrite2DArray1( outImage, iuvw, value ) outImage[uint3( iuvw )] = value.x +#define OGRE_imageWrite2DArray4( outImage, iuvw, value ) outImage[uint3( iuvw )] = value + +#define __sharedOnlyBarrier GroupMemoryBarrierWithGroupSync() + +@end diff --git a/ogre2/src/media/Hlms/Common/Metal/CrossPlatformSettings_piece_all.metal b/ogre2/src/media/Hlms/Common/Metal/CrossPlatformSettings_piece_all.metal index b4786eebe..b20ae2372 100644 --- a/ogre2/src/media/Hlms/Common/Metal/CrossPlatformSettings_piece_all.metal +++ b/ogre2/src/media/Hlms/Common/Metal/CrossPlatformSettings_piece_all.metal @@ -9,13 +9,113 @@ struct float1 float1( float _x ) : x( _x ) {} }; +inline float3x3 toMat3x3( float4x4 m ) +{ + return float3x3( m[0].xyz, m[1].xyz, m[2].xyz ); +} +inline float3x3 toMat3x3( float3x4 m ) +{ + return float3x3( m[0].xyz, m[1].xyz, m[2].xyz ); +} + +#define ogre_float4x3 float3x4 + +//Short used for read operations. It's an int in GLSL & HLSL. An ushort in Metal +#define rshort ushort +#define rshort2 ushort2 +#define rint uint +//Short used for write operations. It's an int in GLSL. An ushort in HLSL & Metal +#define wshort2 ushort2 +#define wshort3 ushort3 + +#define toFloat3x3( x ) toMat3x3( x ) +#define buildFloat3x3( row0, row1, row2 ) float3x3( row0, row1, row2 ) + +#define min3( a, b, c ) min( a, min( b, c ) ) +#define max3( a, b, c ) max( a, max( b, c ) ) + #define mul( x, y ) ((x) * (y)) #define lerp mix #define INLINE inline +#define NO_INTERPOLATION_PREFIX +#define NO_INTERPOLATION_SUFFIX [[flat]] #define finalDrawId drawId +#define floatBitsToUint(x) as_type(x) +#define uintBitsToFloat(x) as_type(x) +#define floatBitsToInt(x) as_type(x) +#define lessThan( a, b ) (a < b) +#define discard discard_fragment() + +#define inVs_vertex input.position +#define inVs_blendWeights input.blendWeights +#define inVs_blendIndices input.blendIndices +#define inVs_qtangent input.qtangent +@property( iOS ) + @property( !hlms_instanced_stereo ) + #define inVs_drawId (baseInstance + instanceId) + @else + #define inVs_drawId ((baseInstance + instanceId) >> 1u) + #define inVs_stereoDrawId (baseInstance + instanceId) + @end +@else + @property( !hlms_instanced_stereo ) + #define inVs_drawId input.drawId + @else + #define inVs_drawId (input.drawId >> 1u) + #define inVs_stereoDrawId input.drawId + @end +@end +@foreach( hlms_uv_count, n ) + #define inVs_uv@n input.uv@n@end + #define outVs_Position outVs.gl_Position -#define OGRE_SampleLevel( tex, sampler, uv, lod ) tex.sample( sampler, float2( uv ), level( lod ) ) +#define outVs_viewportIndex outVs.gl_ViewportIndex +#define outVs_clipDistance0 outVs.gl_ClipDistance[0] + +#define gl_SampleMaskIn0 gl_SampleMask +//#define interpolateAtSample( interp, subsample ) interpolateAtSample( interp, subsample ) +#define findLSB clz +#define findMSB ctz +#define reversebits reverse_bits +#define mod( a, b ) (a - b * floor(a / b)) + +#define outPs_colour0 outPs.colour0 +#define OGRE_Sample( tex, sampler, uv ) tex.sample( sampler, uv ) +#define OGRE_SampleLevel( tex, sampler, uv, lod ) tex.sample( sampler, uv, level( lod ) ) +#define OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) tex.sample( sampler, float2( uv ), arrayIdx ) #define OGRE_SampleArray2DLevel( tex, sampler, uv, arrayIdx, lod ) tex.sample( sampler, float2( uv ), ushort( arrayIdx ), level( lod ) ) +#define OGRE_SampleArrayCubeLevel( tex, sampler, uv, arrayIdx, lod ) tex.sample( sampler, float3( uv ), ushort( arrayIdx ), level( lod ) ) +#define OGRE_SampleGrad( tex, sampler, uv, ddx, ddy ) tex.sample( sampler, uv, gradient2d( ddx, ddy ) ) +#define OGRE_SampleArray2DGrad( tex, sampler, uv, arrayIdx, ddx, ddy ) tex.sample( sampler, uv, ushort( arrayIdx ), gradient2d( ddx, ddy ) ) +#define OGRE_ddx( val ) dfdx( val ) +#define OGRE_ddy( val ) dfdy( val ) +#define OGRE_Load2D( tex, iuv, lod ) tex.read( iuv, lod ) +#define OGRE_LoadArray2D( tex, iuv, arrayIdx, lod ) tex.read( iuv, arrayIdx, lod ) +#define OGRE_Load2DMS( tex, iuv, subsample ) tex.read( iuv, subsample ) + +#define OGRE_Load3D( tex, iuv, lod ) tex.read( ushort3( iuv ), lod ) + +#define bufferFetch( buffer, idx ) buffer[idx] +#define bufferFetch1( buffer, idx ) buffer[idx] + +#define structuredBufferFetch( buffer, idx ) buffer[idx] + +#define OGRE_Texture3D_float4 texture3d + +#define OGRE_SAMPLER_ARG_DECL( samplerName ) , sampler samplerName +#define OGRE_SAMPLER_ARG( samplerName ) , samplerName + +#define CONST_BUFFER_STRUCT_BEGIN( structName, bindingPoint ) struct structName +#define CONST_BUFFER_STRUCT_END( variableName ) + +#define FLAT_INTERPOLANT( decl, bindingPoint ) decl [[flat]] +#define INTERPOLANT( decl, bindingPoint ) decl + +#define OGRE_OUT_REF( declType, variableName ) thread declType &variableName +#define OGRE_INOUT_REF( declType, variableName ) thread declType &variableName + +#define OGRE_ARRAY_START( type ) { +#define OGRE_ARRAY_END } @end diff --git a/ogre2/src/media/Hlms/Common/Metal/Matrix_piece_all.metal b/ogre2/src/media/Hlms/Common/Metal/Matrix_piece_all.metal index 30463e0ac..bed25febb 100644 --- a/ogre2/src/media/Hlms/Common/Metal/Matrix_piece_all.metal +++ b/ogre2/src/media/Hlms/Common/Metal/Matrix_piece_all.metal @@ -9,8 +9,8 @@ inline float4x4 UNPACK_MAT4( device const float4 *matrixBuf, uint pixelIdx ) } @end -@piece( Common_Matrix_DeclUnpackMatrix3x4 ) -inline float3x4 UNPACK_MAT3x4( device const float4 *matrixBuf, uint pixelIdx ) +@piece( Common_Matrix_DeclUnpackMatrix4x3 ) +inline float3x4 UNPACK_MAT4x3( device const float4 *matrixBuf, uint pixelIdx ) { float4 row0 = matrixBuf[(pixelIdx << 2u)]; float4 row1 = matrixBuf[(pixelIdx << 2u) + 1u]; @@ -19,9 +19,14 @@ inline float3x4 UNPACK_MAT3x4( device const float4 *matrixBuf, uint pixelIdx ) } @end -@piece( Common_Matrix_Conversions ) -inline float3x3 toMat3x3( float4x4 m ) +@piece( Common_Matrix_DeclLoadOgreFloat4x3 ) +ogre_float4x3 loadOgreFloat4x3( device const float4 *matrixBuf, uint offsetIdx ) { - return float3x3( m[0].xyz, m[1].xyz, m[2].xyz ); + float4 row0 = matrixBuf[offsetIdx]; + float4 row1 = matrixBuf[offsetIdx + 1u]; + float4 row2 = matrixBuf[offsetIdx + 2u]; + return float3x4( row0, row1, row2 ); } + +#define makeOgreFloat4x3( row0, row1, row2 ) float3x4( row0, row1, row2 ) @end diff --git a/ogre2/src/media/Hlms/Common/Metal/RenderDepthOnly_piece_ps.metal b/ogre2/src/media/Hlms/Common/Metal/RenderDepthOnly_piece_ps.metal index 9ba8cf13f..0f184e33d 100644 --- a/ogre2/src/media/Hlms/Common/Metal/RenderDepthOnly_piece_ps.metal +++ b/ogre2/src/media/Hlms/Common/Metal/RenderDepthOnly_piece_ps.metal @@ -14,7 +14,7 @@ { @property( !hlms_shadowcaster ) float4 colour0 [[ color(0) ]]; - @end @property( hlms_shadowcaster ) + @else @property( !hlms_render_depth_only ) float colour0 [[ color(0) ]]; @end diff --git a/ogre2/src/media/Hlms/Common/Metal/UavCrossPlatform_piece_all.metal b/ogre2/src/media/Hlms/Common/Metal/UavCrossPlatform_piece_all.metal new file mode 100644 index 000000000..f1186305e --- /dev/null +++ b/ogre2/src/media/Hlms/Common/Metal/UavCrossPlatform_piece_all.metal @@ -0,0 +1,21 @@ + +@piece( DeclUavCrossPlatform ) + +#define OGRE_imageLoad2D( inImage, iuv ) inImage.read( ushort2( iuv ) ) +#define OGRE_imageLoad2DArray( inImage, iuvw ) inImage.read( ushort2( iuvw.xy ), ushort( iuvw.z ) ) + +#define OGRE_imageWrite2D1( outImage, iuv, value ) outImage.write( float4( value, 0, 0, 0 ), iuv ) +#define OGRE_imageWrite2D2( outImage, iuv, value ) outImage.write( (value).xyxy, iuv ) +#define OGRE_imageWrite2D4( outImage, iuv, value ) outImage.write( value, iuv ) + +#define OGRE_imageLoad3D( inImage, iuv ) inImage.read( ushort3( iuv ) ) + +#define OGRE_imageWrite3D1( outImage, iuv, value ) outImage.write( value.x, iuv ) +#define OGRE_imageWrite3D4( outImage, iuv, value ) outImage.write( value, iuv ) + +#define OGRE_imageWrite2DArray1( outImage, iuvw, value ) outImage.write( value.x, ushort2( iuvw.xy ), ushort( iuvw.z ) ) +#define OGRE_imageWrite2DArray4( outImage, iuvw, value ) outImage.write( value, ushort2( iuvw.xy ), ushort( iuvw.z ) ) + +#define __sharedOnlyBarrier threadgroup_barrier( mem_flags::mem_threadgroup ) + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/200.TextureRegisters_piece_vs.any b/ogre2/src/media/Hlms/Pbs/Any/200.TextureRegisters_piece_vs.any new file mode 100644 index 000000000..1ad8ba19a --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/200.TextureRegisters_piece_vs.any @@ -0,0 +1,30 @@ + +//Set the sampler starts. Note that 'padd' get calculated before _any_ 'add' +//This piece file is parsed during the vertex shader stage because +//several other pieces may evaluate the variables too early +//We need to set this vars as soon as possible + +@add( diffuse_map_sampler, samplerStateStart ) +@add( normal_map_tex_sampler, samplerStateStart ) +@add( specular_map_sampler, samplerStateStart ) +@add( roughness_map_sampler, samplerStateStart ) +@add( envprobe_map_sampler, samplerStateStart ) +@add( detail_weight_map_sampler,samplerStateStart ) +@add( detail_map0_sampler, samplerStateStart ) +@add( detail_map_nm0_sampler, samplerStateStart ) +@add( detail_map1_sampler, samplerStateStart ) +@add( detail_map_nm1_sampler, samplerStateStart ) +@add( detail_map2_sampler, samplerStateStart ) +@add( detail_map_nm2_sampler, samplerStateStart ) +@add( detail_map3_sampler, samplerStateStart ) +@add( detail_map_nm3_sampler, samplerStateStart ) +@add( emissive_map_sampler, samplerStateStart ) + +@set( envMapRegSampler, envprobe_map_sampler ) + +@property( use_envprobe_map ) + @property( !envprobe_map || envprobe_map == target_envprobe_map ) + /// Auto cubemap textures are set at the beginning. Manual cubemaps are the end. + @set( envMapRegSampler, texEnvProbeMap ) + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/AmbientLighting_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/AmbientLighting_piece_ps.any new file mode 100644 index 000000000..5bb8186c8 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/AmbientLighting_piece_ps.any @@ -0,0 +1,90 @@ + +@property( ambient_sh ) + @property( !ambient_sh_monochrome ) + @piece( DeclIrradianceSH ) + float3 irradianceSH( float3 n PASSBUF_ARG_DECL ) + { + // We can use only the first 2 bands for better performance + /*return + passBuf.sh0.xyz + + passBuf.sh1.xyz * (n.y) + + passBuf.sh2.xyz * (n.z) + + passBuf.sh3.xyz * (n.x) + + passBuf.sh4.xyz * (n.y * n.x) + + passBuf.sh5.xyz * (n.y * n.z) + + passBuf.sh6.xyz * (3.0 * n.z * n.z - 1.0) + + passBuf.sh7.xyz * (n.z * n.x) + + passBuf.sh8.xyz * (n.x * n.x - n.y * n.y);*/ + return + passBuf.sh0.xyz + + float3( passBuf.sh0.w, passBuf.sh1.x, passBuf.sh1.y ) * (n.y) + + float3( passBuf.sh1.z, passBuf.sh1.w, passBuf.sh2.x ) * (n.z) + + float3( passBuf.sh2.y, passBuf.sh2.z, passBuf.sh2.w ) * (n.x) + + float3( passBuf.sh3.x, passBuf.sh3.y, passBuf.sh3.z ) * (n.y * n.x) + + float3( passBuf.sh3.w, passBuf.sh4.x, passBuf.sh4.y ) * (n.y * n.z) + + float3( passBuf.sh4.z, passBuf.sh4.w, passBuf.sh5.x ) * (3.0 * n.z * n.z - 1.0) + + float3( passBuf.sh5.y, passBuf.sh5.z, passBuf.sh5.w ) * (n.z * n.x) + + float3( passBuf.sh6.x, passBuf.sh6.y, passBuf.sh6.z ) * (n.x * n.x - n.y * n.y); + } + @end + @else + @piece( DeclIrradianceSH ) + float irradianceSH( float3 n PASSBUF_ARG_DECL ) + { + // We can use only the first 2 bands for better performance + return + passBuf.sh0.x + + passBuf.sh0.y * (n.y) + + passBuf.sh0.z * (n.z) + + passBuf.sh0.w * (n.x) + + passBuf.sh1.x * (n.y * n.x) + + passBuf.sh1.y * (n.y * n.z) + + passBuf.sh1.z * (3.0 * n.z * n.z - 1.0) + + passBuf.sh1.w * (n.z * n.x) + + passBuf.sh2.x * (n.x * n.x - n.y * n.y); + } + @end + @end +@end + +@property( ambient_hemisphere || vct_ambient_hemisphere ) + @piece( DoAmbientHeader ) + float ambientWD = dot( passBuf.ambientHemisphereDir.xyz, pixelData.normal ) * 0.5 + 0.5; + float ambientWS = dot( passBuf.ambientHemisphereDir.xyz, pixelData.reflDir ) * 0.5 + 0.5; + @end +@end + +@piece( DoAmbientLighting ) + @property( ambient_sh ) + @property( vct_num_probes ) + //Only use ambient lighting if object is outside any VCT probe + if( vctSpecular.w == 0 ) + { + @end + float3 wsNormal = mul( passBuf.invViewMatCubemap, pixelData.normal ); + wsNormal.x = -wsNormal.x; + pixelData.envColourD += irradianceSH( wsNormal PASSBUF_ARG ); + @property( vct_num_probes ) + } + @end + @end + + @property( ambient_hemisphere ) + @property( vct_num_probes ) + //Only use ambient lighting if object is outside any VCT probe + if( vctSpecular.w == 0 ) + { + @end + pixelData.envColourS += lerp( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); + pixelData.envColourD += lerp( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); + @property( vct_num_probes ) + } + @end + @end + + @property( ambient_fixed && vct_num_probes ) + //Only use ambient lighting if object is outside any VCT probe + finalColour += vctSpecular.w == 0 ? float3( 0, 0, 0 ) : + (passBuf.ambientUpperHemi.xyz * pixelData.diffuse.xyz); + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/AreaLights_LTC_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/AreaLights_LTC_piece_ps.any new file mode 100644 index 000000000..7367df1ec --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/AreaLights_LTC_piece_ps.any @@ -0,0 +1,333 @@ +/* Contains heavy code borrowed from https://github.com/selfshadow/ltc_code/ + +Original license: + +Copyright (c) 2017, Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* If you use (or adapt) the source code in your own work, please include a + reference to the paper: + + Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. + Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. + ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. + Project page: https://eheitzresearch.wordpress.com/415-2/ + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Adapted to Ogre by Matias N. Goldberg +*/ + +@property( hlms_lights_area_ltc ) +@piece( DeclAreaLtcLightFuncs ) +#define LUT_SIZE 64.0 +#define LUT_SCALE ((LUT_SIZE - 1.0)/LUT_SIZE) +#define LUT_BIAS (0.5/LUT_SIZE) + +INLINE float3 IntegrateEdgeVec( float3 v1, float3 v2 ) +{ + float x = dot(v1, v2); + float y = abs(x); + + float a = 0.8543985 + (0.4965155 + 0.0145206*y)*y; + float b = 3.4175940 + (4.1616724 + y)*y; + float v = a / b; + + float theta_sintheta = (x > 0.0) ? v : 0.5*rsqrt(max(1.0 - x*x, 1e-7)) - v; + + return cross( v1, v2 ) * theta_sintheta; +} + +INLINE float IntegrateEdge( float3 v1, float3 v2 ) +{ + return IntegrateEdgeVec( v1, v2 ).z; +} + +@property( syntax == metal ) +INLINE void ClipQuadToHorizon( thread float3 L[5], thread int &n ) +@end +@property( syntax != metal ) +INLINE void ClipQuadToHorizon( inout float3 L[5], out int n ) +@end +{ + // detect clipping config + int config = 0; + if (L[0].z > 0.0) config += 1; + if (L[1].z > 0.0) config += 2; + if (L[2].z > 0.0) config += 4; + if (L[3].z > 0.0) config += 8; + + // clip + n = 0; + + if (config == 0) + { + // clip all + } + else if (config == 1) // V1 clip V2 V3 V4 + { + n = 3; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 2) // V2 clip V1 V3 V4 + { + n = 3; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 3) // V1 V2 clip V3 V4 + { + n = 4; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + L[3] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 4) // V3 clip V1 V2 V4 + { + n = 3; + L[0] = -L[3].z * L[2] + L[2].z * L[3]; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + } + else if (config == 5) // V1 V3 clip V2 V4) impossible + { + n = 0; + } + else if (config == 6) // V2 V3 clip V1 V4 + { + n = 4; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 7) // V1 V2 V3 clip V4 + { + n = 5; + L[4] = -L[3].z * L[0] + L[0].z * L[3]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 8) // V4 clip V1 V2 V3 + { + n = 3; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + L[1] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = L[3]; + } + else if (config == 9) // V1 V4 clip V2 V3 + { + n = 4; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[2].z * L[3] + L[3].z * L[2]; + } + else if (config == 10) // V2 V4 clip V1 V3) impossible + { + n = 0; + } + else if (config == 11) // V1 V2 V4 clip V3 + { + n = 5; + L[4] = L[3]; + L[3] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 12) // V3 V4 clip V1 V2 + { + n = 4; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + } + else if (config == 13) // V1 V3 V4 clip V2 + { + n = 5; + L[4] = L[3]; + L[3] = L[2]; + L[2] = -L[1].z * L[2] + L[2].z * L[1]; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + } + else if (config == 14) // V2 V3 V4 clip V1 + { + n = 5; + L[4] = -L[0].z * L[3] + L[3].z * L[0]; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + } + else if (config == 15) // V1 V2 V3 V4 + { + n = 4; + } + + if (n == 3) + L[3] = L[0]; + if (n == 4) + L[4] = L[0]; +} + +INLINE float LTC_Evaluate( float3 N, float3 V, float3 P, float3x3 Minv, + @property( syntax == metal )constant@end float4 points[4], + bool twoSided ) +{ + // construct orthonormal basis around N + float3 T1, T2; + T1 = normalize( V - N*dot(V, N) ); + T2 = cross(N, T1); + + // rotate area light in (T1, T2, N) basis + Minv = mul( Minv, transpose( buildFloat3x3( T1, T2, N ) ) ); + + // polygon (allocate 5 vertices for clipping) + float3 L[5]; + L[0] = mul( Minv, points[0].xyz - P ); + L[1] = mul( Minv, points[1].xyz - P ); + L[2] = mul( Minv, points[2].xyz - P ); + L[3] = mul( Minv, points[3].xyz - P ); + //Initialize L[4]. Some HLSL compiler versions complains this is uninitialized even though + //it shouldn't complain. + //See https://forums.ogre3d.org/viewtopic.php?f=25&t=94804#p544184 + L[4] = float3( 0, 1, 0 ); + + // integrate + float sum = 0.0; + + @property( hlms_lights_ltc_clipless ) + float3 dir = points[0].xyz - P; + float3 lightNormal = cross( points[1].xyz - points[0].xyz, points[3].xyz - points[0].xyz ); + bool behind = (dot(dir, lightNormal) < 0.0); + + L[0] = normalize(L[0]); + L[1] = normalize(L[1]); + L[2] = normalize(L[2]); + L[3] = normalize(L[3]); + + float3 vsum = float3(0.0); + + vsum += IntegrateEdgeVec(L[0], L[1]); + vsum += IntegrateEdgeVec(L[1], L[2]); + vsum += IntegrateEdgeVec(L[2], L[3]); + vsum += IntegrateEdgeVec(L[3], L[0]); + + float len = length(vsum); + float z = vsum.z/len; + + if (behind) + z = -z; + + float2 uv = float2(z*0.5 + 0.5, len); + uv = uv * LUT_SCALE + LUT_BIAS; + + float scale = OGRE_SampleArray2DLevel( ltcMatrix, ltcSampler, uv, 1, 0 ).w; + + sum = len*scale; + + if( behind && !twoSided ) + sum = 0.0; + @end + @property( !hlms_lights_ltc_clipless ) + int n; + ClipQuadToHorizon( L, n ); + + if( n == 0 ) + return 0; + // project onto sphere + L[0] = normalize( L[0] ); + L[1] = normalize( L[1] ); + L[2] = normalize( L[2] ); + L[3] = normalize( L[3] ); + L[4] = normalize( L[4] ); + + // integrate + sum += IntegrateEdge( L[0], L[1] ); + sum += IntegrateEdge( L[1], L[2] ); + sum += IntegrateEdge( L[2], L[3] ); + if( n >= 4 ) + sum += IntegrateEdge( L[3], L[4] ); + if( n == 5 ) + sum += IntegrateEdge( L[4], L[0] ); + + sum = twoSided ? abs(sum) : max(0.0, sum); + @end + + return sum; +} +@end +@end + + +@property( hlms_lights_area_ltc ) +@piece( DoAreaLtcLights ) +for( int i=0; i 0.0@end + @end + + if( fDistance <= light2Buf.areaLtcLights[i].diffuse.w + @insertpiece( obbRestraintTestLtc ) + @insertpiece( andObjAreaLtcLightMaskCmp ) ) + { + float2 ltcUV = float2( pixelData.roughness, sqrt(1.0 - pixelData.NdotV) ); + ltcUV = ltcUV * LUT_SCALE + LUT_BIAS; + + float4 ltc0 = OGRE_SampleArray2DLevel( ltcMatrix, ltcSampler, ltcUV, 0, 0 ); + float4 ltc1 = OGRE_SampleArray2DLevel( ltcMatrix, ltcSampler, ltcUV, 1, 0 ); + + float3x3 Minv = buildFloat3x3( + float3(ltc0.x, 0, ltc0.y), + float3( 0, 1, 0), + float3(ltc0.z, 0, ltc0.w) + ); + + bool doubleSidedLtc = light2Buf.areaLtcLights[i].specular.w != 0.0f; + + @property( !fresnel_scalar ) + float ltcSpecular = LTC_Evaluate( pixelData.normal.xyz, pixelData.viewDir.xyz, inPs.pos.xyz, Minv, + light2Buf.areaLtcLights[i].points, doubleSidedLtc ); + // BRDF shadowing and Fresnel + ltcSpecular *= pixelData.F0 * ltc1.x + (1.0 - pixelData.F0) * ltc1.y; + @else + float3 ltcSpecular; + ltcSpecular.x = LTC_Evaluate( pixelData.normal.xyz, pixelData.viewDir.xyz, inPs.pos.xyz, Minv, + light2Buf.areaLtcLights[i].points, doubleSidedLtc ); + ltcSpecular.yz = ltcSpecular.xx; + // BRDF shadowing and Fresnel + ltcSpecular.xyz *= pixelData.F0.xyz * ltc1.x + (1.0 - pixelData.F0.xyz) * ltc1.y; + @end + + float ltcDiffuse = LTC_Evaluate( pixelData.normal.xyz, pixelData.viewDir.xyz, inPs.pos.xyz, + buildFloat3x3( float3( 1, 0, 0 ), float3( 0, 1, 0 ), float3( 0, 0, 1 ) ), + light2Buf.areaLtcLights[i].points, doubleSidedLtc ); + + @property( obb_restraint_ltc ) + ltcDiffuse *= obbRestraintFade; + ltcSpecular *= obbRestraintFade; + @end + + finalColour += light2Buf.areaLtcLights[i].diffuse.xyz * ltcDiffuse * pixelData.diffuse.xyz; + finalColour += light2Buf.areaLtcLights[i].specular.xyz * ltcSpecular * pixelData.specular.xyz; + } +} +@end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/AreaLights_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/AreaLights_piece_ps.any index f5bd34a50..91ddc8be7 100644 --- a/ogre2/src/media/Hlms/Pbs/Any/AreaLights_piece_ps.any +++ b/ogre2/src/media/Hlms/Pbs/Any/AreaLights_piece_ps.any @@ -4,16 +4,20 @@ @property( hlms_lights_area_tex_mask ) @piece( DeclAreaApproxTextures ) - @property( syntax == glsl ) + @property( syntax == glsl || syntax == glsles ) uniform sampler2DArray areaLightMasks; @end @property( syntax == hlsl ) - Texture2DArray areaLightMasks : register(t@value(areaLightsApproxTexUnit)); - SamplerState areaLightMasksSampler : register(s@value(areaLightsApproxTexUnit)); + @property( !hlms_lights_area_tex_colour ) + Texture2DArray areaLightMasks : register(t@value(areaLightMasks)); + @else + Texture2DArray areaLightMasks : register(t@value(areaLightMasks)); + @end + SamplerState areaLightMasksSampler : register(s@value(areaLightMasks)); @end @property( syntax == metal ) - , texture2d_array areaLightMasks [[texture(@value(areaLightsApproxTexUnit))]] - , sampler areaLightMasksSampler [[sampler(@value(areaLightsApproxTexUnit))]] + , texture2d_array areaLightMasks [[texture(@value(areaLightMasks))]] + , sampler areaLightMasksSampler [[sampler(@value(areaLightMasks))]] @end @end @end @@ -21,169 +25,182 @@ @piece( DoAreaApproxLights ) @property( !hlms_lights_area_tex_colour ) #define AREA_LIGHTS_TEX_SWIZZLE x - @end @property( hlms_lights_area_tex_colour ) + @else #define AREA_LIGHTS_TEX_SWIZZLE xyz @end float3 projectedPosInPlane; -@foreach( hlms_lights_area_approx, n ) - lightDir = passBuf.areaApproxLights[@n].position.xyz - inPs.pos; - projectedPosInPlane.xyz = inPs.pos - dot( -lightDir.xyz, passBuf.areaApproxLights[@n].direction.xyz ) * - passBuf.areaApproxLights[@n].direction.xyz; - fDistance = length( lightDir ); - if( fDistance <= passBuf.areaApproxLights[@n].attenuation.x - /*&& dot( -lightDir, passBuf.areaApproxLights[@n].direction.xyz ) > 0*/ @insertpiece( andObjAreaApproxLightMaskCmp ) ) + for( int i=0; i= hlms_lights_area_tex_mask || !hlms_lights_area_tex_colour ) - float diffuseMask = 1.0f; - @end - @property( @n < hlms_lights_area_tex_mask ) - @property( hlms_lights_area_tex_colour ) - float3 diffuseMask; + lightDir = light1Buf.areaApproxLights[i].position.xyz - inPs.pos; + projectedPosInPlane.xyz = inPs.pos - dot( -lightDir.xyz, light1Buf.areaApproxLights[i].direction.xyz ) * + light1Buf.areaApproxLights[i].direction.xyz; + fDistance = length( lightDir ); + + @property( obb_restraint_approx ) + float obbRestraintFade = getObbRestraintFade( light1Buf.areaApproxLights[i].obbRestraint, inPs.pos, + light1Buf.areaApproxLights[i].obbFadeFactorApprox.xyz ); + @piece( obbRestraintTestApprox )&& obbRestraintFade > 0.0@end @end - // 1 / (1 - 0.02) = 1.020408163 - float diffuseMipsLeft = passBuf.areaLightNumMipmapsSpecFactor * 0.5 - - passBuf.areaLightDiffuseMipmapStart * 1.020408163f; - diffuseMask = OGRE_SampleArray2DLevel( areaLightMasks, areaLightMasksSampler, - lightUVForTex + 0.5f, - passBuf.areaApproxLights[@n].attenuation.w, - passBuf.areaLightDiffuseMipmapStart + - (ROUGHNESS - 0.02f) * diffuseMipsLeft ).AREA_LIGHTS_TEX_SWIZZLE; - @end - - float3 closestPoint = passBuf.areaApproxLights[@n].position.xyz + - passBuf.areaApproxLights[@n].tangent.xyz * lightUV.x / invHalfRectSize.x + - areaLightBitangent.xyz * lightUV.y / invHalfRectSize.y; - - float3 lightDir2 = lightDir / fDistance; - lightDir = closestPoint.xyz - inPs.pos; - fDistance= length( lightDir ); - - float3 toShapeLight = reflect( -viewDir, nNormal ); - float denom = dot( toShapeLight, -passBuf.areaApproxLights[@n].direction.xyz ); - @property( @n >= hlms_lights_area_tex_mask || !hlms_lights_area_tex_colour ) - float specCol = 0; - @end @property( @n < hlms_lights_area_tex_mask && hlms_lights_area_tex_colour ) - float3 specCol = float3( 0, 0, 0 ); - @end - if( denom > 1e-6f || passBuf.areaApproxLights[@n].doubleSided.x != 0.0f ) + if( fDistance <= light1Buf.areaApproxLights[i].attenuation.x + @insertpiece( obbRestraintTestApprox ) + /*&& dot( -lightDir, light1Buf.areaApproxLights[i].direction.xyz ) > 0*/ @insertpiece( andObjAreaApproxLightMaskCmp ) ) { - float3 p0l0 = passBuf.areaApproxLights[@n].position.xyz - inPs.pos; - float t = dot( p0l0, -passBuf.areaApproxLights[@n].direction.xyz ) / denom; - if( t >= 0 ) + projectedPosInPlane.xyz -= light1Buf.areaApproxLights[i].position.xyz; + float3 areaLightBitangent = cross( light1Buf.areaApproxLights[i].direction.xyz, + light1Buf.areaApproxLights[i].tangent.xyz ); + float2 invHalfRectSize = float2( light1Buf.areaApproxLights[i].direction.w, + light1Buf.areaApproxLights[i].tangent.w ); + //lightUV is in light space, in range [-0.5; 0.5] + float2 lightUVForTex; + float2 lightUV; + lightUV.x = dot( projectedPosInPlane.xyz, light1Buf.areaApproxLights[i].tangent.xyz ); + lightUV.y = dot( projectedPosInPlane.xyz, areaLightBitangent ); + lightUV.xy *= invHalfRectSize.xy /*/ sqrt( fDistance )*/; + //Displace the UV by the normal to account for edge cases when + //a surface is close and perpendicular to the light. This is fully a hack and + //the values (e.g. 0.25) is completely eye balled. + lightUVForTex.xy = lightUV.xy; + lightUV.xy += float2( dot( light1Buf.areaApproxLights[i].tangent.xyz, pixelData.normal ), + dot( areaLightBitangent, pixelData.normal ) ) * 3.75 * invHalfRectSize.xy; + lightUV.xy = clamp( lightUV.xy, -0.5f, 0.5f ); + lightUVForTex = clamp( lightUVForTex.xy, -0.5f, 0.5f ); + // float booster = 1.0f - smoothstep( 0.2f, 1.9f, max( abs( lightUV.x ), abs( lightUV.y ) ) ); + // booster = 1.0f + booster * 2.25f; + float booster = lerp( 1.0f, 4.0f, pixelData.roughness ); + + @property( !hlms_lights_area_tex_colour || !hlms_lights_area_tex_mask ) + float diffuseMask = 1.0f; + @else + float3 diffuseMask = float3( 1.0f, 1.0f, 1.0f ); + @end + @property( hlms_lights_area_tex_mask ) + if( i < floatBitsToInt( light1Buf.numAreaApproxLightsWithMask ) ) { - float3 posInShape = inPs.pos.xyz + toShapeLight.xyz * t - passBuf.areaApproxLights[@n].position.xyz; - float2 reflClipSpace; - reflClipSpace.x = dot( passBuf.areaApproxLights[@n].tangent.xyz, posInShape ); - reflClipSpace.y = dot( areaLightBitangent, posInShape ); - - float specVal; - specVal = 0.5f / (length( max( abs( reflClipSpace * invHalfRectSize ) - 0.5f, 0.0f ) ) + 0.5f); - specVal = min( specVal, 1.0f ); - float areaPower = ((ROUGHNESS * 10.0f + 1.0f) * 0.005f) / - (ROUGHNESS * ROUGHNESS * ROUGHNESS); - areaPower = min( areaPower, 512.0f ); //Prevent INFs. - specVal = pow( specVal, areaPower ) * min( areaPower * areaPower, 1.0f ); - - @property( @n >= hlms_lights_area_tex_mask || !hlms_lights_area_tex_colour ) - specCol = specVal; - @end @property( @n < hlms_lights_area_tex_mask && hlms_lights_area_tex_colour ) - specCol = float3( specVal, specVal, specVal ); - @end - - @property( @n < hlms_lights_area_tex_mask ) - specCol *= OGRE_SampleArray2DLevel( areaLightMasks, areaLightMasksSampler, - reflClipSpace * invHalfRectSize + 0.5f, - passBuf.areaApproxLights[@n].attenuation.w, - (ROUGHNESS - 0.02f) * - passBuf.areaLightNumMipmapsSpecFactor ).AREA_LIGHTS_TEX_SWIZZLE; - @end + // 1 / (1 - 0.02) = 1.020408163 + float diffuseMipsLeft = light1Buf.areaLightNumMipmapsSpecFactor * 0.5 - + light1Buf.areaLightDiffuseMipmapStart * 1.020408163f; + diffuseMask = OGRE_SampleArray2DLevel( areaLightMasks, areaLightMasksSampler, + lightUVForTex + 0.5f, + light1Buf.areaApproxLights[i].attenuation.w, + light1Buf.areaLightDiffuseMipmapStart + + (pixelData.roughness - 0.02f) * diffuseMipsLeft ).AREA_LIGHTS_TEX_SWIZZLE; + } + @end + + float3 closestPoint = light1Buf.areaApproxLights[i].position.xyz + + light1Buf.areaApproxLights[i].tangent.xyz * lightUV.x / invHalfRectSize.x + + areaLightBitangent.xyz * lightUV.y / invHalfRectSize.y; + + float3 lightDir2 = lightDir / fDistance; + lightDir = closestPoint.xyz - inPs.pos; + fDistance= length( lightDir ); + + float3 toShapeLight = reflect( -pixelData.viewDir, pixelData.normal ); + float denom = dot( toShapeLight, -light1Buf.areaApproxLights[i].direction.xyz ); + @property( !hlms_lights_area_tex_mask || !hlms_lights_area_tex_colour ) + float specCol = 0; + @else + float3 specCol = float3( 0, 0, 0 ); + @end + if( denom > 1e-6f || light1Buf.areaApproxLights[i].doubleSided.x != 0.0f ) + { + float3 p0l0 = light1Buf.areaApproxLights[i].position.xyz - inPs.pos; + float t = dot( p0l0, -light1Buf.areaApproxLights[i].direction.xyz ) / denom; + if( t >= 0 ) + { + float3 posInShape = inPs.pos.xyz + toShapeLight.xyz * t - light1Buf.areaApproxLights[i].position.xyz; + float2 reflClipSpace; + reflClipSpace.x = dot( light1Buf.areaApproxLights[i].tangent.xyz, posInShape ); + reflClipSpace.y = dot( areaLightBitangent, posInShape ); + + float specVal; + specVal = 0.5f / (length( max( abs( reflClipSpace * invHalfRectSize ) - 0.5f, 0.0f ) ) + 0.5f); + specVal = min( specVal, 1.0f ); + float areaPower = ((pixelData.roughness * 10.0f + 1.0f) * 0.005f) / + (pixelData.roughness * pixelData.roughness * pixelData.roughness); + areaPower = min( areaPower, 512.0f ); //Prevent INFs. + specVal = pow( specVal, areaPower ) * min( areaPower * areaPower, 1.0f ); + + @property( !hlms_lights_area_tex_mask || !hlms_lights_area_tex_colour ) + specCol = specVal; + @else + specCol = float3( specVal, specVal, specVal ); + @end + + @property( hlms_lights_area_tex_mask ) + if( i < floatBitsToInt( light1Buf.numAreaApproxLightsWithMask ) ) + { + specCol *= OGRE_SampleArray2DLevel( areaLightMasks, areaLightMasksSampler, + reflClipSpace * invHalfRectSize + 0.5f, + light1Buf.areaApproxLights[i].attenuation.w, + (pixelData.roughness - 0.02f) * + light1Buf.areaLightNumMipmapsSpecFactor ).AREA_LIGHTS_TEX_SWIZZLE; + } + @end + } } - } - lightDir *= 1.0 / fDistance; - float fAreaW = dot( lightDir, -passBuf.areaApproxLights[@n].direction.xyz ) * 0.5f + 0.5f; - //lightDir = (-passBuf.areaApproxLights[@n].direction.xyz + lightDir) * 0.50f; - //lightDir = lerp( lightDir2, lightDir, fAreaW ); - float globalDot = saturate( dot( -lightDir, passBuf.areaApproxLights[@n].direction.xyz ) ); - globalDot = passBuf.areaApproxLights[@n].doubleSided.x != 0.0f ? 1.0f : globalDot; - tmpColour = BRDF_AreaLightApprox( lightDir, viewDir, NdotV, - passBuf.areaApproxLights[@n].diffuse.xyz * diffuseMask, - passBuf.areaApproxLights[@n].specular.xyz * specCol - @property( syntax != glsl ) - , material, nNormal @insertpiece( brdfExtraParams ) - @end - ) * ( globalDot * globalDot ) * booster; - float atten = 1.0 / (0.5 + (passBuf.areaApproxLights[@n].attenuation.y + passBuf.areaApproxLights[@n].attenuation.z * fDistance) * fDistance ); - finalColour += tmpColour * atten; - //finalColour.xyz = float3( dot( lightDir, nNormal ) ); - //finalColour.xyz = float3( lightUV.xy + 0.5f, 0.0f ); - //finalColour.xyz = float3( closestPoint.xy + 0.5f, 0.0f ); + lightDir *= 1.0 / fDistance; + //float fAreaW = dot( lightDir, -light1Buf.areaApproxLights[i].direction.xyz ) * 0.5f + 0.5f; + //lightDir = (-light1Buf.areaApproxLights[i].direction.xyz + lightDir) * 0.50f; + //lightDir = lerp( lightDir2, lightDir, fAreaW ); + float globalDot = saturate( dot( -lightDir, light1Buf.areaApproxLights[i].direction.xyz ) ); + globalDot = light1Buf.areaApproxLights[i].doubleSided.x != 0.0f ? 1.0f : globalDot; + tmpColour = BRDF_AreaLightApprox( lightDir, + light1Buf.areaApproxLights[i].diffuse.xyz * diffuseMask, + light1Buf.areaApproxLights[i].specular.xyz * specCol, + pixelData ) * ( globalDot * globalDot ) * booster; + float atten = 1.0 / (0.5 + (light1Buf.areaApproxLights[i].attenuation.y + light1Buf.areaApproxLights[i].attenuation.z * fDistance) * fDistance ); + + @property( obb_restraint_approx ) + atten *= obbRestraintFade; + @end + + finalColour += tmpColour * atten; + //finalColour.xyz = float3( dot( lightDir, pixelData.normal ) ); + //finalColour.xyz = float3( lightUV.xy + 0.5f, 0.0f ); + //finalColour.xyz = float3( closestPoint.xy + 0.5f, 0.0f ); + } } -@end @end @piece( DeclareBRDF_AreaLightApprox ) INLINE float3 BRDF_AreaLightApprox ( - float3 lightDir, float3 viewDir, float NdotV, float3 lightDiffuse, float3 lightSpecular - @property( syntax != glsl ) - , Material material, float3 nNormal @insertpiece( brdfExtraParamDefs ) - @end + float3 lightDir, float3 lightDiffuse, float3 lightSpecular, PixelData pixelData ) { - float3 halfWay= normalize( lightDir + viewDir ); - float NdotL = saturate( dot( nNormal, lightDir ) ); - float VdotH = saturate( dot( viewDir, halfWay ) ); + float3 halfWay= normalize( lightDir + pixelData.viewDir ); + float NdotL = saturate( dot( pixelData.normal, lightDir ) ); + float VdotH = saturate( dot( pixelData.viewDir, halfWay ) ); //Formula: // fresnelS = lerp( (1 - V*H)^5, 1, F0 ) - @insertpiece( FresnelType ) fresnelS = @insertpiece( getSpecularFresnel ); + float_fresnel fresnelS = @insertpiece( getSpecularFresnel ); //We should divide Rs by PI, but it was done inside G for performance - float3 Rs = fresnelS * @insertpiece( kS ).xyz * lightSpecular; + float3 Rs = fresnelS * pixelData.specular.xyz * lightSpecular; //Diffuse BRDF (*Normalized* Disney, see course_notes_moving_frostbite_to_pbr.pdf //"Moving Frostbite to Physically Based Rendering" Sebastien Lagarde & Charles de Rousiers) - float energyBias = ROUGHNESS * 0.5; - float energyFactor = lerp( 1.0, 1.0 / 1.51, ROUGHNESS ); - float fd90 = energyBias + 2.0 * VdotH * VdotH * ROUGHNESS; + float energyBias = pixelData.roughness * 0.5; + float energyFactor = lerp( 1.0, 1.0 / 1.51, pixelData.roughness ); + float fd90 = energyBias + 2.0 * VdotH * VdotH * pixelData.roughness; float lightScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotL, 5.0 ); - float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotV, 5.0 ); + float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - pixelData.NdotV, 5.0 ); @property( fresnel_separate_diffuse ) - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnel ); -@end @property( !fresnel_separate_diffuse ) - float fresnelD = 1.0f - @insertpiece( getMaxFresnelS );@end + float_fresnel fresnelD = @insertpiece( getDiffuseFresnel ); +@else + float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); +@end //We should divide Rd by PI, but it is already included in kD - float3 Rd = (lightScatter * viewScatter * energyFactor * fresnelD) * @insertpiece( kD ).xyz * lightDiffuse; + float3 Rd = (lightScatter * viewScatter * energyFactor * fresnelD) * pixelData.diffuse.xyz * lightDiffuse; return NdotL * (Rs + Rd); } diff --git a/ogre2/src/media/Hlms/Pbs/Any/ForwardPlus_DecalsCubemaps_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/ForwardPlus_DecalsCubemaps_piece_ps.any new file mode 100644 index 000000000..0770500b8 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/ForwardPlus_DecalsCubemaps_piece_ps.any @@ -0,0 +1,273 @@ +//#include "SyntaxHighlightingMisc.h" + +@property( hlms_forwardplus ) + +@property( hlms_enable_decals ) +/// Perform decals *after* sampling the diffuse colour. +@piece( forwardPlusDoDecals ) + @insertpiece( forward3dHeader ) + + @property( hlms_decals_normals && normal_map ) + float3 finalDecalTsNormal = float3( 0.0f, 0.0f, 1.0f ); + @end + @property( hlms_decals_emissive ) + float3 finalDecalEmissive = float3( 0.0f, 0.0f, 0.0f ); + @end + + ushort numLightsInGrid = bufferFetch1( f3dGrid, int(sampleOffset + @value(hlms_forwardplus_decals_slot_offset)u) ); + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + float3 posDdx = OGRE_ddx( inPs.pos.xyz ); + float3 posDdy = OGRE_ddy( inPs.pos.xyz ); + + for( uint i=0u; i> 16u; + float2 decalNormals = OGRE_SampleArray2DGrad( decalsNormalsTex, decalsSampler, decalUV.xy, + decalNormalsIdx, decalUvDdx, decalUvDdy ).xy; + @end + @property( hlms_decals_emissive ) + ushort decalEmissiveIdx = floatBitsToUint( texIndices.y ) & 0xFFFFu; + float3 decalEmissive = OGRE_SampleArray2DGrad( decalsEmissiveTex, decalsSampler, decalUV.xy, + decalEmissiveIdx, decalUvDdx, decalUvDdy ).xyz; + @end + + @property( hlms_decals_diffuse && (hlms_decals_normals || hlms_decals_emissive) ) + bool ignoreAlphaDiffuse = (floatBitsToUint( texIndices.y ) & 0xFFFF0000u) != 0u; + @end + + //Mask the decal entirely if localPos is outside the debox + float3 absLocalPos = abs( localPos.xyz ); + bool isOutsideDecal = absLocalPos.x > 0.5f || absLocalPos.y > 0.5f || absLocalPos.z > 0.5f; + + //Mask away objects looking away from the decal. Please note that inPs.normal is not unit-length + //and is before any TBN for normal mapping. In other words it's the geometric normal + //geomNormal is not available because it gets decalred after decals run + //We assume invWorldView is orthogonal, thus the transpose = inverse, hance invWorldView1.xyz + //works as the decal's direction + // + //Use a smooth fade to avoid flickering due to floating point precision when the normal + //and the decal are perpendicular to each other. (tolerance set to 0.0002) + float3 decalDir = normalize( float3( invWorldView1.xyz ) ); + //isOutsideDecal = dot( decalDir.xyz, inPs.normal.xyz ) <= 0.0 ? true : isOutsideDecal; + float normalAway = saturate( (dot( decalDir.xyz, inPs.normal.xyz ) + 0.0002) / 0.0002 ); + normalAway = isOutsideDecal ? 0.0f : normalAway; + + float decalMask = normalAway; + + @property( hlms_decals_diffuse ) + decalMask *= decalDiffuse.w; + float decalMetalness = texIndices.z; + float3 decalF0 = lerp( float3( 0.03f, 0.03f, 0.03f ), decalDiffuse.xyz, decalMetalness ); + decalDiffuse.xyz = decalDiffuse.xyz - decalDiffuse.xyz * decalMetalness; + + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, decalDiffuse.xyz * 0.318309886f, decalMask ); + pixelData.roughness = lerp( pixelData.roughness, texIndices.w, decalMask ); + + @property( !metallic_workflow && !fresnel_workflow && !fresnel_scalar ) + pixelData.specular = lerp( pixelData.specular.xyz, decalF0, decalMask ); + pixelData.F0 = lerp( pixelData.F0, decalMetalness, decalMask ); + @else + pixelData.specular = lerp( pixelData.specular.xyz, float3( 1.0f, 1.0f, 1.0f ), decalMask ); + pixelData.F0.xyz = lerp( pixelData.F0.xyz, decalF0.xyz, decalMask ); + @end + + @property( hlms_decals_normals || hlms_decals_emissive ) + //Reset the mask for the rest of the decal types to ignore our alpha + decalMask = ignoreAlphaDiffuse ? normalAway : decalMask; + @end + @end + @property( hlms_decals_normals && normal_map ) + finalDecalTsNormal.xy += decalNormals.xy * decalMask; + @end + @property( hlms_decals_emissive ) + finalDecalEmissive += (absLocalPos.x > 0.5f || absLocalPos.y > 0.5f || + absLocalPos.z > 0.5f) ? float3( 0.0f, 0.0f, 0.0f ) : + (decalEmissive.xyz * decalMask); + @end + + } +@end /// forwardPlusDoDecals + @property( hlms_decals_normals && normal_map ) + /// Apply decals normal *after* sampling the tangent space normals (and detail normals too). + /// hlms_decals_normals will be unset if the Renderable cannot support normal maps (has no Tangents) + @piece( forwardPlusApplyDecalsNormal ) + finalDecalTsNormal.xyz = normalize( finalDecalTsNormal.xyz ); + @property( normal_map_tex || detail_maps_normal ) + pixelData.normal.xy += finalDecalTsNormal.xy; + pixelData.normal.z *= finalDecalTsNormal.z; + @end + @property( !normal_map_tex && !detail_maps_normal ) + pixelData.normal.xyz = finalDecalTsNormal.xyz; + @end + //Do not normalize as later normalize( TBN * pixelData.normal ) will take care of it + @end + @end +@end /// hlms_enable_decals + +@property( hlms_enable_cubemaps_auto ) +@piece( forwardPlusDoCubemaps ) + numLightsInGrid = bufferFetch1( f3dGrid, int(sampleOffset + @value(hlms_forwardplus_cubemap_slot_offset)u) ); + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + float cubemapAccumWeight = 0; + + float3 pccEnvS = float3( 0, 0, 0 ); + float3 pccEnvD = float3( 0, 0, 0 ); + + @property( vct_num_probes ) + if( pixelData.roughness < 1.0f || vctSpecular.w == 0 ) + { + float accumVctLerp = 0; + float numProbesVctLerp = 0; + @end + for( uint i=0u; i 0 ) + { + float2 cubemapIdx_priority = unpackUshort2ToFloat2( floatBitsToUint( probe.halfSize.w ) ); + float probeCubemapIdx = cubemapIdx_priority.x; + float probePriority = cubemapIdx_priority.y; + + float3 probeToAreaCenterOffsetLS = float3( probe.cubemapPosLS.w, + probe.cubemapPosVS.w, + probeInnerRange.w ); + float ndf = getProbeNDF( posInProbSpace.xyz, probeToAreaCenterOffsetLS.xyz, + probeInnerRange.xyz, probeOuterRange.xyz ); + ndf = saturate( ndf ); + probeFade = 1.0 - ndf; + probeFade = probeFade * probeFade; + probeFade = probeFade * probeFade; + probeFade *= probePriority; + + @property( vct_num_probes ) + float4 reflDirLS_dist = localCorrect( pixelData.reflDir, posInProbSpace, probe ); + float3 reflDirLS = reflDirLS_dist.xyz; + @else + float3 reflDirLS = localCorrect( pixelData.reflDir, posInProbSpace, probe ).xyz; + @end + float3 normalLS = localCorrect( pixelData.normal, posInProbSpace, probe ).xyz; + + float4 pccSingleEnvS; + @property( !hlms_cubemaps_use_dpm ) + pccSingleEnvS = OGRE_SampleArrayCubeLevel( + texEnvProbeMap, samplerState@value(envMapRegSampler), reflDirLS, + probeCubemapIdx, @insertpiece( envSpecularRoughness ) ); + @property( cubemaps_as_diffuse_gi ) + pccEnvD += OGRE_SampleArrayCubeLevel( + texEnvProbeMap, samplerState@value(envMapRegSampler), normalLS, + probeCubemapIdx, 11.0 ).xyz + @insertpiece( ApplyEnvMapScale ) * probeFade; + @end + @else + pccSingleEnvS = OGRE_SampleArray2DLevel( + texEnvProbeMap, samplerState@value(envMapRegSampler), mapCubemapToDpm( reflDirLS ), + probeCubemapIdx, @insertpiece( envSpecularRoughness ) ); + @property( cubemaps_as_diffuse_gi ) + pccEnvD += OGRE_SampleArray2DLevel( + texEnvProbeMap, samplerState@value(envMapRegSampler), mapCubemapToDpm( normalLS ), + probeCubemapIdx, 11.0 ).xyz + @insertpiece( ApplyEnvMapScale ) * probeFade; + @end + @end + + pccSingleEnvS.xyz *= probeFade; + @property( envmap_scale ) + pccSingleEnvS.xyz *= passBuf.ambientUpperHemi.w; + @end + + @property( vct_num_probes ) + float vctLerp = getPccVctBlendWeight( inPs.pos, pixelData.reflDir, reflDirLS_dist.w, + pixelData.roughness, + probe.cubemapPosVS.xyz, + vctSpecPosVS, vctSpecular.w, + passBuf.pccVctMinDistance, + passBuf.invPccVctInvDistance, + pccSingleEnvS.w ); + + pccSingleEnvS *= 1.0f - vctLerp; + accumVctLerp += 1.0f - vctLerp; + numProbesVctLerp += 1.0f; + @end + + pccEnvS += pccSingleEnvS.xyz; + + cubemapAccumWeight += probeFade; + } + } + + @property( cubemaps_as_diffuse_gi ) + pccEnvD.xyz *= cubemapAccumWeight == 0.0f ? 1.0f : (1.0f / cubemapAccumWeight); + @end + pccEnvS.xyz *= cubemapAccumWeight == 0.0f ? 1.0f : (1.0f / cubemapAccumWeight); + + @property( vct_num_probes ) + numProbesVctLerp = numProbesVctLerp == 0.0f ? 1.0f : numProbesVctLerp; + pixelData.envColourS.xyz = ( pccEnvS + + pixelData.envColourS * (numProbesVctLerp - accumVctLerp) ) / + numProbesVctLerp; + @property( cubemaps_as_diffuse_gi ) + pixelData.envColourD += vctSpecular.w > 0 ? float3( 0, 0, 0 ) : pccEnvD; + @end + @else + pixelData.envColourS.xyz = pccEnvS; + @property( cubemaps_as_diffuse_gi ) + pixelData.envColourD.xyz = pccEnvD; + @end + @end + + + @property( vct_num_probes ) + } + @end +@end +@end /// hlms_enable_cubemaps_auto + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_all.any b/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_all.any new file mode 100644 index 000000000..06211d701 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_all.any @@ -0,0 +1,30 @@ +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( irradiance_field ) + +@piece( DeclIrradianceFieldStruct ) + struct IrradianceField + { + float4 viewToIrradianceFieldRow0; + float4 viewToIrradianceFieldRow1; + float4 viewToIrradianceFieldRow2; + + float2 numProbesAggregated; + float padding0; + float padding1; + + float depthBorderedRes; + float depthFullWidth; + float2 depthInvFullResolution; + + float irradBorderedRes; + float irradFullWidth; + float2 irradInvFullResolution; + }; +@end + +@piece( DeclIrradianceFieldUniform ) + IrradianceField irradianceField; +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_ps.any new file mode 100644 index 000000000..507f3aed3 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/IrradianceField_piece_ps.any @@ -0,0 +1,202 @@ +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( irradiance_field ) + +// clang-format off +@piece( DeclIrradianceFieldTextures ) + @property( syntax == glsl ) + uniform sampler2D ifdColour; + uniform sampler2D ifdDepth; + @end + @property( syntax == hlsl ) + Texture2D ifdColour : register(t@value(ifdColour)); + Texture2D ifdDepth : register(t@value(ifdDepth)); + SamplerState ifdSampler : register(s@value(ifdColour)); + @end + @property( syntax == metal ) + , texture2d ifdColour [[texture(@value(ifdColour))]] + , texture2d ifdDepth [[texture(@value(ifdDepth))]] + , sampler ifdSampler [[sampler(@value(ifdColour))]] + @end +@end +// clang-format on + +{ +@piece( DeclIrradianceFieldFuncs ) + #define IrfProbeIndex uint + + INLINE float2 octahedronMappingWrap( float2 v ) + { + float2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return ( 1.0 - abs( v.yx ) ) * signVal; + } + + INLINE float2 octahedronMappingEncode( float3 n ) + { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= ( abs( n.x ) + abs( n.y ) + abs( n.z ) ); + n.xy = n.z >= 0.0 ? n.xy : octahedronMappingWrap( n.xy ); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; + } + + INLINE float3 transformPos3( float3 position, float4 row0, float4 row1, float4 row2 ) + { + float3 retVal; + retVal.x = dot( row0.xyzw, float4( position, 1.0 ) ); + retVal.y = dot( row1.xyzw, float4( position, 1.0 ) ); + retVal.z = dot( row2.xyzw, float4( position, 1.0 ) ); + return retVal; + } + + INLINE float3 transformDir3( float3 dir, float4 row0, float4 row1, float4 row2 ) + { + float3 retVal; + retVal.x = dot( row0.xyz, dir ); + retVal.y = dot( row1.xyz, dir ); + retVal.z = dot( row2.xyz, dir ); + return retVal; + } + + INLINE float2 getIrradianceFieldXY( float3 dir, IrfProbeIndex probeIdx, float borderedRes, + float fullWidth, float2 invFullResolution ) + { + float2 retVal; + /* Perform the following, but in floating point: + retVal.x = ( probeIdx * borderedRes ) % fullWidth; + retVal.y = ( ( probeIdx * borderedRes ) / fullWidth ) * borderedRes;*/ + float temp = probeIdx * borderedRes; + retVal.y = floor( temp * invFullResolution.x ); + retVal.x = temp - retVal.y * fullWidth; + retVal.y *= borderedRes; + + // Skip top-left border + retVal.xy += 1.0f; + + //dir.y = -dir.y; + // Quantize direction to fix noise artifacts where the texels output from + // octahedronMappingEncode keep jumping due to octahedronMappingWrap being too sharp + // https://github.com/OGRECave/ogre-next/issues/29#issuecomment-541491145 + dir = ceil( dir * 1048576.0 ); + dir *= 1.0 / 1048576.0; + float2 uv = octahedronMappingEncode( dir ) * ( borderedRes - 2.0f ); + + retVal += uv; + retVal *= invFullResolution; + return retVal; + } + + /** + \param probeOrigin + \param numProbesAggregated + numProbesAggregated.x must contain IrradianceFieldSettings::mNumProbes[0] + numProbesAggregated.x must contain ( mNumProbes[0] * mNumProbes[1] ) + \return + */ + IrfProbeIndex getProbeIdx( float3 probeOrigin, float2 numProbesAggregated ) + { + return IrfProbeIndex( probeOrigin.x + probeOrigin.y * numProbesAggregated.x + + probeOrigin.z * numProbesAggregated.y ); + } +@end +} + +{ +@piece( applyIrradianceField ) + + // ifdGridPos in range [0; mNumProbes) + float3 ifdGridPos = + transformPos3( inPs.pos.xyz, // + passBuf.irradianceField.viewToIrradianceFieldRow0, + passBuf.irradianceField.viewToIrradianceFieldRow1, + passBuf.irradianceField.viewToIrradianceFieldRow2 ); + + float3 ifdGridProbeOrigin = trunc( ifdGridPos ); + float3 ifdSpaceNormal = normalize( transformDir3( pixelData.normal, // + passBuf.irradianceField.viewToIrradianceFieldRow0, + passBuf.irradianceField.viewToIrradianceFieldRow1, + passBuf.irradianceField.viewToIrradianceFieldRow2 ) ); + + // ifdAlpha is how far from the floor( ifdGridPos ). on [0, 1] for each axis. + float3 ifdAlpha = saturate( fract( ifdGridPos ) ); + + float3 ifdIrradiance = float3( 0, 0, 0 ); + float sumIfdWeight = 0; + + // Iterate over adjacent probe cage + for( int i = 0; i < 8; ++i ) + //for( int i = 0; i < 1; ++i ) + { + // Compute the offset grid coord and clamp to the probe grid boundary + // Offset = 0 or 1 along each axis + float3 probeOffset = float3( int3( i, i >> 1, i >> 2 ) & int3( 1, 1, 1 ) ); + float3 probeOrigin = ifdGridProbeOrigin + probeOffset; + + IrfProbeIndex probeIdx = + getProbeIdx( probeOrigin, passBuf.irradianceField.numProbesAggregated.xy ); + + float3 dir = probeOrigin - ifdGridPos; + float r = length( dir ); + dir *= 1.0 / r; + + // Ignore probes that are behind us, but don't black them out completely + // as detailed surface may otherwise have very few probes ppointing at it + float weight; + weight = dot( dir, ifdSpaceNormal ) * 200.0; + weight = saturate( weight ) + 0.2; + + // Compute the trilinear weights based on the grid cell vertex to smoothly + // transition between probes. Avoid ever going entirely to zero because that + // will cause problems at the border probes. + // We're using 1-a when offset = 0 and a when offset = 1. + float3 trilinear; + trilinear.x = probeOffset.x < 1 ? ( 1.0 - ifdAlpha.x ) : ifdAlpha.x; + trilinear.y = probeOffset.y < 1 ? ( 1.0 - ifdAlpha.y ) : ifdAlpha.y; + trilinear.z = probeOffset.z < 1 ? ( 1.0 - ifdAlpha.z ) : ifdAlpha.z; + + // Visibility (Chebyshev) + float2 ifdDepthUV = getIrradianceFieldXY( + -dir, probeIdx, passBuf.irradianceField.depthBorderedRes, + passBuf.irradianceField.depthFullWidth, passBuf.irradianceField.depthInvFullResolution ); + float2 temp = OGRE_SampleLevel( ifdDepth, ifdSampler, ifdDepthUV, 0 ).xy; + float mean = temp.x; + float meanSq = temp.y; + if( r > mean ) + { + float variance = abs( mean * mean - meanSq ) + 1e-6; + float dev = ( r - mean ); + float chebyshevWeight = variance / ( variance + dev * dev ); + chebyshevWeight = max( chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.0 ); + + weight *= chebyshevWeight; + } + + // Avoid zero weight + weight = max( 0.000001, weight ); + + const float crushThreshold = 0.2; + if (weight < crushThreshold) { + weight *= weight * weight * (1.0 / (crushThreshold*crushThreshold)); + } + + weight *= trilinear.x * trilinear.y * trilinear.z; + + float2 ifdColourUV = getIrradianceFieldXY( + ifdSpaceNormal, probeIdx, passBuf.irradianceField.irradBorderedRes, + passBuf.irradianceField.irradFullWidth, passBuf.irradianceField.irradInvFullResolution ); + + float3 irrColour = OGRE_SampleLevel( ifdColour, ifdSampler, ifdColourUV, 0 ).xyz; +// irrColour = sqrt(irrColour); + ifdIrradiance += irrColour * weight; + sumIfdWeight += weight; + } + +// ifdIrradiance = ifdIrradiance * ifdIrradiance; + + pixelData.envColourD.xyz += ifdIrradiance * ( 1.0 / sumIfdWeight ); +@end +} + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/IrradianceVolume_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/IrradianceVolume_piece_ps.any new file mode 100644 index 000000000..3d1491bc9 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/IrradianceVolume_piece_ps.any @@ -0,0 +1,79 @@ + +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( irradiance_volumes ) +@piece( applyIrradianceVolumes ) + float3 worldNormal = mul( pixelData.normal.xyz, toFloat3x3(passBuf.invView) ); + float3 worldPos = mul( float4( inPs.pos.xyz, 1.0 ), passBuf.invView ).xyz; + + float3 irradiancePos = worldPos.xyz * passBuf.irradianceSize.xyz - passBuf.irradianceOrigin.xyz; + //Floor irradiancePos.y and put the fractional part so we can lerp. + irradiancePos.y -= 0.5f; //Texel centers are at center. Move it to origin. + float origYPos; + float fIrradianceYWeight = modf( irradiancePos.y, origYPos ); + origYPos *= 6.0; + origYPos += 0.5f; //Make sure we sample at center (so HW doesn't do linear + //filtering on the Y axis. We'll do that manually) + + float3 isNegative = float3( lessThan( worldNormal.xyz, float3( 0, 0, 0 ) ) ); + + float3 tmpAmbientSample; + + //We need to make 3 samples (actually 6), one for each axis. + /* The code is basically doing: + float3 cAmbientCube[6]; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = worldNormalSq.x * cAmbientCube[isNegative.x] + + worldNormalSq.y * cAmbientCube[isNegative.y+2] + + worldNormalSq.z * cAmbientCube[isNegative.z+4]; + + We have 6 colour values per voxel. But GPUs can only store 1 colour value per cell. + So we 6x the height to workaround that limitation. This also means we loose the ability + to do HW bilinear filtering around the Y axis; therefore we do it ourselves manually. + Because of this, instead of doing 3 samples, we end up doing 6 (in order to perform + filtering around the Y axis) + **/ + + float irradianceTexInvHeight = passBuf.irradianceSize.w; + + irradiancePos.y = (origYPos + isNegative.x) * irradianceTexInvHeight; + float3 xAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + irradiancePos.y += 6.0f * irradianceTexInvHeight; + tmpAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + + xAmbientSample = lerp( xAmbientSample, tmpAmbientSample, fIrradianceYWeight ); + + irradiancePos.y = (origYPos + (2.0f + isNegative.y)) * irradianceTexInvHeight; + float3 yAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + irradiancePos.y += 6.0f * irradianceTexInvHeight; + tmpAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + + yAmbientSample = lerp( yAmbientSample, tmpAmbientSample, fIrradianceYWeight ); + + irradiancePos.y = (origYPos + (4.0f + isNegative.z)) * irradianceTexInvHeight; + float3 zAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + irradiancePos.y += 6.0f * irradianceTexInvHeight; + tmpAmbientSample = OGRE_Sample( irradianceVolume, irradianceVolumeSampler, irradiancePos ).xyz; + + zAmbientSample = lerp( zAmbientSample, tmpAmbientSample, fIrradianceYWeight ); + + float3 worldNormalSq = worldNormal.xyz * worldNormal.xyz; + float3 ambientTerm = worldNormalSq.x * xAmbientSample.xyz + + worldNormalSq.y * yAmbientSample.xyz + + worldNormalSq.z * zAmbientSample.xyz; + ambientTerm *= passBuf.irradianceOrigin.w; //irradianceOrigin.w = irradianceMaxPower + + @property( syntax == metal ) + if( irradiancePos.x < 0 || irradiancePos.x > 1 || + irradiancePos.z < 0 || irradiancePos.z > 1 || + irradiancePos.y <= (6.0f * irradianceTexInvHeight) || irradiancePos.y >= 1 ) + { + //Metal does not support border colour addressing mode. + ambientTerm = float3( 0 ); + } + @end + + finalColour.xyz += ambientTerm.xyz * pixelData.diffuse.xyz; +@end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/LightProfiles_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/LightProfiles_piece_ps.any new file mode 100644 index 000000000..11c53d698 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/LightProfiles_piece_ps.any @@ -0,0 +1,55 @@ + +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( light_profiles_texture ) + +@piece( DeclLightProfilesTexture ) + @property( syntax == glsl || syntax == glsles ) + uniform sampler2D lightProfiles; + @end + @property( syntax == hlsl ) + Texture2D lightProfiles : register(t@value(lightProfiles)); + SamplerState lightProfilesSampler : register(s@value(lightProfiles)); + @end + @property( syntax == metal ) + , texture2d lightProfiles [[texture(@value(lightProfiles))]] + , sampler lightProfilesSampler [[sampler(@value(lightProfiles))]] + @end +@end + + +@piece( DeclLightProfilesTextureFuncs ) + @property( syntax == metal ) + #define OGRE_PHOTOMETRIC_ARG_DECL , texture2d lightProfiles, sampler lightProfilesSampler + #define OGRE_PHOTOMETRIC_ARG , lightProfiles, lightProfilesSampler + @else + #define OGRE_PHOTOMETRIC_ARG_DECL + #define OGRE_PHOTOMETRIC_ARG + @end + + // polynomial degree 1 + // input [-1, 1] and output [0, PI] + // See + // https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/ + float fast_acos(float inX) + { + float C0 = 1.56467f; + float C1 = -0.155972; + + float x = abs(inX); + float res = C1 * x + C0; // p(x) + res *= sqrt(1.0f - x); + + return (inX >= 0) ? res : 3.14159265359f - res; // Undo range reduction + } + + float getPhotometricAttenuation( float cosAngle, float profileIdx OGRE_PHOTOMETRIC_ARG_DECL ) + { + //float angle = acos( clamp( cosAngle, -1.0, 1.0 ) ) * ( 1.0 / 3.14159265359f ); + float angle = fast_acos( clamp( cosAngle, -1.0, 1.0 ) ) * ( 1.0 / 3.14159265359f ); + return OGRE_SampleLevel( lightProfiles, lightProfilesSampler, + float2( angle, profileIdx ), 0.0 ).r; + } +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/200.BRDFs_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Main/200.BRDFs_piece_ps.any new file mode 100644 index 000000000..5f395e9db --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/200.BRDFs_piece_ps.any @@ -0,0 +1,264 @@ + +//#include "SyntaxHighlightingMisc.h" + +//For mortals: +// getSpecularFresnel = F0 + pow( 1.0 - VdotH, 5.0 ) * (1.0 - F0) +// getDiffuseFresnel = 1.0 - F0 + pow( 1.0 - NdotL, 5.0 ) * F0 +// getSpecularFresnelWithRoughness = F0 + pow( 1.0 - VdotH, 5.0 ) * (max(roughness, (1.0 - F0)) - F0) +// getDiffuseFresnelWithRoughness = max(roughness, (1.0 - F0) - F0 + pow( 1.0 - NdotL, 5.0 ) * F0 +@piece( getSpecularFresnel )pixelData.F0 + pow( 1.0 - VdotH, 5.0 ) * (1.0 - pixelData.F0)@end +@piece( getDiffuseFresnel )1.0 - pixelData.F0 + pow( 1.0 - NdotL, 5.0 ) * pixelData.F0@end +@piece( getSpecularFresnelWithRoughness )pixelData.F0 + pow( 1.0 - pixelData.NdotV, 5.0 ) * (max( make_float_fresnel( 1.0 - pixelData.roughness ), pixelData.F0 ) - pixelData.F0)@end +@piece( getDiffuseFresnelWithRoughness )max( make_float_fresnel( 1.0 - pixelData.roughness ), pixelData.F0 ) - pixelData.F0 + pow( 1.0 - NdotL, 5.0 ) * pixelData.F0@end + +@property( !fresnel_scalar ) + @piece( getMaxFresnelS )fresnelS@end +@else + @piece( getMaxFresnelS )max3( fresnelS.x, fresnelS.y, fresnelS.z )@end +@end + +@property( BRDF_BlinnPhong ) +@piece( DeclareBRDF ) +//Blinn-Phong +INLINE float3 BRDF( float3 lightDir, float3 lightDiffuse, float3 lightSpecular, PixelData pixelData ) +{ + float3 halfWay = normalize( lightDir + pixelData.viewDir ); + float NdotL = saturate( dot( pixelData.normal, lightDir ) ); //Diffuse (Lambert) + float NdotH = clamp( dot( pixelData.normal, halfWay ), 0.001, 1.0 ); //Specular + @property( !legacy_math_brdf ) + float VdotH = clamp( dot( pixelData.viewDir, halfWay ), 0.001, 1.0 ); //Fresnel + + //Fresnel term (Schlick's approximation) + float_fresnel fresnelS = @insertpiece( getSpecularFresnel ); + @property( fresnel_separate_diffuse ) + float_fresnel fresnelD = @insertpiece( getDiffuseFresnel ); + @else + float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); + @end + @end + + @property( !roughness_is_shininess ) + float shininess = exp2( 10.0 * (1.0 - pixelData.roughness) + 1.0 ) * 0.25; + @else + float shininess = pixelData.roughness; + @end + float blinnPhong = pow( NdotH, shininess ); + + @property( !legacy_math_brdf ) + //Normalize Blinn-Phong using (n + 8) / (8 * pi) + //Note this factor is an approximation. The real normalization is + //*much* more expensive. See: + //http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/ + blinnPhong *= (shininess + 8.0) / (8.0 * 3.141592654); + + //Avoid very small denominators, they go to NaN or cause aliasing artifacts + //Note: For blinn-phong we use larger denominators otherwise specular blows out of proportion + float_fresnel Rs = ( fresnelS * blinnPhong ) / max( 4.0 * pixelData.NdotV * NdotL, 0.75 ); + //Make diffuse look closer to Default. + fresnelD *= lerp( 1.0, 1.0 / 1.51, pixelData.roughness ); + @else + float Rs = blinnPhong; + float fresnelD = 1.0; + @end + + return NdotL * (pixelData.specular.xyz * lightSpecular * Rs + + pixelData.diffuse.xyz * lightDiffuse * fresnelD); +} +@end +@end + +@property( BRDF_CookTorrance ) +@piece( DeclareBRDF ) +//Cook-Torrance +INLINE float3 BRDF( float3 lightDir, float3 lightDiffuse, float3 lightSpecular, PixelData pixelData ) +{ + float3 halfWay = normalize( lightDir + pixelData.viewDir ); + float NdotL = saturate( dot( pixelData.normal, lightDir ) ); + float NdotH = clamp( dot( pixelData.normal, halfWay ), 0.001, 1.0 ); + float VdotH = clamp( dot( pixelData.viewDir, halfWay ), 0.001, 1.0 ); + + float sqR = pixelData.roughness * pixelData.roughness; + + //Roughness/Distribution/NDF term (Beckmann distribution) + //Formula: + // Where alpha = NdotH and m = roughness + // R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( -tan(alpha)^2 / m^2 ) ] + // R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( ( cos(alpha)^2 - 1 ) / (m^2 cos(alpha)^2 ) ] + float NdotH_sq = NdotH * NdotH; + float roughness_a = 1.0 / ( 3.141592654 * sqR * NdotH_sq * NdotH_sq );//( 1 / (m^2 x cos(alpha)^4 ) + float roughness_b = NdotH_sq - 1.0; //( cos(alpha)^2 - 1 ) + float roughness_c = sqR * NdotH_sq; //( m^2 cos(alpha)^2 ) + + //Avoid Inf * 0 = NaN; we need Inf * 0 = 0 + float R = min( roughness_a, 65504.0 ) * exp( roughness_b / roughness_c ); + + //Geometric/Visibility term (Cook Torrance) + float shared_geo = 2.0 * NdotH / VdotH; + float geo_b = shared_geo * pixelData.NdotV; + float geo_c = shared_geo * NdotL; + float G = min( 1.0, min( geo_b, geo_c ) ); + + //Fresnel term (Schlick's approximation) + //Formula: + // fresnelS = lerp( (1 - V*H)^5, 1, F0 ) + // fresnelD = lerp( (1 - N*L)^5, 1, 1 - F0 ) [See s2010_course_note_practical_implementation_at_triace.pdf] + float_fresnel fresnelS = @insertpiece( getSpecularFresnel ); + @property( fresnel_separate_diffuse ) + float_fresnel fresnelD = @insertpiece( getDiffuseFresnel ); + @else + float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); + @end + + //Avoid very small denominators, they go to NaN or cause aliasing artifacts + float_fresnel Rs = ( fresnelS * (R * G) ) / max( 4.0 * pixelData.NdotV * NdotL, 0.01 ); + + return NdotL * (pixelData.specular.xyz * lightSpecular * Rs + + pixelData.diffuse.xyz * lightDiffuse * fresnelD); +} +@end +@end + +@property( BRDF_Default ) +@piece( DeclareBRDF ) +//Default BRDF +INLINE float3 BRDF( float3 lightDir, float3 lightDiffuse, float3 lightSpecular, PixelData pixelData ) +{ + float3 halfWay = normalize( lightDir + pixelData.viewDir ); + float NdotL = saturate( dot( pixelData.normal, lightDir ) ); + float NdotH = saturate( dot( pixelData.normal, halfWay ) ); + float VdotH = saturate( dot( pixelData.viewDir, halfWay ) ); + + float sqR = pixelData.roughness * pixelData.roughness; + + //Roughness/Distribution/NDF term (GGX) + //Formula: + // Where alpha = roughness + // R = alpha^2 / [ PI * [ ( NdotH^2 * (alpha^2 - 1) ) + 1 ]^2 ] + float f = ( NdotH * sqR - NdotH ) * NdotH + 1.0; + float R = sqR / (f * f + 1e-6f); + + //Geometric/Visibility term (Smith GGX Height-Correlated) +@property( GGX_height_correlated ) + float Lambda_GGXV = NdotL * sqrt( (-pixelData.NdotV * sqR + pixelData.NdotV) * pixelData.NdotV + sqR ); + float Lambda_GGXL = pixelData.NdotV * sqrt( (-NdotL * sqR + NdotL) * NdotL + sqR ); + + float G = 0.5 / (( Lambda_GGXV + Lambda_GGXL + 1e-6f ) * 3.141592654); +@else + float gL = NdotL * (1-sqR) + sqR; + float gV = pixelData.NdotV * (1-sqR) + sqR; + float G = 1.0 / (( gL * gV + 1e-4f ) * 4 * 3.141592654); +@end + + //Formula: + // fresnelS = lerp( (1 - V*H)^5, 1, F0 ) + float_fresnel fresnelS = @insertpiece( getSpecularFresnel ); + + //We should divide Rs by PI, but it was done inside G for performance + float3 Rs = ( fresnelS * (R * G) ) * pixelData.specular.xyz * lightSpecular; + + //Diffuse BRDF (*Normalized* Disney, see course_notes_moving_frostbite_to_pbr.pdf + //"Moving Frostbite to Physically Based Rendering" Sebastien Lagarde & Charles de Rousiers) + float energyBias = pixelData.roughness * 0.5; + float energyFactor = lerp( 1.0, 1.0 / 1.51, pixelData.roughness ); + float fd90 = energyBias + 2.0 * VdotH * VdotH * pixelData.roughness; + float lightScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotL, 5.0 ); + float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - pixelData.NdotV, 5.0 ); + + @property( fresnel_separate_diffuse ) + float_fresnel fresnelD = @insertpiece( getDiffuseFresnel ); + @else + float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); + @end + + //We should divide Rd by PI, but it is already included in kD + float3 Rd = (lightScatter * viewScatter * energyFactor * fresnelD) * pixelData.diffuse.xyz * lightDiffuse; + + return NdotL * (Rs + Rd); +} +@end +@end + +@property( hlms_enable_vpls ) +@piece( DeclareBRDF_InstantRadiosity ) +//Simplified cheap BRDF for Instant Radiosity. +float3 BRDF_IR( float3 lightDir, float3 lightDiffuse, PixelData pixelData ) +{ + float NdotL = clamp( dot( pixelData.normal, lightDir ), 0.0, 1.0 ); + float_fresnel fresnelD = @insertpiece( getDiffuseFresnel ); + + //We should divide Rd by PI, but it is already included in kD + return NdotL * fresnelD * pixelData.diffuse.xyz * lightDiffuse; +} +@end +@end + +/// Applying Fresnel term to prefiltered cubemap has a bad effect of always showing high specular +/// color at edge, even for rough surface. See https://seblagarde.wordpress.com/2011/08/17/hello-world/ +/// and see http://www.ogre3d.org/forums/viewtopic.php?f=25&p=523550#p523544 +/// "The same Fresnel term which is appropriate for unfiltered environment maps (i.e. perfectly smooth +/// mirror surfaces) is not appropriate for filtered environment maps since there you are averaging +/// incoming light colors from many directions, but using a single Fresnel value computed for the +/// reflection direction. The correct function has similar values as the regular Fresnel expression +/// at v=n, but at glancing angle it behaves differently. In particular, the lerp(from base specular +/// to white) does not go all the way to white at glancing angles in the case of rough surfaces." +/// So we use getSpecularFresnelWithRoughness instead. +@piece( BRDF_EnvMap ) + //Normally we'd use VdotH. However: + // H = normalize(lightDir + viewDir) + //since: + // lightDir = pixelData.reflDir + //then: + // H = geomNormal + //Thus H = N, and therefore we use VdotN (NdotV) + //float VdotH = saturate( dot( pixelData.viewDir, normalize( pixelData.reflDir + pixelData.viewDir ) ) ); + float_fresnel fresnelS = @insertpiece( getSpecularFresnelWithRoughness ); + + @property( ltc_texture_available ) + #define brdfLUT ltcMatrix + float2 envBRDF = OGRE_SampleArray2D( brdfLUT, ltcSampler, + float2( pixelData.NdotV, + 1.0 - pixelData.perceptualRoughness ), 2 ).xy; + @else + float2 envBRDF = float2( 1.0f, 0.0f ); + @end + + @property( fresnel_separate_diffuse ) + float NdotL = saturate( dot( pixelData.normal, pixelData.reflDir ) ); + float_fresnel fresnelD = @insertpiece( getDiffuseFresnelWithRoughness ); + @else + float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); + @end + + finalColour += pixelData.envColourD * pixelData.diffuse.xyz * fresnelD + + pixelData.envColourS * pixelData.specular.xyz * ( fresnelS * envBRDF.x + envBRDF.y ); +@end + +@property( hlms_fine_light_mask || hlms_forwardplus_fine_light_mask ) + @property( syntax == metal ) + @piece( DeclareObjLightMask )uint objLightMask = inPs.objLightMask;@end + @else + @piece( DeclareObjLightMask )uint objLightMask = worldMaterialIdx[inPs.drawId].z;@end + @end +@end + +@property( hlms_fine_light_mask ) + @property( syntax != hlsl ) + @piece( ObjLightMaskCmp )if( (objLightMask & floatBitsToUint( light0Buf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u )@end + @property( hlms_static_branch_lights ) + @piece( ObjLightMaskCmpNonCasterLoop )if( (objLightMask & floatBitsToUint( light0Buf.lights[@value(fineMaskLightIdx) + i].position.w )) != 0u )@end + @piece( ObjLightMaskCmpNonCasterLoopEnd )@add( fineMaskLightIdx, hlms_lights_directional_non_caster )@end + @end + @piece( andObjLightMaskCmp )&& ((objLightMask & floatBitsToUint( light0Buf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u)@end + @piece( andObjAreaApproxLightMaskCmp )&& ((objLightMask & floatBitsToUint( light1Buf.areaApproxLights[i].position.w )) != 0u)@end + @piece( andObjAreaLtcLightMaskCmp )&& ((objLightMask & floatBitsToUint( light2Buf.areaLtcLights[i].position.w )) != 0u)@end + @else + @piece( ObjLightMaskCmp )if( (objLightMask & light0Buf.lights[@counter(fineMaskLightIdx)].lightMask) != 0u )@end + @property( hlms_static_branch_lights ) + @piece( ObjLightMaskCmpNonCasterLoop )if( (objLightMask & light0Buf.lights[@value(fineMaskLightIdx) + i].lightMask) != 0u )@end + @piece( ObjLightMaskCmpNonCasterLoopEnd )@add( fineMaskLightIdx, hlms_lights_directional_non_caster )@end + @end + @piece( andObjLightMaskCmp )&& ((objLightMask & light0Buf.lights[@counter(fineMaskLightIdx)].lightMask) != 0u)@end + @piece( andObjAreaApproxLightMaskCmp )&& ((objLightMask & light1Buf.areaApproxLights[i].lightMask) != 0u)@end + @piece( andObjAreaLtcLightMaskCmp )&& ((objLightMask & light2Buf.areaLtcLights[i].lightMask) != 0u)@end + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/200.BlendModes_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Main/200.BlendModes_piece_ps.any new file mode 100644 index 000000000..e5f133807 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/200.BlendModes_piece_ps.any @@ -0,0 +1,108 @@ + +//#include "SyntaxHighlightingMisc.h" + +//Reset t to 0 just in case (values are preserved from previous stages) +@pset( t, 0 ) + +@property( !hlms_shadowcaster ) +@piece( NormalNonPremul ) + //Normal Non Premultiplied @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, detailCol@value(t).xyz, detailCol@value(t).a ); + pixelData.diffuse.w = lerp( pixelData.diffuse.w, 1.0, detailCol@value(t).w ); +@end + +@piece( NormalPremul ) + //Normal Premultiplied @value(t) + pixelData.diffuse.xyz = (1.0 - detailCol@value(t).a) * pixelData.diffuse.xyz + detailCol@value(t).xyz; + pixelData.diffuse.w = lerp( pixelData.diffuse.w, 1.0, detailCol@value(t).w ); +@end + +@piece( Add ) + //Add @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + min( pixelData.diffuse.xyz + detailCol@value(t).xyz, float3(1.0, 1.0, 1.0) ), + detailCol@value(t).a ); +@end + +@piece( Subtract ) + //Subtract @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + max( pixelData.diffuse.xyz - detailCol@value(t).xyz, float3(0.0, 0.0, 0.0) ), + detailCol@value(t).a ); +@end + +@piece( Multiply ) + //Multiply @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + pixelData.diffuse.xyz * detailCol@value(t).xyz, + detailCol@value(t).a ); +@end + +@piece( Multiply2x ) + //Multiply2x @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + min( pixelData.diffuse.xyz * detailCol@value(t).xyz * 2.0, float3(1.0, 1.0, 1.0) ), + detailCol@value(t).a ); +@end + +@piece( Screen ) + //Screen @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + 1.0 - (1.0 - pixelData.diffuse.xyz) * (1.0 - detailCol@value(t).xyz), + detailCol@value(t).a ); +@end + +@piece( Overlay ) + //Overlay @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + pixelData.diffuse.xyz * ( pixelData.diffuse.xyz + 2.0 * detailCol@value(t).xyz * (1.0 - pixelData.diffuse.xyz) ), + detailCol@value(t).a ); +@end + +@piece( Lighten ) + //Lighten @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + max( pixelData.diffuse.xyz, detailCol@value(t).xyz ), + detailCol@value(t).a ); +@end + +@piece( Darken ) + //Darken @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + min( pixelData.diffuse.xyz, detailCol@value(t).xyz ), + detailCol@value(t).a ); +@end + +@piece( GrainExtract ) + //GrainExtract @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + (pixelData.diffuse.xyz - detailCol@value(t).xyz) + 0.5f, + detailCol@value(t).a ); +@end + +@piece( GrainMerge ) + //GrainMerge @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + (pixelData.diffuse.xyz + detailCol@value(t).xyz) - 0.5f, + detailCol@value(t).a ); +@end + +@piece( Difference ) + //Difference @value(t) + pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, + abs(pixelData.diffuse.xyz - detailCol@value(t).xyz), + detailCol@value(t).a ); +@end +@else + +@piece( NormalNonPremul ) + //Normal Non Premultiplied @value(t) + pixelData.diffuse = lerp( pixelData.diffuse, float4( 1.0, 1.0, 1.0,1.0 ), detailCol@value(t) ); +@end + +@piece( NormalPremul ) + //Normal Premultiplied @value(t) + pixelData.diffuse = lerp( pixelData.diffuse, float4( 1.0, 1.0, 1.0,1.0 ), detailCol@value(t) ); +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/DetailMaps_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/Any/Main/200.DetailMaps_piece_ps.any similarity index 100% rename from ogre2/src/media/Hlms/Pbs/GLSL/DetailMaps_piece_ps.glsl rename to ogre2/src/media/Hlms/Pbs/Any/Main/200.DetailMaps_piece_ps.any diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/200.ForwardPlus_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Main/200.ForwardPlus_piece_ps.any new file mode 100644 index 000000000..f067a0646 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/200.ForwardPlus_piece_ps.any @@ -0,0 +1,273 @@ + +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( hlms_forwardplus ) + +@property( hlms_forwardplus_fine_light_mask ) + @piece( andObjLightMaskFwdPlusCmp )&& ((objLightMask & floatBitsToUint( lightDiffuse.w )) != 0u)@end +@end + +/// The header is automatically inserted. Whichever subsystem needs it first, will call it +@piece( forward3dHeader ) + @property( hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v) + #define FWDPLUS_APPLY_OFFSET_X(v) (v) + @end + + @property( hlms_instanced_stereo ) + float2 fwdFragCoord = inPs.cullCamPosXY.xy * (1.0f / inPs.cullCamPosXY.z); + fwdFragCoord.xy = fwdFragCoord.xy * 0.5f + 0.5f; + @else + #define fwdFragCoord gl_FragCoord + @end + + @property( hlms_forwardplus == forward3d ) + float f3dMinDistance = passBuf.f3dData.x; + float f3dInvMaxDistance = passBuf.f3dData.y; + float f3dNumSlicesSub1 = passBuf.f3dData.z; + uint cellsPerTableOnGrid0= floatBitsToUint( passBuf.f3dData.w ); + + // See C++'s Forward3D::getSliceAtDepth + /*float fSlice = 1.0 - saturate( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance ); + fSlice = (fSlice * fSlice) * (fSlice * fSlice); + fSlice = (fSlice * fSlice); + fSlice = floor( (1.0 - fSlice) * f3dNumSlicesSub1 );*/ + float fSlice = saturate( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance ); + fSlice = floor( fSlice * f3dNumSlicesSub1 ); + uint slice = uint( fSlice ); + + //TODO: Profile performance: derive this mathematically or use a lookup table? + uint offset = cellsPerTableOnGrid0 * (((1u << (slice << 1u)) - 1u) / 3u); + + float lightsPerCell = passBuf.f3dGridHWW[0].w; + + @property( !hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.f3dViewportOffset.y) + #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.f3dViewportOffset.x) + @end + + //passBuf.f3dGridHWW[slice].x = grid_width / renderTarget->width; + //passBuf.f3dGridHWW[slice].y = grid_height / renderTarget->height; + //passBuf.f3dGridHWW[slice].z = grid_width * lightsPerCell; + //uint sampleOffset = 0; + @property( hlms_forwardplus_flipY || syntax != glsl ) + float windowHeight = passBuf.f3dGridHWW[1].w; //renderTarget->height + uint sampleOffset = offset + + uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(fwdFragCoord.y) ) * + passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + + uint(floor( FWDPLUS_APPLY_OFFSET_X(fwdFragCoord.x) * + passBuf.f3dGridHWW[slice].x ) * lightsPerCell); + @else + uint sampleOffset = offset + + uint(floor( FWDPLUS_APPLY_OFFSET_Y(fwdFragCoord.y) * + passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + + uint(floor( FWDPLUS_APPLY_OFFSET_X(fwdFragCoord.x) * + passBuf.f3dGridHWW[slice].x ) * lightsPerCell); + @end + @end @property( hlms_forwardplus != forward3d ) + float f3dMinDistance = passBuf.f3dData.x; + float f3dInvExponentK = passBuf.f3dData.y; + float f3dNumSlicesSub1 = passBuf.f3dData.z; + + // See C++'s ForwardClustered::getSliceAtDepth + float fSlice = log2( max( -inPs.pos.z - f3dMinDistance, 1.0 ) ) * f3dInvExponentK; + fSlice = floor( min( fSlice, f3dNumSlicesSub1 ) ); + uint sliceSkip = uint( fSlice * @value( fwd_clustered_width_x_height ) ); + + @property( !hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.fwdScreenToGrid.w) + #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.fwdScreenToGrid.z) + @end + + uint sampleOffset = sliceSkip + + uint(floor( FWDPLUS_APPLY_OFFSET_X(fwdFragCoord.x) * passBuf.fwdScreenToGrid.x )); + @property( hlms_forwardplus_flipY || syntax != glsl ) + float windowHeight = passBuf.f3dData.w; //renderTarget->height + sampleOffset += uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(fwdFragCoord.y) ) * + passBuf.fwdScreenToGrid.y ) * + @value( fwd_clustered_width )); + @else + sampleOffset += uint(floor( FWDPLUS_APPLY_OFFSET_Y(fwdFragCoord.y) * + passBuf.fwdScreenToGrid.y ) * + @value( fwd_clustered_width )); + @end + + sampleOffset *= @value( fwd_clustered_lights_per_cell )u; + @end + + @property( hlms_forwardplus_debug )ushort totalNumLightsInGrid = 0u;@end +@end + +@piece( forward3dLighting ) + @property( !hlms_enable_decals ) + @insertpiece( forward3dHeader ) + ushort numLightsInGrid; + @end + + @property( hlms_decals_emissive ) + finalColour += finalDecalEmissive; + @end + + numLightsInGrid = bufferFetch1( f3dGrid, int(sampleOffset) ); + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + for( ushort i=0u; i= spotParams.y ) + { + float3 tmpColour = BRDF( lightDir, lightDiffuse.xyz, lightSpecular, pixelData ); + finalColour += tmpColour * atten; + } + } + } + +@property( hlms_enable_vpls ) + prevLightCount = numLightsInGrid; + numLightsInGrid = bufferFetch1( f3dGrid, int(sampleOffset + 2u) ); + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + for( ushort i=prevLightCount; i ltcMatrix : register(t@value(ltcMatrix)); + SamplerState ltcSampler : register(s@value(ltcMatrix)); + @end + @property( syntax == metal ) + , texture2d_array ltcMatrix [[texture(@value(ltcMatrix))]] + , sampler ltcSampler [[sampler(@value(ltcMatrix))]] + @end + @end +@end + +@property( envmap_scale ) + @piece( ApplyEnvMapScale )* passBuf.ambientUpperHemi.w@end +@end + +@property( use_envprobe_map ) + @property( !envprobe_map || envprobe_map == target_envprobe_map ) + /// "No cubemap"? Then we're in auto mode or... + /// We're rendering to the cubemap probe we're using as manual. Use the auto mode as fallback. + @piece( pccProbeSource )passBuf.autoProbe@end + @end + @property( envprobe_map && envprobe_map != target_envprobe_map && use_parallax_correct_cubemaps ) + @piece( pccProbeSource )manualProbe@end + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/500.Structs_piece_vs_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Main/500.Structs_piece_vs_piece_ps.any new file mode 100644 index 000000000..1ec8b9bb7 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/500.Structs_piece_vs_piece_ps.any @@ -0,0 +1,439 @@ +@piece( PassStructDecl ) +struct ShadowReceiverData +{ + float4x4 texViewProj; +@property( exponential_shadow_maps ) + float4 texViewZRow; +@end + float2 shadowDepthRange; + float2 padding; + float4 invShadowMapSize; +}; + +struct Light +{ + @property( syntax != hlsl ) + float4 position; //.w contains the objLightMask + @else + float3 position; + uint lightMask; + @end + float4 diffuse; //.w contains numNonCasterDirectionalLights + float3 specular; +@property( hlms_num_shadow_map_lights ) + float3 attenuation; + //Spotlights: + // spotDirection.xyz is direction + // spotParams.xyz contains falloff params + float4 spotDirection; + float4 spotParams; +@end + +#define lightTexProfileIdx spotDirection.w +}; + +#define numNonCasterDirectionalLights lights[0].diffuse.w + +#define areaLightDiffuseMipmapStart areaApproxLights[0].diffuse.w +#define areaLightNumMipmapsSpecFactor areaApproxLights[0].specular.w + +#define numAreaApproxLights areaApproxLights[0].doubleSided.y +#define numAreaApproxLightsWithMask areaApproxLights[0].doubleSided.z + +#define numAreaLtcLights areaLtcLights[0].points[0].w +#define numAreaLtcLights areaLtcLights[0].points[0].w + +struct AreaLight +{ + @property( syntax != hlsl ) + float4 position; //.w contains the objLightMask + @else + float3 position; + uint lightMask; + @end + float4 diffuse; //[0].w contains diffuse mipmap start + float4 specular; //[0].w contains mipmap scale + float4 attenuation; //.w contains texture array idx + //Custom 2D Shape: + // direction.xyz direction + // direction.w invHalfRectSize.x + // tangent.xyz tangent + // tangent.w invHalfRectSize.y + float4 direction; + float4 tangent; + float4 doubleSided; //.y contains numAreaApproxLights + //.z contains numAreaApproxLightsWithMask + @property( obb_restraint_approx ) + float4 obbFadeFactorApprox; //.w unused + float4 obbRestraint[3]; + @end +}; + +struct AreaLtcLight +{ + @property( syntax != hlsl ) + float4 position; //.w contains the objLightMask + @else + float3 position; + uint lightMask; + @end + float4 diffuse; //.w contains attenuation range + float4 specular; //.w contains doubleSided + float4 points[4]; //.w contains numAreaLtcLights + //points[1].w, points[2].w, points[3].w contain obbFadeFactorLtc.xyz + @property( obb_restraint_ltc ) + float4 obbRestraint[3]; + @end +}; + +@insertpiece( DeclCubemapProbeStruct ) +@insertpiece( DeclVctStruct ) +@insertpiece( DeclIrradianceFieldStruct ) + +//Uniforms that change per pass +CONST_BUFFER_STRUCT_BEGIN( PassBuffer, 0 ) +{ + //Vertex shader (common to both receiver and casters) +@property( !hlms_instanced_stereo ) + float4x4 viewProj; +@else + float4x4 viewProj[2]; + @property( hlms_forwardplus ) + float4x4 leftEyeViewSpaceToCullCamClipSpace; + @end + float4 leftToRightView; +@end + +@property( hlms_global_clip_planes ) + float4 clipPlane0; +@end + +@property( hlms_shadowcaster_point ) + float4 cameraPosWS; //Camera position in world space +@end + +@property( !hlms_shadowcaster ) + //Vertex shader + float4x4 view; + @property( hlms_num_shadow_map_lights )ShadowReceiverData shadowRcv[@value(hlms_num_shadow_map_lights)];@end + + @property( hlms_use_uv_baking ) + float4 pixelOffset2x; //.zw are unused. + @end + + //------------------------------------------------------------------------- + + //Pixel shader + float3x3 invViewMatCubemap; +@property( syntax == hlsl ) + float padding; //Compatibility with GLSL +@end + + float4 pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps; + + float4 aspectRatio_planarReflNumMips_unused2; + + float2 invWindowRes; + float2 windowResolution; + +@property( ambient_hemisphere || ambient_fixed || envmap_scale || vct_ambient_hemisphere ) + float4 ambientUpperHemi; +@end +@property( ambient_hemisphere || vct_ambient_hemisphere ) + float4 ambientLowerHemi; + float4 ambientHemisphereDir; +@end + +@property( ambient_sh ) + @property( ambient_sh_monochrome ) + float4 sh0; + float4 sh1; + float4 sh2; // sh2.yzw are unused + @else + @foreach( 7, n ) + float4 sh@n;@end + @end +@end + +@property( irradiance_volumes ) + float4 irradianceOrigin; //.w = maxPower + float4 irradianceSize; //.w = 1.0f / irradianceTexture->getHeight() + float4x4 invView; +@end + +@property( hlms_pssm_splits )@psub( hlms_pssm_splits_minus_one, hlms_pssm_splits, 1 )@foreach( hlms_pssm_splits, n ) + float pssmSplitPoints@n;@end @end +@property( hlms_pssm_blend )@foreach( hlms_pssm_splits_minus_one, n ) + float pssmBlendPoints@n;@end @end +@property( hlms_pssm_fade ) + float pssmFadePoint;@end + +@property( !use_light_buffers ) + @property( hlms_lights_spot )Light lights[@value(hlms_lights_spot)];@end + @property( hlms_lights_area_approx )AreaLight areaApproxLights[@value(hlms_lights_area_approx)];@end + @property( hlms_lights_area_ltc )AreaLtcLight areaLtcLights[@value(hlms_lights_area_ltc)];@end +@end // !use_light_buffers + +@end @property( hlms_shadowcaster ) + //Vertex shader + @property( exponential_shadow_maps )float4 viewZRow;@end + float2 depthRange; +@end + +@property( hlms_forwardplus ) + //Forward3D + //f3dData.x = minDistance; + //f3dData.y = invMaxDistance; + //f3dData.z = f3dNumSlicesSub1; + //f3dData.w = uint cellsPerTableOnGrid0 (floatBitsToUint); + + //Clustered Forward: + //f3dData.x = minDistance; + //f3dData.y = invExponentK; + //f3dData.z = f3dNumSlicesSub1; + //f3dData.w = renderWindow->getHeight(); + float4 f3dData; + @property( hlms_forwardplus == forward3d ) + float4 f3dGridHWW[@value( forward3d_num_slices )]; + float4 f3dViewportOffset; + @end + @property( hlms_forwardplus != forward3d ) + float4 fwdScreenToGrid; + @end +@end + + @insertpiece( DeclPlanarReflUniforms ) + +@property( parallax_correct_cubemaps && !hlms_enable_cubemaps_auto ) + CubemapProbe autoProbe; +@end + + @insertpiece( DeclVctUniform ) + @insertpiece( DeclIrradianceFieldUniform ) + + @insertpiece( custom_passBuffer ) + +#define pccVctMinDistance pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.x +#define invPccVctInvDistance pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.y +#define rightEyePixelStartX pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.z +#define envMapNumMipmaps pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.w + +#define aspectRatio aspectRatio_planarReflNumMips_unused2.x +#define planarReflNumMips aspectRatio_planarReflNumMips_unused2.y +} +CONST_BUFFER_STRUCT_END( passBuf ); + +@property( use_light_buffers ) + +CONST_BUFFER_STRUCT_BEGIN( Light0Buffer, 4 ) +{ + Light lights[16]; +} +CONST_BUFFER_STRUCT_END( light0Buf ); + +CONST_BUFFER_STRUCT_BEGIN( Light1Buffer, 5 ) +{ + AreaLight areaApproxLights[2]; +} +CONST_BUFFER_STRUCT_END( light1Buf ); + +CONST_BUFFER_STRUCT_BEGIN( Light2Buffer, 6 ) +{ + AreaLtcLight areaLtcLights[2]; +} +CONST_BUFFER_STRUCT_END( light2Buf ); + + +@else + +#define light0Buf passBuf +#define light1Buf passBuf +#define light2Buf passBuf + +@end // use_light_buffers + +@end + +@property( syntax == metal ) + @piece( PassDecl ) + , constant PassBuffer &passBuf [[buffer(CONST_SLOT_START+0)]] + @property( use_light_buffers ) + , constant Light0Buffer &light0Buf [[buffer(CONST_SLOT_START+4)]] + , constant Light1Buffer &light1Buf [[buffer(CONST_SLOT_START+5)]] + , constant Light2Buffer &light2Buf [[buffer(CONST_SLOT_START+6)]] + @end // use_light_buffers + @end +@end + +@property( fresnel_scalar ) + @piece( FresnelSwizzle )xyz@end +@else + @piece( FresnelSwizzle )x@end +@end + +@piece( MaterialStructDecl ) +//Uniforms that change per Item/Entity, but change very infrequently +struct Material +{ + /* kD is already divided by PI to make it energy conserving. + (formula is finalDiffuse = NdotL * surfaceDiffuse / PI) + */ + float4 bgDiffuse; + float4 kD; //kD.w is alpha_test_threshold + float4 kS; //kS.w is roughness + //Fresnel coefficient, may be per colour component (float3) or scalar (float) + //F0.w is transparency + float4 F0; + float4 normalWeights; + float4 cDetailWeights; + float4 detailOffsetScale[4]; + float4 emissive; //emissive.w contains mNormalMapWeight. + float refractionStrength; + float _padding10; + float _padding11; + float _padding12; + float4 userValue[3]; + + @property( syntax != metal ) + uint4 indices0_3; + uint4 indices4_7; + @else + ushort diffuseIdx; + ushort normalIdx; + ushort specularIdx; + ushort roughnessIdx; + ushort weightMapIdx; + ushort detailMapIdx0; + ushort detailMapIdx1; + ushort detailMapIdx2; + + ushort detailMapIdx3; + ushort detailNormMapIdx0; + ushort detailNormMapIdx1; + ushort detailNormMapIdx2; + + ushort detailNormMapIdx3; + ushort emissiveMapIdx; + ushort envMapIdx; + @end + + @insertpiece( custom_materialBuffer ) +}; + @property( normal_weight_tex )#define normalMapWeight material.emissive.w@end + + @property( syntax != metal ) + CONST_BUFFER( MaterialBuf, 1 ) + { + Material materialArray[@value( materials_per_buffer )]; + }; + @end +@end + +@property( syntax == metal ) + @piece( MaterialDecl ) + , constant Material *materialArray [[buffer(CONST_SLOT_START+1)]] + @end +@end + +@property( syntax != metal ) + @piece( InstanceStructDecl ) + //Uniforms that change per Item/Entity + CONST_BUFFER( InstanceBuffer, 2 ) + { + //.x = + //The lower 9 bits contain the material's start index. + //The higher 23 bits contain the world matrix start index. + // + //.y = + //shadowConstantBias. Send the bias directly to avoid an + //unnecessary indirection during the shadow mapping pass. + //Must be loaded with uintBitsToFloat + // + //.z = + //lightMask. Ogre must have been compiled with OGRE_NO_FINE_LIGHT_MASK_GRANULARITY + @property( fast_shader_build_hack ) + uint4 worldMaterialIdx[2]; + @else + uint4 worldMaterialIdx[4096]; + @end + }; + @end +@else + @piece( InstanceDecl ) + , constant uint4 *worldMaterialIdx [[buffer(CONST_SLOT_START+2)]] + @end +@end + +@property( envprobe_map && envprobe_map != target_envprobe_map && use_parallax_correct_cubemaps && !hlms_enable_cubemaps_auto ) +@piece( PccManualProbeDecl ) + @property( syntax != metal ) + CONST_BUFFER( ManualProbe, 3 ) + { + CubemapProbe manualProbe; + }; + @else + , constant CubemapProbe &manualProbe [[buffer(CONST_SLOT_START+3)]] + @end +@end +@end + +//Reset texcoord to 0 for every shader stage (since values are preserved). +@pset( texcoord, 0 ) + +@piece( VStoPS_block ) + @property( syntax == metal ) + @property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) + ushort materialId [[flat]]; + @end + @property( hlms_fine_light_mask || hlms_forwardplus_fine_light_mask ) + uint objLightMask [[flat]]; + @end + @property( use_planar_reflections ) + ushort planarReflectionIdx [[flat]]; + @end + @else + @property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) + FLAT_INTERPOLANT( ushort drawId, @counter(texcoord) ); + @end + @end + + @property( !hlms_shadowcaster ) + @property( hlms_normal || hlms_qtangent ) + INTERPOLANT( float3 pos, @counter(texcoord) ); + INTERPOLANT( float3 normal, @counter(texcoord) ); + @property( normal_map ) + INTERPOLANT( float3 tangent, @counter(texcoord) ); + @property( hlms_qtangent )FLAT_INTERPOLANT( float biNormalReflection, @counter(texcoord) );@end + @end + @end + @foreach( hlms_uv_count, n ) + INTERPOLANT( float@value( hlms_uv_count@n ) uv@n, @counter(texcoord) );@end + + @foreach( hlms_num_shadow_map_lights, n ) + @property( !hlms_shadowmap@n_is_point_light ) + INTERPOLANT( float4 posL@n, @counter(texcoord) );@end @end + @property( hlms_pssm_splits )INTERPOLANT( float depth, @counter(texcoord) );@end + @property( hlms_use_prepass_msaa > 1 ) + INTERPOLANT( float2 zwDepth, @counter(texcoord) ); + @end + + @property( hlms_forwardplus && hlms_instanced_stereo ) + INTERPOLANT( float3 cullCamPosXY, @counter(texcoord) ); + @end + @else + @property( alpha_test ) + @foreach( hlms_uv_count, n ) + INTERPOLANT( float@value( hlms_uv_count@n ) uv@n, @counter(texcoord) );@end + @end + @property( (!hlms_shadow_uses_depth_texture || exponential_shadow_maps) && !hlms_shadowcaster_point ) + INTERPOLANT( float depth, @counter(texcoord) ); + @end + @property( hlms_shadowcaster_point ) + INTERPOLANT( float3 toCameraWS, @counter(texcoord) ); + @property( !exponential_shadow_maps ) + FLAT_INTERPOLANT( float constBias, @counter(texcoord) ); + @end + @end + @end + @insertpiece( custom_VStoPS ) +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/800.PixelShader_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Main/800.PixelShader_piece_ps.any new file mode 100644 index 000000000..068e4518c --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/800.PixelShader_piece_ps.any @@ -0,0 +1,809 @@ +@piece( envSpecularRoughness ) pixelData.perceptualRoughness * passBuf.envMapNumMipmaps @end + +@piece( DefaultHeaderPS ) + @property( !fresnel_scalar ) + #define float_fresnel float + #define make_float_fresnel( x ) x + @else + #define float_fresnel float3 + #define make_float_fresnel( x ) float3( x, x, x ) + @end + + @insertpiece( DeclReverseDepthMacros ) + + @property( syntax == metal ) + #define PASSBUF_ARG_DECL , constant PassBuffer &passBuf + #define PASSBUF_ARG , passBuf + @else + #define PASSBUF_ARG_DECL + #define PASSBUF_ARG + @end + + @property( hlms_enable_cubemaps_auto ) + @insertpiece( UnpackHelpers ) + @end + + struct PixelData + { + @property( !hlms_shadowcaster ) + float3 normal; + @property( normal_map ) + float3 geomNormal; + @else + #define geomNormal normal + @end + float4 diffuse; + float3 specular; + float perceptualRoughness; + float roughness; + float_fresnel F0; + + @property( needs_view_dir ) + float3 viewDir; + float NdotV; + @end + + @property( needs_refl_dir ) + float3 reflDir; + @property( needs_env_brdf ) + float3 envColourS; + float3 envColourD; + @end + @end + @else + float4 diffuse; //We only use the .w component, Alpha + @end + }; + + #define SampleDetailWeightMap( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) + @foreach( detail_maps_diffuse, n ) + @property( detail_map@n )#define SampleDetailCol@n( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx )@end + @end + @property( diffuse_map ) + #define SampleDiffuse( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) @property( diffuse_map_grayscale ).rrra@end + @end + @property( specular_map ) + #define SampleSpecular( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) + @end + @property( roughness_map ) + #define SampleRoughness( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) + @end + @property( emissive_map ) + #define SampleEmissive( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) + @end + @property( use_envprobe_map ) + #define SampleEnvProbe( tex, sampler, uv, lod ) OGRE_SampleLevel( tex, sampler, uv, lod ) + @end + + @property( hlms_lights_spot_textured ) + @insertpiece( DeclQuat_zAxis ) + INLINE float3 qmul( float4 q, float3 v ) + { + return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz ); + } + @end + + @property( normal_map_tex || detail_maps_normal ) + INLINE float3 reconstructZfromTSNormal( float2 tsNormal2 ) + { + float3 tsNormal; + tsNormal.xy = tsNormal2.xy; + tsNormal.z = sqrt( max( 0.0f, 1.0f - tsNormal.x * tsNormal.x - tsNormal.y * tsNormal.y ) ); + return tsNormal.xyz; + } + + @property( normal_sampling_format == normal_rg_snorm ) + //Normal texture must be in UV8/RG8_SNORM or BC5S format! + #define getTSNormal( normalMap, samplerState, uv, normalIdx ) reconstructZfromTSNormal( OGRE_SampleArray2D( normalMap, samplerState, uv, normalIdx ).xy ) + @end + @property( normal_sampling_format == normal_rg_unorm ) + //Normal texture must be in RG8_UNORM or similar format! + #define getTSNormal( normalMap, samplerState, uv, normalIdx ) reconstructZfromTSNormal( OGRE_SampleArray2D( normalMap, samplerState, uv, normalIdx ).xy * 2.0 - 1.0 ) + @end + @property( normal_sampling_format == normal_bc3_unorm ) + //Normal texture must be in BC3 or similar format! + #define getTSNormal( normalMap, samplerState, uv, normalIdx ) reconstructZfromTSNormal( OGRE_SampleArray2D( normalMap, samplerState, uv, normalIdx ).yw * 2.0 - 1.0 ) + @end + @property( normal_sampling_format == normal_la ) + //Normal texture must be in LA format! + #define getTSNormal( normalMap, samplerState, uv, normalIdx ) reconstructZfromTSNormal( OGRE_SampleArray2D( normalMap, samplerState, uv, normalIdx ).xw * 2.0 - 1.0 ) + @end + @end + + @property( obb_restraint_approx || obb_restraint_ltc ) + /// Returns value in range [-inf; 1] + /// Values <= 0 means 'pos' is outside the obb + float getObbRestraintFade( @property( syntax == metal )constant@end float4 obbRestraint[3], + float3 pos, float3 obbFadeFactors ) + { + float3 obbDistToBounds; + obbDistToBounds.x = dot( obbRestraint[0].xyzw, float4( pos.xyz, 1.0 ) ); + obbDistToBounds.y = dot( obbRestraint[1].xyzw, float4( pos.xyz, 1.0 ) ); + obbDistToBounds.z = dot( obbRestraint[2].xyzw, float4( pos.xyz, 1.0 ) ); + //Until this point, obbDistToBounds in range [-1;1] means we're inside the OBB. + obbDistToBounds = abs( obbDistToBounds ); + + float3 obbFade = (1.0 - obbDistToBounds) * obbFadeFactors; + return min( min3( obbFade.x, obbFade.y, obbFade.z ), 1.0 ); + } + @end + + @property( (hlms_normal || hlms_qtangent) && !hlms_prepass && needs_view_dir ) + @insertpiece( DeclareBRDF ) + @insertpiece( DeclareBRDF_InstantRadiosity ) + @insertpiece( DeclareBRDF_AreaLightApprox ) + @end + + @insertpiece( DeclVctFuncs ) + @insertpiece( DeclIrradianceFieldFuncs ) + @insertpiece( DeclRefractionsFuncs ) + @insertpiece( DeclIrradianceSH ) + @insertpiece( DeclLightProfilesTextureFuncs ) +@end + + +//----------------------------------------------------------------------------- +// BODY CODE +//----------------------------------------------------------------------------- + +@piece( LoadMaterial ) + @property( !lower_gpu_overhead ) + @property( syntax != metal ) + ushort materialId = worldMaterialIdx[inPs.drawId].x & 0x1FFu; + #define material materialArray[materialId] + @else + #define material materialArray[inPs.materialId] + @end + @else + #define material materialArray[0] + @end +@end + +@piece( UnpackTextureIndices0 ) + @property( syntax == metal ) + @property( diffuse_map ) ushort texIndex_diffuseIdx = material.diffuseIdx;@end + @property( detail_weight_map ) ushort texIndex_weightMapIdx = material.weightMapIdx;@end + @property( detail_map0 ) ushort texIndex_detailMapIdx0 = material.detailMapIdx0;@end + @property( detail_map1 ) ushort texIndex_detailMapIdx1 = material.detailMapIdx1;@end + @property( detail_map2 ) ushort texIndex_detailMapIdx2 = material.detailMapIdx2;@end + @property( detail_map3 ) ushort texIndex_detailMapIdx3 = material.detailMapIdx3;@end + @else + @property( diffuse_map ) ushort texIndex_diffuseIdx = material.indices0_3.x & 0x0000FFFFu;@end + @property( detail_weight_map ) ushort texIndex_weightMapIdx = material.indices0_3.z & 0x0000FFFFu;@end + @property( detail_map0 ) ushort texIndex_detailMapIdx0 = material.indices0_3.z >> 16u;@end + @property( detail_map1 ) ushort texIndex_detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;@end + @property( detail_map2 ) ushort texIndex_detailMapIdx2 = material.indices0_3.w >> 16u;;@end + @property( detail_map3 ) ushort texIndex_detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;@end + @end +@end +@piece( UnpackTextureIndices1 ) + @property( syntax == metal ) + @property( normal_map_tex ) ushort texIndex_normalIdx = material.normalIdx;@end + @property( specular_map ) ushort texIndex_specularIdx = material.specularIdx;@end + @property( roughness_map ) ushort texIndex_roughnessIdx = material.roughnessIdx;@end + @property( detail_map_nm0 ) ushort texIndex_detailNormMapIdx0 = material.detailNormMapIdx0;@end + @property( detail_map_nm1 ) ushort texIndex_detailNormMapIdx1 = material.detailNormMapIdx1;@end + @property( detail_map_nm2 ) ushort texIndex_detailNormMapIdx2 = material.detailNormMapIdx2;@end + @property( detail_map_nm3 ) ushort texIndex_detailNormMapIdx3 = material.detailNormMapIdx3;@end + @property( emissive_map ) ushort texIndex_emissiveMapIdx = material.emissiveMapIdx;@end + @property( use_envprobe_map ) ushort texIndex_envMapIdx = material.envMapIdx;@end + @else + @property( normal_map_tex ) ushort texIndex_normalIdx = material.indices0_3.x >> 16u;@end + @property( specular_map ) ushort texIndex_specularIdx = material.indices0_3.y & 0x0000FFFFu;@end + @property( roughness_map ) ushort texIndex_roughnessIdx = material.indices0_3.y >> 16u;@end + @property( detail_map_nm0 ) ushort texIndex_detailNormMapIdx0 = material.indices4_7.x >> 16u;@end + @property( detail_map_nm1 ) ushort texIndex_detailNormMapIdx1 = material.indices4_7.y & 0x0000FFFFu;@end + @property( detail_map_nm2 ) ushort texIndex_detailNormMapIdx2 = material.indices4_7.y >> 16u;@end + @property( detail_map_nm3 ) ushort texIndex_detailNormMapIdx3 = material.indices4_7.z & 0x0000FFFFu;@end + @property( emissive_map ) ushort texIndex_emissiveMapIdx = material.indices4_7.z >> 16u;@end + @property( use_envprobe_map ) ushort texIndex_envMapIdx = material.indices4_7.w & 0x0000FFFFu;@end + @end +@end + +@piece( LoadDetailWeights ) + @property( detail_maps_diffuse || detail_maps_normal ) + //Prepare weight map for the detail maps. + @property( detail_weight_map ) + float4 detailWeights = SampleDetailWeightMap( textureMaps@value(detail_weight_map_idx), + samplerState@value(detail_weight_map_sampler), + UV_DETAIL_WEIGHT( inPs.uv@value(uv_detail_weight).xy ), + texIndex_weightMapIdx ); + @property( detail_weights )detailWeights *= material.cDetailWeights;@end + @else + @property( detail_weights ) + float4 detailWeights = material.cDetailWeights; + @else + float4 detailWeights = float4( 1.0, 1.0, 1.0, 1.0 ); + @end + @end + @end +@end + +@piece( SampleDetailMaps ) + /// Sample detail maps and weight them against the weight map in the next foreach loop. + @foreach( detail_maps_diffuse, n ) + @property( detail_map@n ) + float4 detailCol@n = SampleDetailCol@n( textureMaps@value(detail_map@n_idx), + samplerState@value(detail_map@n_sampler), + UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), + texIndex_detailMapIdx@n ); + detailWeights.@insertpiece(detail_swizzle@n) *= detailCol@n.w; + detailCol@n.w = detailWeights.@insertpiece(detail_swizzle@n); + @end + @end +@end + +@piece( SampleDiffuseMap ) + /// DIFFUSE MAP + @property( diffuse_map ) + pixelData.diffuse = SampleDiffuse( textureMaps@value( diffuse_map_idx ), + samplerState@value(diffuse_map_sampler), + UV_DIFFUSE( inPs.uv@value(uv_diffuse).xy ), + texIndex_diffuseIdx ); + @else + /// If there are no diffuse maps, we must initialize it to some value. + pixelData.diffuse.xyzw = material.bgDiffuse.xyzw; + @end + + /// Blend the detail diffuse maps with the main diffuse. + @foreach( detail_maps_diffuse, n ) + @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end + + /// Apply the material's diffuse over the textures + pixelData.diffuse.xyz *= material.kD.xyz; + @property( transparent_mode || hlms_screen_space_refractions ) + pixelData.diffuse.xyz *= (pixelData.diffuse.w * pixelData.diffuse.w); + @end + + @property( alpha_test && (!alpha_test_shadow_caster_only || hlms_shadowcaster) ) + if( material.kD.w @insertpiece( alpha_test_cmp_func ) pixelData.diffuse.w ) + discard; + @end +@end + +@piece( SampleSpecularMap ) + /// SPECUlAR MAP + pixelData.specular.xyz = material.kS.xyz; + @property( !metallic_workflow ) + pixelData.F0 = material.F0.@insertpiece( FresnelSwizzle ); + @property( specular_map && !fresnel_workflow ) + pixelData.specular.xyz *= SampleSpecular( textureMaps@value( specular_map_idx ), + samplerState@value(specular_map_sampler), + UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + texIndex_specularIdx ).xyz; + @end + @property( specular_map && fresnel_workflow ) + pixelData.F0 *= SampleSpecular( textureMaps@value( specular_map_idx ), + samplerState@value(specular_map_sampler), + UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + texIndex_specularIdx ).@insertpiece( FresnelSwizzle ); + @end + @else + float metalness = material.F0.x; + @property( specular_map ) + metalness *= SampleSpecular( textureMaps@value( specular_map_idx ), + samplerState@value(specular_map_sampler), + UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + texIndex_specularIdx ).x; + @end + pixelData.F0 = lerp( make_float_fresnel( 0.03f ), pixelData.diffuse.xyz * 3.14159f, metalness ); + pixelData.diffuse.xyz = pixelData.diffuse.xyz - pixelData.diffuse.xyz * metalness; + @property( hlms_alphablend || hlms_screen_space_refractions ) + pixelData.F0 *= material.F0.w; ///Should this be done for non-metallic as well??? + @end + @end + @property( transparent_mode || hlms_screen_space_refractions ) + pixelData.F0 *= pixelData.diffuse.w; + @end +@end + +@piece( SampleRoughnessMap ) + /// ROUGHNESS MAP + pixelData.perceptualRoughness = material.kS.w; + @property( roughness_map ) + pixelData.perceptualRoughness *= + SampleRoughness( textureMaps@value( roughness_map_idx ), + samplerState@value( roughness_map_sampler ), + UV_ROUGHNESS( inPs.uv@value(uv_roughness).xy ), + texIndex_roughnessIdx ).x; + @end + @property( perceptual_roughness ) + pixelData.roughness = max( pixelData.perceptualRoughness * pixelData.perceptualRoughness, 0.001f ); + @else + pixelData.roughness = max( pixelData.perceptualRoughness, 0.001f ); + @end +@end + +@property( two_sided_lighting ) + @property( hlms_forwardplus_flipY ) + @piece( two_sided_flip_normal )* (gl_FrontFacing ? -1.0 : 1.0)@end + @else + @piece( two_sided_flip_normal )* (gl_FrontFacing ? 1.0 : -1.0)@end + @end +@end +@piece( LoadNormalData ) + @property( !normal_map ) + // Geometric normal + pixelData.normal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); + @else + //Normal mapping. + pixelData.geomNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); + float3 vTangent = normalize( inPs.tangent ); + + @property( hlms_qtangent ) + @piece( tbnApplyReflection ) * inPs.biNormalReflection@end + @end + + //Get the TBN matrix + float3 vBinormal = normalize( cross( pixelData.geomNormal, vTangent )@insertpiece( tbnApplyReflection ) ); + float3x3 TBN = buildFloat3x3( vTangent, vBinormal, pixelData.geomNormal ); + + @property( normal_map_tex ) + pixelData.normal = getTSNormal( textureMaps@value( normal_map_tex_idx ), + samplerState@value( normal_map_tex_sampler ), + UV_NORMAL( inPs.uv@value(uv_normal).xy ), + texIndex_normalIdx ); + @else + pixelData.normal = float3( 0.0, 0.0, 1.0 ); + @end + @property( normal_weight_tex ) + // Apply the weight to the main normal map + pixelData.normal = lerp( float3( 0.0, 0.0, 1.0 ), pixelData.normal, normalMapWeight ); + @end + @end +@end + +@piece( SampleAndApplyDetailNormalMaps ) + /// If there is no normal map, the first iteration must + /// initialize pixelData.normal instead of try to merge with it. + @property( normal_map_tex ) + @piece( detail_nm_op_sum )+=@end + @piece( detail_nm_op_mul )*=@end + @else + @piece( detail_nm_op_sum )=@end + @piece( detail_nm_op_mul )=@end + @end + + @property( detail_maps_normal ) + @foreach( 4, n ) + @property( normal_weight_detail@n ) + @piece( detail@n_nm_weight_mul ) * material.normalWeights.@insertpiece( detail_swizzle@n )@end + @end + @end + @end + + @foreach( detail_maps_normal, n ) + @piece( SampleDetailMapNm@n )getTSNormal( textureMaps@value(detail_map_nm@n_idx), + samplerState@value(detail_map_nm@n_sampler), + UV_DETAIL_NM@n( inPs.uv@value(uv_detail_nm@n).xy@insertpiece( offsetDetail@n ) ), + texIndex_detailNormMapIdx@n ) * detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul )@end + @end + + /// Blend the detail normal maps with the main normal. + @foreach( second_valid_detail_map_nm, n, first_valid_detail_map_nm ) + float3 vDetail = @insertpiece( SampleDetailMapNm@n ); + pixelData.normal.xy @insertpiece( detail_nm_op_sum ) vDetail.xy; + pixelData.normal.z @insertpiece( detail_nm_op_mul ) vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul ); + @end + @foreach( detail_maps_normal, n, second_valid_detail_map_nm ) + @property( detail_map_nm@n ) + vDetail = @insertpiece( SampleDetailMapNm@n ); + pixelData.normal.xy += vDetail.xy; + pixelData.normal.z *= vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul ); + @end + @end +@end + +@piece( LightingHeader ) + //Everything's in Camera space + @property( needs_view_dir ) + @property( !hlms_instanced_stereo ) + pixelData.viewDir = normalize( -inPs.pos ); + @else + pixelData.viewDir = -inPs.pos; + if( gl_FragCoord.x > passBuf.rightEyePixelStartX ) + pixelData.viewDir += passBuf.leftToRightView.xyz; + pixelData.viewDir = normalize( pixelData.viewDir ); + @end + pixelData.NdotV = saturate( dot( pixelData.normal, pixelData.viewDir ) ); + @end + + @property( !ambient_fixed || vct_num_probes ) + float3 finalColour = float3(0, 0, 0); + @else + float3 finalColour = passBuf.ambientUpperHemi.xyz * pixelData.diffuse.xyz; + @end + + @property( hlms_lights_point || hlms_lights_spot || hlms_lights_area_approx || hlms_lights_area_ltc ) + float3 lightDir; + float fDistance; + float3 tmpColour; + float spotCosAngle; + @end + @property( needs_refl_dir ) + pixelData.reflDir = 2.0 * dot( pixelData.viewDir, pixelData.normal ) * pixelData.normal - pixelData.viewDir; + @end + + @insertpiece( DoAmbientHeader ) +@end + +@piece( DoDirectionalLights ) + @property( hlms_lights_directional ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( light0Buf.lights[0].position.xyz, light0Buf.lights[0].diffuse.xyz, light0Buf.lights[0].specular, pixelData ) @insertpiece( DarkenWithShadowFirstLight ); + @end + @foreach( hlms_lights_directional, n, 1 ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( light0Buf.lights[@n].position.xyz, light0Buf.lights[@n].diffuse.xyz, light0Buf.lights[@n].specular, pixelData )@insertpiece( DarkenWithShadow );@end + + @property( !hlms_static_branch_lights ) + @foreach( hlms_lights_directional_non_caster, n, hlms_lights_directional ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( light0Buf.lights[@n].position.xyz, light0Buf.lights[@n].diffuse.xyz, light0Buf.lights[@n].specular, pixelData );@end + @else + for( int n=0; n= light0Buf.lights[@n].spotParams.y @insertpiece( andObjLightMaskCmp ) ) + { + @property( hlms_lights_spot_textured ) + float3 posInLightSpace = qmul( spotQuaternion[@value(spot_params)], inPs.pos ); + float spotAtten = texture( texSpotLight, normalize( posInLightSpace ).xy ).x; //TODO + @else + float spotAtten = saturate( (spotCosAngle - light0Buf.lights[@n].spotParams.y) * light0Buf.lights[@n].spotParams.x ); + spotAtten = pow( spotAtten, light0Buf.lights[@n].spotParams.z ); + @end + + @property( light_profiles_texture ) + spotAtten *= getPhotometricAttenuation( spotCosAngle, + light0Buf.lights[@n].lightTexProfileIdx + OGRE_PHOTOMETRIC_ARG ); + @end + + tmpColour = BRDF( lightDir, light0Buf.lights[@n].diffuse.xyz, light0Buf.lights[@n].specular, pixelData )@insertpiece( DarkenWithShadow ); + float atten = 1.0 / (0.5 + (light0Buf.lights[@n].attenuation.y + light0Buf.lights[@n].attenuation.z * fDistance) * fDistance ); + finalColour += tmpColour * (atten * spotAtten); + } + @end +@end + +@piece( DoEmissiveLight ) + @property( emissive_map || emissive_constant ) + ///Emissive is not part of PixelData because emissive can just be accumulated to finalColour + @property( emissive_map ) + float3 emissiveCol = SampleEmissive( textureMaps@value( emissive_map_idx ), + samplerState@value(emissive_map_sampler), + UV_EMISSIVE( inPs.uv@value(uv_emissive).xy ), + texIndex_emissiveMapIdx ).xyz; + @property( emissive_constant ) + emissiveCol *= material.emissive.xyz; + @end + @property( emissive_as_lightmap ) + emissiveCol *= pixelData.diffuse.xyz; + @end + finalColour += emissiveCol; + @else + finalColour += material.emissive.xyz; + @end + @end +@end + +@piece( CubemapManualPcc ) + float3 posInProbSpace = toProbeLocalSpace( inPs.pos, @insertpiece( pccProbeSource ) ); + float probeFade = getProbeFade( posInProbSpace, @insertpiece( pccProbeSource ) ); +@property( vct_num_probes ) + if( probeFade > 0 && (pixelData.roughness < 1.0f || vctSpecular.w == 0) ) +@else + if( probeFade > 0 ) +@end + { + probeFade = saturate( probeFade * 200.0 ); + @property( vct_num_probes ) + float4 reflDirLS_dist = localCorrect( pixelData.reflDir, posInProbSpace, @insertpiece( pccProbeSource ) ); + float3 reflDirLS = reflDirLS_dist.xyz; + @else + float3 reflDirLS = localCorrect( pixelData.reflDir, posInProbSpace, @insertpiece( pccProbeSource ) ).xyz; + @end + float3 nNormalLS = localCorrect( pixelData.normal, posInProbSpace, @insertpiece( pccProbeSource ) ).xyz; + float4 envS = SampleEnvProbe( texEnvProbeMap, samplerState@value(envMapRegSampler), + reflDirLS, @insertpiece( envSpecularRoughness ) ); + @property( envmap_scale ) + envS.xyz *= passBuf.ambientUpperHemi.w; + @end + @property( cubemaps_as_diffuse_gi ) + float3 envD = SampleEnvProbe( texEnvProbeMap, samplerState@value(envMapRegSampler), + nNormalLS, 11.0 ).xyz @insertpiece( ApplyEnvMapScale ); + envD.xyz *= probeFade; + @end + + envS.xyz *= probeFade; + + @property( vct_num_probes ) + float vctLerp = getPccVctBlendWeight( inPs.pos, pixelData.reflDir, reflDirLS_dist.w, + pixelData.roughness, + @insertpiece( pccProbeSource ).cubemapPosVS.xyz, + vctSpecPosVS, vctSpecular.w, + passBuf.pccVctMinDistance, + passBuf.invPccVctInvDistance, + envS.w ); + + pixelData.envColourS = lerp( envS.xyz, pixelData.envColourS, vctLerp ); + @property( cubemaps_as_diffuse_gi ) + pixelData.envColourD += vctSpecular.w > 0 ? float3( 0, 0, 0 ) : envD; + @end + @else + pixelData.envColourS += envS.xyz; + @property( cubemaps_as_diffuse_gi ) + pixelData.envColourD += envD; + @end + @end + } +@end + +@piece( CubemapGlobal ) + pixelData.envColourS += SampleEnvProbe( texEnvProbeMap, samplerState@value(envMapRegSampler), + mul( pixelData.reflDir, passBuf.invViewMatCubemap ), + @insertpiece( envSpecularRoughness ) ).xyz @insertpiece( ApplyEnvMapScale ); + @property( cubemaps_as_diffuse_gi ) + pixelData.envColourD += SampleEnvProbe( texEnvProbeMap, samplerState@value(envMapRegSampler), + mul( pixelData.normal, passBuf.invViewMatCubemap ), + 11.0 ).xyz @insertpiece( ApplyEnvMapScale ); + @end +@end + +@property( !hlms_shadowcaster ) +@piece( DefaultBodyPS ) + @property( hlms_screen_pos_uv ) + float2 screenPosUv = gl_FragCoord.xy * passBuf.invWindowRes.xy; + @end + @property( hlms_screen_pos_int ) + rshort2 iFragCoord = + rshort2( gl_FragCoord.x, + @property( !hlms_forwardplus_flipY && syntax == glsl )passBuf.windowResolution.y - @end + gl_FragCoord.y ); + @end + + @property( hlms_normal || hlms_qtangent ) + PixelData pixelData; + + @insertpiece( LoadMaterial ) + @insertpiece( UnpackTextureIndices0 ) + @insertpiece( UnpackTextureIndices1 ) + @insertpiece( DeclareObjLightMask ) + @insertpiece( custom_ps_posMaterialLoad ) + + @insertpiece( LoadDetailWeights ) + + @insertpiece( SampleDetailMaps ) + + @property( !hlms_prepass || alpha_test ) + @insertpiece( SampleDiffuseMap ) + @end + + @insertpiece( SampleSpecularMap ) + @insertpiece( SampleRoughnessMap ) + +@property( hlms_bake_lighting_only ) + pixelData.diffuse.xyz = float3( 1.0f, 1.0f, 1.0f ); + pixelData.specular.xyz = float3( 0.0f, 0.0f, 0.0f ); +@end + + @insertpiece( forwardPlusDoDecals ) + + @property( !hlms_use_prepass ) + @insertpiece( LoadNormalData ) + @insertpiece( SampleAndApplyDetailNormalMaps ) + + @insertpiece( custom_ps_posSampleNormal ) + + @insertpiece( forwardPlusApplyDecalsNormal ) + + @property( normal_map ) + pixelData.normal = normalize( mul( TBN, pixelData.normal ) ); + @end + + @insertpiece( DoDirectionalShadowMaps ) + + @end @property( hlms_use_prepass ) + @property( hlms_use_prepass_msaa ) + //SV_Coverage/gl_SampleMaskIn is always before depth & stencil tests, + //so we need to perform the test ourselves + //See http://www.yosoygames.com.ar/wp/2017/02/beware-of-sv_coverage/ + uint sampleMask = uint( gl_SampleMaskIn0 ); + float msaaDepth; + uint subsampleDepthMask; + float pixelDepthZ; + float pixelDepthW; + float2 pixelDepthZW; + float pixelDepth; + int intPixelDepth; + int intMsaaDepth; + //Unfortunately there are precision errors, so we allow some ulp errors. + //200 & 5 are arbitrary, but were empirically found to be very good values. + int ulpError = int( lerp( 200.0, 5.0, gl_FragCoord.z ) ); + @foreach( hlms_use_prepass_msaa, n ) + pixelDepthZW = interpolateAtSample( inPs.zwDepth, @n ); + pixelDepthZ = pixelDepthZW.x; + pixelDepthW = pixelDepthZW.y; + pixelDepth = pixelDepthZ / pixelDepthW; + msaaDepth = OGRE_Load2DMS( gBuf_depthTexture, iFragCoord.xy, @n ).x; + intPixelDepth = floatBitsToInt( pixelDepth ); + intMsaaDepth = floatBitsToInt( msaaDepth ); + subsampleDepthMask = (abs( intPixelDepth - intMsaaDepth ) <= ulpError) ? 0xffffffffu : ~(1u << @nu); + //subsampleDepthMask = int( (pixelDepth <= msaaDepth) ? 0xffffffffu : ~(1u << @nu) ); + sampleMask &= subsampleDepthMask; + @end + + sampleMask = sampleMask == 0u ? 1u : sampleMask; + + int gBufSubsample = int( findLSB( sampleMask ) ); + + pixelData.normal = normalize( OGRE_Load2DMS( gBuf_normals, iFragCoord, gBufSubsample ).xyz * 2.0 - 1.0 ); + float2 shadowRoughness = OGRE_Load2DMS( gBuf_shadowRoughness, iFragCoord, gBufSubsample ).xy; + @else + pixelData.normal = normalize( OGRE_Load2D( gBuf_normals, iFragCoord, 0 ).xyz * 2.0 - 1.0 ); + float2 shadowRoughness = OGRE_Load2D( gBuf_shadowRoughness, iFragCoord, 0 ).xy; + @end + + float fShadow = shadowRoughness.x; + + @property( roughness_map ) + pixelData.roughness = shadowRoughness.y * 0.98 + 0.02; + @end + @end + + @property( !hlms_prepass ) + @insertpiece( LightingHeader ) + + @insertpiece( custom_ps_preLights ) + + @property( !custom_disable_directional_lights ) + @insertpiece( DoDirectionalLights ) + @end + + @insertpiece( DoPointLights ) + @insertpiece( DoSpotLights ) + + @insertpiece( DoAreaApproxLights ) + @insertpiece( DoAreaLtcLights ) + + @insertpiece( forward3dLighting ) + + @property( needs_env_brdf ) + pixelData.envColourS = float3( 0, 0, 0 ); + pixelData.envColourD = float3( 0, 0, 0 ); + @end + + @insertpiece( applyVoxelConeTracing ) + @insertpiece( applyIrradianceField ) + + @insertpiece( forwardPlusDoCubemaps ) + @insertpiece( applyIrradianceVolumes ) + + @insertpiece( DoEmissiveLight ) + + @property( use_envprobe_map ) + @property( use_parallax_correct_cubemaps && !hlms_enable_cubemaps_auto ) + @insertpiece( CubemapManualPcc ) + @end @property( !use_parallax_correct_cubemaps ) + @insertpiece( CubemapGlobal ) + @end + @end + + @property( hlms_use_ssr ) + //TODO: SSR pass should be able to combine global & local cubemap. + float4 ssrReflection = OGRE_Load2D( ssrTexture, iFragCoord, 0 ).xyzw; + @property( use_envprobe_map ) + pixelData.envColourS = lerp( pixelData.envColourS.xyz, ssrReflection.xyz, ssrReflection.w ); + @else + pixelData.envColourS += ssrReflection.xyz * ssrReflection.w; + @end + @end + + @insertpiece( DoPlanarReflectionsPS ) + + @insertpiece( DoAmbientLighting ) + + @property( needs_env_brdf ) + @insertpiece( BRDF_EnvMap ) + @end + + @insertpiece( applyRefractions ) + @end ///!hlms_prepass + + @end ///!hlms_normal || hlms_qtangent + + @property( !hlms_render_depth_only ) + @property( !hlms_prepass ) + @property( hlms_normal || hlms_qtangent ) + @property( !hw_gamma_write ) + //Linear to Gamma space + outPs_colour0.xyz = sqrt( finalColour ); + @else + outPs_colour0.xyz = finalColour; + @end + + @property( hlms_alphablend ) + @property( use_texture_alpha ) + outPs_colour0.w = material.F0.w * pixelData.diffuse.w; + @else + outPs_colour0.w = material.F0.w; + @end + @else + outPs_colour0.w = 1.0; + @end + + @property( debug_pssm_splits ) + outPs_colour0.xyz = mix( outPs_colour0.xyz, debugPssmSplit.xyz, 0.2f ); + @end + @property( hlms_gen_normals_gbuffer ) + outPs_normals = float4( pixelData.normal * 0.5 + 0.5, 1.0 ); + @end + @else + outPs_colour0 = float4( 1.0, 1.0, 1.0, 1.0 ); + @property( hlms_gen_normals_gbuffer ) + outPs_normals = float4( 0.5, 0.5, 1.0, 1.0 ); + @end + @end + @else + outPs_normals = float4( pixelData.normal * 0.5 + 0.5, 1.0 ); + @property( hlms_pssm_splits ) + outPs_shadowRoughness = float2( fShadow, (pixelData.roughness - 0.02) * 1.02040816 ); + @end @property( !hlms_pssm_splits ) + outPs_shadowRoughness = float2( 1.0, (pixelData.roughness - 0.02) * 1.02040816 ); + @end + @end + @end +@end ///DefaultBodyPS +@else ///!hlms_shadowcaster + +@piece( DefaultBodyPS ) + @property( alpha_test ) + PixelData pixelData; + @insertpiece( LoadMaterial ) + @insertpiece( UnpackTextureIndices0 ) + @insertpiece( LoadDetailWeights ) + @insertpiece( SampleDetailMaps ) + @insertpiece( SampleDiffuseMap ) + @end + @insertpiece( DoShadowCastPS ) +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Main/800.VertexShader_piece_vs.any b/ogre2/src/media/Hlms/Pbs/Any/Main/800.VertexShader_piece_vs.any new file mode 100644 index 000000000..64c144fd0 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Main/800.VertexShader_piece_vs.any @@ -0,0 +1,288 @@ + +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@piece( DefaultHeaderVS ) + @property( hlms_skeleton ) + #define worldViewMat passBuf.view + @else + #define worldViewMat worldView + @end + + @insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) + @insertpiece( Common_Matrix_DeclUnpackMatrix4x3 ) + + // START UNIFORM DECLARATION + @insertpiece( PassStructDecl ) + @property( hlms_skeleton || hlms_shadowcaster || hlms_pose )@insertpiece( InstanceStructDecl )@end + @insertpiece( custom_vs_uniformStructDeclaration ) + // END UNIFORM DECLARATION + + @property( hlms_qtangent ) + @insertpiece( DeclQuat_xAxis ) + @property( normal_map ) + @insertpiece( DeclQuat_yAxis ) + @end + @end +@end + +@property( !hlms_skeleton ) + @piece( local_vertex )inputPos@end + @piece( local_normal )inputNormal@end + @piece( local_tangent )tangent@end +@else + @piece( local_vertex )worldPos@end + @piece( local_normal )worldNorm@end + @piece( local_tangent )worldTang@end +@end + +@property( hlms_skeleton ) +@piece( SkeletonTransform ) + uint _idx = (inVs_blendIndices[0] << 1u) + inVs_blendIndices[0]; //inVs_blendIndices[0] * 3u; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) + uint matStart = worldMaterialIdx[inVs_drawId].x >> 9u; + float4 worldMat[3]; + worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); + worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); + worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); + float4 worldPos; + worldPos.x = dot( worldMat[0], inputPos ); + worldPos.y = dot( worldMat[1], inputPos ); + worldPos.z = dot( worldMat[2], inputPos ); + worldPos.xyz *= inVs_blendWeights[0]; + @property( hlms_normal || hlms_qtangent ) + float3 worldNorm; + worldNorm.x = dot( worldMat[0].xyz, inputNormal ); + worldNorm.y = dot( worldMat[1].xyz, inputNormal ); + worldNorm.z = dot( worldMat[2].xyz, inputNormal ); + worldNorm *= inVs_blendWeights[0]; + @end + @property( normal_map ) + float3 worldTang; + worldTang.x = dot( worldMat[0].xyz, tangent ); + worldTang.y = dot( worldMat[1].xyz, tangent ); + worldTang.z = dot( worldMat[2].xyz, tangent ); + worldTang *= inVs_blendWeights[0]; + @end + + @psub( NeedsMoreThan1BonePerVertex, hlms_bones_per_vertex, 1 ) + @property( NeedsMoreThan1BonePerVertex ) + float4 tmp; + tmp.w = 1.0; + @end //!NeedsMoreThan1BonePerVertex + @foreach( hlms_bones_per_vertex, n, 1 ) + _idx = (inVs_blendIndices[@n] << 1u) + inVs_blendIndices[@n]; //inVs_blendIndices[@n] * 3; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) + worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); + worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); + worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); + tmp.x = dot( worldMat[0], inputPos ); + tmp.y = dot( worldMat[1], inputPos ); + tmp.z = dot( worldMat[2], inputPos ); + worldPos.xyz += (tmp * inVs_blendWeights[@n]).xyz; + @property( hlms_normal || hlms_qtangent ) + tmp.x = dot( worldMat[0].xyz, inputNormal ); + tmp.y = dot( worldMat[1].xyz, inputNormal ); + tmp.z = dot( worldMat[2].xyz, inputNormal ); + worldNorm += tmp.xyz * inVs_blendWeights[@n]; + @end + @property( normal_map ) + tmp.x = dot( worldMat[0].xyz, tangent ); + tmp.y = dot( worldMat[1].xyz, tangent ); + tmp.z = dot( worldMat[2].xyz, tangent ); + worldTang += tmp.xyz * inVs_blendWeights[@n]; + @end + @end + + worldPos.w = 1.0; +@end // SkeletonTransform +@end // !hlms_skeleton + +@property( hlms_pose ) +@piece( PoseTransform ) + // Pose data starts after all 3x4 bone matrices + uint poseDataStart = (worldMaterialIdx[inVs_drawId].x >> 9u) @property( hlms_skeleton ) + @value(hlms_bones_per_vertex)u * 3u@end ; + float4 inputPos = inVs_vertex; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) )float3 inputNormal = normal;@end + + float4 poseData = bufferFetch( worldMatBuf, int( poseDataStart ) ); + + @property( syntax != hlsl ) + @property( syntax != metal ) + uint baseVertexID = floatBitsToUint( poseData.x ); + @end + uint vertexID = uint( inVs_vertexId )- baseVertexID; + @else + uint vertexID = inVs_vertexId; + @end + + @psub( MoreThanOnePose, hlms_pose, 1 ) + @property( !MoreThanOnePose ) + float4 poseWeights = bufferFetch( worldMatBuf, int(poseDataStart + 1u) ); + float4 posePos = bufferFetch( poseBuf, int( vertexID @property( hlms_pose_normals )<< 1u@end ) ); + inputPos += posePos * poseWeights.x; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + float4 poseNormal = bufferFetch( poseBuf, int( (vertexID << 1u) + 1u ) ); + inputNormal += poseNormal.xyz * poseWeights.x; + @end + @pset( NumPoseWeightVectors, 1 ) + @else + // NumPoseWeightVectors = (hlms_pose / 4) + min(hlms_pose % 4, 1) + @pdiv( NumPoseWeightVectorsA, hlms_pose, 4 ) + @pmod( NumPoseWeightVectorsB, hlms_pose, 4 ) + @pmin( NumPoseWeightVectorsC, NumPoseWeightVectorsB, 1 ) + @padd( NumPoseWeightVectors, NumPoseWeightVectorsA, NumPoseWeightVectorsC ) + uint numVertices = floatBitsToUint( poseData.y ); + + @psub( MoreThanOnePoseWeightVector, NumPoseWeightVectors, 1 ) + @property( !MoreThanOnePoseWeightVector ) + float4 poseWeights = bufferFetch( worldMatBuf, int( poseDataStart + 1u ) ); + @foreach( hlms_pose, n ) + inputPos += bufferFetch( poseBuf, int( (vertexID + numVertices * @nu) @property( hlms_pose_normals )<< 1u@end ) ) * poseWeights[@n]; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + inputNormal += bufferFetch( poseBuf, int( ((vertexID + numVertices * @nu) << 1u) + 1u ) ).xyz * poseWeights[@n]; + @end + @end + @else + float poseWeights[@value(NumPoseWeightVectors) * 4]; + @foreach( NumPoseWeightVectors, n) + float4 weights@n = bufferFetch( worldMatBuf, int( poseDataStart + 1u + @nu ) ); + poseWeights[@n * 4 + 0] = weights@n[0]; + poseWeights[@n * 4 + 1] = weights@n[1]; + poseWeights[@n * 4 + 2] = weights@n[2]; + poseWeights[@n * 4 + 3] = weights@n[3]; + @end + @foreach( hlms_pose, n ) + inputPos += bufferFetch( poseBuf, int( (vertexID + numVertices * @nu) @property( hlms_pose_normals )<< 1u@end ) ) * poseWeights[@n]; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + inputNormal += bufferFetch( poseBuf, int( ((vertexID + numVertices * @nu) << 1u) + 1u ) ).xyz * poseWeights[@nu]; + @end + @end + @end + @end + + // If hlms_skeleton is defined the transforms will be provided by bones. + // If hlms_pose is not combined with hlms_skeleton the object's worldMat and worldView have to be set. + @property( !hlms_skeleton ) + float4 worldMat[3]; + worldMat[0] = bufferFetch( worldMatBuf, int( poseDataStart + @value(NumPoseWeightVectors)u + 1u ) ); + worldMat[1] = bufferFetch( worldMatBuf, int( poseDataStart + @value(NumPoseWeightVectors)u + 2u ) ); + worldMat[2] = bufferFetch( worldMatBuf, int( poseDataStart + @value(NumPoseWeightVectors)u + 3u ) ); + float4 worldPos; + worldPos.x = dot( worldMat[0], inputPos ); + worldPos.y = dot( worldMat[1], inputPos ); + worldPos.z = dot( worldMat[2], inputPos ); + worldPos.w = 1.0; + + @property( hlms_normal || hlms_qtangent ) + @foreach( 4, n ) + float4 row@n = bufferFetch( worldMatBuf, int( poseDataStart + @value(NumPoseWeightVectors)u + 4u + @nu ) ); + @end + float4x4 worldView = float4x4( row0, row1, row2, row3 ); + @property( syntax == hlsl ) + worldView = transpose( worldView ); + @end + @end + @end +@end // PoseTransform +@end // hlms_pose + +@piece( CalculatePsPos )mul( @insertpiece(local_vertex), worldViewMat ).xyz@end + +@piece( VertexTransform ) + @insertpiece( custom_vs_preTransform ) + //Lighting is in view space + @property( hlms_normal || hlms_qtangent ) outVs.pos = @insertpiece( CalculatePsPos );@end + @property( hlms_normal || hlms_qtangent ) outVs.normal = mul( @insertpiece(local_normal), toFloat3x3( worldViewMat ) );@end + @property( normal_map ) outVs.tangent = mul( @insertpiece(local_tangent), toFloat3x3( worldViewMat ) );@end + @property( !hlms_dual_paraboloid_mapping ) + @property( !hlms_use_uv_baking ) + @property( !hlms_instanced_stereo ) + outVs_Position = mul( worldPos, passBuf.viewProj ); + @else + outVs_Position = mul( worldPos, passBuf.viewProj[(inVs_stereoDrawId & 0x01u)] ); + @property( hlms_forwardplus ) + outVs.cullCamPosXY.xyz = mul( float4( outVs.pos.xyz, 1.0f ), + passBuf.leftEyeViewSpaceToCullCamClipSpace ).xyw; + @end + @end + @else + outVs_Position.xy = inVs_uv@value( hlms_uv_baking ).xy * 2.0f - 1.0f + passBuf.pixelOffset2x.xy; + @property( !hlms_forwardplus_flipY || syntax != glsl ) + outVs_Position.y = -outVs_Position.y; + @end + outVs_Position.zw = float2( 0.0f, 1.0f ); + @end + @else + //Dual Paraboloid Mapping + outVs_Position.w = 1.0f; + @property( hlms_normal || hlms_qtangent )outVs_Position.xyz = outVs.pos;@end + @property( !hlms_normal && !hlms_qtangent )outVs_Position.xyz = @insertpiece( CalculatePsPos );@end + float L = length( outVs_Position.xyz ); + outVs_Position.z += 1.0f; + outVs_Position.xy /= outVs_Position.z; + outVs_Position.z = (L - NearPlane) / (FarPlane - NearPlane); + @end +@end + +@piece( DefaultBodyVS ) + @property( !hlms_pose )#define inputPos inVs_vertex@end + //This newline is required else the Hlms parser will put '#define a #define b' in the same line + @property( !hlms_pose_normals )#define inputNormal normal@end + + @property( !hlms_skeleton && !hlms_pose ) + ogre_float4x3 worldMat = UNPACK_MAT4x3( worldMatBuf, inVs_drawId @property( !hlms_shadowcaster )<< 1u@end ); + @property( hlms_normal || hlms_qtangent ) + float4x4 worldView = UNPACK_MAT4( worldMatBuf, (inVs_drawId << 1u) + 1u ); + @end + + float4 worldPos = float4( mul(inVs_vertex, worldMat).xyz, 1.0f ); + @end + + @property( hlms_qtangent ) + //Decode qTangent to TBN with reflection + float3 normal = xAxis( normalize( inVs_qtangent ) ); + @property( normal_map ) + float3 tangent = yAxis( inVs_qtangent ); + outVs.biNormalReflection = sign( inVs_qtangent.w ); //We ensure in C++ qtangent.w is never 0 + @end + @end + + @insertpiece( PoseTransform ) + @insertpiece( SkeletonTransform ) + @insertpiece( VertexTransform ) + + @insertpiece( DoShadowReceiveVS ) + @insertpiece( DoShadowCasterVS ) + + /// hlms_uv_count will be 0 on shadow caster passes w/out alpha test + @foreach( hlms_uv_count, n ) + outVs.uv@n = inVs_uv@n;@end + +@property( syntax != metal ) + @property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) + outVs.drawId = inVs_drawId; + @end +@else + @property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) + outVs.materialId = worldMaterialIdx[inVs_drawId].x & 0x1FFu; + @end + + @property( hlms_fine_light_mask || hlms_forwardplus_fine_light_mask ) + outVs.objLightMask = worldMaterialIdx[inVs_drawId].z; + @end + + @property( use_planar_reflections ) + outVs.planarReflectionIdx = (ushort)(worldMaterialIdx[inVs_drawId].w); + @end +@end + + @property( hlms_use_prepass_msaa > 1 ) + outVs.zwDepth.xy = outVs_Position.zw; + @end + + @property( hlms_global_clip_planes ) + outVs_clipDistance0 = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); + @end + + @property( hlms_instanced_stereo ) + outVs_viewportIndex = int( inVs_stereoDrawId & 0x01u ); + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_all.any b/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_all.any index de83f524e..0429814ce 100644 --- a/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_all.any +++ b/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_all.any @@ -1,10 +1,6 @@ //#include "SyntaxHighlightingMisc.h" -@property( !has_planar_reflections ) - @set( use_planar_reflections, 0 ) -@end - @property( has_planar_reflections ) @piece( DeclPlanarReflUniforms ) diff --git a/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_ps.any index c575ccf36..c6c3966f9 100644 --- a/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_ps.any +++ b/ogre2/src/media/Hlms/Pbs/Any/PlanarReflections_piece_ps.any @@ -3,43 +3,40 @@ @property( use_planar_reflections ) -@property( syntax == glsl ) +@property( syntax == glsl || syntax == glsles ) @piece( DeclPlanarReflTextures ) uniform sampler2D planarReflectionTex; @end @end @property( syntax == hlsl ) @piece( DeclPlanarReflTextures ) - Texture2D planarReflectionTex : register(t@value(planarReflectionTexUnit)); - SamplerState planarReflectionSampler : register(s@value(planarReflectionTexUnit)); + Texture2D planarReflectionTex : register(t@value(planarReflectionTex)); + SamplerState planarReflectionSampler : register(s@value(planarReflectionTex)); @end @end @property( syntax == metal ) @piece( DeclPlanarReflTextures ) - , texture2d planarReflectionTex [[texture(@value(planarReflectionTexUnit))]] - , sampler planarReflectionSampler [[sampler(@value(planarReflectionTexUnit))]] + , texture2d planarReflectionTex [[texture(@value(planarReflectionTex))]] + , sampler planarReflectionSampler [[sampler(@value(planarReflectionTex))]] @end @end @piece( DoPlanarReflectionsPS ) - @property( syntax == glsl ) - uint planarReflectionIdx = instance.worldMaterialIdx[inPs.drawId].w; - @end - @property( syntax == hlsl ) + @property( syntax != metal ) uint planarReflectionIdx = worldMaterialIdx[inPs.drawId].w; - @end - @property( syntax == metal ) + @else ushort planarReflectionIdx = inPs.planarReflectionIdx; @end float4 planarReflection = passBuf.planarReflections[planarReflectionIdx]; float distanceToPlanarReflPlane = dot( planarReflection.xyz, inPs.pos.xyz ) + planarReflection.w; - float3 pointInPlane = inPs.pos.xyz - nNormal * distanceToPlanarReflPlane; + float3 pointInPlane = inPs.pos.xyz - pixelData.normal * distanceToPlanarReflPlane; float3 projPointInPlane = mul( float4( pointInPlane.xyz, 1.0 ), passBuf.planarReflProjectionMat ).xyw; float2 planarReflUVs = projPointInPlane.xy / projPointInPlane.z; float3 planarReflectionS = OGRE_SampleLevel( planarReflectionTex, planarReflectionSampler, - planarReflUVs.xy, ROUGHNESS * 12.0 ).xyz; + planarReflUVs.xy, + pixelData.perceptualRoughness * passBuf.planarReflNumMips ).xyz; //Fade out as our surface gets away from the reflection plane (planarWeight = 0 means fully faded out) float planarWeight = max( 1.0 - abs( distanceToPlanarReflPlane ) * passBuf.invMaxDistanceToPlanarRefl.x, 0.0 ); @@ -55,12 +52,11 @@ // (x - cos20) / (1-cos20); // x/(1-cos20) - cos20/(1-cos20); // x * 16.581718739 - 15.581718739; - planarWeight *= saturate( dot( planarReflection.xyz, nNormal.xyz ) * 16.581718739 - 15.581718739 ); - @property( hlms_use_ssr || ((envprobe_map && envprobe_map != target_envprobe_map) || parallax_correct_cubemaps) ) - envColourS = lerp( envColourS, planarReflectionS, planarWeight ); - @end @property( !hlms_use_ssr && !((envprobe_map && envprobe_map != target_envprobe_map) || parallax_correct_cubemaps) ) - float3 envColourS = planarReflectionS * planarWeight; - float3 envColourD = float3( 0, 0, 0 ); + planarWeight *= saturate( dot( planarReflection.xyz, pixelData.normal.xyz ) * 16.581718739 - 15.581718739 ); + @property( hlms_use_ssr || vct_num_probes || ((envprobe_map && envprobe_map != target_envprobe_map) || parallax_correct_cubemaps) ) + pixelData.envColourS = lerp( pixelData.envColourS, planarReflectionS, planarWeight ); + @else + pixelData.envColourS += planarReflectionS * planarWeight; @end @end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Refractions_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Refractions_piece_ps.any new file mode 100644 index 000000000..415ccbe30 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Refractions_piece_ps.any @@ -0,0 +1,63 @@ + +#include "/media/matias/Datos/SyntaxHighlightingMisc.h" + +@property( hlms_screen_space_refractions ) +@piece( DeclRefractionsFuncs ) + float3 OGRE_refract( float3 viewDir, float3 normal, float refractionIndex, float NdotV ) + { + float3 retVal; + float k = 1.0 - refractionIndex * refractionIndex * (1.0 - NdotV * NdotV); + if( k < 0.0 ) + retVal = float3( 0, 0, 0 ); + else + retVal = -refractionIndex * viewDir - (sqrt( k ) - refractionIndex * NdotV) * normal; + return retVal; + } +@end + +@piece( applyRefractions ) + @property( !fresnel_scalar ) + float refractF0 = pixelData.F0; + @else + float refractF0 = max( pixelData.F0.x, pixelData.F0.y, pixelData.F0.z ); + @end + + // refractNormal must be in view space, and we ignore .z component + float2 refractNormal2d = OGRE_refract( pixelData.viewDir, pixelData.normal, + refractF0, pixelData.NdotV ).xy; + float2 refractUv = screenPosUv.xy + refractNormal2d.xy * + float2( material.refractionStrength, + material.refractionStrength * passBuf.aspectRatio ) / + ( (-inPs.pos.z + 1.0) * (-inPs.pos.z + 1.0) ); + float3 refractionCol = OGRE_SampleLevel( refractionMap, refractionMapSampler, refractUv, 0 ).xyz; + float refractionDepth = OGRE_SampleLevel( depthTextureNoMsaa, refractionMapSampler, refractUv, 0 ).x; + + // We may need to fallback to regular transparency if we're sampling to close to the edges + // or the object being refracted is in front of us. + float3 fallbackRefractionCol = OGRE_Load2D( refractionMap, iFragCoord.xy, 0 ).xyz; + + refractUv = saturate( abs( screenPosUv.xy * 2.0 - 1.0 ) * 10.0 - 9.0 ); + float fallbackRefrW = max( refractUv.x, refractUv.y ); + fallbackRefrW = fallbackRefrW * fallbackRefrW; + + @property( hlms_no_reverse_depth ) + if( refractionDepth < gl_FragCoord.z - 0.025 ) + @else + if( refractionDepth > gl_FragCoord.z + 0.025 ) + @end + { + // We're trying to refract an object that is in front of us. We can't do that. + fallbackRefrW = 1.0; + } + + refractionCol = lerp( refractionCol, fallbackRefractionCol, fallbackRefrW ); + + @property( use_texture_alpha ) + float refractionAlpha = material.F0.w * pixelData.diffuse.w; + @else + float refractionAlpha = material.F0.w; + @end + + finalColour += refractionCol.xyz * (1.0 - refractionAlpha); +@end +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any index 9d7c6e2d3..58b8b7e01 100644 --- a/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any +++ b/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any @@ -1,4 +1,4 @@ - + //#include "SyntaxHighlightingMisc.h" @property( hlms_num_shadow_map_lights ) @@ -20,30 +20,23 @@ @end @end -@property( syntax == glsl ) - #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (depth >= 1.0 ? 1.0 : texture( tex, vec3( uv, depth ) )) +@property( syntax == glsl || syntax == glsles ) + #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (OGRE_DEPTH_CMP_GE( depth, OGRE_DEPTH_DEFAULT_CLEAR ) ? 1.0 : texture( tex, vec3( uv, depth ) )) #define OGRE_SAMPLE_SHADOW_ESM( tex, sampler, uv ) textureLod( tex, uv, 0 ).x - #define PASSBUF_ARG_DECL - #define PASSBUF_ARG @end @property( syntax == hlsl ) - #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (depth >= 1.0f ? 1.0 : tex.SampleCmpLevelZero( sampler, uv.xy, depth ).x) + #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (OGRE_DEPTH_CMP_GE( depth, OGRE_DEPTH_DEFAULT_CLEAR ) ? 1.0 : tex.SampleCmpLevelZero( sampler, uv.xy, depth ).x) #define OGRE_SAMPLE_SHADOW_ESM( tex, sampler, uv ) tex.SampleLevel( sampler, uv, 0 ).x - #define PASSBUF_ARG_DECL - #define PASSBUF_ARG @end @property( syntax == metal ) - #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (depth >= 1.0f ? 1.0 : tex.sample_compare( sampler, float2( uv.xy ), depth )) + #define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (OGRE_DEPTH_CMP_GE( depth, OGRE_DEPTH_DEFAULT_CLEAR ) ? 1.0 : tex.sample_compare( sampler, float2( uv.xy ), depth )) #define OGRE_SAMPLE_SHADOW_ESM( tex, sampler, uv ) tex.sample( sampler, float2( uv.xy ), level(0) ).x - - #define PASSBUF_ARG_DECL , constant PassData &passBuf - #define PASSBUF_ARG , passBuf @end @end -@property( syntax == glsl && !hlms_shadow_uses_depth_texture ) +@property( ( syntax == glsl || syntax == glsles ) && !hlms_shadow_uses_depth_texture ) @piece( regularTexturePcfGlSampling ) float2 fW; float4 c; @@ -53,7 +46,7 @@ row[1] = 0; @foreach( pcf_iterations, n ) - @property( pcf_3x3 || pcf_4x4 )uv += offsets[@n] * float2( invShadowMapSize.xy );@end + @property( pcf >= 3 )uv += offsets[@n] * float2( invShadowMapSize.xy );@end // 2x2 PCF //The 0.00196 is a magic number that prevents floating point @@ -67,32 +60,32 @@ c.z = texture(shadowMap, uv + float2( invShadowMapSize.x, 0.0 ) ).r; c.x = texture(shadowMap, uv + float2( 0.0, invShadowMapSize.y ) ).r; c.y = texture(shadowMap, uv + float2( invShadowMapSize.x, invShadowMapSize.y ) ).r; - @end @property( hlms_tex_gather ) + @else c = textureGather( shadowMap, uv + invShadowMapSize.xy * 0.5 ); @end c = step( fDepth, c ); - @property( !pcf_3x3 && !pcf_4x4 ) + @property( pcf < 3 ) //2x2 PCF: It's slightly faster to calculate this directly. retVal += mix( mix( c.w, c.z, fW.x ), mix( c.x, c.y, fW.x ), fW.y ); - @end @property( pcf_3x3 || pcf_4x4 ) + @else row[0] += mix( c.w, c.z, fW.x ); row[1] += mix( c.x, c.y, fW.x ); @end @end - @property( (pcf_3x3 || pcf_4x4) ) + @property( pcf >= 3 ) //NxN PCF: It's much faster to leave the final mix out of the loop (when N > 2). retVal = mix( row[0], row[1], fW.y ); @end @end @end -@property( syntax == glsl ) +@property( syntax == glsl || syntax == glsles ) @property( !exponential_shadow_maps ) @property( hlms_shadow_uses_depth_texture )@piece( TEXTURE2DSHADOW )sampler2DShadow@end @end @property( !hlms_shadow_uses_depth_texture )@piece( TEXTURE2DSHADOW )sampler2D@end @end @@ -115,9 +108,9 @@ @end @piece( SamplerShadow )@insertpiece( SAMPLERSTATESHADOW ) shadowSampler, @end @piece( DeclShadowSamplers ) - @insertpiece( SAMPLERSTATESHADOW ) shadowSampler: register(s@value(textureRegShadowMapStart)); + @insertpiece( SAMPLERSTATESHADOW ) shadowSampler: register(s@value(texShadowMap0)); @foreach( hlms_num_shadow_map_textures, n ) - Texture2D texShadowMap@n : register(t@counter(textureRegShadowMapStart));@end + Texture2D texShadowMap@n : register(t@value(texShadowMap@n));@end @end @end @property( syntax == metal ) @@ -131,7 +124,7 @@ /// sampler shadowSampler is declared as constexpr in PixelShader_ps.metal @piece( DeclShadowSamplers ) @foreach( hlms_num_shadow_map_textures, n ) - , @insertpiece( TEXTURE2DSHADOW ) texShadowMap@n [[texture(@counter(textureRegShadowMapStart))]]@end + , @insertpiece( TEXTURE2DSHADOW ) texShadowMap@n [[texture(@value(texShadowMap@n))]]@end @end @end @@ -158,15 +151,27 @@ { @property( @m < 2 ) //Spot and directional lights - float fDepth = psPosLN.z; + @property( !exponential_shadow_maps && !hlms_no_reverse_depth ) + float fDepth = psPosLN.z / psPosLN.w; + @else + //Exponential shadows maps normally use R16_UNORM colour buffer to store linear depth + //Its depth buffer may still have been reverse Z, but the colour rtt is what we're sampling + //Also when no reverse Z is used, we use "pseudo linear" for regular PCF, which means + //we shouldn't divide by .w either + float fDepth = psPosLN.z; + @end float2 uv = float2( psPosLN.xy / psPosLN.w ); - @end @property( @m >= 2 ) + @else //Point lights float3 cubemapDir = posVS.xyz - lightPos.xyz; float fDepth = length( cubemapDir ); cubemapDir *= 1.0 / fDepth; cubemapDir = mul( cubemapDir.xyz, passBuf.invViewMatCubemap ); - fDepth = (fDepth - invDepthRange.x) * invDepthRange.y; + @property( hlms_no_reverse_depth ) + fDepth = (fDepth - invDepthRange.x) * invDepthRange.y; + @else + fDepth = (invDepthRange.x - fDepth) * invDepthRange.y; + @end float2 uv; uv.x = (cubemapDir.x / (1.0 + abs( cubemapDir.z ))) * 0.25 + @@ -177,54 +182,110 @@ @end @property( !exponential_shadow_maps ) - float retVal = 0; + float retVal = 0.; - @property( pcf_3x3 || pcf_4x4 ) + @property( pcf >= 3 ) float2 offsets[@value(pcf_iterations)] = - @property( syntax == glsl ) + @property( syntax == glsl || syntax == glsles ) float2[@value(pcf_iterations)]( @end - @property( syntax != glsl ) + @property( syntax != glsl && syntax != glsles ) { @end - @property( pcf_3x3 ) - float2( 0, 0 ), //0, 0 - float2( 1, 0 ), //1, 0 - float2( 0, 1 ), //1, 1 - float2(-1, 0 ) //0, 1 + @property( pcf == 3 ) + float2( 0., 0. ), //0, 0 + float2( 1., 0. ), //1, 0 + float2( 0., 1. ), //1, 1 + float2(-1., 0. ) //0, 1 + @end + @property( pcf == 4 ) + float2( -1., -1. ), //-1, -1 + float2( 1., 0. ), // 0, -1 + float2( 1., 0. ), // 1, -1 + + float2(-2., 1. ), //-1, 0 + float2( 1., 0. ), // 0, 0 + float2( 1., 0. ), // 1, 0 + + float2(-2., 1. ), //-1, 1 + float2( 1., 0. ), // 0, 1 + float2( 1., 0. ) // 1, 1 + @end + @property( pcf == 5 ) + float2(-1, -1),//-1, -1 + float2(1, 0), // 0, -1 + float2(1, 0), // 1, -1 + float2(1, 0), // 2, -1 + + float2(-3, 1),//-1, 0 + float2(1, 0), // 0, 0 + float2(1, 0), // 1, 0 + float2(1, 0), // 2, 0 + + float2(-3, 1), //-1, 1 + float2(1, 0), // 0, 1 + float2(1, 0), // 1, 1 + float2(1, 0), // 2, 1 + + float2(-3, 1),//-1, 2 + float2(1, 0), // 0, 2 + float2(1, 0), // 1, 2 + float2(1, 0) // 2, 2 @end - @property( pcf_4x4 ) - float2( 0, 0 ), //0, 0 - float2( 1, 0 ), //1, 0 - float2( 1, 0 ), //2, 0 - - float2(-2, 1 ), //0, 1 - float2( 1, 0 ), //1, 1 - float2( 1, 0 ), //2, 1 - - float2(-2, 1 ), //0, 2 - float2( 1, 0 ), //1, 2 - float2( 1, 0 ) //2, 2 + @property( pcf == 6 ) + float2(-2, -2),//-2, -2 + float2(1, 0), //-1, -2 + float2(1, 0), // 0, -2 + float2(1, 0), // 1, -2 + float2(1, 0), // 2, -2 + + float2(-4, 1),//-2, -1 + float2(1, 0), //-1, -1 + float2(1, 0), // 0, -1 + float2(1, 0), // 1, -1 + float2(1, 0), // 2, -1 + + float2(-4, 1),//-2, 0 + float2(1, 0), //-1, 0 + float2(1, 0), // 0, 0 + float2(1, 0), // 1, 0 + float2(1, 0), // 2, 0 + + float2(-4, 1),//-2, 1 + float2(1, 0), //-1, 1 + float2(1, 0), // 0, 1 + float2(1, 0), // 1, 1 + float2(1, 0), // 2, 1 + + float2(-4, 1),//-2, 2 + float2(1, 0), //-1, 2 + float2(1, 0), // 0, 2 + float2(1, 0), // 1, 2 + float2(1, 0) // 2, 2 @end - @property( syntax == glsl ) + @property( syntax == glsl || syntax == glsles ) ); @end - @property( syntax != glsl ) + @property( syntax != glsl && syntax != glsles ) }; @end @end @insertpiece( regularTexturePcfGlSampling ) - @property( syntax != glsl || hlms_shadow_uses_depth_texture ) + @property( syntax != glsl && syntax != glsles || hlms_shadow_uses_depth_texture ) @foreach( pcf_iterations, n ) - @property( pcf_3x3 || pcf_4x4 )uv += offsets[@n] * invShadowMapSize.xy;@end + @property( pcf >= 3 )uv += offsets[@n] * invShadowMapSize.xy;@end retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );@end @end - @property( pcf_3x3 ) + @property( pcf == 3 ) retVal *= 0.25; - @end @property( pcf_4x4 ) + @end @property( pcf == 4 ) retVal *= 0.11111111111111; + @end @property( pcf == 5) + retVal *= 0.0625; + @end @property( pcf == 6 ) + retVal *= 0.04; @end @end ///! exponential_shadow_maps @property( exponential_shadow_maps ) @@ -249,7 +310,7 @@ @end @end -@property( syntax != glsl ) +@property( syntax != glsl && syntax != glsles ) @piece( UseSamplerShadow )shadowSampler, @end @end @@ -347,7 +408,7 @@ @pset( CurrentPointLight, hlms_lights_directional_non_caster ) @piece( DarkenWithShadowPoint ) * getShadowPoint( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow ) - inPs.pos.xyz, passBuf.lights[@counter(CurrentPointLight)].position.xyz, + inPs.pos.xyz, light0Buf.lights[@counter(CurrentPointLight)].position.xyz, passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize, passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy hlms_shadowmap@counter(CurrentShadowMap)_uv_param PASSBUF_ARG ) diff --git a/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_vs.any b/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_vs.any index c12f93c20..ee2df78fe 100644 --- a/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_vs.any +++ b/ogre2/src/media/Hlms/Pbs/Any/ShadowMapping_piece_vs.any @@ -10,14 +10,14 @@ @foreach( hlms_num_shadow_map_lights, n ) @property( !hlms_shadowmap@n_is_point_light ) - @property( !hlms_shadowmap@n_is_directional_light ) + @property( !hlms_shadowmap@n_is_directional_light && hlms_no_reverse_depth ) outVs.posL@n.z = outVs.posL@n.z * passBuf.shadowRcv[@n].shadowDepthRange.y; @end - @property( syntax == glsl )outVs.posL@n.z = (outVs.posL@n.z * 0.5) + 0.5;@end + @property( hlms_no_reverse_depth && (syntax == glsl || syntax == glsles) )outVs.posL@n.z = (outVs.posL@n.z * 0.5) + 0.5;@end @end @end - @property( hlms_pssm_splits )outVs.depth = outVs_Position.z;@end + @property( hlms_pssm_splits )outVs.depth = outVs_Position.w;@end @end @end @property( exponential_shadow_maps ) @@ -35,7 +35,7 @@ @end @end - @property( hlms_pssm_splits )outVs.depth = outVs_Position.z;@end + @property( hlms_pssm_splits )outVs.depth = outVs_Position.w;@end @end @end @end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_all.any b/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_all.any new file mode 100644 index 000000000..afed4a02c --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_all.any @@ -0,0 +1,35 @@ + +@property( vct_num_probes ) + +@piece( DeclVctStruct ) + struct VctProbeParams + { + float4 invRes_resolution_specSdfMaxMip_multiplier; + float4 ambientUpperHemi_specularSdfFactor; + float4 ambientLowerHemi_blendFade; + + float4 xform_row0; + float4 xform_row1; + float4 xform_row2; + + float4 invXform_row0; + float4 invXform_row1; + float4 invXform_row2; + }; + + #define vctInvResolution invRes_resolution_specSdfMaxMip_multiplier.x + #define vctResolution invRes_resolution_specSdfMaxMip_multiplier.y + #define vctSpecSdfMaxMip invRes_resolution_specSdfMaxMip_multiplier.z + #define vctMultiplier invRes_resolution_specSdfMaxMip_multiplier.w + + #define vctAmbientUpperHemi ambientUpperHemi_specularSdfFactor.xyz + #define vctAmbientLowerHemi ambientLowerHemi_blendFade.xyz + + #define vctSpecularSdfFactor ambientUpperHemi_specularSdfFactor.w + #define vctBlendFade ambientLowerHemi_blendFade.w +@end +@piece( DeclVctUniform ) + VctProbeParams vctProbeParams; +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_ps.any b/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_ps.any new file mode 100644 index 000000000..c8b912f3a --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/Any/Vct_piece_ps.any @@ -0,0 +1,455 @@ + +@property( vct_num_probes ) + +@piece( DeclVctTextures ) + @property( syntax == glsl ) + uniform sampler3D vctProbe; + @property( vct_anisotropic ) + uniform sampler3D vctProbeX; + uniform sampler3D vctProbeY; + uniform sampler3D vctProbeZ; + @end + @end + @property( syntax == hlsl ) + Texture3D vctProbe : register(t@value(vctProbe)); + SamplerState vctProbeSampler : register(s@value(vctProbe)); + @property( vct_anisotropic ) + Texture3D vctProbeX : register(t@value(vctProbeX)); + Texture3D vctProbeY : register(t@value(vctProbeY)); + Texture3D vctProbeZ : register(t@value(vctProbeZ)); + @end + @end + @property( syntax == metal ) + , texture3d vctProbe [[texture(@value(vctProbe))]] + , sampler vctProbeSampler [[sampler(@value(vctProbe))]] + @property( vct_anisotropic ) + , texture3d vctProbeX [[texture(@value(vctProbeX))]] + , texture3d vctProbeY [[texture(@value(vctProbeY))]] + , texture3d vctProbeZ [[texture(@value(vctProbeZ))]] + @end + @end +@end + +@piece( DeclVctFuncs ) + @property( vct_anisotropic ) + #define OGRE_VCT_ANISO_PROBE_ARG_DECL , OGRE_Texture3D_float4 probeX, OGRE_Texture3D_float4 probeY, OGRE_Texture3D_float4 probeZ + #define OGRE_VCT_ANISO_PROBE_ARG , probeX, probeY, probeZ + #define OGRE_VCT_ANISO_ROOT_PROBE_ARG , vctProbeX, vctProbeY, vctProbeZ + @else + #define OGRE_VCT_ANISO_PROBE_ARG_DECL + #define OGRE_VCT_ANISO_PROBE_ARG + #define OGRE_VCT_ANISO_ROOT_PROBE_ARG + @end + + /// Generates a TBN matrix when no tangent information is present using + /// DDX information. + /// Should only we used as a fallback as the result isn't fully stable due to how DDX works + /// and due to floating point precision. It is possible for the TBN to change as you zoom-in + /// to the triangle. + INLINE float3x3 generateTbn( float3 geomNormal, float3 pos ) + { + float3 tangentX = OGRE_ddx( pos.xyz ).xyz; + tangentX = normalize( tangentX ); + + float3 binormal = cross( geomNormal, tangentX ) ; + float3x3 TBN = buildFloat3x3( tangentX, binormal, geomNormal ); + return TBN; + } + + @foreach( 2, n ) + @property( @n == 0 ) + INLINE float4 voxelConeTraceDiff + @else + INLINE float4 voxelConeTraceSpec + @end + ( VctProbeParams probeParams, float3 posLS, + float3 dirLS, float tanHalfAngle, + @property( use_parallax_correct_cubemaps && @n == 1 ) + OGRE_OUT_REF( float3, vctSpecPosLS ), + @end + OGRE_Texture3D_float4 probe + OGRE_SAMPLER_ARG_DECL( probeSampler ) + OGRE_VCT_ANISO_PROBE_ARG_DECL ) + { + float dist = probeParams.vctInvResolution; + float alpha = 0.0; + float4 color = float4( 0.0, 0.0, 0.0, 0.0 ); + + float diameter = max( probeParams.vctInvResolution, 2.0 * tanHalfAngle * dist ); + + @property( @n == 0 ) + @property( vct_cone_dirs == 6 ) + float lodLevel = 0.0; + float lodStep = 0.71; + @else + float lodLevel = 1.0; + float lodStep = 1.0; + @end + @else + float lodLevel = log2( diameter * probeParams.vctResolution ); + @end + + @property( @n == 1 && vct_enable_specular_sdf_quality ) + float skipLod = 1; + @end + + float3 uwvPos = posLS; + + //The formula is: + // threshold = 0.5f + invResolution * exp2( lodLevel ) * 0.5; + //Thus: + // threshold = 0.5f + invRes * exp2( log2( diameter * probeParams.vctResolution ) ) * 0.5; + // threshold = 0.5f + invRes * diameter * probeParams.vctResolution ) * 0.5; + // threshold = 0.5f + diameter * 0.5; + float threshold = 0.5f + diameter * 0.5; + + @property( !vct_anisotropic ) + #define VCT_ANISOTROPIC_EARLY_OUT + @else + #define VCT_ANISOTROPIC_EARLY_OUT && lodLevel <= 0.5 + @end + while( alpha < 0.95 && + abs(uwvPos - 0.5).x < threshold && + abs(uwvPos - 0.5).y < threshold && + abs(uwvPos - 0.5).z < threshold VCT_ANISOTROPIC_EARLY_OUT ) + { + uwvPos = posLS + dist * dirLS; + float4 scolor = OGRE_SampleLevel( probe, probeSampler, uwvPos, lodLevel ); + float a = (1.0f - alpha); + color.xyz += scolor.xyz * a; + alpha += a * scolor.w; + + @property( @n == 1 && vct_enable_specular_sdf_quality ) + //When roughness is close to 0.02, specular cone tracing becomes path tracing. + //This is very slow. However we can greatly speed it up by skipping gaps of empty + //voxels. + // + //We use the alpha (opacity) component of the higher mips to approximate + //the SDF (Signed Distance Field) and thus know how much to skip. This is + //theoretically wrong, but not very wrong because the mips are very close to + //its true SDF representation thus in it works practice. + // + //Some of these formulas have been empirically tuned to match a good + //performance/quality ratio + // + //Once the roughness is higher, this formula starts hurting quality (produces + //noticeable artifacts) and thus we disable it. + // + //This formula has tweakable parameters to leverage performance vs quality + float finalOpac = OGRE_SampleLevel( probe, probeSampler, uwvPos, skipLod ).w; + float skipFactor = exp2( max( 0.0f, skipLod * 0.5f - 1.0f ) ) * (1.0f - finalOpac) + + finalOpac; + skipFactor = lerp( skipFactor, 1.0f, + min( -1.0 + finalOpac * probeParams.vctSpecularSdfFactor + + tanHalfAngle * 50.0f, 1.0f ) ); + skipLod = clamp( skipLod + (1.0f - finalOpac) * 2.0f - 1.0f, + 1.0f, probeParams.vctSpecSdfMaxMip ); + + dist += diameter * 0.5f * skipFactor; + @else + dist += diameter * 0.5f; + @end + diameter = max( probeParams.vctInvResolution, 2.0 * tanHalfAngle * dist ); + @property( @n == 0 && vct_cone_dirs == 4 ) + lodLevel += lodStep; + @else + lodLevel = log2( diameter * probeParams.vctResolution ); + @end + + threshold = 0.5f + diameter * 0.5; + } + + @property( vct_anisotropic ) + float3 isNegative; + isNegative.x = dirLS.x < 0 ? 0.5f : 0.0f; + isNegative.y = dirLS.y < 0 ? 0.5f : 0.0f; + isNegative.z = dirLS.z < 0 ? 0.5f : 0.0f; + + float3 dirLSSquared = dirLS.xyz * dirLS.xyz; + + while( alpha < 0.95 && + abs(uwvPos - 0.5).x < threshold && + abs(uwvPos - 0.5).y < threshold && + abs(uwvPos - 0.5).z < threshold ) + { + uwvPos = posLS + dist * dirLS; + float3 sampleUVW = uwvPos; + sampleUVW.x = saturate( sampleUVW.x ) * 0.5; + + float4 xColor = OGRE_SampleLevel( probeX, probeSampler, + sampleUVW + float3( isNegative.x, 0, 0 ), + lodLevel ); + float4 yColor = OGRE_SampleLevel( probeY, probeSampler, + sampleUVW + float3( isNegative.y, 0, 0 ), + lodLevel ); + float4 zColor = OGRE_SampleLevel( probeZ, probeSampler, + sampleUVW + float3( isNegative.z, 0, 0 ), + lodLevel ); + + float4 scolor = dirLSSquared.x * xColor + + dirLSSquared.y * yColor + + dirLSSquared.z * zColor; + float a = (1.0f - alpha); + color.xyz += scolor.xyz * a; + alpha += a * scolor.w; + dist += diameter * 0.5f; + diameter = max( probeParams.vctInvResolution, 2.0 * tanHalfAngle * dist ); + @property( @n == 0 && vct_cone_dirs == 4 ) + lodLevel += lodStep; + @else + lodLevel = log2( diameter * probeParams.vctResolution ); + @end + + threshold = 0.5f + diameter * 0.5; + } + @end + + color.w = 1.0f - min( 1.0f, alpha / 0.95f ); + + @property( use_parallax_correct_cubemaps && @n == 1 ) + vctSpecPosLS = uwvPos; + @end + + return color; + } + @end + + INLINE float3 toVctProbeSpacePos( float3 pos, VctProbeParams probeParams ) + { + float3 posLS; + posLS.x = dot( probeParams.xform_row0.xyzw, float4( pos, 1.0 ) ); + posLS.y = dot( probeParams.xform_row1.xyzw, float4( pos, 1.0 ) ); + posLS.z = dot( probeParams.xform_row2.xyzw, float4( pos, 1.0 ) ); + return posLS; + } + + INLINE float3 toVctProbeSpaceDir( float3 dir, VctProbeParams probeParams ) + { + float3 dirLS; + dirLS.x = dot( probeParams.xform_row0.xyz, dir ); + dirLS.y = dot( probeParams.xform_row1.xyz, dir ); + dirLS.z = dot( probeParams.xform_row2.xyz, dir ); + return normalize( dirLS ); + } + + + INLINE float3 fromVctToViewSpace( float3 pos, VctProbeParams probeParams ) + { + float3 posVS; + posVS.x = dot( probeParams.invXform_row0.xyzw, float4( pos, 1.0 ) ); + posVS.y = dot( probeParams.invXform_row1.xyzw, float4( pos, 1.0 ) ); + posVS.z = dot( probeParams.invXform_row2.xyzw, float4( pos, 1.0 ) ); + return posVS; + } + + #define M_PI 3.141592654f + + INLINE void computeVctProbe + ( + OGRE_INOUT_REF( float3, outDiffuse ), OGRE_INOUT_REF( float4, outSpecular ), + PixelData pixelData, float3 pos, float3x3 TBN, + @property( vct_ambient_hemisphere ) + float ambientWD, float ambientWS, + @end + @property( use_parallax_correct_cubemaps ) + OGRE_INOUT_REF( float3, vctSpecPosVS ), + @end + VctProbeParams probeParams, + OGRE_Texture3D_float4 probe OGRE_SAMPLER_ARG_DECL( probeSampler ) + OGRE_VCT_ANISO_PROBE_ARG_DECL + ) + { + float3 posLS = toVctProbeSpacePos( pos, probeParams ); + + if( posLS.x < 0.0 || posLS.x > 1.0 || + posLS.y < 0.0 || posLS.y > 1.0 || + posLS.z < 0.0 || posLS.z > 1.0 ) + { + return; + } + + //Bias away from current position in order to avoid self-occlusion (specular reflections + //won't work otherwise). When the geometry is facing diagonally to the axes, we want that + //bias to be stronger as aliasing can still cause oclussion (i.e. imagine the ray hitting + //the steps of a staircase). + float3 dirLS = toVctProbeSpaceDir( pixelData.geomNormal.xyz, probeParams ); + float maxVal = max3( abs( dirLS.x ), abs( dirLS.y ), abs( dirLS.z ) ) + 1e-6f; + posLS += (dirLS / maxVal) * probeParams.vctInvResolution * lerp( 15.0f, 1.0f, maxVal ); + + @property( vct_num_probes > 1 ) + float3 blendv = abs( posLS * 2.0f - 1.0f ); + float blend = saturate( 1.0f - max3( blendv.x, blendv.y, blendv.z ) ); + @else + float blend = 1.0f; + @end + + @property( !vct_disable_diffuse ) + @property( vct_cone_dirs == 6 ) + float3 cone_dirs[6] = + OGRE_ARRAY_START( float3 ) + float3( 0.0, 0.0, 1.0 ), + float3( 0.866025, 0.0, 0.5 ), + float3( 0.267617, 0.823639, 0.5 ), + float3( -0.700629, 0.509037, 0.5 ), + float3( -0.700629, -0.509037, 0.5 ), + float3( 0.267617, -0.823639, 0.5 ) + OGRE_ARRAY_END; + + float coneWeights[6] = OGRE_ARRAY_START( float ) 0.25, 0.15, 0.15, 0.15, 0.15, 0.15 OGRE_ARRAY_END; + float coneAngleTan = 0.577; + @else + float3 cone_dirs[4] = + OGRE_ARRAY_START( float3 ) + float3( 0.707107, 0.0, 0.707107 ), + float3( 0.0, 0.707107, 0.707107 ), + float3( -0.707107, 0.0, 0.707107 ), + float3( 0.0, -0.707107, 0.707107 ) + OGRE_ARRAY_END; + + float coneWeights[4] = OGRE_ARRAY_START( float ) 0.25, 0.25, 0.25, 0.25 OGRE_ARRAY_END; + float coneAngleTan = 0.98269; + @end + + //Radiance / diffuse + float4 light = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + for( int i=0; i<@value( vct_cone_dirs ); ++i ) + { + float3 dir = toVctProbeSpaceDir( mul( TBN, cone_dirs[i] ), probeParams ); + light += coneWeights[i] * voxelConeTraceDiff( probeParams, posLS, dir, + coneAngleTan, + probe OGRE_SAMPLER_ARG( probeSampler ) + OGRE_VCT_ANISO_PROBE_ARG ); + } + @property( vct_ambient_hemisphere ) + //Add ambient light after all cones have been weighted + light.xyz += lerp( probeParams.vctAmbientLowerHemi.xyz, + probeParams.vctAmbientUpperHemi.xyz, ambientWD ) * light.w; + @else + //Add ambient light after all cones have been weighted + light.xyz += probeParams.vctAmbientUpperHemi.xyz * light.w; + @end + @end + + float blendWeight = probeParams.vctBlendFade * blend * probeParams.vctMultiplier; + + @property( !vct_disable_diffuse ) + outDiffuse.xyz += light.xyz * blendWeight; + @end + + //Irradiance / specular + @property( !vct_disable_specular ) + @property( use_parallax_correct_cubemaps ) + float3 vctSpecPosLS; + @end + float3 reflVecLS = toVctProbeSpaceDir( pixelData.reflDir, probeParams ); + // 1 / (1 - 0.02) = 1.020408163 + float vctRoughness = (pixelData.roughness - 0.02) * 1.020408163f; + float specConeAngleTan = max( 0.0f, tan( vctRoughness * 0.5f * M_PI * 0.99f ) ); + float4 irrLight = voxelConeTraceSpec( probeParams, posLS, reflVecLS, + specConeAngleTan, + @property( use_parallax_correct_cubemaps ) + vctSpecPosLS, + @end + probe OGRE_SAMPLER_ARG( probeSampler ) + OGRE_VCT_ANISO_PROBE_ARG ); + @property( vct_ambient_hemisphere ) + irrLight.xyz += lerp( probeParams.vctAmbientLowerHemi.xyz, + probeParams.vctAmbientUpperHemi.xyz, ambientWS ) * irrLight.w; + @else + irrLight.xyz += probeParams.vctAmbientUpperHemi.xyz * irrLight.w; + @end + outSpecular += float4( irrLight.xyz * blendWeight, blend ); + + @property( use_parallax_correct_cubemaps ) + vctSpecPosVS = fromVctToViewSpace( vctSpecPosLS, probeParams ); + @end + @else + outSpecular.w += blend; + @end + } + + INLINE float getPccVctBlendWeight( float3 inPsPos, float3 reflDir, float fDist, + float roughness, float3 cubemapPosVS, + float3 vctSpecPosVS, float vctSpecularW, + float pccVctMinDistanceVar, float invPccVctInvDistanceVar, + float pccCompressedDepth ) + { + //Calculate interesectionPosVS as the intersection between the reflection ray and a cube + float3 interesectionPosVS = inPsPos + reflDir * fDist; + + //Now increase interesectionPosVS accuracy (it will no longer be a box) + //by taking the compressed PCC depth stored in pccCompressedDepth + //The compressed PCC depth is in the form of: + // interesectionPosVS = cubemapPosVS + reflDirLS * (pccCompressedDir * 2.0); + interesectionPosVS = cubemapPosVS.xyz + + (interesectionPosVS - cubemapPosVS.xyz) * (pccCompressedDepth * 2.0); + float3 vctSpecPosToPccSpecPos = interesectionPosVS - vctSpecPosVS; + //Calculate distance to VCT pos and blend based on that + float distToVct = max3( abs( vctSpecPosToPccSpecPos ).x, + abs( vctSpecPosToPccSpecPos ).y, + abs( vctSpecPosToPccSpecPos ).z ); + float vctLerp = (distToVct - pccVctMinDistanceVar) * invPccVctInvDistanceVar; + vctLerp = saturate( vctLerp ); + + //vctLerp has quantization artifacts due to 8-bit precision when interpolating via HW + //texture filtering present in vctSpecPosVS. They're very noticeable at non-zero roughness. + //Hide these artifacts by reusing the PCC compressed depth as a mask. + float pccErrorMask = ( pccCompressedDepth - 0.5f ) * ( pccCompressedDepth - 0.5f ) * 4.0f; + float roughThreshWeight = roughness - 0.02f; + roughThreshWeight = min( roughThreshWeight * 200.0f, 1.0f ); + vctLerp = lerp( vctLerp, vctLerp * pccErrorMask, roughThreshWeight ); + + //At very high roughness, VCT (anisotropic) is much more accurate. Thus bias towards VCT + vctLerp = min( vctLerp + roughness * roughness * roughness, 1.0f ); + + //If no VCT probe was found, fallback to PCC + vctLerp = (vctSpecularW == 0) ? 0.0f : vctLerp; + + return vctLerp; + } +@end + +@piece( applyVoxelConeTracing ) + @property( !normal_map ) + float3x3 TBN = generateTbn( pixelData.geomNormal, inPs.pos ); + @end + + @property( use_parallax_correct_cubemaps ) + float3 vctSpecPosVS = float3( 0, 0, 0 ); + @end + + float3 vctDiffuse = float3( 0, 0, 0 ); + float4 vctSpecular = float4( 0, 0, 0, 0 ); + computeVctProbe( vctDiffuse, vctSpecular, pixelData, inPs.pos, TBN, + @property( vct_ambient_hemisphere ) + ambientWD, ambientWS, + @end + @property( use_parallax_correct_cubemaps ) + vctSpecPosVS, + @end + passBuf.vctProbeParams, + vctProbe OGRE_SAMPLER_ARG( vctProbeSampler ) + OGRE_VCT_ANISO_ROOT_PROBE_ARG ); + + @property( vct_num_probes > 1 ) + //We've added multiple probes together that are overlapping. Average them + //based on their influnce (i.e. proximity to probe's center) + if( vctSpecular.w > 0 ) + { + float accumProbeInfluenceBorderBlend = 1.0f / vctSpecular.w; + @property( !vct_disable_diffuse ) + vctDiffuse.xyz *= accumProbeInfluenceBorderBlend; + @end + vctSpecular.xyz *= accumProbeInfluenceBorderBlend; + } + @end + + @property( !vct_disable_diffuse ) + pixelData.envColourD.xyz += vctDiffuse.xyz; + @end + @property( !vct_disable_specular ) + pixelData.envColourS.xyz += vctSpecular.xyz; + @end +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/Forward3D_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSL/Forward3D_piece_ps.glsl index a159709ed..991e168e2 100644 --- a/ogre2/src/media/Hlms/Pbs/GLSL/Forward3D_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Pbs/GLSL/Forward3D_piece_ps.glsl @@ -1,232 +1,16 @@ @property( hlms_forwardplus ) -@property( hlms_forwardplus_fine_light_mask ) - @piece( andObjLightMaskFwdPlusCmp )&& ((objLightMask & floatBitsToUint( lightDiffuse.w )) != 0u)@end -@end -@piece( forward3dLighting ) - @property( hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v) - #define FWDPLUS_APPLY_OFFSET_X(v) (v) - @end - - @property( hlms_forwardplus_fine_light_mask && !hlms_fine_light_mask ) - uint objLightMask = instance.worldMaterialIdx[inPs.drawId].z; - @end - @property( hlms_forwardplus == forward3d ) - float f3dMinDistance = passBuf.f3dData.x; - float f3dInvMaxDistance = passBuf.f3dData.y; - float f3dNumSlicesSub1 = passBuf.f3dData.z; - uint cellsPerTableOnGrid0= floatBitsToUint( passBuf.f3dData.w ); - - // See C++'s Forward3D::getSliceAtDepth - /*float fSlice = 1.0 - clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); - fSlice = (fSlice * fSlice) * (fSlice * fSlice); - fSlice = (fSlice * fSlice); - fSlice = floor( (1.0 - fSlice) * f3dNumSlicesSub1 );*/ - float fSlice = clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); - fSlice = floor( fSlice * f3dNumSlicesSub1 ); - uint slice = uint( fSlice ); - - //TODO: Profile performance: derive this mathematically or use a lookup table? - uint offset = cellsPerTableOnGrid0 * (((1u << (slice << 1u)) - 1u) / 3u); - - float lightsPerCell = passBuf.f3dGridHWW[0].w; - - @property( !hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.f3dViewportOffset.y) - #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.f3dViewportOffset.x) - @end - - //passBuf.f3dGridHWW[slice].x = grid_width / renderTarget->width; - //passBuf.f3dGridHWW[slice].y = grid_height / renderTarget->height; - //passBuf.f3dGridHWW[slice].z = grid_width * lightsPerCell; - //uint sampleOffset = 0; - @property( hlms_forwardplus_flipY ) - float windowHeight = passBuf.f3dGridHWW[1].w; //renderTarget->height - uint sampleOffset = offset + - uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) ) * - passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + - uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * - passBuf.f3dGridHWW[slice].x ) * lightsPerCell); - @end @property( !hlms_forwardplus_flipY ) - uint sampleOffset = offset + - uint(floor( FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) * - passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + - uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * - passBuf.f3dGridHWW[slice].x ) * lightsPerCell); - @end - @end @property( hlms_forwardplus != forward3d ) - float f3dMinDistance = passBuf.f3dData.x; - float f3dInvExponentK = passBuf.f3dData.y; - float f3dNumSlicesSub1 = passBuf.f3dData.z; - - // See C++'s ForwardClustered::getSliceAtDepth - float fSlice = log2( max( -inPs.pos.z - f3dMinDistance, 1 ) ) * f3dInvExponentK; - fSlice = floor( min( fSlice, f3dNumSlicesSub1 ) ); - uint sliceSkip = uint( fSlice * @value( fwd_clustered_width_x_height ) ); - @property( !hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.fwdScreenToGrid.w) - #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.fwdScreenToGrid.z) +@property( hlms_enable_decals ) + @piece( DeclDecalsSamplers ) + @property( hlms_decals_diffuse )uniform sampler2DArray decalsDiffuseTex;@end + @property( hlms_decals_normals )uniform sampler2DArray decalsNormalsTex;@end + @property( hlms_decals_diffuse == hlms_decals_emissive ) + #define decalsEmissiveTex decalsDiffuseTex @end - - uint sampleOffset = sliceSkip + - uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * passBuf.fwdScreenToGrid.x )); - @property( hlms_forwardplus_flipY ) - float windowHeight = passBuf.f3dData.w; //renderTarget->height - sampleOffset += uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) ) * - passBuf.fwdScreenToGrid.y ) * - @value( fwd_clustered_width )); - @end @property( !hlms_forwardplus_flipY ) - sampleOffset += uint(floor( FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) * - passBuf.fwdScreenToGrid.y ) * - @value( fwd_clustered_width )); + @property( hlms_decals_emissive && hlms_decals_diffuse != hlms_decals_emissive ) + uniform sampler2DArray decalsEmissiveTex; @end - - sampleOffset *= @value( fwd_clustered_lights_per_cell )u; - @end - - uint numLightsInGrid = bufferFetch( f3dGrid, int(sampleOffset) ).x; - - @property( hlms_forwardplus_debug )uint totalNumLightsInGrid = numLightsInGrid;@end - - for( uint i=0u; i= spotParams.y ) - { - vec3 tmpColour = BRDF( lightDir, viewDir, NdotV, lightDiffuse.xyz, lightSpecular ); - finalColour += tmpColour * atten; - } - } - } - -@property( hlms_enable_vpls ) - prevLightCount = numLightsInGrid; - numLightsInGrid = bufferFetch( f3dGrid, int(sampleOffset + 2u) ).x; - - @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end - - for( uint i=prevLightCount; i> 16u;@end -@property( specular_map ) specularIdx = material.indices0_3.y & 0x0000FFFFu;@end -@property( roughness_map ) roughnessIdx = material.indices0_3.y >> 16u;@end -@property( detail_weight_map ) weightMapIdx = material.indices0_3.z & 0x0000FFFFu;@end -@property( detail_map0 ) detailMapIdx0 = material.indices0_3.z >> 16u;@end -@property( detail_map1 ) detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;@end -@property( detail_map2 ) detailMapIdx2 = material.indices0_3.w >> 16u;@end -@property( detail_map3 ) detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;@end -@property( detail_map_nm0 ) detailNormMapIdx0 = material.indices4_7.x >> 16u;@end -@property( detail_map_nm1 ) detailNormMapIdx1 = material.indices4_7.y & 0x0000FFFFu;@end -@property( detail_map_nm2 ) detailNormMapIdx2 = material.indices4_7.y >> 16u;@end -@property( detail_map_nm3 ) detailNormMapIdx3 = material.indices4_7.z & 0x0000FFFFu;@end -@property( emissive_map ) emissiveMapIdx = material.indices4_7.z >> 16u;@end -@property( use_envprobe_map ) envMapIdx = material.indices4_7.w & 0x0000FFFFu;@end - - @insertpiece( DeclareObjLightMask ) - - @insertpiece( custom_ps_posMaterialLoad ) - -@property( detail_maps_diffuse || detail_maps_normal ) - //Prepare weight map for the detail maps. - @property( detail_weight_map ) - vec4 detailWeights = @insertpiece( SamplerDetailWeightMap ); - @property( detail_weights )detailWeights *= material.cDetailWeights;@end - @end @property( !detail_weight_map ) - @property( detail_weights )vec4 detailWeights = material.cDetailWeights;@end - @property( !detail_weights )vec4 detailWeights = vec4( 1.0, 1.0, 1.0, 1.0 );@end - @end -@end - - /// Sample detail maps and weight them against the weight map in the next foreach loop. -@foreach( detail_maps_diffuse, n )@property( detail_map@n ) - vec4 detailCol@n = texture( textureMaps[@value(detail_map@n_idx)], - vec3( UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), - detailMapIdx@n ) ); - @property( !hw_gamma_read )//Gamma to linear space - detailCol@n.xyz = detailCol@n.xyz * detailCol@n.xyz;@end - detailWeights.@insertpiece(detail_swizzle@n) *= detailCol@n.w; - detailCol@n.w = detailWeights.@insertpiece(detail_swizzle@n);@end -@end - -@property( !hlms_prepass || alpha_test ) - @insertpiece( SampleDiffuseMap ) - - /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no - /// diffuse maps, we must initialize it to some value. If there are no diffuse or detail maps, - /// we must not access diffuseCol at all, but rather use material.kD directly (see piece( kD ) ). - @property( !diffuse_map )diffuseCol = material.bgDiffuse;@end - - /// Blend the detail diffuse maps with the main diffuse. - @foreach( detail_maps_diffuse, n ) - @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end - - /// Apply the material's diffuse over the textures - @property( !transparent_mode ) - diffuseCol.xyz *= material.kD.xyz; - @end @property( transparent_mode ) - diffuseCol.xyz *= material.kD.xyz * diffuseCol.w * diffuseCol.w; - @end - - @property( alpha_test ) - if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol.a ) - discard; - @end -@end - -@property( !hlms_use_prepass ) - @property( !normal_map ) - // Geometric normal - nNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); - @end @property( normal_map ) - //Normal mapping. - vec3 geomNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); - vec3 vTangent = normalize( inPs.tangent ); - - //Get the TBN matrix - vec3 vBinormal = normalize( cross( geomNormal, vTangent )@insertpiece( tbnApplyReflection ) ); - mat3 TBN = mat3( vTangent, vBinormal, geomNormal ); - - @property( normal_map_tex )nNormal = getTSNormal( vec3( UV_NORMAL( inPs.uv@value(uv_normal).xy ), - normalIdx ) );@end - @property( normal_weight_tex ) - // Apply the weight to the main normal map - nNormal = mix( vec3( 0.0, 0.0, 1.0 ), nNormal, normalMapWeight ); - @end - @end - - /// If there is no normal map, the first iteration must - /// initialize nNormal instead of try to merge with it. - @property( normal_map_tex ) - @piece( detail_nm_op_sum )+=@end - @piece( detail_nm_op_mul )*=@end - @end @property( !normal_map_tex ) - @piece( detail_nm_op_sum )=@end - @piece( detail_nm_op_mul )=@end - @end - - /// Blend the detail normal maps with the main normal. - @foreach( second_valid_detail_map_nm, n, first_valid_detail_map_nm ) - vec3 vDetail = @insertpiece( SampleDetailMapNm@n ); - nNormal.xy @insertpiece( detail_nm_op_sum ) vDetail.xy; - nNormal.z @insertpiece( detail_nm_op_mul ) vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end - @foreach( detail_maps_normal, n, second_valid_detail_map_nm )@property( detail_map_nm@n ) - vDetail = @insertpiece( SampleDetailMapNm@n ); - nNormal.xy += vDetail.xy; - nNormal.z *= vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end @end - - @insertpiece( custom_ps_posSampleNormal ) - - @property( normal_map ) - nNormal = normalize( TBN * nNormal ); - @end - - @insertpiece( DoDirectionalShadowMaps ) - - @insertpiece( SampleRoughnessMap ) - -@end @property( hlms_use_prepass ) - ivec2 iFragCoord = ivec2( gl_FragCoord.x, - @property( !hlms_forwardplus_flipY )passBuf.windowHeight.x - @end - gl_FragCoord.y ); - - @property( hlms_use_prepass_msaa ) - //SV_Coverage/gl_SampleMaskIn is always before depth & stencil tests, - //so we need to perform the test ourselves - //See http://www.yosoygames.com.ar/wp/2017/02/beware-of-sv_coverage/ - float msaaDepth; - int subsampleDepthMask; - float pixelDepthZ; - float pixelDepthW; - float pixelDepth; - int intPixelDepth; - int intMsaaDepth; - //Unfortunately there are precision errors, so we allow some ulp errors. - //200 & 5 are arbitrary, but were empirically found to be very good values. - int ulpError = int( lerp( 200.0, 5.0, gl_FragCoord.z ) ); - @foreach( hlms_use_prepass_msaa, n ) - pixelDepthZ = interpolateAtSample( inPs.zwDepth.x, @n ); - pixelDepthW = interpolateAtSample( inPs.zwDepth.y, @n ); - pixelDepth = pixelDepthZ / pixelDepthW; - msaaDepth = texelFetch( gBuf_depthTexture, iFragCoord.xy, @n ); - intPixelDepth = floatBitsToInt( pixelDepth ); - intMsaaDepth = floatBitsToInt( msaaDepth ); - subsampleDepthMask = int( (abs( intPixelDepth - intMsaaDepth ) <= ulpError) ? 0xffffffffu : ~(1u << @nu) ); - //subsampleDepthMask = int( (pixelDepth <= msaaDepth) ? 0xffffffffu : ~(1u << @nu) ); - gl_SampleMaskIn &= subsampleDepthMask; - @end - - gl_SampleMaskIn[0] = gl_SampleMaskIn[0] == 0u ? 1u : gl_SampleMaskIn[0]; - - int gBufSubsample = findLSB( gl_SampleMaskIn[0] ); - @end @property( !hlms_use_prepass_msaa ) - //On non-msaa RTTs gBufSubsample is the LOD level. - int gBufSubsample = 0; - @end - - nNormal = normalize( texelFetch( gBuf_normals, iFragCoord, gBufSubsample ).xyz * 2.0 - 1.0 ); - vec2 shadowRoughness = texelFetch( gBuf_shadowRoughness, iFragCoord, gBufSubsample ).xy; - - float fShadow = shadowRoughness.x; - - @property( roughness_map ) - ROUGHNESS = shadowRoughness.y * 0.98 + 0.02; /// ROUGHNESS is a constant otherwise - @end -@end - -@insertpiece( SampleSpecularMap ) - -@property( !hlms_prepass ) - //Everything's in Camera space -@property( hlms_lights_spot || use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere || hlms_forwardplus ) - vec3 viewDir = normalize( -inPs.pos ); - float NdotV = clamp( dot( nNormal, viewDir ), 0.0, 1.0 ); -@end - -@property( !ambient_fixed ) - vec3 finalColour = vec3(0); -@end @property( ambient_fixed ) - vec3 finalColour = passBuf.ambientUpperHemi.xyz * @insertpiece( kD ).xyz; -@end - - @insertpiece( custom_ps_preLights ) - -@property( !custom_disable_directional_lights ) -@property( hlms_lights_directional ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[0].position.xyz, viewDir, NdotV, passBuf.lights[0].diffuse, passBuf.lights[0].specular ) @insertpiece(DarkenWithShadowFirstLight); -@end -@foreach( hlms_lights_directional, n, 1 ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadow );@end -@foreach( hlms_lights_directional_non_caster, n, hlms_lights_directional ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular );@end -@end - -@property( hlms_lights_point || hlms_lights_spot || hlms_lights_area_approx ) vec3 lightDir; - float fDistance; - vec3 tmpColour; - float spotCosAngle;@end - - //Point lights -@foreach( hlms_lights_point, n, hlms_lights_directional_non_caster ) - lightDir = passBuf.lights[@n].position.xyz - inPs.pos; - fDistance= length( lightDir ); - if( fDistance <= passBuf.lights[@n].attenuation.x @insertpiece( andObjLightMaskCmp ) ) - { - lightDir *= 1.0 / fDistance; - tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadowPoint ); - float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); - finalColour += tmpColour * atten; - }@end - - //Spot lights - //spotParams[@value(spot_params)].x = 1.0 / cos( InnerAngle ) - cos( OuterAngle ) - //spotParams[@value(spot_params)].y = cos( OuterAngle / 2 ) - //spotParams[@value(spot_params)].z = falloff -@foreach( hlms_lights_spot, n, hlms_lights_point ) - lightDir = passBuf.lights[@n].position.xyz - inPs.pos; - fDistance= length( lightDir ); -@property( !hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), passBuf.lights[@n].spotDirection.xyz );@end -@property( hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), zAxis( passBuf.lights[@n].spotQuaternion ) );@end - if( fDistance <= passBuf.lights[@n].attenuation.x && spotCosAngle >= passBuf.lights[@n].spotParams.y @insertpiece( andObjLightMaskCmp ) ) - { - lightDir *= 1.0 / fDistance; - @property( hlms_lights_spot_textured ) - vec3 posInLightSpace = qmul( spotQuaternion[@value(spot_params)], inPs.pos ); - float spotAtten = texture( texSpotLight, normalize( posInLightSpace ).xy ).x; - @end - @property( !hlms_lights_spot_textured ) - float spotAtten = clamp( (spotCosAngle - passBuf.lights[@n].spotParams.y) * passBuf.lights[@n].spotParams.x, 0.0, 1.0 ); - spotAtten = pow( spotAtten, passBuf.lights[@n].spotParams.z ); - @end - tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadow ); - float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); - finalColour += tmpColour * (atten * spotAtten); - }@end - - //Custom 2D shape lights - @insertpiece( DoAreaApproxLights ) - -@insertpiece( forward3dLighting ) -@insertpiece( applyIrradianceVolumes ) - -@property( emissive_map || emissive_constant ) - @insertpiece( SampleEmissiveMap ) - finalColour += emissiveCol.xyz; -@end - -@property( use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere ) - vec3 reflDir = 2.0 * dot( viewDir, nNormal ) * nNormal - viewDir; - - @property( use_envprobe_map ) - @property( use_parallax_correct_cubemaps ) - vec3 envColourS; - vec3 envColourD; - vec3 posInProbSpace = toProbeLocalSpace( inPs.pos, @insertpiece( pccProbeSource ) ); - float probeFade = getProbeFade( posInProbSpace, @insertpiece( pccProbeSource ) ); - if( probeFade > 0 ) - { - vec3 reflDirLS = localCorrect( reflDir, posInProbSpace, @insertpiece( pccProbeSource ) ); - vec3 nNormalLS = localCorrect( nNormal, posInProbSpace, @insertpiece( pccProbeSource ) ); - envColourS = textureLod( texEnvProbeMap, - reflDirLS, ROUGHNESS * 12.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - envColourD = textureLod( texEnvProbeMap, - nNormalLS, 11.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - - envColourS = envColourS * clamp( probeFade * 200.0, 0.0, 1.0 ); - envColourD = envColourD * clamp( probeFade * 200.0, 0.0, 1.0 ); - } - else - { - //TODO: Fallback to a global cubemap. - envColourS = vec3( 0, 0, 0 ); - envColourD = vec3( 0, 0, 0 ); - } - @end @property( !use_parallax_correct_cubemaps ) - vec3 envColourS = textureLod( texEnvProbeMap, reflDir * passBuf.invViewMatCubemap, ROUGHNESS * 12.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - vec3 envColourD = textureLod( texEnvProbeMap, nNormal * passBuf.invViewMatCubemap, 11.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - @end - @property( !hw_gamma_read ) //Gamma to linear space - envColourS = envColourS * envColourS; - envColourD = envColourD * envColourD; - @end - @end - - @property( hlms_use_ssr ) - //TODO: SSR pass should be able to combine global & local cubemap. - vec4 ssrReflection = texelFetch( ssrTexture, iFragCoord, 0 ).xyzw; - @property( use_envprobe_map ) - envColourS = mix( envColourS.xyz, ssrReflection.xyz, ssrReflection.w ); - @end @property( !use_envprobe_map ) - vec3 envColourS = ssrReflection.xyz * ssrReflection.w; - vec3 envColourD = vec3( 0, 0, 0 ); - @end - @end - - @insertpiece( DoPlanarReflectionsPS ) - - @property( ambient_hemisphere ) - float ambientWD = dot( passBuf.ambientHemisphereDir.xyz, nNormal ) * 0.5 + 0.5; - float ambientWS = dot( passBuf.ambientHemisphereDir.xyz, reflDir ) * 0.5 + 0.5; - - @property( use_envprobe_map || hlms_use_ssr || use_planar_reflections ) - envColourS += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); - envColourD += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); - @end @property( !use_envprobe_map && !hlms_use_ssr && !use_planar_reflections ) - vec3 envColourS = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); - vec3 envColourD = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); - @end - @end - - @insertpiece( BRDF_EnvMap ) -@end -@end ///!hlms_prepass - -@property( !hlms_render_depth_only ) - @property( !hlms_prepass ) - @property( !hw_gamma_write ) - //Linear to Gamma space - outColour.xyz = sqrt( finalColour ); - @end @property( hw_gamma_write ) - outColour.xyz = finalColour; - @end - - @property( hlms_alphablend ) - @property( use_texture_alpha ) - outColour.w = material.F0.w * diffuseCol.w; - @end @property( !use_texture_alpha ) - outColour.w = material.F0.w; - @end - @end @property( !hlms_alphablend ) - outColour.w = 1.0;@end - - @end @property( !hlms_normal && !hlms_qtangent ) - outColour = vec4( 1.0, 1.0, 1.0, 1.0 ); - @end - - @property( debug_pssm_splits ) - outColour.xyz = mix( outColour.xyz, debugPssmSplit.xyz, 0.2f ); - @end - @end @property( hlms_prepass ) - outNormals = vec4( nNormal * 0.5 + 0.5, 1.0 ); - @property( hlms_pssm_splits ) - outShadowRoughness = vec2( fShadow, (ROUGHNESS - 0.02) * 1.02040816 ); - @end @property( !hlms_pssm_splits ) - outShadowRoughness = vec2( 1.0, (ROUGHNESS - 0.02) * 1.02040816 ); - @end - @end -@end - + @insertpiece( DefaultBodyPS ) @insertpiece( custom_ps_posExecution ) } -@end -@property( hlms_shadowcaster ) +@else ///!hlms_shadowcaster @insertpiece( DeclShadowCasterMacros ) @property( alpha_test ) - Material material; - float diffuseCol; - @property( num_textures )uniform sampler2DArray textureMaps[@value( num_textures )];@end - @property( diffuse_map )uint diffuseIdx;@end - @property( detail_weight_map )uint weightMapIdx;@end - @foreach( 4, n ) - @property( detail_map@n )uint detailMapIdx@n;@end @end + @foreach( num_textures, n ) + uniform sampler2DArray textureMaps@n;@end @end @property( hlms_shadowcaster_point || exponential_shadow_maps ) - @insertpiece( PassDecl ) + @insertpiece( PassStructDecl ) @end void main() { @insertpiece( custom_ps_preExecution ) - -@property( alpha_test ) - @property( !lower_gpu_overhead ) - uint materialId = instance.worldMaterialIdx[inPs.drawId].x & 0x1FFu; - material = materialArray.m[materialId]; - @end @property( lower_gpu_overhead ) - material = materialArray.m[0]; - @end -@property( diffuse_map ) diffuseIdx = material.indices0_3.x & 0x0000FFFFu;@end -@property( detail_weight_map ) weightMapIdx = material.indices0_3.z & 0x0000FFFFu;@end -@property( detail_map0 ) detailMapIdx0 = material.indices0_3.z >> 16u;@end -@property( detail_map1 ) detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;@end -@property( detail_map2 ) detailMapIdx2 = material.indices0_3.w >> 16u;@end -@property( detail_map3 ) detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;@end - -@property( detail_maps_diffuse || detail_maps_normal ) - //Prepare weight map for the detail maps. - @property( detail_weight_map ) - vec4 detailWeights = @insertpiece( SamplerDetailWeightMap ); - @property( detail_weights )detailWeights *= material.cDetailWeights;@end - @end @property( !detail_weight_map ) - @property( detail_weights )vec4 detailWeights = material.cDetailWeights;@end - @property( !detail_weights )vec4 detailWeights = vec4( 1.0, 1.0, 1.0, 1.0 );@end - @end -@end - - /// Sample detail maps and weight them against the weight map in the next foreach loop. -@foreach( detail_maps_diffuse, n )@property( detail_map@n ) - float detailCol@n = texture( textureMaps[@value(detail_map@n_idx)], - vec3( UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), - detailMapIdx@n ) ).w; - detailCol@n = detailWeights.@insertpiece(detail_swizzle@n) * detailCol@n;@end -@end - -@insertpiece( SampleDiffuseMap ) - - /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no - /// diffuse maps, we must initialize it to some value. If there are no diffuse or detail maps, - /// we must not access diffuseCol at all, but rather use material.kD directly (see piece( kD ) ). - @property( !diffuse_map )diffuseCol = material.bgDiffuse.w;@end - - /// Blend the detail diffuse maps with the main diffuse. -@foreach( detail_maps_diffuse, n ) - @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end - - /// Apply the material's alpha over the textures -@property( TODO_REFACTOR_ACCOUNT_MATERIAL_ALPHA ) diffuseCol.xyz *= material.kD.xyz;@end - - if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol ) - discard; -@end /// !alpha_test - - @insertpiece( DoShadowCastPS ) - + @insertpiece( DefaultBodyPS ) @insertpiece( custom_ps_posExecution ) } -@end +@end ///hlms_shadowcaster diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl b/ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl index 5f00ee59f..044f9fa54 100644 --- a/ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl +++ b/ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl @@ -11,8 +11,8 @@ out gl_PerVertex layout(std140) uniform; -@insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) -@insertpiece( Common_Matrix_DeclUnpackMatrix3x4 ) +@insertpiece( DefaultHeaderVS ) +@insertpiece( custom_vs_uniformDeclaration ) in vec4 vertex; @@ -20,16 +20,17 @@ in vec4 vertex; @property( hlms_qtangent )in vec4 qtangent;@end @property( normal_map && !hlms_qtangent ) -in vec3 tangent; -@property( hlms_binormal )in vec3 binormal;@end + in vec3 tangent; + @property( hlms_binormal )in vec3 binormal;@end @end @property( hlms_skeleton ) -in uvec4 blendIndices; -in vec4 blendWeights;@end + in uvec4 blendIndices; + in vec4 blendWeights; +@end @foreach( hlms_uv_count, n ) -in vec@value( hlms_uv_count@n ) uv@n;@end + in vec@value( hlms_uv_count@n ) uv@n;@end @property( GL_ARB_base_instance ) in uint drawId; @@ -38,161 +39,26 @@ in vec@value( hlms_uv_count@n ) uv@n;@end @insertpiece( custom_vs_attributes ) @property( !hlms_shadowcaster || !hlms_shadow_uses_depth_texture || alpha_test || exponential_shadow_maps ) -out block -{ -@insertpiece( VStoPS_block ) -} outVs; + out block + { + @insertpiece( VStoPS_block ) + } outVs; @end -// START UNIFORM DECLARATION -@insertpiece( PassDecl ) -@property( hlms_skeleton || hlms_shadowcaster )@insertpiece( InstanceDecl )@end +// START UNIFORM GL DECLARATION /*layout(binding = 0) */uniform samplerBuffer worldMatBuf; -@insertpiece( custom_vs_uniformDeclaration ) @property( !GL_ARB_base_instance )uniform uint baseInstance;@end -// END UNIFORM DECLARATION - -@property( hlms_qtangent ) -@insertpiece( DeclQuat_xAxis ) -@property( normal_map ) -@insertpiece( DeclQuat_yAxis ) -@end @end - -@property( !hlms_skeleton ) -@piece( local_vertex )vertex@end -@piece( local_normal )normal@end -@piece( local_tangent )tangent@end -@end -@property( hlms_skeleton ) -@piece( local_vertex )worldPos@end -@piece( local_normal )worldNorm@end -@piece( local_tangent )worldTang@end -@end - -@property( hlms_skeleton )@piece( SkeletonTransform ) - uint _idx = (blendIndices[0] << 1u) + blendIndices[0]; //blendIndices[0] * 3u; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) - uint matStart = instance.worldMaterialIdx[drawId].x >> 9u; - vec4 worldMat[3]; - worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); - worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); - worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); - vec4 worldPos; - worldPos.x = dot( worldMat[0], vertex ); - worldPos.y = dot( worldMat[1], vertex ); - worldPos.z = dot( worldMat[2], vertex ); - worldPos.xyz *= blendWeights[0]; - @property( hlms_normal || hlms_qtangent )vec3 worldNorm; - worldNorm.x = dot( worldMat[0].xyz, normal ); - worldNorm.y = dot( worldMat[1].xyz, normal ); - worldNorm.z = dot( worldMat[2].xyz, normal ); - worldNorm *= blendWeights[0];@end - @property( normal_map )vec3 worldTang; - worldTang.x = dot( worldMat[0].xyz, tangent ); - worldTang.y = dot( worldMat[1].xyz, tangent ); - worldTang.z = dot( worldMat[2].xyz, tangent ); - worldTang *= blendWeights[0];@end - - @psub( NeedsMoreThan1BonePerVertex, hlms_bones_per_vertex, 1 ) - @property( NeedsMoreThan1BonePerVertex )vec4 tmp; - tmp.w = 1.0;@end //!NeedsMoreThan1BonePerVertex - @foreach( hlms_bones_per_vertex, n, 1 ) - _idx = (blendIndices[@n] << 1u) + blendIndices[@n]; //blendIndices[@n] * 3; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) - worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); - worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); - worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); - tmp.x = dot( worldMat[0], vertex ); - tmp.y = dot( worldMat[1], vertex ); - tmp.z = dot( worldMat[2], vertex ); - worldPos.xyz += (tmp * blendWeights[@n]).xyz; - @property( hlms_normal || hlms_qtangent ) - tmp.x = dot( worldMat[0].xyz, normal ); - tmp.y = dot( worldMat[1].xyz, normal ); - tmp.z = dot( worldMat[2].xyz, normal ); - worldNorm += tmp.xyz * blendWeights[@n];@end - @property( normal_map ) - tmp.x = dot( worldMat[0].xyz, tangent ); - tmp.y = dot( worldMat[1].xyz, tangent ); - tmp.z = dot( worldMat[2].xyz, tangent ); - worldTang += tmp.xyz * blendWeights[@n];@end - @end - - worldPos.w = 1.0; -@end @end //SkeletonTransform // !hlms_skeleton - -@property( hlms_skeleton ) - @piece( worldViewMat )passBuf.view@end -@end @property( !hlms_skeleton ) - @piece( worldViewMat )worldView@end -@end - -@piece( CalculatePsPos )(@insertpiece(local_vertex) * @insertpiece( worldViewMat )).xyz@end - -@piece( VertexTransform ) -@insertpiece( custom_vs_preTransform ) - //Lighting is in view space - @property( hlms_normal || hlms_qtangent )outVs.pos = @insertpiece( CalculatePsPos );@end - @property( hlms_normal || hlms_qtangent )outVs.normal = @insertpiece(local_normal) * mat3(@insertpiece( worldViewMat ));@end - @property( normal_map )outVs.tangent = @insertpiece(local_tangent) * mat3(@insertpiece( worldViewMat ));@end -@property( !hlms_dual_paraboloid_mapping ) - gl_Position = worldPos * passBuf.viewProj;@end -@property( hlms_dual_paraboloid_mapping ) - //Dual Paraboloid Mapping - gl_Position.w = 1.0f; - @property( hlms_normal || hlms_qtangent )gl_Position.xyz = outVs.pos;@end - @property( !hlms_normal && !hlms_qtangent )gl_Position.xyz = @insertpiece( CalculatePsPos );@end - float L = length( gl_Position.xyz ); - gl_Position.z += 1.0f; - gl_Position.xy /= gl_Position.z; - gl_Position.z = (L - NearPlane) / (FarPlane - NearPlane);@end +@property( hlms_pose ) + uniform samplerBuffer poseBuf; @end +// END UNIFORM GL DECLARATION void main() { @property( !GL_ARB_base_instance ) uint drawId = baseInstance + uint( gl_InstanceID ); @end - @insertpiece( custom_vs_preExecution ) - -@property( !hlms_skeleton ) - - mat3x4 worldMat = UNPACK_MAT3x4( worldMatBuf, drawId @property( !hlms_shadowcaster )<< 1u@end ); - @property( hlms_normal || hlms_qtangent ) - mat4 worldView = UNPACK_MAT4( worldMatBuf, (drawId << 1u) + 1u ); - @end - - vec4 worldPos = vec4( (vertex * worldMat).xyz, 1.0f ); -@end - -@property( hlms_qtangent ) - //Decode qTangent to TBN with reflection - vec3 normal = xAxis( normalize( qtangent ) ); - @property( normal_map ) - vec3 tangent = yAxis( qtangent ); - outVs.biNormalReflection = sign( qtangent.w ); //We ensure in C++ qtangent.w is never 0 - @end -@end - - @insertpiece( SkeletonTransform ) - @insertpiece( VertexTransform ) - - @insertpiece( DoShadowReceiveVS ) - @insertpiece( DoShadowCasterVS ) - - /// hlms_uv_count will be 0 on shadow caster passes w/out alpha test -@foreach( hlms_uv_count, n ) - outVs.uv@n = uv@n;@end - -@property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) - outVs.drawId = drawId;@end - - @property( hlms_use_prepass_msaa > 1 ) - outVs.zwDepth.xy = outVs.gl_Position.zw; - @end - -@property( hlms_global_clip_planes ) - gl_ClipDistance[0] = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); -@end - + @insertpiece( DefaultBodyVS ) @insertpiece( custom_vs_posExecution ) } diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/BRDFs_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/BRDFs_piece_ps.glsl similarity index 96% rename from ogre2/src/media/Hlms/Pbs/GLSL/BRDFs_piece_ps.glsl rename to ogre2/src/media/Hlms/Pbs/GLSLES/BRDFs_piece_ps.glsl index 2aba21aa7..c86fbbd73 100644 --- a/ogre2/src/media/Hlms/Pbs/GLSL/BRDFs_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Pbs/GLSLES/BRDFs_piece_ps.glsl @@ -1,11 +1,11 @@ -@property( !metallic_workflow && (!specular_map || !fresnel_workflow) ) +@property( !metallic_workflow && (!specular_map || !fresnel_workflow) && !hlms_decals_diffuse ) @property( !transparent_mode ) @piece( F0 )material.F0@end @end @property( transparent_mode ) //Premultiply F0.xyz with the alpha from the texture, but only in transparent mode. @piece( F0 )(material.F0.@insertpiece( FresnelSwizzle ) * diffuseCol.w)@end @end -@end @property( metallic_workflow || (specular_map && fresnel_workflow) ) +@end @property( metallic_workflow || (specular_map && fresnel_workflow) || hlms_decals_diffuse ) @piece( F0 )F0@end @end @@ -236,4 +236,5 @@ vec3 BRDF_IR( vec3 lightDir, vec3 lightDiffuse ) @piece( ObjLightMaskCmp )if( (objLightMask & floatBitsToUint( passBuf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u )@end @piece( andObjLightMaskCmp )&& ((objLightMask & floatBitsToUint( passBuf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u)@end @piece( andObjAreaApproxLightMaskCmp )&& ((objLightMask & floatBitsToUint( passBuf.areaApproxLights[@counter(fineMaskAreaApproxLightIdx)].position.w )) != 0u)@end + @piece( andObjAreaLtcLightMaskCmp )&& ((objLightMask & floatBitsToUint( passBuf.areaLtcLights[@counter(fineMaskAreaLtcLightIdx)].position.w )) != 0u)@end @end diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/BlendModes_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/BlendModes_piece_ps.glsl similarity index 100% rename from ogre2/src/media/Hlms/Pbs/GLSL/BlendModes_piece_ps.glsl rename to ogre2/src/media/Hlms/Pbs/GLSLES/BlendModes_piece_ps.glsl diff --git a/ogre2/src/media/Hlms/Pbs/Metal/DetailMaps_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/GLSLES/DetailMaps_piece_ps.glsl similarity index 100% rename from ogre2/src/media/Hlms/Pbs/Metal/DetailMaps_piece_ps.metal rename to ogre2/src/media/Hlms/Pbs/GLSLES/DetailMaps_piece_ps.glsl diff --git a/ogre2/src/media/Hlms/Pbs/GLSLES/Forward3D_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/Forward3D_piece_ps.glsl new file mode 100644 index 000000000..b7edd58ad --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/GLSLES/Forward3D_piece_ps.glsl @@ -0,0 +1,261 @@ +@property( hlms_forwardplus ) + +@property( hlms_forwardplus_fine_light_mask ) + @piece( andObjLightMaskFwdPlusCmp )&& ((objLightMask & floatBitsToUint( lightDiffuse.w )) != 0u)@end +@end + +@property( hlms_enable_decals ) +@piece( DeclDecalsSamplers ) + @property( hlms_decals_diffuse )uniform sampler2DArray decalsDiffuseTex;@end + @property( hlms_decals_normals )uniform sampler2DArray decalsNormalsTex;@end + @property( hlms_decals_diffuse == hlms_decals_emissive ) + #define decalsEmissiveTex decalsDiffuseTex + @end + @property( hlms_decals_emissive && hlms_decals_diffuse != hlms_decals_emissive ) + uniform sampler2DArray decalsEmissiveTex; + @end +@end +@end + +/// The header is automatically inserted. Whichever subsystem needs it first, will call it +@piece( forward3dHeader ) + @property( hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v) + #define FWDPLUS_APPLY_OFFSET_X(v) (v) + @end + + @property( hlms_forwardplus_fine_light_mask && !hlms_fine_light_mask ) + uint objLightMask = instance.worldMaterialIdx[inPs.drawId].z; + @end + @property( hlms_forwardplus == forward3d ) + float f3dMinDistance = passBuf.f3dData.x; + float f3dInvMaxDistance = passBuf.f3dData.y; + float f3dNumSlicesSub1 = passBuf.f3dData.z; + uint cellsPerTableOnGrid0= floatBitsToUint( passBuf.f3dData.w ); + + // See C++'s Forward3D::getSliceAtDepth + /*float fSlice = 1.0 - clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); + fSlice = (fSlice * fSlice) * (fSlice * fSlice); + fSlice = (fSlice * fSlice); + fSlice = floor( (1.0 - fSlice) * f3dNumSlicesSub1 );*/ + float fSlice = clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); + fSlice = floor( fSlice * f3dNumSlicesSub1 ); + uint slice = uint( fSlice ); + + //TODO: Profile performance: derive this mathematically or use a lookup table? + uint offset = cellsPerTableOnGrid0 * (((1u << (slice << 1u)) - 1u) / 3u); + + float lightsPerCell = passBuf.f3dGridHWW[0].w; + + @property( !hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.f3dViewportOffset.y) + #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.f3dViewportOffset.x) + @end + + //passBuf.f3dGridHWW[slice].x = grid_width / renderTarget->width; + //passBuf.f3dGridHWW[slice].y = grid_height / renderTarget->height; + //passBuf.f3dGridHWW[slice].z = grid_width * lightsPerCell; + //uint sampleOffset = 0; + @property( hlms_forwardplus_flipY ) + float windowHeight = passBuf.f3dGridHWW[1].w; //renderTarget->height + uint sampleOffset = offset + + uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) ) * + passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + + uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * + passBuf.f3dGridHWW[slice].x ) * lightsPerCell); + @end @property( !hlms_forwardplus_flipY ) + uint sampleOffset = offset + + uint(floor( FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) * + passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + + uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * + passBuf.f3dGridHWW[slice].x ) * lightsPerCell); + @end + @end @property( hlms_forwardplus != forward3d ) + float f3dMinDistance = passBuf.f3dData.x; + float f3dInvExponentK = passBuf.f3dData.y; + float f3dNumSlicesSub1 = passBuf.f3dData.z; + + // See C++'s ForwardClustered::getSliceAtDepth + float fSlice = log2( max( -inPs.pos.z - f3dMinDistance, 1 ) ) * f3dInvExponentK; + fSlice = floor( min( fSlice, f3dNumSlicesSub1 ) ); + uint sliceSkip = uint( fSlice * @value( fwd_clustered_width_x_height ) ); + + @property( !hlms_forwardplus_covers_entire_target ) + #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.fwdScreenToGrid.w) + #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.fwdScreenToGrid.z) + @end + + uint sampleOffset = sliceSkip + + uint(floor( FWDPLUS_APPLY_OFFSET_X(gl_FragCoord.x) * passBuf.fwdScreenToGrid.x )); + @property( hlms_forwardplus_flipY ) + float windowHeight = passBuf.f3dData.w; //renderTarget->height + sampleOffset += uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) ) * + passBuf.fwdScreenToGrid.y ) * + @value( fwd_clustered_width )); + @end @property( !hlms_forwardplus_flipY ) + sampleOffset += uint(floor( FWDPLUS_APPLY_OFFSET_Y(gl_FragCoord.y) * + passBuf.fwdScreenToGrid.y ) * + @value( fwd_clustered_width )); + @end + + sampleOffset *= @value( fwd_clustered_lights_per_cell )u; + @end + + @property( hlms_forwardplus_debug )uint totalNumLightsInGrid = 0u;@end +@end + +@piece( forward3dLighting ) + @property( !hlms_enable_decals ) + @insertpiece( forward3dHeader ) + uint numLightsInGrid; + @end + + @property( hlms_decals_emissive ) + finalColour += finalDecalEmissive; + @end + + numLightsInGrid = bufferFetch( f3dGrid, int(sampleOffset) ).x; + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + for( uint i=0u; i= spotParams.y ) + { + vec3 tmpColour = BRDF( lightDir, viewDir, NdotV, lightDiffuse.xyz, lightSpecular ); + finalColour += tmpColour * atten; + } + } + } + +@property( hlms_enable_vpls ) + prevLightCount = numLightsInGrid; + numLightsInGrid = bufferFetch( f3dGrid, int(sampleOffset + 2u) ).x; + + @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end + + for( uint i=prevLightCount; i> 16u;@end +@property( specular_map ) specularIdx = material.indices0_3.y & 0x0000FFFFu;@end +@property( roughness_map ) roughnessIdx = material.indices0_3.y >> 16u;@end +@property( detail_weight_map ) weightMapIdx = material.indices0_3.z & 0x0000FFFFu;@end +@property( detail_map0 ) detailMapIdx0 = material.indices0_3.z >> 16u;@end +@property( detail_map1 ) detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;@end +@property( detail_map2 ) detailMapIdx2 = material.indices0_3.w >> 16u;@end +@property( detail_map3 ) detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;@end +@property( detail_map_nm0 ) detailNormMapIdx0 = material.indices4_7.x >> 16u;@end +@property( detail_map_nm1 ) detailNormMapIdx1 = material.indices4_7.y & 0x0000FFFFu;@end +@property( detail_map_nm2 ) detailNormMapIdx2 = material.indices4_7.y >> 16u;@end +@property( detail_map_nm3 ) detailNormMapIdx3 = material.indices4_7.z & 0x0000FFFFu;@end +@property( emissive_map ) emissiveMapIdx = material.indices4_7.z >> 16u;@end +@property( use_envprobe_map ) envMapIdx = material.indices4_7.w & 0x0000FFFFu;@end + + @insertpiece( DeclareObjLightMask ) + + @insertpiece( custom_ps_posMaterialLoad ) + +@property( detail_maps_diffuse || detail_maps_normal ) + //Prepare weight map for the detail maps. + @property( detail_weight_map ) + vec4 detailWeights = @insertpiece( SamplerDetailWeightMap ); + @property( detail_weights )detailWeights *= material.cDetailWeights;@end + @end @property( !detail_weight_map ) + @property( detail_weights )vec4 detailWeights = material.cDetailWeights;@end + @property( !detail_weights )vec4 detailWeights = vec4( 1.0, 1.0, 1.0, 1.0 );@end + @end +@end + + /// Sample detail maps and weight them against the weight map in the next foreach loop. +@foreach( detail_maps_diffuse, n )@property( detail_map@n ) + vec4 detailCol@n = texture( textureMaps[@value(detail_map@n_idx)], + vec3( UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), + detailMapIdx@n ) ); + @property( !hw_gamma_read )//Gamma to linear space + detailCol@n.xyz = detailCol@n.xyz * detailCol@n.xyz;@end + detailWeights.@insertpiece(detail_swizzle@n) *= detailCol@n.w; + detailCol@n.w = detailWeights.@insertpiece(detail_swizzle@n);@end +@end + +@property( !hlms_prepass || alpha_test ) + @insertpiece( SampleDiffuseMap ) + + /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no + /// diffuse maps, we must initialize it to some value. If there are no diffuse or detail maps, + /// we must not access diffuseCol at all, but rather use material.kD directly (see piece( kD ) ). + @property( !diffuse_map )diffuseCol = material.bgDiffuse;@end + + /// Blend the detail diffuse maps with the main diffuse. + @foreach( detail_maps_diffuse, n ) + @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end + + /// Apply the material's diffuse over the textures + @property( !transparent_mode ) + diffuseCol.xyz *= material.kD.xyz; + @end @property( transparent_mode ) + diffuseCol.xyz *= material.kD.xyz * diffuseCol.w * diffuseCol.w; + @end + + @property( alpha_test && !alpha_test_shadow_caster_only ) + if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol.a ) + discard; + @end +@end + + @insertpiece( SampleSpecularMap ) + @insertpiece( SampleRoughnessMap ) + + @insertpiece( forwardPlusDoDecals ) + +@property( !hlms_use_prepass ) + @property( !normal_map ) + // Geometric normal + nNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); + @end @property( normal_map ) + //Normal mapping. + vec3 geomNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); + vec3 vTangent = normalize( inPs.tangent ); + + //Get the TBN matrix + vec3 vBinormal = normalize( cross( geomNormal, vTangent )@insertpiece( tbnApplyReflection ) ); + mat3 TBN = mat3( vTangent, vBinormal, geomNormal ); + + @property( normal_map_tex )nNormal = getTSNormal( vec3( UV_NORMAL( inPs.uv@value(uv_normal).xy ), + normalIdx ) );@end + @property( normal_weight_tex ) + // Apply the weight to the main normal map + nNormal = mix( vec3( 0.0, 0.0, 1.0 ), nNormal, normalMapWeight ); + @end + @end + + /// If there is no normal map, the first iteration must + /// initialize nNormal instead of try to merge with it. + @property( normal_map_tex ) + @piece( detail_nm_op_sum )+=@end + @piece( detail_nm_op_mul )*=@end + @end @property( !normal_map_tex ) + @piece( detail_nm_op_sum )=@end + @piece( detail_nm_op_mul )=@end + @end + + /// Blend the detail normal maps with the main normal. + @foreach( second_valid_detail_map_nm, n, first_valid_detail_map_nm ) + vec3 vDetail = @insertpiece( SampleDetailMapNm@n ); + nNormal.xy @insertpiece( detail_nm_op_sum ) vDetail.xy; + nNormal.z @insertpiece( detail_nm_op_mul ) vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end + @foreach( detail_maps_normal, n, second_valid_detail_map_nm )@property( detail_map_nm@n ) + vDetail = @insertpiece( SampleDetailMapNm@n ); + nNormal.xy += vDetail.xy; + nNormal.z *= vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end @end + + @insertpiece( custom_ps_posSampleNormal ) + + @insertpiece( forwardPlusApplyDecalsNormal ) + + @property( normal_map ) + nNormal = normalize( TBN * nNormal ); + @end + + @insertpiece( DoDirectionalShadowMaps ) + +@end @property( hlms_use_prepass ) + ivec2 iFragCoord = ivec2( gl_FragCoord.x, + @property( !hlms_forwardplus_flipY )passBuf.windowHeight.x - @end + gl_FragCoord.y ); + + @property( hlms_use_prepass_msaa ) + //SV_Coverage/gl_SampleMaskIn is always before depth & stencil tests, + //so we need to perform the test ourselves + //See http://www.yosoygames.com.ar/wp/2017/02/beware-of-sv_coverage/ + float msaaDepth; + int subsampleDepthMask; + float pixelDepthZ; + float pixelDepthW; + float pixelDepth; + int intPixelDepth; + int intMsaaDepth; + //Unfortunately there are precision errors, so we allow some ulp errors. + //200 & 5 are arbitrary, but were empirically found to be very good values. + int ulpError = int( lerp( 200.0, 5.0, gl_FragCoord.z ) ); + @foreach( hlms_use_prepass_msaa, n ) + pixelDepthZ = interpolateAtSample( inPs.zwDepth.x, @n ); + pixelDepthW = interpolateAtSample( inPs.zwDepth.y, @n ); + pixelDepth = pixelDepthZ / pixelDepthW; + msaaDepth = texelFetch( gBuf_depthTexture, iFragCoord.xy, @n ); + intPixelDepth = floatBitsToInt( pixelDepth ); + intMsaaDepth = floatBitsToInt( msaaDepth ); + subsampleDepthMask = int( (abs( intPixelDepth - intMsaaDepth ) <= ulpError) ? 0xffffffffu : ~(1u << @nu) ); + //subsampleDepthMask = int( (pixelDepth <= msaaDepth) ? 0xffffffffu : ~(1u << @nu) ); + gl_SampleMaskIn &= subsampleDepthMask; + @end + + gl_SampleMaskIn[0] = gl_SampleMaskIn[0] == 0u ? 1u : gl_SampleMaskIn[0]; + + int gBufSubsample = findLSB( gl_SampleMaskIn[0] ); + @end @property( !hlms_use_prepass_msaa ) + //On non-msaa RTTs gBufSubsample is the LOD level. + int gBufSubsample = 0; + @end + + nNormal = normalize( texelFetch( gBuf_normals, iFragCoord, gBufSubsample ).xyz * 2.0 - 1.0 ); + vec2 shadowRoughness = texelFetch( gBuf_shadowRoughness, iFragCoord, gBufSubsample ).xy; + + float fShadow = shadowRoughness.x; + + @property( roughness_map ) + ROUGHNESS = shadowRoughness.y * 0.98 + 0.02; /// ROUGHNESS is a constant otherwise + @end +@end + +@property( !hlms_prepass ) + //Everything's in Camera space +@property( hlms_lights_spot || use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere || hlms_forwardplus ) + vec3 viewDir = normalize( -inPs.pos ); + float NdotV = clamp( dot( nNormal, viewDir ), 0.0, 1.0 ); +@end + +@property( !ambient_fixed ) + vec3 finalColour = vec3(0); +@end @property( ambient_fixed ) + vec3 finalColour = passBuf.ambientUpperHemi.xyz * @insertpiece( kD ).xyz; +@end + + @insertpiece( custom_ps_preLights ) + +@property( !custom_disable_directional_lights ) +@property( hlms_lights_directional ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( passBuf.lights[0].position.xyz, viewDir, NdotV, passBuf.lights[0].diffuse, passBuf.lights[0].specular ) @insertpiece(DarkenWithShadowFirstLight); +@end +@foreach( hlms_lights_directional, n, 1 ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadow );@end +@foreach( hlms_lights_directional_non_caster, n, hlms_lights_directional ) + @insertpiece( ObjLightMaskCmp ) + finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular );@end +@end + +@property( hlms_lights_point || hlms_lights_spot || hlms_lights_area_approx || hlms_lights_area_ltc ) vec3 lightDir; + float fDistance; + vec3 tmpColour; + float spotCosAngle;@end + + //Point lights +@foreach( hlms_lights_point, n, hlms_lights_directional_non_caster ) + lightDir = passBuf.lights[@n].position.xyz - inPs.pos; + fDistance= length( lightDir ); + if( fDistance <= passBuf.lights[@n].attenuation.x @insertpiece( andObjLightMaskCmp ) ) + { + lightDir *= 1.0 / fDistance; + tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadowPoint ); + float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); + finalColour += tmpColour * atten; + }@end + + //Spot lights + //spotParams[@value(spot_params)].x = 1.0 / cos( InnerAngle ) - cos( OuterAngle ) + //spotParams[@value(spot_params)].y = cos( OuterAngle / 2 ) + //spotParams[@value(spot_params)].z = falloff +@foreach( hlms_lights_spot, n, hlms_lights_point ) + lightDir = passBuf.lights[@n].position.xyz - inPs.pos; + fDistance= length( lightDir ); +@property( !hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), passBuf.lights[@n].spotDirection.xyz );@end +@property( hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), zAxis( passBuf.lights[@n].spotQuaternion ) );@end + if( fDistance <= passBuf.lights[@n].attenuation.x && spotCosAngle >= passBuf.lights[@n].spotParams.y @insertpiece( andObjLightMaskCmp ) ) + { + lightDir *= 1.0 / fDistance; + @property( hlms_lights_spot_textured ) + vec3 posInLightSpace = qmul( spotQuaternion[@value(spot_params)], inPs.pos ); + float spotAtten = texture( texSpotLight, normalize( posInLightSpace ).xy ).x; + @end + @property( !hlms_lights_spot_textured ) + float spotAtten = clamp( (spotCosAngle - passBuf.lights[@n].spotParams.y) * passBuf.lights[@n].spotParams.x, 0.0, 1.0 ); + spotAtten = pow( spotAtten, passBuf.lights[@n].spotParams.z ); + @end + tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular )@insertpiece( DarkenWithShadow ); + float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); + finalColour += tmpColour * (atten * spotAtten); + }@end + + //Custom 2D shape lights + @insertpiece( DoAreaApproxLights ) + @insertpiece( DoAreaLtcLights ) + +@insertpiece( forward3dLighting ) +@insertpiece( applyIrradianceVolumes ) + +@property( emissive_map || emissive_constant ) + @insertpiece( SampleEmissiveMap ) + finalColour += emissiveCol.xyz; +@end + +@property( use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere ) + vec3 reflDir = 2.0 * dot( viewDir, nNormal ) * nNormal - viewDir; + + @property( use_envprobe_map ) + @property( use_parallax_correct_cubemaps ) + vec3 envColourS; + vec3 envColourD; + vec3 posInProbSpace = toProbeLocalSpace( inPs.pos, @insertpiece( pccProbeSource ) ); + float probeFade = getProbeFade( posInProbSpace, @insertpiece( pccProbeSource ) ); + if( probeFade > 0 ) + { + vec3 reflDirLS = localCorrect( reflDir, posInProbSpace, @insertpiece( pccProbeSource ) ); + vec3 nNormalLS = localCorrect( nNormal, posInProbSpace, @insertpiece( pccProbeSource ) ); + envColourS = textureLod( texEnvProbeMap, + reflDirLS, ROUGHNESS * 12.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; + envColourD = textureLod( texEnvProbeMap, + nNormalLS, 11.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; + + envColourS = envColourS * clamp( probeFade * 200.0, 0.0, 1.0 ); + envColourD = envColourD * clamp( probeFade * 200.0, 0.0, 1.0 ); + } + else + { + //TODO: Fallback to a global cubemap. + envColourS = vec3( 0, 0, 0 ); + envColourD = vec3( 0, 0, 0 ); + } + @end @property( !use_parallax_correct_cubemaps ) + vec3 envColourS = textureLod( texEnvProbeMap, reflDir * passBuf.invViewMatCubemap, ROUGHNESS * 12.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; + vec3 envColourD = textureLod( texEnvProbeMap, nNormal * passBuf.invViewMatCubemap, 11.0 ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; + @end + @property( !hw_gamma_read ) //Gamma to linear space + envColourS = envColourS * envColourS; + envColourD = envColourD * envColourD; + @end + @end + + @property( hlms_use_ssr ) + //TODO: SSR pass should be able to combine global & local cubemap. + vec4 ssrReflection = texelFetch( ssrTexture, iFragCoord, 0 ).xyzw; + @property( use_envprobe_map ) + envColourS = mix( envColourS.xyz, ssrReflection.xyz, ssrReflection.w ); + @end @property( !use_envprobe_map ) + vec3 envColourS = ssrReflection.xyz * ssrReflection.w; + vec3 envColourD = vec3( 0, 0, 0 ); + @end + @end + + @insertpiece( DoPlanarReflectionsPS ) + + @property( ambient_hemisphere ) + float ambientWD = dot( passBuf.ambientHemisphereDir.xyz, nNormal ) * 0.5 + 0.5; + float ambientWS = dot( passBuf.ambientHemisphereDir.xyz, reflDir ) * 0.5 + 0.5; + + @property( use_envprobe_map || hlms_use_ssr || use_planar_reflections ) + envColourS += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); + envColourD += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); + @end @property( !use_envprobe_map && !hlms_use_ssr && !use_planar_reflections ) + vec3 envColourS = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); + vec3 envColourD = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); + @end + @end + + @insertpiece( BRDF_EnvMap ) +@end +@end ///!hlms_prepass + +@property( !hlms_render_depth_only ) + @property( !hlms_prepass ) + @property( !hw_gamma_write ) + //Linear to Gamma space + outColour.xyz = sqrt( finalColour ); + @end @property( hw_gamma_write ) + outColour.xyz = finalColour; + @end + + @property( hlms_alphablend ) + @property( use_texture_alpha ) + outColour.w = material.F0.w * diffuseCol.w; + @end @property( !use_texture_alpha ) + outColour.w = material.F0.w; + @end + @end @property( !hlms_alphablend ) + outColour.w = 1.0;@end + + @end @property( !hlms_normal && !hlms_qtangent ) + outColour = vec4( 1.0, 1.0, 1.0, 1.0 ); + @end + + @property( debug_pssm_splits ) + outColour.xyz = mix( outColour.xyz, debugPssmSplit.xyz, 0.2f ); + @end + @end @property( hlms_prepass ) + outNormals = vec4( nNormal * 0.5 + 0.5, 1.0 ); + @property( hlms_pssm_splits ) + outShadowRoughness = vec2( fShadow, (ROUGHNESS - 0.02) * 1.02040816 ); + @end @property( !hlms_pssm_splits ) + outShadowRoughness = vec2( 1.0, (ROUGHNESS - 0.02) * 1.02040816 ); + @end + @end +@end + + @insertpiece( custom_ps_posExecution ) +} +@end +@property( hlms_shadowcaster ) + +@insertpiece( DeclShadowCasterMacros ) + +@property( alpha_test ) + Material material; + float diffuseCol; + @property( num_textures )uniform sampler2DArray textureMaps[@value( num_textures )];@end + @property( diffuse_map )uint diffuseIdx;@end + @property( detail_weight_map )uint weightMapIdx;@end + @foreach( 4, n ) + @property( detail_map@n )uint detailMapIdx@n;@end @end +@end + +@property( hlms_shadowcaster_point || exponential_shadow_maps ) + @insertpiece( PassDecl ) +@end + +void main() +{ + @insertpiece( custom_ps_preExecution ) + +@property( alpha_test ) + @property( !lower_gpu_overhead ) + uint materialId = instance.worldMaterialIdx[inPs.drawId].x & 0x1FFu; + material = materialArray.m[materialId]; + @end @property( lower_gpu_overhead ) + material = materialArray.m[0]; + @end +@property( diffuse_map ) diffuseIdx = material.indices0_3.x & 0x0000FFFFu;@end +@property( detail_weight_map ) weightMapIdx = material.indices0_3.z & 0x0000FFFFu;@end +@property( detail_map0 ) detailMapIdx0 = material.indices0_3.z >> 16u;@end +@property( detail_map1 ) detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;@end +@property( detail_map2 ) detailMapIdx2 = material.indices0_3.w >> 16u;@end +@property( detail_map3 ) detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;@end + +@property( detail_maps_diffuse || detail_maps_normal ) + //Prepare weight map for the detail maps. + @property( detail_weight_map ) + vec4 detailWeights = @insertpiece( SamplerDetailWeightMap ); + @property( detail_weights )detailWeights *= material.cDetailWeights;@end + @end @property( !detail_weight_map ) + @property( detail_weights )vec4 detailWeights = material.cDetailWeights;@end + @property( !detail_weights )vec4 detailWeights = vec4( 1.0, 1.0, 1.0, 1.0 );@end + @end +@end + + /// Sample detail maps and weight them against the weight map in the next foreach loop. +@foreach( detail_maps_diffuse, n )@property( detail_map@n ) + float detailCol@n = texture( textureMaps[@value(detail_map@n_idx)], + vec3( UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), + detailMapIdx@n ) ).w; + detailCol@n = detailWeights.@insertpiece(detail_swizzle@n) * detailCol@n;@end +@end + +@insertpiece( SampleDiffuseMap ) + + /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no + /// diffuse maps, we must initialize it to some value. If there are no diffuse or detail maps, + /// we must not access diffuseCol at all, but rather use material.kD directly (see piece( kD ) ). + @property( !diffuse_map )diffuseCol = material.bgDiffuse.w;@end + + /// Blend the detail diffuse maps with the main diffuse. +@foreach( detail_maps_diffuse, n ) + @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end + + /// Apply the material's alpha over the textures +@property( TODO_REFACTOR_ACCOUNT_MATERIAL_ALPHA ) diffuseCol.xyz *= material.kD.xyz;@end + + if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol ) + discard; +@end /// !alpha_test + + @insertpiece( DoShadowCastPS ) + + @insertpiece( custom_ps_posExecution ) +} +@end diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/Structs_piece_vs_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/Structs_piece_vs_piece_ps.glsl similarity index 95% rename from ogre2/src/media/Hlms/Pbs/GLSL/Structs_piece_vs_piece_ps.glsl rename to ogre2/src/media/Hlms/Pbs/GLSLES/Structs_piece_vs_piece_ps.glsl index 8ef0c15aa..b6b5dfc43 100644 --- a/ogre2/src/media/Hlms/Pbs/GLSL/Structs_piece_vs_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Pbs/GLSLES/Structs_piece_vs_piece_ps.glsl @@ -48,6 +48,14 @@ struct AreaLight vec4 doubleSided; }; +struct AreaLtcLight +{ + vec4 position; //.w contains the objLightMask + vec4 diffuse; //.w contains attenuation range + vec4 specular; //.w contains doubleSided + vec3 points[4]; +}; + @insertpiece( DeclCubemapProbeStruct ) //Uniforms that change per pass @@ -101,6 +109,7 @@ layout_constbuffer(binding = 0) uniform PassBuffer float pssmFadePoint;@end @property( hlms_lights_spot )Light lights[@value(hlms_lights_spot)];@end @property( hlms_lights_area_approx )AreaLight areaApproxLights[@value(hlms_lights_area_approx)];@end + @property( hlms_lights_area_ltc )AreaLtcLight areaLtcLights[@value(hlms_lights_area_ltc)];@end @end @property( hlms_shadowcaster ) //Vertex shader @property( exponential_shadow_maps )vec4 viewZRow;@end @@ -188,7 +197,7 @@ layout_constbuffer(binding = 2) uniform InstanceBuffer // //.z = //lightMask. Ogre must have been compiled with OGRE_NO_FINE_LIGHT_MASK_GRANULARITY - uvec4 worldMaterialIdx[4096]; + uvec4 worldMaterialIdx[1024]; } instance; @end diff --git a/ogre2/src/media/Hlms/Pbs/GLSL/Textures_piece_ps.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/Textures_piece_ps.glsl similarity index 56% rename from ogre2/src/media/Hlms/Pbs/GLSL/Textures_piece_ps.glsl rename to ogre2/src/media/Hlms/Pbs/GLSLES/Textures_piece_ps.glsl index cbc01aec0..32f7281b3 100644 --- a/ogre2/src/media/Hlms/Pbs/GLSL/Textures_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Pbs/GLSLES/Textures_piece_ps.glsl @@ -18,36 +18,65 @@ @property( !hlms_prepass ) @property( !metallic_workflow ) @property( specular_map && !fresnel_workflow ) - @piece( SampleSpecularMap ) specularCol = texture( textureMaps[@value( specular_map_idx )], - vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx) ).xyz * material.kS.xyz;@end + @piece( SampleSpecularMap ) + specularCol = texture( textureMaps[@value( specular_map_idx )], + vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + specularIdx) ).xyz * material.kS.xyz; + @property( hlms_decals_diffuse ) + F0 = material.F0.@insertpiece( FresnelSwizzle ); + @end + @end @piece( kS )specularCol@end @end @property( specular_map && fresnel_workflow ) - @piece( SampleSpecularMap ) F0 = texture( textureMaps[@value( specular_map_idx )], - vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx) ).@insertpiece( FresnelSwizzle ) * material.F0.@insertpiece( FresnelSwizzle );@end + @piece( SampleSpecularMap ) + F0 = texture( textureMaps[@value( specular_map_idx )], + vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + specularIdx) ).@insertpiece( FresnelSwizzle ) * material.F0.@insertpiece( FresnelSwizzle ); + @property( hlms_decals_diffuse ) + specularCol.xyz = material.kS.xyz; + @end + @end @end @property( !specular_map || fresnel_workflow ) - @piece( kS )material.kS@end - @end -@end @property( metallic_workflow ) -@piece( SampleSpecularMap ) - @property( specular_map ) - float metalness = texture( textureMaps[@value( specular_map_idx )], - vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx) ).x * material.F0.x; - F0 = mix( vec3( 0.03f ), @insertpiece( kD ).xyz * 3.14159f, metalness ); - @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * metalness; - @end @property( !specular_map ) - F0 = mix( vec3( 0.03f ), @insertpiece( kD ).xyz * 3.14159f, material.F0.x ); - @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * material.F0.x; + @property( !hlms_decals_diffuse ) + @piece( kS )material.kS@end + @end + @property( hlms_decals_diffuse ) + @property( !specular_map ) + //We'll need write access to F0 & specularCol + @piece( SampleSpecularMap ) + F0 = material.F0.@insertpiece( FresnelSwizzle ); + specularCol.xyz = material.kS.xyz; + @end + @end + @piece( kS )specularCol@end + @end @end - @property( hlms_alphablend )F0 *= material.F0.w;@end - @property( transparent_mode )F0 *= diffuseCol.w;@end -@end /// SampleSpecularMap +@end +@property( metallic_workflow ) + @piece( SampleSpecularMap ) + @property( specular_map ) + float metalness = texture( textureMaps[@value( specular_map_idx )], + vec3( UV_SPECULAR( inPs.uv@value(uv_specular).xy ), + specularIdx) ).x * material.F0.x; + F0 = mix( vec3( 0.03f ), @insertpiece( kD ).xyz * 3.14159f, metalness ); + @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * metalness; + @end @property( !specular_map ) + F0 = mix( vec3( 0.03f ), @insertpiece( kD ).xyz * 3.14159f, material.F0.x ); + @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * material.F0.x; + @end + @property( hlms_alphablend )F0 *= material.F0.w;@end + @property( transparent_mode )F0 *= diffuseCol.w;@end + @property( hlms_decals_diffuse )specularCol.xyz = material.kS.xyz;@end + @end /// SampleSpecularMap - @piece( kS )material.kS.xyz@end + @property( !hlms_decals_diffuse ) + @piece( kS )material.kS.xyz@end + @end + @property( hlms_decals_diffuse ) + @piece( kS )specularCol@end + @end @end @end @@ -59,6 +88,10 @@ ROUGHNESS = max( ROUGHNESS, 0.001f ); @end @end +@property( !roughness_map && hlms_decals_diffuse ) + //We'll need write access to ROUGHNESS + @piece( SampleRoughnessMap )ROUGHNESS = material.kS.w;@end +@end @foreach( detail_maps_normal, n ) @piece( SampleDetailMapNm@n )getTSDetailNormal( textureMaps[@value(detail_map_nm@n_idx)], diff --git a/ogre2/src/media/Hlms/Pbs/GLSLES/VertexShader_vs.glsl b/ogre2/src/media/Hlms/Pbs/GLSLES/VertexShader_vs.glsl new file mode 100644 index 000000000..38b8b022e --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/GLSLES/VertexShader_vs.glsl @@ -0,0 +1,294 @@ +@insertpiece( SetCrossPlatformSettings ) +@insertpiece( SetCompatibilityLayer ) + +@property( GL3+ ) +out gl_PerVertex +{ + vec4 gl_Position; +@property( hlms_global_clip_planes ) + float gl_ClipDistance[@value(hlms_global_clip_planes)]; +@end +}; +@end + +layout(std140) uniform; + +@insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) +@insertpiece( Common_Matrix_DeclUnpackMatrix3x4 ) + +in vec4 vertex; + +@property( hlms_normal )in vec3 normal;@end +@property( hlms_qtangent )in vec4 qtangent;@end + +@property( normal_map && !hlms_qtangent ) +in vec3 tangent; +@property( hlms_binormal )in vec3 binormal;@end +@end + +@property( hlms_skeleton ) +in uvec4 blendIndices; +in vec4 blendWeights;@end + +@foreach( hlms_uv_count, n ) +in vec@value( hlms_uv_count@n ) uv@n;@end + +@property( GL_ARB_base_instance ) + in uint drawId; +@end + +@insertpiece( custom_vs_attributes ) + +@property( !hlms_shadowcaster || !hlms_shadow_uses_depth_texture || alpha_test || exponential_shadow_maps ) +out block +{ +@insertpiece( VStoPS_block ) +} outVs; +@end + +// START UNIFORM DECLARATION +@insertpiece( PassDecl ) +@property( hlms_skeleton || hlms_shadowcaster || hlms_pose )@insertpiece( InstanceDecl )@end +/*layout(binding = 0) */uniform samplerBuffer worldMatBuf; +@insertpiece( custom_vs_uniformDeclaration ) +@property( !GL_ARB_base_instance )uniform uint baseInstance;@end +@property( hlms_pose ) + uniform samplerBuffer poseBuf; +@end +// END UNIFORM DECLARATION + +@property( hlms_qtangent ) +@insertpiece( DeclQuat_xAxis ) +@property( normal_map ) +@insertpiece( DeclQuat_yAxis ) +@end @end + +@property( !hlms_pose ) +@piece( input_vertex )vertex@end +@end +@property( hlms_pose ) +@piece( input_vertex )inputPos@end +@end + +@property( !hlms_pose_normals ) +@piece( input_normal )normal@end +@end +@property( hlms_pose_normals ) +@piece( input_normal )inputNormal@end +@end + +@property( !hlms_skeleton ) +@piece( local_vertex )@insertpiece( input_vertex )@end +@piece( local_normal )@insertpiece( input_normal )@end +@piece( local_tangent )tangent@end +@end +@property( hlms_skeleton ) +@piece( local_vertex )worldPos@end +@piece( local_normal )worldNorm@end +@piece( local_tangent )worldTang@end +@end + +@property( hlms_skeleton )@piece( SkeletonTransform ) + uint _idx = (blendIndices[0] << 1u) + blendIndices[0]; //blendIndices[0] * 3u; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) + uint matStart = instance.worldMaterialIdx[drawId].x >> 9u; + vec4 worldMat[3]; + worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); + worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); + worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); + vec4 worldPos; + worldPos.x = dot( worldMat[0], @insertpiece( input_vertex ) ); + worldPos.y = dot( worldMat[1], @insertpiece( input_vertex ) ); + worldPos.z = dot( worldMat[2], @insertpiece( input_vertex ) ); + worldPos.xyz *= blendWeights[0]; + @property( hlms_normal || hlms_qtangent )vec3 worldNorm; + worldNorm.x = dot( worldMat[0].xyz, @insertpiece( input_normal ) ); + worldNorm.y = dot( worldMat[1].xyz, @insertpiece( input_normal ) ); + worldNorm.z = dot( worldMat[2].xyz, @insertpiece( input_normal ) ); + worldNorm *= blendWeights[0];@end + @property( normal_map )vec3 worldTang; + worldTang.x = dot( worldMat[0].xyz, tangent ); + worldTang.y = dot( worldMat[1].xyz, tangent ); + worldTang.z = dot( worldMat[2].xyz, tangent ); + worldTang *= blendWeights[0];@end + + @psub( NeedsMoreThan1BonePerVertex, hlms_bones_per_vertex, 1 ) + @property( NeedsMoreThan1BonePerVertex )vec4 tmp; + tmp.w = 1.0;@end //!NeedsMoreThan1BonePerVertex + @foreach( hlms_bones_per_vertex, n, 1 ) + _idx = (blendIndices[@n] << 1u) + blendIndices[@n]; //blendIndices[@n] * 3; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) + worldMat[0] = bufferFetch( worldMatBuf, int(matStart + _idx + 0u) ); + worldMat[1] = bufferFetch( worldMatBuf, int(matStart + _idx + 1u) ); + worldMat[2] = bufferFetch( worldMatBuf, int(matStart + _idx + 2u) ); + tmp.x = dot( worldMat[0], @insertpiece( input_vertex ) ); + tmp.y = dot( worldMat[1], @insertpiece( input_vertex ) ); + tmp.z = dot( worldMat[2], @insertpiece( input_vertex ) ); + worldPos.xyz += (tmp * blendWeights[@n]).xyz; + @property( hlms_normal || hlms_qtangent ) + tmp.x = dot( worldMat[0].xyz, @insertpiece( input_normal ) ); + tmp.y = dot( worldMat[1].xyz, @insertpiece( input_normal ) ); + tmp.z = dot( worldMat[2].xyz, @insertpiece( input_normal ) ); + worldNorm += tmp.xyz * blendWeights[@n];@end + @property( normal_map ) + tmp.x = dot( worldMat[0].xyz, tangent ); + tmp.y = dot( worldMat[1].xyz, tangent ); + tmp.z = dot( worldMat[2].xyz, tangent ); + worldTang += tmp.xyz * blendWeights[@n];@end + @end + + worldPos.w = 1.0; +@end @end //SkeletonTransform // !hlms_skeleton + +@property( hlms_pose )@piece( PoseTransform ) + // Pose data starts after all 3x4 bone matrices + int poseDataStart = int(instance.worldMaterialIdx[drawId].x >> 9u) @property( hlms_skeleton ) + @value(hlms_bones_per_vertex) * 3@end ; + vec4 inputPos = vertex; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) )vec3 inputNormal = normal;@end + + vec4 poseData = bufferFetch( worldMatBuf, poseDataStart ); + int baseVertexID = int(floatBitsToUint( poseData.x )); + int vertexID = gl_VertexID - baseVertexID; + + @psub( MoreThanOnePose, hlms_pose, 1 ) + @property( !MoreThanOnePose ) + vec4 poseWeights = bufferFetch( worldMatBuf, poseDataStart + 1 ); + vec4 posePos = bufferFetch( poseBuf, vertexID @property( hlms_pose_normals )<< 1@end ); + inputPos += posePos * poseWeights.x; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + vec4 poseNormal = bufferFetch( poseBuf, (vertexID << 1) + 1 ); + inputNormal += poseNormal.xyz * poseWeights.x; + @end + @pset( NumPoseWeightVectors, 1 ) + @end @property( MoreThanOnePose ) + // NumPoseWeightVectors = (hlms_pose / 4) + min(hlms_pose % 4, 1) + @pdiv( NumPoseWeightVectorsA, hlms_pose, 4 ) + @pmod( NumPoseWeightVectorsB, hlms_pose, 4 ) + @pmin( NumPoseWeightVectorsC, NumPoseWeightVectorsB, 1 ) + @padd( NumPoseWeightVectors, NumPoseWeightVectorsA, NumPoseWeightVectorsC) + int numVertices = int(floatBitsToUint( poseData.y )); + + @psub( MoreThanOnePoseWeightVector, NumPoseWeightVectors, 1) + @property( !MoreThanOnePoseWeightVector ) + vec4 poseWeights = bufferFetch( worldMatBuf, poseDataStart + 1 ); + @foreach( hlms_pose, n ) + inputPos += bufferFetch( poseBuf, (vertexID + numVertices * @n) @property( hlms_pose_normals )<< 1@end ) * poseWeights[@n]; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + inputNormal += bufferFetch( poseBuf, ((vertexID + numVertices * @n) << 1) + 1 ).xyz * poseWeights[@n]; + @end + @end + @end @property( MoreThanOnePoseWeightVector ) + float poseWeights[@value(NumPoseWeightVectors) * 4]; + @foreach( NumPoseWeightVectors, n) + vec4 weights@n = bufferFetch( worldMatBuf, poseDataStart + 1 + @n ); + poseWeights[@n * 4 + 0] = weights@n[0]; + poseWeights[@n * 4 + 1] = weights@n[1]; + poseWeights[@n * 4 + 2] = weights@n[2]; + poseWeights[@n * 4 + 3] = weights@n[3]; + @end + @foreach( hlms_pose, n ) + inputPos += bufferFetch( poseBuf, (vertexID + numVertices * @n) @property( hlms_pose_normals )<< 1@end ) * poseWeights[@n]; + @property( hlms_pose_normals && (hlms_normal || hlms_qtangent) ) + inputNormal += bufferFetch( poseBuf, ((vertexID + numVertices * @n) << 1) + 1 ).xyz * poseWeights[@n]; + @end + @end + @end + @end + + // If hlms_skeleton is defined the transforms will be provided by bones. + // If hlms_pose is not combined with hlms_skeleton the object's worldMat and worldView have to be set. + @property( !hlms_skeleton ) + vec4 worldMat[3]; + worldMat[0] = bufferFetch( worldMatBuf, poseDataStart + @value(NumPoseWeightVectors) + 1 ); + worldMat[1] = bufferFetch( worldMatBuf, poseDataStart + @value(NumPoseWeightVectors) + 2 ); + worldMat[2] = bufferFetch( worldMatBuf, poseDataStart + @value(NumPoseWeightVectors) + 3 ); + vec4 worldPos; + worldPos.x = dot( worldMat[0], inputPos ); + worldPos.y = dot( worldMat[1], inputPos ); + worldPos.z = dot( worldMat[2], inputPos ); + worldPos.w = 1.0; + + @property( hlms_normal || hlms_qtangent ) + @foreach( 4, n ) + vec4 row@n = bufferFetch( worldMatBuf, poseDataStart + @value(NumPoseWeightVectors) + 4 + @n ); @end + mat4 worldView = mat4( row0, row1, row2, row3 ); + @end + @end +@end @end // PoseTransform + +@property( hlms_skeleton ) + @piece( worldViewMat )passBuf.view@end +@end @property( !hlms_skeleton ) + @piece( worldViewMat )worldView@end +@end + +@piece( CalculatePsPos )(@insertpiece(local_vertex) * @insertpiece( worldViewMat )).xyz@end + +@piece( VertexTransform ) +@insertpiece( custom_vs_preTransform ) + //Lighting is in view space + @property( hlms_normal || hlms_qtangent )outVs.pos = @insertpiece( CalculatePsPos );@end + @property( hlms_normal || hlms_qtangent )outVs.normal = @insertpiece(local_normal) * mat3(@insertpiece( worldViewMat ));@end + @property( normal_map )outVs.tangent = @insertpiece(local_tangent) * mat3(@insertpiece( worldViewMat ));@end +@property( !hlms_dual_paraboloid_mapping ) + gl_Position = worldPos * passBuf.viewProj;@end +@property( hlms_dual_paraboloid_mapping ) + //Dual Paraboloid Mapping + gl_Position.w = 1.0f; + @property( hlms_normal || hlms_qtangent )gl_Position.xyz = outVs.pos;@end + @property( !hlms_normal && !hlms_qtangent )gl_Position.xyz = @insertpiece( CalculatePsPos );@end + float L = length( gl_Position.xyz ); + gl_Position.z += 1.0f; + gl_Position.xy /= gl_Position.z; + gl_Position.z = (L - NearPlane) / (FarPlane - NearPlane);@end +@end + +void main() +{ +@property( !GL_ARB_base_instance ) + uint drawId = baseInstance + uint( gl_InstanceID ); +@end + + @insertpiece( custom_vs_preExecution ) + +@property( !hlms_skeleton && !hlms_pose ) + + mat3x4 worldMat = UNPACK_MAT3x4( worldMatBuf, drawId @property( !hlms_shadowcaster )<< 1u@end ); + @property( hlms_normal || hlms_qtangent ) + mat4 worldView = UNPACK_MAT4( worldMatBuf, (drawId << 1u) + 1u ); + @end + + vec4 worldPos = vec4( (vertex * worldMat).xyz, 1.0f ); +@end + +@property( hlms_qtangent ) + //Decode qTangent to TBN with reflection + vec3 normal = xAxis( normalize( qtangent ) ); + @property( normal_map ) + vec3 tangent = yAxis( qtangent ); + outVs.biNormalReflection = sign( qtangent.w ); //We ensure in C++ qtangent.w is never 0 + @end +@end + + @insertpiece( PoseTransform ) + @insertpiece( SkeletonTransform ) + @insertpiece( VertexTransform ) + + @insertpiece( DoShadowReceiveVS ) + @insertpiece( DoShadowCasterVS ) + + /// hlms_uv_count will be 0 on shadow caster passes w/out alpha test +@foreach( hlms_uv_count, n ) + outVs.uv@n = uv@n;@end + +@property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) + outVs.drawId = drawId;@end + + @property( hlms_use_prepass_msaa > 1 ) + outVs.zwDepth.xy = outVs.gl_Position.zw; + @end + +@property( hlms_global_clip_planes ) + gl_ClipDistance[0] = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); +@end + + @insertpiece( custom_vs_posExecution ) +} diff --git a/ogre2/src/media/Hlms/Pbs/HLSL/Forward3D_piece_ps.hlsl b/ogre2/src/media/Hlms/Pbs/HLSL/Forward3D_piece_ps.hlsl new file mode 100644 index 000000000..b5e41431b --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/HLSL/Forward3D_piece_ps.hlsl @@ -0,0 +1,17 @@ +@property( hlms_forwardplus ) + +@property( hlms_enable_decals ) + @piece( DeclDecalsSamplers ) + SamplerState decalsSampler : register(s@value(decalsSampler)); + @property( hlms_decals_diffuse )Texture2DArray decalsDiffuseTex : register(t@value(decalsDiffuseTex));@end + @property( hlms_decals_normals )Texture2DArray decalsNormalsTex : register(t@value(decalsNormalsTex));@end + @property( hlms_decals_diffuse == hlms_decals_emissive ) + #define decalsEmissiveTex decalsDiffuseTex + @end + @property( hlms_decals_emissive && hlms_decals_diffuse != hlms_decals_emissive ) + Texture2DArray decalsEmissiveTex : register(t@value(decalsEmissiveTex)); + @end + @end +@end + +@end diff --git a/ogre2/src/media/Hlms/Pbs/HLSL/PixelShader_ps.hlsl b/ogre2/src/media/Hlms/Pbs/HLSL/PixelShader_ps.hlsl new file mode 100644 index 000000000..8a44cba6c --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/HLSL/PixelShader_ps.hlsl @@ -0,0 +1,188 @@ + +//#include "SyntaxHighlightingMisc.h" + +@insertpiece( SetCrossPlatformSettings ) +@insertpiece( DeclareUvModifierMacros ) + +// START UNIFORM DECLARATION +@property( !hlms_shadowcaster || alpha_test ) + @property( !hlms_shadowcaster ) + @insertpiece( PassStructDecl ) + @end + @insertpiece( MaterialStructDecl ) + @insertpiece( InstanceStructDecl ) + @insertpiece( PccManualProbeDecl ) +@end +@insertpiece( custom_ps_uniformDeclaration ) +// END UNIFORM DECLARATION + +@insertpiece( DeclLightProfilesTexture ) + +@insertpiece( DefaultHeaderPS ) + +struct PS_INPUT +{ +@insertpiece( VStoPS_block ) +}; + +@property( !hlms_shadowcaster ) + +@property( !hlms_render_depth_only ) + @property( hlms_gen_normals_gbuffer ) + #define outPs_normals outPs.normals + @end + @property( hlms_prepass ) + #define outPs_shadowRoughness outPs.shadowRoughness + @end +@end + +@property( hlms_use_prepass ) + @property( !hlms_use_prepass_msaa ) + Texture2D gBuf_normals : register(t@value(gBuf_normals)); + Texture2D gBuf_shadowRoughness : register(t@value(gBuf_shadowRoughness)); + @else + Texture2DMS gBuf_normals : register(t@value(gBuf_normals)); + Texture2DMS gBuf_shadowRoughness : register(t@value(gBuf_shadowRoughness)); + Texture2DMS gBuf_depthTexture : register(t@value(gBuf_depthTexture)); + @end + + @property( hlms_use_ssr ) + Texture2D ssrTexture : register(t@value(ssrTexture)); + @end +@end + +@property( hlms_ss_refractions_available ) + @property( !hlms_use_prepass || !hlms_use_prepass_msaa ) + @property( !hlms_use_prepass_msaa ) + Texture2D gBuf_depthTexture : register(t@value(gBuf_depthTexture)); + #define depthTextureNoMsaa gBuf_depthTexture + @else + Texture2D depthTextureNoMsaa : register(t@value(depthTextureNoMsaa)); + @end + @end + Texture2D refractionMap : register(t@value(refractionMap)); + SamplerState refractionMapSampler : register(s@value(refractionMap)); +@end + +@insertpiece( DeclPlanarReflTextures ) +@insertpiece( DeclAreaApproxTextures ) + +@property( hlms_forwardplus ) + Buffer f3dGrid : register(t@value(f3dGrid)); + Buffer f3dLightList : register(t@value(f3dLightList)); +@end + +@property( irradiance_volumes ) + Texture3D irradianceVolume : register(t@value(irradianceVolume)); + SamplerState irradianceVolumeSampler : register(s@value(irradianceVolume)); +@end + +@foreach( num_textures, n ) + Texture2DArray textureMaps@n : register(t@value(textureMaps@n));@end + +@property( use_envprobe_map ) + @property( !hlms_enable_cubemaps_auto ) + TextureCube texEnvProbeMap : register(t@value(texEnvProbeMap)); + @else + @property( !hlms_cubemaps_use_dpm ) + TextureCubeArray texEnvProbeMap : register(t@value(texEnvProbeMap)); + @else + @property( use_envprobe_map )Texture2DArray texEnvProbeMap : register(t@value(texEnvProbeMap));@end + @insertpiece( DeclDualParaboloidFunc ) + @end + @end + @property( envMapRegSampler < samplerStateStart ) + SamplerState samplerState@value(envMapRegSampler) : register(s@value(envMapRegSampler)); + @end +@end + +@foreach( num_samplers, n ) + SamplerState samplerState@value(samplerStateStart) : register(s@counter(samplerStateStart));@end + +@property( use_parallax_correct_cubemaps ) + @insertpiece( DeclParallaxLocalCorrect ) +@end + +@insertpiece( DeclDecalsSamplers ) + +@insertpiece( DeclShadowMapMacros ) +@insertpiece( DeclShadowSamplers ) +@insertpiece( DeclShadowSamplingFuncs ) + +@insertpiece( DeclAreaLtcTextures ) +@insertpiece( DeclAreaLtcLightFuncs ) + +@insertpiece( DeclVctTextures ) +@insertpiece( DeclIrradianceFieldTextures ) + +@insertpiece( DeclOutputType ) + +@insertpiece( custom_ps_functions ) + +@insertpiece( output_type ) main +( + PS_INPUT inPs + @property( hlms_vpos ), float4 gl_FragCoord : SV_Position@end + @property( two_sided_lighting ), bool gl_FrontFacing : SV_IsFrontFace@end + @property( hlms_use_prepass_msaa && hlms_use_prepass ), uint gl_SampleMask : SV_Coverage@end +) +{ + PS_OUTPUT outPs; + @insertpiece( custom_ps_preExecution ) + @insertpiece( DefaultBodyPS ) + @insertpiece( custom_ps_posExecution ) + + @property( hlms_use_prepass_msaa && false ) + //Useful debug stuff for debugging precision issues. + /*float testD = gBuf_depthTexture.Load( iFragCoord.xy, 0 ); + outPs.colour0.xyz = testD * testD * testD * testD * testD * testD * testD * testD;*/ + /*float3 col3 = lerp( outPs.colour0.xyz, float3( 1, 1, 1 ), 0.85 ); + outPs.colour0.xyz = 0; + if( gl_SampleMaskIn & 0x1 ) + outPs.colour0.x = col3.x; + if( gl_SampleMaskIn & 0x2 ) + outPs.colour0.y = col3.y; + if( gl_SampleMaskIn & 0x4 ) + outPs.colour0.z = col3.z; + if( gl_SampleMaskIn & 0x8 ) + outPs.colour0.w = 1.0;*/ + /*outPs.colour0.x = pixelDepth; + outPs.colour0.y = msaaDepth; + outPs.colour0.z = 0; + outPs.colour0.w = 1;*/ + @end + +@property( !hlms_render_depth_only ) + return outPs; +@end +} +@else ///!hlms_shadowcaster + +@insertpiece( DeclShadowCasterMacros ) + +@foreach( num_textures, n ) + Texture2DArray textureMaps@n : register(t@value(textureMaps@n));@end +@foreach( num_samplers, n ) + SamplerState samplerState@value(samplerStateStart) : register(s@counter(samplerStateStart));@end + +@property( hlms_shadowcaster_point || exponential_shadow_maps ) + @insertpiece( PassStructDecl ) +@end + +@insertpiece( DeclOutputType ) + +@insertpiece( output_type ) main( PS_INPUT inPs ) +{ +@property( !hlms_render_depth_only || exponential_shadow_maps || hlms_shadowcaster_point ) + PS_OUTPUT outPs; +@end + + @insertpiece( custom_ps_preExecution ) + @insertpiece( DefaultBodyPS ) + @insertpiece( custom_ps_posExecution ) + +@property( !hlms_render_depth_only || exponential_shadow_maps || hlms_shadowcaster_point ) + return outPs; +@end +} +@end diff --git a/ogre2/src/media/Hlms/Pbs/HLSL/Textures_piece_ps.hlsl b/ogre2/src/media/Hlms/Pbs/HLSL/Textures_piece_ps.hlsl new file mode 100644 index 000000000..2e1df3879 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/HLSL/Textures_piece_ps.hlsl @@ -0,0 +1,11 @@ + +@property( !hlms_render_depth_only && !hlms_shadowcaster ) + @piece( ExtraOutputTypes ) + @property( hlms_gen_normals_gbuffer ) + float4 normals : SV_Target@counter(rtv_target); + @end + @property( hlms_prepass ) + float2 shadowRoughness : SV_Target@counter(rtv_target); + @end + @end +@end diff --git a/ogre2/src/media/Hlms/Pbs/HLSL/VertexShader_vs.hlsl b/ogre2/src/media/Hlms/Pbs/HLSL/VertexShader_vs.hlsl new file mode 100644 index 000000000..4a120abe3 --- /dev/null +++ b/ogre2/src/media/Hlms/Pbs/HLSL/VertexShader_vs.hlsl @@ -0,0 +1,75 @@ + +//#include "SyntaxHighlightingMisc.h" + +@insertpiece( SetCrossPlatformSettings ) + +@insertpiece( DefaultHeaderVS ) +@insertpiece( custom_vs_uniformDeclaration ) + +struct VS_INPUT +{ + float4 vertex : POSITION; +@property( hlms_normal ) float3 normal : NORMAL;@end +@property( hlms_qtangent ) float4 qtangent : NORMAL;@end + +@property( normal_map && !hlms_qtangent ) + float3 tangent : TANGENT; + @property( hlms_binormal )float3 binormal : BINORMAL;@end +@end + +@property( hlms_skeleton ) + uint4 blendIndices : BLENDINDICES; + float4 blendWeights : BLENDWEIGHT; +@end + +@property( hlms_vertex_id ) + uint vertexId: SV_VertexID; +@end + +@foreach( hlms_uv_count, n ) + float@value( hlms_uv_count@n ) uv@n : TEXCOORD@n;@end + uint drawId : DRAWID; + @insertpiece( custom_vs_attributes ) +}; + +struct PS_INPUT +{ + @insertpiece( VStoPS_block ) + float4 gl_Position: SV_Position; + + @property( hlms_instanced_stereo ) + uint gl_ViewportIndex : SV_ViewportArrayIndex; + @end + + @pdiv( full_pso_clip_distances, hlms_pso_clip_distances, 4 ) + @pmod( partial_pso_clip_distances, hlms_pso_clip_distances, 4 ) + @foreach( full_pso_clip_distances, n ) + float4 gl_ClipDistance@n : SV_ClipDistance@n; + @end + @property( partial_pso_clip_distances ) + float@value( partial_pso_clip_distances ) gl_ClipDistance@value( full_pso_clip_distances ) : SV_ClipDistance@value( full_pso_clip_distances ); + @end +}; + +// START UNIFORM D3D DECLARATION +Buffer worldMatBuf : register(t0); +@property( hlms_pose ) + Buffer poseBuf : register(t@value(poseBuf)); +@end +// END UNIFORM D3D DECLARATION + +PS_INPUT main( VS_INPUT input ) +{ + PS_INPUT outVs; +@property( !hlms_qtangent && hlms_normal ) + float3 normal = input.normal; + @property( normal_map )float3 tangent = input.tangent;@end + @property( hlms_binormal )float3 binormal = input.binormal;@end +@end + + @insertpiece( custom_vs_preExecution ) + @insertpiece( DefaultBodyVS ) + @insertpiece( custom_vs_posExecution ) + + return outVs; +} diff --git a/ogre2/src/media/Hlms/Pbs/Metal/BRDFs_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/BRDFs_piece_ps.metal deleted file mode 100644 index 4ecc346f2..000000000 --- a/ogre2/src/media/Hlms/Pbs/Metal/BRDFs_piece_ps.metal +++ /dev/null @@ -1,242 +0,0 @@ -@property( !metallic_workflow && (!specular_map || !fresnel_workflow) ) - @property( !transparent_mode ) - @piece( F0 )material.F0@end - @end @property( transparent_mode ) - //Premultiply F0.xyz with the alpha from the texture, but only in transparent mode. - @property( fresnel_scalar ) - @piece( F0 )(material.F0.@insertpiece( FresnelSwizzle ) * diffuseCol.w)@end - @end @property( !fresnel_scalar ) - @piece( F0 )float1(material.F0.@insertpiece( FresnelSwizzle ) * diffuseCol.w)@end - @end - @end -@end @property( metallic_workflow || (specular_map && fresnel_workflow) ) - @piece( F0 )F0@end -@end - -@property( !fresnel_scalar ) - @piece( maxR1F0 )max( 1.0 - ROUGHNESS, @insertpiece( F0 ).x )@end -@end @property( fresnel_scalar ) - @piece( maxR1F0 )max( (1.0 - ROUGHNESS), @insertpiece( F0 ).xyz )@end -@end - -//For mortals: -// getSpecularFresnel = F0 + pow( 1.0 - VdotH, 5.0 ) * (1.0 - F0) -// getDiffuseFresnel = 1.0 - F0 + pow( 1.0 - NdotL, 5.0 ) * F0 -// getSpecularFresnelWithRoughness = F0 + pow( 1.0 - VdotH, 5.0 ) * (max(ROUGHNESS, (1.0 - F0)) - F0) -// getDiffuseFresnelWithRoughness = max(ROUGHNESS, (1.0 - F0) - F0 + pow( 1.0 - NdotL, 5.0 ) * F0 -@piece( getSpecularFresnel )@insertpiece( F0 ).@insertpiece( FresnelSwizzle ) + pow( 1.0 - VdotH, 5.0 ) * (1.0 - @insertpiece( F0 ).@insertpiece( FresnelSwizzle ))@end -@piece( getDiffuseFresnel )1.0 - @insertpiece( F0 ).@insertpiece( FresnelSwizzle ) + pow( 1.0 - NdotL, 5.0 ) * @insertpiece( F0 ).@insertpiece( FresnelSwizzle )@end - -@piece( getSpecularFresnelWithRoughness )@insertpiece( F0 ).@insertpiece( FresnelSwizzle ) + pow( 1.0 - VdotH, 5.0 ) * (@insertpiece( maxR1F0 ) - @insertpiece( F0 ).@insertpiece( FresnelSwizzle ))@end -@piece( getDiffuseFresnelWithRoughness )@insertpiece( maxR1F0 ) - @insertpiece( F0 ).@insertpiece( FresnelSwizzle ) + pow( 1.0 - NdotL, 5.0 ) * @insertpiece( F0 ).@insertpiece( FresnelSwizzle )@end - -@property( !fresnel_scalar ) - @piece( getMaxFresnelS )fresnelS@end -@end @property( fresnel_scalar ) - @piece( getMaxFresnelS )max( fresnelS.x, max( fresnelS.y, fresnelS.z ) )@end -@end - -@property( BRDF_BlinnPhong ) -@piece( DeclareBRDF ) -//Blinn-Phong -inline float3 BRDF( float3 lightDir, float3 viewDir, float NdotV, float3 lightDiffuse, - float3 lightSpecular, Material material, float3 nNormal @insertpiece( brdfExtraParamDefs ) ) -{ - float3 halfWay= normalize( lightDir + viewDir ); - float NdotL = saturate( dot( nNormal, lightDir ) ); //Diffuse (Lambert) - float NdotH = clamp( dot( nNormal, halfWay ), 0.001, 1.0 ); //Specular - @property( !legacy_math_brdf ) - float VdotH = clamp( dot( viewDir, halfWay ), 0.001, 1.0 ); //Fresnel - - //Fresnel term (Schlick's approximation) - @insertpiece( FresnelType ) fresnelS = @insertpiece( getSpecularFresnel ); - @property( fresnel_separate_diffuse ) - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnel ); - @end @property( !fresnel_separate_diffuse ) - float fresnelD = 1.0f - @insertpiece( getMaxFresnelS ); - @end - @end - - @property( !roughness_is_shininess ) - float shininess = exp2( 10.0 * (1.0 - ROUGHNESS) + 1.0 ) * 0.25; - @end @property( roughness_is_shininess ) - float shininess = ROUGHNESS; - @end - float blinnPhong = pow( NdotH, shininess ); - - @property( !legacy_math_brdf ) - //Normalize Blinn-Phong using (n + 8) / (8 * pi) - //Note this factor is an approximation. The real normalization is - //*much* more expensive. See: - //http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/ - blinnPhong *= (shininess + 8.0) / (8.0 * 3.141592654); - - //Avoid very small denominators, they go to NaN or cause aliasing artifacts - //Note: For blinn-phong we use larger denominators otherwise specular blows out of proportion - @insertpiece( FresnelType ) Rs = ( fresnelS * blinnPhong ) / max( 4.0 * NdotV * NdotL, 0.75 ); - //Make diffuse look closer to Default. - fresnelD *= mix( 1.0, 1.0 / 1.51, ROUGHNESS ); - @end @property( legacy_math_brdf ) - float Rs = blinnPhong; - float fresnelD = 1.0; - @end - - return NdotL * (@insertpiece( kS ).xyz * lightSpecular * Rs + - @insertpiece( kD ).xyz * lightDiffuse * fresnelD); -} -@end -@end - -@property( BRDF_CookTorrance ) -@piece( DeclareBRDF ) -//Cook-Torrance -inline float3 BRDF( float3 lightDir, float3 viewDir, float NdotV, float3 lightDiffuse, float3 lightSpecular, Material material, float3 nNormal @insertpiece( brdfExtraParamDefs ) ) -{ - float3 halfWay= normalize( lightDir + viewDir ); - float NdotL = saturate( dot( nNormal, lightDir ) ); - float NdotH = clamp( dot( nNormal, halfWay ), 0.001, 1.0 ); - float VdotH = clamp( dot( viewDir, halfWay ), 0.001, 1.0 ); - - float sqR = ROUGHNESS * ROUGHNESS; - - //Roughness/Distribution/NDF term (Beckmann distribution) - //Formula: - // Where alpha = NdotH and m = roughness - // R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( -tan(alpha)^2 / m^2 ) ] - // R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( ( cos(alpha)^2 - 1 ) / (m^2 cos(alpha)^2 ) ] - float NdotH_sq = NdotH * NdotH; - float roughness_a = 1.0 / ( 3.141592654 * sqR * NdotH_sq * NdotH_sq );//( 1 / (m^2 x cos(alpha)^4 ) - float roughness_b = NdotH_sq - 1.0; //( cos(alpha)^2 - 1 ) - float roughness_c = sqR * NdotH_sq; //( m^2 cos(alpha)^2 ) - - //Avoid Inf * 0 = NaN; we need Inf * 0 = 0 - float R = min( roughness_a, 65504.0 ) * exp( roughness_b / roughness_c ); - - //Geometric/Visibility term (Cook Torrance) - float shared_geo = 2.0 * NdotH / VdotH; - float geo_b = shared_geo * NdotV; - float geo_c = shared_geo * NdotL; - float G = min( 1.0, min( geo_b, geo_c ) ); - - //Fresnel term (Schlick's approximation) - //Formula: - // fresnelS = lerp( (1 - V*H)^5, 1, F0 ) - // fresnelD = lerp( (1 - N*L)^5, 1, 1 - F0 ) [See s2010_course_note_practical_implementation_at_triace.pdf] - @insertpiece( FresnelType ) fresnelS = @insertpiece( getSpecularFresnel ); -@property( fresnel_separate_diffuse ) - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnel ); -@end @property( !fresnel_separate_diffuse ) - float fresnelD = 1.0f - @insertpiece( getMaxFresnelS );@end - - //Avoid very small denominators, they go to NaN or cause aliasing artifacts - @insertpiece( FresnelType ) Rs = ( fresnelS * (R * G) ) / max( 4.0 * NdotV * NdotL, 0.01 ); - - return NdotL * (@insertpiece( kS ).xyz * lightSpecular * Rs + - @insertpiece( kD ).xyz * lightDiffuse * fresnelD); -} -@end -@end - -@property( BRDF_Default ) -@piece( DeclareBRDF ) -//Default BRDF -inline float3 BRDF( float3 lightDir, float3 viewDir, float NdotV, float3 lightDiffuse, float3 lightSpecular, Material material, float3 nNormal @insertpiece( brdfExtraParamDefs ) ) -{ - float3 halfWay= normalize( lightDir + viewDir ); - float NdotL = saturate( dot( nNormal, lightDir ) ); - float NdotH = saturate( dot( nNormal, halfWay ) ); - float VdotH = saturate( dot( viewDir, halfWay ) ); - - float sqR = ROUGHNESS * ROUGHNESS; - - //Roughness/Distribution/NDF term (GGX) - //Formula: - // Where alpha = roughness - // R = alpha^2 / [ PI * [ ( NdotH^2 * (alpha^2 - 1) ) + 1 ]^2 ] - float f = ( NdotH * sqR - NdotH ) * NdotH + 1.0; - float R = sqR / (f * f + 1e-6f); - - //Geometric/Visibility term (Smith GGX Height-Correlated) -@property( GGX_height_correlated ) - float Lambda_GGXV = NdotL * sqrt( (-NdotV * sqR + NdotV) * NdotV + sqR ); - float Lambda_GGXL = NdotV * sqrt( (-NdotL * sqR + NdotL) * NdotL + sqR ); - - float G = 0.5 / (( Lambda_GGXV + Lambda_GGXL + 1e-6f ) * 3.141592654); -@end @property( !GGX_height_correlated ) - float gL = NdotL * (1-sqR) + sqR; - float gV = NdotV * (1-sqR) + sqR; - float G = 1.0 / (( gL * gV + 1e-4f ) * 4 * 3.141592654); -@end - - //Formula: - // fresnelS = lerp( (1 - V*H)^5, 1, F0 ) - @insertpiece( FresnelType ) fresnelS = @insertpiece( getSpecularFresnel ); - - //We should divide Rs by PI, but it was done inside G for performance - float3 Rs = ( fresnelS * (R * G) ) * @insertpiece( kS ).xyz * lightSpecular; - - //Diffuse BRDF (*Normalized* Disney, see course_notes_moving_frostbite_to_pbr.pdf - //"Moving Frostbite to Physically Based Rendering" Sebastien Lagarde & Charles de Rousiers) - float energyBias = ROUGHNESS * 0.5; - float energyFactor = mix( 1.0, 1.0 / 1.51, ROUGHNESS ); - float fd90 = energyBias + 2.0 * VdotH * VdotH * ROUGHNESS; - float lightScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotL, 5.0 ); - float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotV, 5.0 ); - -@property( fresnel_separate_diffuse ) - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnel ); -@end @property( !fresnel_separate_diffuse ) - float fresnelD = 1.0f - @insertpiece( getMaxFresnelS );@end - - //We should divide Rd by PI, but it is already included in kD - float3 Rd = (lightScatter * viewScatter * energyFactor * fresnelD) * @insertpiece( kD ).xyz * lightDiffuse; - - return NdotL * (Rs + Rd); -} -@end -@end - -@property( hlms_enable_vpls ) -@piece( DeclareBRDF_InstantRadiosity ) -//Simplified cheap BRDF for Instant Radiosity. -float3 BRDF_IR( float3 lightDir, float3 lightDiffuse, - Material material, float3 nNormal @insertpiece( brdfExtraParamDefs ) ) -{ - float NdotL = clamp( dot( nNormal, lightDir ), 0.0, 1.0 ); - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnel ); - - //We should divide Rd by PI, but it is already included in kD - return NdotL * fresnelD * @insertpiece( kD ).xyz * lightDiffuse; -} -@end -@end - -/// Applying Fresnel term to prefiltered cubemap has a bad effect of always showing high specular -/// color at edge, even for rough surface. See https://seblagarde.wordpress.com/2011/08/17/hello-world/ -/// and see http://www.ogre3d.org/forums/viewtopic.php?f=25&p=523550#p523544 -/// "The same Fresnel term which is appropriate for unfiltered environment maps (i.e. perfectly smooth -/// mirror surfaces) is not appropriate for filtered environment maps since there you are averaging -/// incoming light colors from many directions, but using a single Fresnel value computed for the -/// reflection direction. The correct function has similar values as the regular Fresnel expression -/// at v=n, but at glancing angle it behaves differently. In particular, the lerp(from base specular -/// to white) does not go all the way to white at glancing angles in the case of rough surfaces." -/// So we use getSpecularFresnelWithRoughness instead. -@piece( BRDF_EnvMap ) - float NdotL = saturate( dot( nNormal, reflDir ) ); - float VdotH = saturate( dot( viewDir, normalize( reflDir + viewDir ) ) ); - @insertpiece( FresnelType ) fresnelS = @insertpiece( getSpecularFresnelWithRoughness ); - - @property( fresnel_separate_diffuse ) - @insertpiece( FresnelType ) fresnelD = @insertpiece( getDiffuseFresnelWithRoughness ); - @end @property( !fresnel_separate_diffuse ) - float fresnelD = 1.0f - @insertpiece( getMaxFresnelS );@end - - finalColour += envColourD * @insertpiece( kD ).xyz * fresnelD + - envColourS * @insertpiece( kS ).xyz * fresnelS; -@end - -@property( hlms_fine_light_mask ) - @piece( ObjLightMaskCmp )if( (inPs.objLightMask & as_type( passBuf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u )@end - @piece( andObjLightMaskCmp )&& ((inPs.objLightMask & as_type( passBuf.lights[@counter(fineMaskLightIdx)].position.w )) != 0u)@end - @piece( andObjAreaApproxLightMaskCmp )&& ((inPs.objLightMask & as_type( passBuf.areaApproxLights[@counter(fineMaskAreaApproxLightIdx)].position.w )) != 0u)@end -@end diff --git a/ogre2/src/media/Hlms/Pbs/Metal/BlendModes_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/BlendModes_piece_ps.metal deleted file mode 100644 index a933fc45f..000000000 --- a/ogre2/src/media/Hlms/Pbs/Metal/BlendModes_piece_ps.metal +++ /dev/null @@ -1,105 +0,0 @@ -//Reset t to 0 just in case (values are preserved from previous stages) -@pset( t, 0 ) - -@property( !hlms_shadowcaster ) -@piece( NormalNonPremul ) - //Normal Non Premultiplied @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, detailCol@value(t).xyz, detailCol@value(t).a ); - diffuseCol.w = mix( diffuseCol.w, 1.0, detailCol@value(t).w ); -@end - -@piece( NormalPremul ) - //Normal Premultiplied @value(t) - diffuseCol.xyz = (1.0 - detailCol@value(t).a) * diffuseCol.xyz + detailCol@value(t).xyz; - diffuseCol.w = mix( diffuseCol.w, 1.0, detailCol@value(t).w ); -@end - -@piece( Add ) - //Add @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - min( diffuseCol.xyz + detailCol@value(t).xyz, float3(1.0, 1.0, 1.0) ), - detailCol@value(t).a ); -@end - -@piece( Subtract ) - //Subtract @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - max( diffuseCol.xyz - detailCol@value(t).xyz, float3(0.0, 0.0, 0.0) ), - detailCol@value(t).a ); -@end - -@piece( Multiply ) - //Multiply @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - diffuseCol.xyz * detailCol@value(t).xyz, - detailCol@value(t).a ); -@end - -@piece( Multiply2x ) - //Multiply2x @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - min( diffuseCol.xyz * detailCol@value(t).xyz * 2.0, float3(1.0, 1.0, 1.0) ), - detailCol@value(t).a ); -@end - -@piece( Screen ) - //Screen @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - 1.0 - (1.0 - diffuseCol.xyz) * (1.0 - detailCol@value(t).xyz), - detailCol@value(t).a ); -@end - -@piece( Overlay ) - //Overlay @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - diffuseCol.xyz * ( diffuseCol.xyz + 2.0 * detailCol@value(t).xyz * (1.0 - diffuseCol.xyz) ), - detailCol@value(t).a ); -@end - -@piece( Lighten ) - //Lighten @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - max( diffuseCol.xyz, detailCol@value(t).xyz ), - detailCol@value(t).a ); -@end - -@piece( Darken ) - //Darken @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - min( diffuseCol.xyz, detailCol@value(t).xyz ), - detailCol@value(t).a ); -@end - -@piece( GrainExtract ) - //GrainExtract @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - (diffuseCol.xyz - detailCol@value(t).xyz) + 0.5f, - detailCol@value(t).a ); -@end - -@piece( GrainMerge ) - //GrainMerge @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - (diffuseCol.xyz + detailCol@value(t).xyz) - 0.5f, - detailCol@value(t).a ); -@end - -@piece( Difference ) - //Difference @value(t) - diffuseCol.xyz = mix( diffuseCol.xyz, - abs(diffuseCol.xyz - detailCol@value(t).xyz), - detailCol@value(t).a ); -@end -@end @property( hlms_shadowcaster ) - -@piece( NormalNonPremul ) - //Normal Non Premultiplied @value(t) - diffuseCol = mix( diffuseCol, 1.0, detailCol@value(t) ); -@end - -@piece( NormalPremul ) - //Normal Premultiplied @value(t) - diffuseCol = mix( diffuseCol, 1.0, detailCol@value(t) ); -@end - -@end diff --git a/ogre2/src/media/Hlms/Pbs/Metal/Forward3D_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/Forward3D_piece_ps.metal index 5849bafe6..c3ad0672e 100644 --- a/ogre2/src/media/Hlms/Pbs/Metal/Forward3D_piece_ps.metal +++ b/ogre2/src/media/Hlms/Pbs/Metal/Forward3D_piece_ps.metal @@ -1,219 +1,17 @@ @property( hlms_forwardplus ) -@property( hlms_forwardplus_fine_light_mask ) - @piece( andObjLightMaskFwdPlusCmp )&& ((inPs.objLightMask & as_type( lightDiffuse.w )) != 0u)@end -@end -@piece( forward3dLighting ) - @property( hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v) - #define FWDPLUS_APPLY_OFFSET_X(v) (v) - @end - - @property( hlms_forwardplus == forward3d ) - float f3dMinDistance = passBuf.f3dData.x; - float f3dInvMaxDistance = passBuf.f3dData.y; - float f3dNumSlicesSub1 = passBuf.f3dData.z; - uint cellsPerTableOnGrid0= as_type( passBuf.f3dData.w ); - - // See C++'s Forward3D::getSliceAtDepth - /*float fSlice = 1.0 - clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); - fSlice = (fSlice * fSlice) * (fSlice * fSlice); - fSlice = (fSlice * fSlice); - fSlice = floor( (1.0 - fSlice) * f3dNumSlicesSub1 );*/ - float fSlice = clamp( (-inPs.pos.z + f3dMinDistance) * f3dInvMaxDistance, 0.0, 1.0 ); - fSlice = floor( fSlice * f3dNumSlicesSub1 ); - uint slice = uint( fSlice ); - - //TODO: Profile performance: derive this mathematically or use a lookup table? - uint offset = cellsPerTableOnGrid0 * (((1u << (slice << 1u)) - 1u) / 3u); - - float lightsPerCell = passBuf.f3dGridHWW[0].w; - float windowHeight = passBuf.f3dGridHWW[1].w; //renderTarget->height - @property( !hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.f3dViewportOffset.y) - #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.f3dViewportOffset.x) +@property( hlms_enable_decals ) + @piece( DeclDecalsSamplers ) + , sampler decalsSampler [[sampler(@value(decalsSampler))]] + @property( hlms_decals_diffuse ), texture2d_array decalsDiffuseTex [[texture(@value(decalsDiffuseTex))]]@end + @property( hlms_decals_normals ), texture2d_array decalsNormalsTex [[texture(@value(decalsNormalsTex))]]@end + @property( hlms_decals_diffuse == hlms_decals_emissive ) + #define decalsEmissiveTex decalsDiffuseTex @end - - //passBuf.f3dGridHWW[slice].x = grid_width / renderTarget->width; - //passBuf.f3dGridHWW[slice].y = grid_height / renderTarget->height; - //passBuf.f3dGridHWW[slice].z = grid_width * lightsPerCell; - //uint sampleOffset = 0; - uint sampleOffset = offset + - uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(inPs.gl_FragCoord.y)) * - passBuf.f3dGridHWW[slice].y ) * passBuf.f3dGridHWW[slice].z) + - uint(floor( FWDPLUS_APPLY_OFFSET_X(inPs.gl_FragCoord.x) * - passBuf.f3dGridHWW[slice].x ) * lightsPerCell); - @end @property( hlms_forwardplus != forward3d ) - float f3dMinDistance = passBuf.f3dData.x; - float f3dInvExponentK = passBuf.f3dData.y; - float f3dNumSlicesSub1 = passBuf.f3dData.z; - - // See C++'s ForwardClustered::getSliceAtDepth - float fSlice = log2( max( -inPs.pos.z - f3dMinDistance, 1.0 ) ) * f3dInvExponentK; - fSlice = floor( min( fSlice, f3dNumSlicesSub1 ) ); - uint sliceSkip = uint( fSlice * @value( fwd_clustered_width_x_height ) ); - - @property( !hlms_forwardplus_covers_entire_target ) - #define FWDPLUS_APPLY_OFFSET_Y(v) (v - passBuf.fwdScreenToGrid.w) - #define FWDPLUS_APPLY_OFFSET_X(v) (v - passBuf.fwdScreenToGrid.z) + @property( hlms_decals_emissive && hlms_decals_diffuse != hlms_decals_emissive ) + , texture2d_array decalsEmissiveTex [[texture(@value(decalsEmissiveTex))]] @end - - uint sampleOffset = sliceSkip + - uint(floor( FWDPLUS_APPLY_OFFSET_X(inPs.gl_FragCoord.x) * - passBuf.fwdScreenToGrid.x )); - float windowHeight = passBuf.f3dData.w; //renderTarget->height - sampleOffset += uint(floor( (windowHeight - FWDPLUS_APPLY_OFFSET_Y(inPs.gl_FragCoord.y)) * - passBuf.fwdScreenToGrid.y ) * - @value( fwd_clustered_width )); - - sampleOffset *= @value( fwd_clustered_lights_per_cell )u; @end - - ushort numLightsInGrid = f3dGrid[int(sampleOffset)]; - - @property( hlms_forwardplus_debug )uint totalNumLightsInGrid = numLightsInGrid;@end - - for( ushort i=0u; i= spotParams.y ) - { - float3 tmpColour = BRDF( lightDir, viewDir, NdotV, lightDiffuse.xyz, lightSpecular, - material, nNormal @insertpiece( brdfExtraParams ) ); - finalColour += tmpColour * atten; - } - } - } - -@property( hlms_enable_vpls ) - prevLightCount = numLightsInGrid; - numLightsInGrid = f3dGrid[int(sampleOffset + 2u)]; - - @property( hlms_forwardplus_debug )totalNumLightsInGrid += numLightsInGrid;@end - - for( ushort i=prevLightCount; i 1 || - irradiancePos.z < 0 || irradiancePos.z > 1 || - irradiancePos.y <= (6.0f * irradianceTexInvHeight) || irradiancePos.y >= 1 ) - { - //Metal does not support border colour addressing mode. - ambientTerm = float3( 0 ); - } - - finalColour.xyz += ambientTerm.xyz * @insertpiece( kD ).xyz; -@end -@end diff --git a/ogre2/src/media/Hlms/Pbs/Metal/PixelShader_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/PixelShader_ps.metal index b366a2a8b..6165f9e12 100644 --- a/ogre2/src/media/Hlms/Pbs/Metal/PixelShader_ps.metal +++ b/ogre2/src/media/Hlms/Pbs/Metal/PixelShader_ps.metal @@ -1,3 +1,6 @@ + +//#include "SyntaxHighlightingMisc.h" + @insertpiece( SetCrossPlatformSettings ) @insertpiece( DeclareUvModifierMacros ) @@ -11,62 +14,22 @@ @insertpiece( custom_ps_uniformStructDeclaration ) // END UNIFORM STRUCT DECLARATION +@insertpiece( DefaultHeaderPS ) + struct PS_INPUT { @insertpiece( VStoPS_block ) -@property( hlms_vpos ) float4 gl_FragCoord [[position]];@end }; @property( !hlms_shadowcaster ) -@property( irradiance_volumes ) - @insertpiece( Common_Matrix_Conversions ) -@end - -@property( !roughness_map )#define ROUGHNESS material.kS.w@end - -@property( normal_map ) -@property( hlms_qtangent ) -@piece( tbnApplyReflection ) * inPs.biNormalReflection@end -@end -@end - -@property( hlms_lights_spot_textured )@insertpiece( DeclQuat_zAxis ) -inline float3 qmul( float4 q, float3 v ) -{ - return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz ); -} -@end - -@property( normal_map_tex || detail_maps_normal ) -inline float3 getTSNormal( sampler samplerState, texture2d_array normalMap, float2 uv, ushort normalIdx ) -{ - float3 tsNormal; -@property( signed_int_textures ) - //Normal texture must be in U8V8 or BC5 format! - tsNormal.xy = normalMap.sample( samplerState, uv, normalIdx ).xy; -@end @property( !signed_int_textures ) - //Normal texture must be in LA format! - tsNormal.xy = normalMap.sample( samplerState, uv, normalIdx ).xw * 2.0 - 1.0; -@end - tsNormal.z = sqrt( max( 0.0f, 1.0f - tsNormal.x * tsNormal.x - tsNormal.y * tsNormal.y ) ); - - return tsNormal; -} -@end -@property( normal_weight_tex )#define normalMapWeight material.emissive.w@end -@property( detail_maps_normal ) - @foreach( 4, n ) - @property( normal_weight_detail@n ) - @piece( detail@n_nm_weight_mul ) * material.normalWeights.@insertpiece( detail_swizzle@n )@end - @end +@property( !hlms_render_depth_only ) + @property( hlms_gen_normals_gbuffer ) + #define outPs_normals outPs.normals + @end + @property( hlms_prepass ) + #define outPs_shadowRoughness outPs.shadowRoughness @end -@end - -@property( (hlms_normal || hlms_qtangent) && !hlms_prepass ) -@insertpiece( DeclareBRDF ) -@insertpiece( DeclareBRDF_InstantRadiosity ) -@insertpiece( DeclareBRDF_AreaLightApprox ) @end @property( use_parallax_correct_cubemaps ) @@ -76,10 +39,20 @@ inline float3 getTSNormal( sampler samplerState, texture2d_array normalMa @insertpiece( DeclShadowMapMacros ) @insertpiece( DeclShadowSamplingFuncs ) +@insertpiece( DeclAreaLtcLightFuncs ) + +@property( hlms_enable_cubemaps_auto && hlms_cubemaps_use_dpm ) + @insertpiece( DeclDualParaboloidFunc ) +@end + constexpr sampler shadowSampler = sampler( coord::normalized, address::clamp_to_edge, filter::linear, + @property( hlms_no_reverse_depth ) compare_func::less_equal ); + @else + compare_func::greater_equal ); + @end @insertpiece( DeclOutputType ) @@ -88,6 +61,12 @@ constexpr sampler shadowSampler = sampler( coord::normalized, fragment @insertpiece( output_type ) main_metal ( PS_INPUT inPs [[stage_in]] + @property( hlms_vpos ) + , float4 gl_FragCoord [[position]] + @end + @property( two_sided_lighting ) + , bool gl_FrontFacing [[front_facing]] + @end @property( hlms_use_prepass_msaa && hlms_use_prepass ) , uint gl_SampleMask [[sample_mask]] @end @@ -102,8 +81,8 @@ fragment @insertpiece( output_type ) main_metal @insertpiece( custom_ps_uniformDeclaration ) // END UNIFORM DECLARATION @property( hlms_forwardplus ) - , device const ushort *f3dGrid [[buffer(TEX_SLOT_START+1)]] - , device const float4 *f3dLightList [[buffer(TEX_SLOT_START+2)]] + , device const ushort *f3dGrid [[buffer(TEX_SLOT_START+@value(f3dGrid))]] + , device const float4 *f3dLightList [[buffer(TEX_SLOT_START+@value(f3dLightList))]] @end @property( hlms_use_prepass ) @@ -120,389 +99,65 @@ fragment @insertpiece( output_type ) main_metal @end @end - @property( irradiance_volumes ) - , texture3d irradianceVolume [[texture(@value(irradianceVolumeTexUnit))]] - , sampler irradianceVolumeSampler [[sampler(@value(irradianceVolumeTexUnit))]] + @property( hlms_ss_refractions_available ) + @property( !hlms_use_prepass || !hlms_use_prepass_msaa || 1 ) + @property( !hlms_use_prepass_msaa ) + , texture2d gBuf_depthTexture [[texture(@value(gBuf_depthTexture))]] + #define depthTextureNoMsaa gBuf_depthTexture + @else + , texture2d depthTextureNoMsaa [[texture(@value(depthTextureNoMsaa))]] + @end + @end + , texture2d refractionMap [[texture(@value(refractionMap))]] + , sampler refractionMapSampler [[sampler(@value(refractionMap))]] @end @insertpiece( DeclPlanarReflTextures ) @insertpiece( DeclAreaApproxTextures ) + @insertpiece( DeclLightProfilesTexture ) - @property( two_sided_lighting ) - , bool gl_FrontFacing [[front_facing]] - @piece( two_sided_flip_normal )* (gl_FrontFacing ? 1.0 : -1.0)@end + @property( irradiance_volumes ) + , texture3d irradianceVolume [[texture(@value(irradianceVolume))]] + , sampler irradianceVolumeSampler [[sampler(@value(irradianceVolume))]] @end @foreach( num_textures, n ) - , texture2d_array textureMaps@n [[texture(@counter(textureRegStart))]]@end + , texture2d_array textureMaps@n [[texture(@value(textureMaps@n))]]@end @property( use_envprobe_map ) - , texturecube texEnvProbeMap [[texture(@value(envMapReg))]] - , sampler envMapSamplerState [[sampler(@value(envMapReg))]]@end - @foreach( numSamplerStates, n ) - , sampler samplerState@n [[sampler(@counter(samplerStateStart))]]@end + @property( !hlms_enable_cubemaps_auto ) + , texturecube texEnvProbeMap [[texture(@value(texEnvProbeMap))]] + @end + @property( hlms_enable_cubemaps_auto ) + @property( !hlms_cubemaps_use_dpm ) + , texturecube_array texEnvProbeMap [[texture(@value(texEnvProbeMap))]] + @end + @property( hlms_cubemaps_use_dpm ) + , texture2d_array texEnvProbeMap [[texture(@value(texEnvProbeMap))]] + @end + @end + @property( envMapRegSampler < samplerStateStart ) + , sampler samplerState@value(envMapRegSampler) [[sampler(@value(envMapRegSampler))]] + @end + @end + @foreach( num_samplers, n ) + , sampler samplerState@value(samplerStateStart) [[sampler(@counter(samplerStateStart))]]@end + @insertpiece( DeclDecalsSamplers ) @insertpiece( DeclShadowSamplers ) + @insertpiece( DeclAreaLtcTextures ) + @insertpiece( DeclVctTextures ) + @insertpiece( DeclIrradianceFieldTextures ) ) { PS_OUTPUT outPs; - @insertpiece( custom_ps_preExecution ) - - Material material; - -@property( diffuse_map ) ushort diffuseIdx;@end -@property( normal_map_tex ) ushort normalIdx;@end -@property( specular_map ) ushort specularIdx;@end -@property( roughness_map ) ushort roughnessIdx;@end -@property( detail_weight_map ) ushort weightMapIdx;@end -@foreach( 4, n ) - @property( detail_map@n )ushort detailMapIdx@n;@end @end -@foreach( 4, n ) - @property( detail_map_nm@n )ushort detailNormMapIdx@n;@end @end -@property( emissive_map ) ushort emissiveMapIdx;@end -@property( use_envprobe_map ) ushort envMapIdx;@end - -float4 diffuseCol; -@property( specular_map && !metallic_workflow && !fresnel_workflow )float3 specularCol;@end -@property( metallic_workflow || (specular_map && fresnel_workflow) )@insertpiece( FresnelType ) F0;@end -@property( roughness_map )float ROUGHNESS;@end - -@property( hlms_normal || hlms_qtangent ) float3 nNormal;@end - -@property( hlms_normal || hlms_qtangent ) - @property( !lower_gpu_overhead ) - material = materialArray[inPs.materialId]; - @end @property( lower_gpu_overhead ) - material = materialArray[0]; - @end -@property( diffuse_map ) diffuseIdx = material.diffuseIdx;@end -@property( normal_map_tex ) normalIdx = material.normalIdx;@end -@property( specular_map ) specularIdx = material.specularIdx;@end -@property( roughness_map ) roughnessIdx = material.roughnessIdx;@end -@property( detail_weight_map ) weightMapIdx = material.weightMapIdx;@end -@property( detail_map0 ) detailMapIdx0 = material.detailMapIdx0;@end -@property( detail_map1 ) detailMapIdx1 = material.detailMapIdx1;@end -@property( detail_map2 ) detailMapIdx2 = material.detailMapIdx2;@end -@property( detail_map3 ) detailMapIdx3 = material.detailMapIdx3;@end -@property( detail_map_nm0 ) detailNormMapIdx0 = material.detailNormMapIdx0;@end -@property( detail_map_nm1 ) detailNormMapIdx1 = material.detailNormMapIdx1;@end -@property( detail_map_nm2 ) detailNormMapIdx2 = material.detailNormMapIdx2;@end -@property( detail_map_nm3 ) detailNormMapIdx3 = material.detailNormMapIdx3;@end -@property( emissive_map ) emissiveMapIdx = material.emissiveMapIdx;@end -@property( use_envprobe_map ) envMapIdx = material.envMapIdx;@end - - @insertpiece( custom_ps_posMaterialLoad ) - -@property( detail_maps_diffuse || detail_maps_normal ) - //Prepare weight map for the detail maps. - @property( detail_weight_map ) - float4 detailWeights = @insertpiece( SamplerDetailWeightMap ); - @property( detail_weights )detailWeights *= material.cDetailWeights;@end - @end @property( !detail_weight_map ) - @property( detail_weights )float4 detailWeights = material.cDetailWeights;@end - @property( !detail_weights )float4 detailWeights = float4( 1.0, 1.0, 1.0, 1.0 );@end - @end -@end - - /// Sample detail maps and weight them against the weight map in the next foreach loop. -@foreach( detail_maps_diffuse, n )@property( detail_map@n ) - float4 detailCol@n = textureMaps@value(detail_map@n_idx).sample( - samplerState@value(detail_map@n_idx), - UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), - detailMapIdx@n ); - @property( !hw_gamma_read )//Gamma to linear space - detailCol@n.xyz = detailCol@n.xyz * detailCol@n.xyz;@end - detailWeights.@insertpiece(detail_swizzle@n) *= detailCol@n.w; - detailCol@n.w = detailWeights.@insertpiece(detail_swizzle@n);@end -@end - -@property( !hlms_prepass || alpha_test ) - @insertpiece( SampleDiffuseMap ) - - /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no - /// diffuse maps, we must initialize it to some value. - @property( !diffuse_map )diffuseCol = material.bgDiffuse;@end - - /// Blend the detail diffuse maps with the main diffuse. - @foreach( detail_maps_diffuse, n ) - @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end - - /// Apply the material's diffuse over the textures - @property( !transparent_mode ) - diffuseCol.xyz *= material.kD.xyz; - @end @property( transparent_mode ) - diffuseCol.xyz *= material.kD.xyz * diffuseCol.w * diffuseCol.w; - @end - - @property( alpha_test ) - if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol.a ) - discard; - @end -@end - -@property( !hlms_use_prepass ) - @property( !normal_map ) - // Geometric normal - nNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); - @end @property( normal_map ) - //Normal mapping. - float3 geomNormal = normalize( inPs.normal ) @insertpiece( two_sided_flip_normal ); - float3 vTangent = normalize( inPs.tangent ); - - //Get the TBN matrix - float3 vBinormal = normalize( cross( geomNormal, vTangent )@insertpiece( tbnApplyReflection ) ); - float3x3 TBN = float3x3( vTangent, vBinormal, geomNormal ); - - @property( normal_map_tex )nNormal = getTSNormal( samplerState@value( normal_map_tex_idx ), - textureMaps@value( normal_map_tex_idx ), - UV_NORMAL( inPs.uv@value(uv_normal).xy ), - normalIdx );@end - @property( normal_weight_tex ) - // Apply the weight to the main normal map - nNormal = mix( float3( 0.0, 0.0, 1.0 ), nNormal, normalMapWeight ); - @end - @end - - /// If there is no normal map, the first iteration must - /// initialize nNormal instead of try to merge with it. - @property( normal_map_tex ) - @piece( detail_nm_op_sum )+=@end - @piece( detail_nm_op_mul )*=@end - @end @property( !normal_map_tex ) - @piece( detail_nm_op_sum )=@end - @piece( detail_nm_op_mul )=@end - @end - - /// Blend the detail normal maps with the main normal. - @foreach( second_valid_detail_map_nm, n, first_valid_detail_map_nm ) - float3 vDetail = @insertpiece( SampleDetailMapNm@n ); - nNormal.xy @insertpiece( detail_nm_op_sum ) vDetail.xy; - nNormal.z @insertpiece( detail_nm_op_mul ) vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end - @foreach( detail_maps_normal, n, second_valid_detail_map_nm )@property( detail_map_nm@n ) - vDetail = @insertpiece( SampleDetailMapNm@n ); - nNormal.xy += vDetail.xy; - nNormal.z *= vDetail.z + 1.0 - detailWeights.@insertpiece(detail_swizzle@n) @insertpiece( detail@n_nm_weight_mul );@end @end - - @insertpiece( custom_ps_posSampleNormal ) - - @property( normal_map ) - nNormal = normalize( TBN * nNormal ); - @end - - @insertpiece( DoDirectionalShadowMaps ) - - @insertpiece( SampleRoughnessMap ) - -@end @property( hlms_use_prepass ) - ushort2 iFragCoord = ushort2( inPs.gl_FragCoord.xy ); - - @property( hlms_use_prepass_msaa ) - int gBufSubsample = ctz( gl_SampleMask ); - - nNormal = normalize( gBuf_normals.read( iFragCoord, gBufSubsample ).xyz * 2.0 - 1.0 ); - float2 shadowRoughness = gBuf_shadowRoughness.read( iFragCoord, gBufSubsample ).xy; - @end @property( !hlms_use_prepass_msaa ) - nNormal = normalize( gBuf_normals.read( iFragCoord, 0 ).xyz * 2.0 - 1.0 ); - float2 shadowRoughness = gBuf_shadowRoughness.read( iFragCoord, 0 ).xy; - @end - - float fShadow = shadowRoughness.x; - - @property( roughness_map ) - ROUGHNESS = shadowRoughness.y * 0.98 + 0.02; /// ROUGHNESS is a constant otherwise - @end -@end - - @insertpiece( SampleSpecularMap ) - -@property( !hlms_prepass ) - //Everything's in Camera space -@property( hlms_lights_spot || use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere || hlms_forwardplus ) - float3 viewDir = normalize( -inPs.pos ); - float NdotV = saturate( dot( nNormal, viewDir ) ); -@end - -@property( !ambient_fixed ) - float3 finalColour = float3(0, 0, 0); -@end @property( ambient_fixed ) - float3 finalColour = passBuf.ambientUpperHemi.xyz * @insertpiece( kD ).xyz; -@end - - @insertpiece( custom_ps_preLights ) - -@property( !custom_disable_directional_lights ) -@property( hlms_lights_directional ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[0].position.xyz, viewDir, NdotV, passBuf.lights[0].diffuse, passBuf.lights[0].specular, material, nNormal @insertpiece( brdfExtraParams ) ) @insertpiece( DarkenWithShadowFirstLight ); -@end -@foreach( hlms_lights_directional, n, 1 ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular, material, nNormal @insertpiece( brdfExtraParams ) )@insertpiece( DarkenWithShadow );@end -@foreach( hlms_lights_directional_non_caster, n, hlms_lights_directional ) - @insertpiece( ObjLightMaskCmp ) - finalColour += BRDF( passBuf.lights[@n].position.xyz, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular, material, nNormal @insertpiece( brdfExtraParams ) );@end -@end - -@property( hlms_lights_point || hlms_lights_spot || hlms_lights_area_approx ) float3 lightDir; - float fDistance; - float3 tmpColour; - float spotCosAngle;@end - - //Point lights -@foreach( hlms_lights_point, n, hlms_lights_directional_non_caster ) - lightDir = passBuf.lights[@n].position.xyz - inPs.pos; - fDistance= length( lightDir ); - if( fDistance <= passBuf.lights[@n].attenuation.x @insertpiece( andObjLightMaskCmp ) ) - { - lightDir *= 1.0 / fDistance; - tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular, material, nNormal @insertpiece( brdfExtraParams ) )@insertpiece( DarkenWithShadowPoint ); - float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); - finalColour += tmpColour * atten; - }@end - - //Spot lights - //spotParams[@value(spot_params)].x = 1.0 / cos( InnerAngle ) - cos( OuterAngle ) - //spotParams[@value(spot_params)].y = cos( OuterAngle / 2 ) - //spotParams[@value(spot_params)].z = falloff -@foreach( hlms_lights_spot, n, hlms_lights_point ) - lightDir = passBuf.lights[@n].position.xyz - inPs.pos; - fDistance= length( lightDir ); -@property( !hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), passBuf.lights[@n].spotDirection.xyz );@end -@property( hlms_lights_spot_textured ) spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[@n].position.xyz ), zAxis( passBuf.lights[@n].spotQuaternion ) );@end - if( fDistance <= passBuf.lights[@n].attenuation.x && spotCosAngle >= passBuf.lights[@n].spotParams.y @insertpiece( andObjLightMaskCmp ) ) - { - lightDir *= 1.0 / fDistance; - @property( hlms_lights_spot_textured ) - float3 posInLightSpace = qmul( spotQuaternion[@value(spot_params)], inPs.pos ); - float spotAtten = texture( texSpotLight, normalize( posInLightSpace ).xy ).x; //TODO - @end - @property( !hlms_lights_spot_textured ) - float spotAtten = saturate( (spotCosAngle - passBuf.lights[@n].spotParams.y) * passBuf.lights[@n].spotParams.x ); - spotAtten = pow( spotAtten, passBuf.lights[@n].spotParams.z ); - @end - tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[@n].diffuse, passBuf.lights[@n].specular, material, nNormal @insertpiece( brdfExtraParams ) )@insertpiece( DarkenWithShadow ); - float atten = 1.0 / (0.5 + (passBuf.lights[@n].attenuation.y + passBuf.lights[@n].attenuation.z * fDistance) * fDistance ); - finalColour += tmpColour * (atten * spotAtten); - }@end - - //Custom 2D shape lights - @insertpiece( DoAreaApproxLights ) - -@insertpiece( forward3dLighting ) -@insertpiece( applyIrradianceVolumes ) - -@property( emissive_map || emissive_constant ) - @insertpiece( SampleEmissiveMap ) - finalColour += emissiveCol.xyz; -@end - -@property( use_envprobe_map || hlms_use_ssr || use_planar_reflections || ambient_hemisphere ) - float3 reflDir = 2.0 * dot( viewDir, nNormal ) * nNormal - viewDir; - - @property( use_envprobe_map ) - @property( use_parallax_correct_cubemaps ) - float3 envColourS; - float3 envColourD; - float3 posInProbSpace = toProbeLocalSpace( inPs.pos, @insertpiece( pccProbeSource ) ); - float probeFade = getProbeFade( posInProbSpace, @insertpiece( pccProbeSource ) ); - if( probeFade > 0 ) - { - float3 reflDirLS = localCorrect( reflDir, posInProbSpace, @insertpiece( pccProbeSource ) ); - float3 nNormalLS = localCorrect( nNormal, posInProbSpace, @insertpiece( pccProbeSource ) ); - envColourS = texEnvProbeMap.sample( envMapSamplerState, - reflDirLS, level( ROUGHNESS * 12.0 ) ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - envColourD = texEnvProbeMap.sample( envMapSamplerState, - nNormalLS, level( 11.0 ) ).xyz @insertpiece( ApplyEnvMapScale );// * 0.0152587890625; - - envColourS = envColourS * saturate( probeFade * 200.0 ); - envColourD = envColourD * saturate( probeFade * 200.0 ); - } - else - { - //TODO: Fallback to a global cubemap. - envColourS = float3( 0, 0, 0 ); - envColourD = float3( 0, 0, 0 ); - } - @end @property( !use_parallax_correct_cubemaps ) - float3 envColourS = texEnvProbeMap.sample( envMapSamplerState, reflDir * passBuf.invViewMatCubemap, level( ROUGHNESS * 12.0 ) ).xyz @insertpiece( ApplyEnvMapScale ); - float3 envColourD = texEnvProbeMap.sample( envMapSamplerState, nNormal * passBuf.invViewMatCubemap, level( 11.0 ) ).xyz @insertpiece( ApplyEnvMapScale ); - @end - @property( !hw_gamma_read ) //Gamma to linear space - envColourS = envColourS * envColourS; - envColourD = envColourD * envColourD; - @end - @end - - @property( hlms_use_ssr ) - //TODO: SSR pass should be able to combine global & local cubemap. - float4 ssrReflection = ssrTexture.read( iFragCoord, 0 ).xyzw; - @property( use_envprobe_map ) - envColourS = mix( envColourS.xyz, ssrReflection.xyz, ssrReflection.w ); - @end @property( !use_envprobe_map ) - float3 envColourS = ssrReflection.xyz * ssrReflection.w; - float3 envColourD = float3( 0, 0, 0 ); - @end - @end - - @insertpiece( DoPlanarReflectionsPS ) - - @property( ambient_hemisphere ) - float ambientWD = dot( passBuf.ambientHemisphereDir.xyz, nNormal ) * 0.5 + 0.5; - float ambientWS = dot( passBuf.ambientHemisphereDir.xyz, reflDir ) * 0.5 + 0.5; - - @property( use_envprobe_map || hlms_use_ssr || use_planar_reflections ) - envColourS += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); - envColourD += mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); - @end @property( !use_envprobe_map && !hlms_use_ssr && !use_planar_reflections ) - float3 envColourS = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWD ); - float3 envColourD = mix( passBuf.ambientLowerHemi.xyz, passBuf.ambientUpperHemi.xyz, ambientWS ); - @end - @end - - @insertpiece( BRDF_EnvMap ) -@end -@end ///!hlms_prepass - -@property( !hlms_prepass ) - @property( !hw_gamma_write ) - //Linear to Gamma space - outPs.colour0.xyz = sqrt( finalColour ); - @end @property( hw_gamma_write ) - outPs.colour0.xyz = finalColour; - @end - - @property( hlms_alphablend ) - @property( use_texture_alpha ) - outPs.colour0.w = material.F0.w * diffuseCol.w; - @end @property( !use_texture_alpha ) - outPs.colour0.w = material.F0.w; - @end - @end @property( !hlms_alphablend ) - outPs.colour0.w = 1.0;@end - - @end @property( !hlms_normal && !hlms_qtangent ) - outPs.colour0 = float4( 1.0, 1.0, 1.0, 1.0 ); - @end - - @property( debug_pssm_splits ) - outPs.colour0.xyz = mix( outPs.colour0.xyz, debugPssmSplit.xyz, 0.2f ); - @end -@end @property( hlms_prepass ) - outPs.normals = float4( nNormal * 0.5 + 0.5, 1.0 ); - @property( hlms_pssm_splits ) - outPs.shadowRoughness = float2( fShadow, (ROUGHNESS - 0.02) * 1.02040816 ); - @end @property( !hlms_pssm_splits ) - outPs.shadowRoughness = float2( 1.0, (ROUGHNESS - 0.02) * 1.02040816 ); - @end -@end - + @insertpiece( DefaultBodyPS ) @insertpiece( custom_ps_posExecution ) @property( !hlms_render_depth_only ) return outPs; @end } -@end -@property( hlms_shadowcaster ) +@else ///!hlms_shadowcaster @insertpiece( DeclShadowCasterMacros ) @@ -527,75 +182,16 @@ fragment @insertpiece( output_type ) main_metal // END UNIFORM DECLARATION @foreach( num_textures, n ) - , texture2d_array textureMaps@n [[texture(@counter(textureRegStart))]]@end - @foreach( numSamplerStates, n ) - , sampler samplerState@n [[sampler(@counter(samplerStateStart))]]@end + , texture2d_array textureMaps@n [[texture(@value(textureMaps@n))]]@end + @foreach( num_samplers, n ) + , sampler samplerState@value(samplerStateStart) [[sampler(@counter(samplerStateStart))]]@end ) { @property( !hlms_render_depth_only || exponential_shadow_maps || hlms_shadowcaster_point ) PS_OUTPUT outPs; @end @insertpiece( custom_ps_preExecution ) - -@property( alpha_test ) - Material material; -@property( diffuse_map ) ushort diffuseIdx;@end -@property( detail_weight_map ) ushort weightMapIdx;@end -@foreach( 4, n ) - @property( detail_map@n )ushort detailMapIdx@n;@end @end - - float diffuseCol; - - @property( !lower_gpu_overhead ) - material = materialArray[inPs.materialId]; - @end @property( lower_gpu_overhead ) - material = materialArray[0]; - @end -@property( diffuse_map ) diffuseIdx = material.diffuseIdx;@end -@property( detail_weight_map ) weightMapIdx = material.weightMapIdx;@end -@property( detail_map0 ) detailMapIdx0 = material.detailMapIdx0;@end -@property( detail_map1 ) detailMapIdx1 = material.detailMapIdx1;@end -@property( detail_map2 ) detailMapIdx2 = material.detailMapIdx2;@end -@property( detail_map3 ) detailMapIdx3 = material.detailMapIdx3;@end - -@property( detail_maps_diffuse || detail_maps_normal ) - //Prepare weight map for the detail maps. - @property( detail_weight_map ) - float4 detailWeights = @insertpiece( SamplerDetailWeightMap ); - @property( detail_weights )detailWeights *= material.cDetailWeights;@end - @end @property( !detail_weight_map ) - @property( detail_weights )float4 detailWeights = material.cDetailWeights;@end - @property( !detail_weights )float4 detailWeights = float4( 1.0, 1.0, 1.0, 1.0 );@end - @end -@end - - /// Sample detail maps and weight them against the weight map in the next foreach loop. -@foreach( detail_maps_diffuse, n )@property( detail_map@n ) - float detailCol@n = textureMaps@value(detail_map@n_idx).sample( - samplerState@value(detail_map@n_idx), - UV_DETAIL@n( inPs.uv@value(uv_detail@n).xy@insertpiece( offsetDetail@n ) ), - detailMapIdx@n ).w; - detailCol@n = detailWeights.@insertpiece(detail_swizzle@n) * detailCol@n;@end -@end - -@insertpiece( SampleDiffuseMap ) - - /// 'insertpiece( SampleDiffuseMap )' must've written to diffuseCol. However if there are no - /// diffuse maps, we must initialize it to some value. - @property( !diffuse_map )diffuseCol = material.bgDiffuse.w;@end - - /// Blend the detail diffuse maps with the main diffuse. -@foreach( detail_maps_diffuse, n ) - @insertpiece( blend_mode_idx@n ) @add( t, 1 ) @end - - /// Apply the material's diffuse over the textures -@property( TODO_REFACTOR_ACCOUNT_MATERIAL_ALPHA ) diffuseCol.xyz *= material.kD.xyz;@end - if( material.kD.w @insertpiece( alpha_test_cmp_func ) diffuseCol ) - discard; -@end /// !alpha_test - - @insertpiece( DoShadowCastPS ) - + @insertpiece( DefaultBodyPS ) @insertpiece( custom_ps_posExecution ) @property( !hlms_render_depth_only || exponential_shadow_maps || hlms_shadowcaster_point ) diff --git a/ogre2/src/media/Hlms/Pbs/Metal/Structs_piece_vs_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/Structs_piece_vs_piece_ps.metal deleted file mode 100644 index 7131a6619..000000000 --- a/ogre2/src/media/Hlms/Pbs/Metal/Structs_piece_vs_piece_ps.metal +++ /dev/null @@ -1,252 +0,0 @@ -@piece( PassStructDecl ) -struct ShadowReceiverData -{ - float4x4 texViewProj; -@property( exponential_shadow_maps ) - float4 texViewZRow; -@end - float2 shadowDepthRange; - float2 padding; - float4 invShadowMapSize; -}; - -struct Light -{ - float4 position; //.w contains the objLightMask - float3 diffuse; - float3 specular; -@property( hlms_num_shadow_map_lights ) - float3 attenuation; - float3 spotDirection; - float3 spotParams; -@end -}; - -#define areaLightDiffuseMipmapStart areaApproxLights[0].diffuse.w -#define areaLightNumMipmapsSpecFactor areaApproxLights[0].specular.w - -struct AreaLight -{ - float4 position; //.w contains the objLightMask - float4 diffuse; //[0].w contains diffuse mipmap start - float4 specular; //[0].w contains mipmap scale - float4 attenuation; //.w contains texture array idx - //Custom 2D Shape: - // direction.xyz direction - // direction.w invHalfRectSize.x - // tangent.xyz tangent - // tangent.w invHalfRectSize.y - float4 direction; - float4 tangent; - float4 doubleSided; -}; - -@insertpiece( DeclCubemapProbeStruct ) - -//Uniforms that change per pass -struct PassData -{ - //Vertex shader (common to both receiver and casters) - float4x4 viewProj; - -@property( hlms_global_clip_planes ) - float4 clipPlane0; -@end - -@property( hlms_shadowcaster_point ) - float4 cameraPosWS; //Camera position in world space -@end - -@property( !hlms_shadowcaster ) - //Vertex shader - float4x4 view; - @property( hlms_num_shadow_map_lights )ShadowReceiverData shadowRcv[@value(hlms_num_shadow_map_lights)];@end - - //------------------------------------------------------------------------- - - //Pixel shader - float3x3 invViewMatCubemap; - -@property( hlms_use_prepass ) - float4 windowHeight; -@end - -@property( ambient_hemisphere || ambient_fixed || envmap_scale ) - float4 ambientUpperHemi; -@end -@property( ambient_hemisphere ) - float4 ambientLowerHemi; - float4 ambientHemisphereDir; -@end -@property( irradiance_volumes ) - float4 irradianceOrigin; //.w = maxPower - float4 irradianceSize; //.w = 1.0f / irradianceTexture->getHeight() - float4x4 invView; -@end -@property( hlms_pssm_splits )@psub( hlms_pssm_splits_minus_one, hlms_pssm_splits, 1 )@foreach( hlms_pssm_splits, n ) - float pssmSplitPoints@n;@end @end -@property( hlms_pssm_blend )@foreach( hlms_pssm_splits_minus_one, n ) - float pssmBlendPoints@n;@end @end -@property( hlms_pssm_fade ) - float pssmFadePoint;@end - @property( hlms_lights_spot )Light lights[@value(hlms_lights_spot)];@end - @property( hlms_lights_area_approx )AreaLight areaApproxLights[@value(hlms_lights_area_approx)];@end -@end @property( hlms_shadowcaster ) - //Vertex shader - @property( exponential_shadow_maps )float4 viewZRow;@end - float2 depthRange; -@end - -@property( hlms_forwardplus ) - //Forward3D - //f3dData.x = minDistance; - //f3dData.y = invMaxDistance; - //f3dData.z = f3dNumSlicesSub1; - //f3dData.w = uint cellsPerTableOnGrid0 (floatBitsToUint); - - //Clustered Forward: - //f3dData.x = minDistance; - //f3dData.y = invExponentK; - //f3dData.z = f3dNumSlicesSub1; - //f3dData.w = renderWindow->getHeight(); - float4 f3dData; - @property( hlms_forwardplus == forward3d ) - float4 f3dGridHWW[@value( forward3d_num_slices )]; - float4 f3dViewportOffset; - @end - @property( hlms_forwardplus != forward3d ) - float4 fwdScreenToGrid; - @end -@end - - @insertpiece( DeclPlanarReflUniforms ) - -@property( parallax_correct_cubemaps ) - CubemapProbe autoProbe; -@end - - @insertpiece( custom_passBuffer ) -};@end - -@piece( PassDecl ) -, constant PassData &passBuf [[buffer(CONST_SLOT_START+0)]] -@end - -@property( fresnel_scalar )@piece( FresnelType )float3@end @piece( FresnelSwizzle )xyz@end @end -@property( !fresnel_scalar )@piece( FresnelType )float@end @piece( FresnelSwizzle )x@end @end - -@piece( MaterialStructDecl ) -//Uniforms that change per Item/Entity, but change very infrequently -struct Material -{ - /* kD is already divided by PI to make it energy conserving. - (formula is finalDiffuse = NdotL * surfaceDiffuse / PI) - */ - float4 bgDiffuse; - float4 kD; //kD.w is alpha_test_threshold - float4 kS; //kS.w is roughness - //Fresnel coefficient, may be per colour component (float3) or scalar (float) - //F0.w is transparency - float4 F0; - float4 normalWeights; - float4 cDetailWeights; - float4 detailOffsetScale[4]; - float4 emissive; //emissive.w contains mNormalMapWeight. - float4 userValue[3]; - - //uint4 indices0_3; - ushort diffuseIdx; - ushort normalIdx; - ushort specularIdx; - ushort roughnessIdx; - ushort weightMapIdx; - ushort detailMapIdx0; - ushort detailMapIdx1; - ushort detailMapIdx2; - - //uint4 indices4_7; - ushort detailMapIdx3; - ushort detailNormMapIdx0; - ushort detailNormMapIdx1; - ushort detailNormMapIdx2; - ushort detailNormMapIdx3; - ushort emissiveMapIdx; - ushort envMapIdx; - - @insertpiece( custom_materialBuffer ) -};@end - -@piece( MaterialDecl ) -, constant Material *materialArray [[buffer(CONST_SLOT_START+1)]] -@end - - -@piece( InstanceDecl ) -//Uniforms that change per Item/Entity -//.x = -//The lower 9 bits contain the material's start index. -//The higher 23 bits contain the world matrix start index. -// -//.y = -//shadowConstantBias. Send the bias directly to avoid an -//unnecessary indirection during the shadow mapping pass. -//Must be loaded with uintBitsToFloat -, constant uint4 *worldMaterialIdx [[buffer(CONST_SLOT_START+2)]] -@end - -@property( envprobe_map && envprobe_map != target_envprobe_map && use_parallax_correct_cubemaps ) -@piece( PccManualProbeDecl ) -, constant CubemapProbe &manualProbe [[buffer(CONST_SLOT_START+3)]] -@end -@end - -//Reset texcoord to 0 for every shader stage (since values are preserved). -@pset( texcoord, 0 ) - -@piece( VStoPS_block ) - @property( !hlms_shadowcaster ) - @property( !lower_gpu_overhead ) - ushort materialId [[flat]]; - @end - @property( hlms_fine_light_mask || hlms_forwardplus_fine_light_mask ) - uint objLightMask [[flat]]; - @end - @property( use_planar_reflections ) - ushort planarReflectionIdx [[flat]]; - @end - @property( hlms_normal || hlms_qtangent ) - float3 pos; - float3 normal; - @property( normal_map )float3 tangent; - @property( hlms_qtangent )float biNormalReflection [[flat]];@end - @end - @end - @foreach( hlms_uv_count, n ) - float@value( hlms_uv_count@n ) uv@n;@end - - @foreach( hlms_num_shadow_map_lights, n ) - @property( !hlms_shadowmap@n_is_point_light ) - float4 posL@n;@end @end - - @property( hlms_pssm_splits )float depth;@end - @end - - @property( hlms_shadowcaster ) - @property( alpha_test ) - ushort drawId [[flat]]; - @foreach( hlms_uv_count, n ) - float@value( hlms_uv_count@n ) uv@n;@end - @end - @property( (!hlms_shadow_uses_depth_texture || exponential_shadow_maps) && !hlms_shadowcaster_point ) - float depth; - @end - @property( hlms_shadowcaster_point ) - float3 toCameraWS; - @property( !exponential_shadow_maps ) - float constBias [[flat]]; - @end - @end - @end - - @insertpiece( custom_VStoPS ) -@end diff --git a/ogre2/src/media/Hlms/Pbs/Metal/Textures_piece_ps.metal b/ogre2/src/media/Hlms/Pbs/Metal/Textures_piece_ps.metal index 857854437..fb76fb715 100644 --- a/ogre2/src/media/Hlms/Pbs/Metal/Textures_piece_ps.metal +++ b/ogre2/src/media/Hlms/Pbs/Metal/Textures_piece_ps.metal @@ -1,194 +1,11 @@ -//Set the sampler starts. Note that 'padd' get calculated before _any_ 'add' -@set( texUnit, 1 ) - -@property( hlms_forwardplus ) - @add( texUnit, 2 ) -@end - -@property( hlms_use_prepass ) - @set( gBuf_normals, texUnit ) - @add( gBuf_shadowRoughness, texUnit, 1 ) - @add( texUnit, 2 ) - - @property( hlms_use_ssr ) - @set( ssrTexture, texUnit ) - @add( texUnit, 1 ) - @end -@end - -@property( irradiance_volumes ) - @set( irradianceVolumeTexUnit, texUnit ) - @add( texUnit, 1 ) -@end - -@property( hlms_lights_area_tex_mask ) - @set( areaLightsApproxTexUnit, texUnit ) - @add( texUnit, 1 ) -@end - -@set( textureRegShadowMapStart, texUnit ) -@add( texUnit, hlms_num_shadow_map_textures ) - -@property( parallax_correct_cubemaps ) - @set( globaPccTexUnit, texUnit ) - @add( texUnit, 1 ) -@end - -@property( has_planar_reflections ) - @set( planarReflectionTexUnit, texUnit ) - @add( texUnit, 1 ) -@end - -@set( textureRegStart, texUnit ) -@set( samplerStateStart, texUnit ) -@set( numSamplerStates, num_textures ) -@add( texUnit, num_textures ) - -@set( envMapReg, texUnit ) - -@property( (envprobe_map && envprobe_map != target_envprobe_map) || parallax_correct_cubemaps ) - @set( use_envprobe_map, 1 ) - - @property( !envprobe_map || envprobe_map == target_envprobe_map ) - /// "No cubemap"? Then we're in auto mode or... - /// We're rendering to the cubemap probe we're using as manual. Use the auto mode as fallback. - @piece( pccProbeSource )passBuf.autoProbe@end - @set( use_parallax_correct_cubemaps, 1 ) - /// Auto cubemap textures are set at the beginning. Manual cubemaps are the end. - @set( envMapReg, globaPccTexUnit ) - @end - @property( envprobe_map && envprobe_map != target_envprobe_map && use_parallax_correct_cubemaps ) - @piece( pccProbeSource )manualProbe@end - @end -@end - -@property( diffuse_map ) - @property( !hlms_shadowcaster ) - @piece( SampleDiffuseMap ) diffuseCol = textureMaps@value( diffuse_map_idx ).sample( - samplerState@value(diffuse_map_idx), - UV_DIFFUSE( inPs.uv@value(uv_diffuse).xy ), - diffuseIdx ); -@property( !hw_gamma_read ) diffuseCol = diffuseCol * diffuseCol;@end @end - @end @property( hlms_shadowcaster ) - @piece( SampleDiffuseMap ) diffuseCol = textureMaps@value( diffuse_map_idx ).sample( - samplerState@value(diffuse_map_idx), - UV_DIFFUSE( inPs.uv@value(uv_diffuse).xy ), - diffuseIdx ).w;@end - @end -@end - -@property( transparent_mode ) - @piece( diffuseExtraParamDef ), float4 diffuseCol@end - @piece( diffuseExtraParam ), diffuseCol.xyzw@end -@end @property( !transparent_mode ) - @piece( diffuseExtraParamDef ), float3 diffuseCol@end - @piece( diffuseExtraParam ), diffuseCol.xyz@end -@end -//diffuseCol always has some colour and is multiplied against material.kD in PixelShader_ps. -@piece( kD )diffuseCol@end - -@property( !hlms_prepass ) -@property( !metallic_workflow ) - @property( specular_map && !fresnel_workflow ) - @piece( SampleSpecularMap ) specularCol = textureMaps@value( specular_map_idx ).sample( - samplerState@value(specular_map_idx), - UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx ).xyz * material.kS.xyz;@end - @piece( specularExtraParamDef ), float3 specularCol@end - @piece( specularExtraParam ), specularCol.xyz@end - @piece( kS )specularCol@end - @end - @property( specular_map && fresnel_workflow ) - @piece( SampleSpecularMap ) F0 = textureMaps@value( specular_map_idx ).sample( - samplerState@value(specular_map_idx), - UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx ).@insertpiece( FresnelSwizzle ) * material.F0.@insertpiece( FresnelSwizzle );@end - @piece( specularExtraParamDef ), @insertpiece( FresnelType ) F0@end - @piece( specularExtraParam ), F0@end - @end - @property( !specular_map || fresnel_workflow ) - @piece( kS )material.kS@end - @end -@end @property( metallic_workflow ) -@piece( SampleSpecularMap ) - @property( specular_map ) - float metalness = textureMaps@value( specular_map_idx ).sample( - samplerState@value(specular_map_idx), - UV_SPECULAR( inPs.uv@value(uv_specular).xy ), - specularIdx ).x * material.F0.x; - F0 = mix( 0.03f, @insertpiece( kD ).xyz * 3.14159f, metalness ); - @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * metalness; - @end @property( !specular_map ) - F0 = mix( 0.03f, @insertpiece( kD ).xyz * 3.14159f, material.F0.x ); - @insertpiece( kD ).xyz = @insertpiece( kD ).xyz - @insertpiece( kD ).xyz * material.F0.x; - @end - @property( hlms_alphablend )F0 *= material.F0.w;@end - @property( transparent_mode )F0 *= diffuseCol.w;@end -@end /// SampleSpecularMap - - @piece( kS )material.kS.xyz@end - @piece( metallicExtraParamDef ), float3 F0@end - @piece( metallicExtraParam ), F0@end -@end -@end - -@property( roughness_map ) - @piece( SampleRoughnessMap ) ROUGHNESS = material.kS.w * textureMaps@value( roughness_map_idx ).sample( - samplerState@value( roughness_map_idx ), - UV_ROUGHNESS( inPs.uv@value(uv_roughness).xy ), - roughnessIdx ).x; - ROUGHNESS = max( ROUGHNESS, 0.001f );@end - @piece( roughnessExtraParamDef ), float ROUGHNESS@end - @piece( roughnessExtraParam ), ROUGHNESS@end -@end - -@piece( brdfExtraParamDefs )@insertpiece( diffuseExtraParamDef )@insertpiece( specularExtraParamDef )@insertpiece( roughnessExtraParamDef )@insertpiece( metallicExtraParamDef )@end -@piece( brdfExtraParams )@insertpiece( diffuseExtraParam )@insertpiece( specularExtraParam )@insertpiece( roughnessExtraParam )@insertpiece( metallicExtraParam )@end - -@foreach( detail_maps_normal, n ) - @piece( SampleDetailMapNm@n )getTSNormal( samplerState@value(detail_map_nm@n_idx), - textureMaps@value(detail_map_nm@n_idx), - UV_DETAIL_NM@n( inPs.uv@value(uv_detail_nm@n).xy@insertpiece( offsetDetail@n ) ), - detailNormMapIdx@n ) * detailWeights.@insertpiece(detail_swizzle@n) - @insertpiece( detail@n_nm_weight_mul )@end -@end - -@property( detail_weight_map ) - @piece( SamplerDetailWeightMap )textureMaps@value(detail_weight_map_idx).sample( - samplerState@value(detail_weight_map_idx), - UV_DETAIL_WEIGHT( inPs.uv@value(uv_detail_weight).xy ), - weightMapIdx )@end -@end - -@property( envmap_scale ) - @piece( ApplyEnvMapScale )* passBuf.ambientUpperHemi.w@end -@end - -@property( emissive_map ) - @piece( SampleEmissiveMap ) - float3 emissiveCol = textureMaps@value( emissive_map_idx ).sample( - samplerState@value(emissive_map_sampler), - UV_EMISSIVE( inPs.uv@value(uv_emissive).xy ), - emissiveMapIdx ).xyz; - @property( emissive_constant ) - emissiveCol *= material.emissive.xyz; +@property( !hlms_render_depth_only && !hlms_shadowcaster ) + @piece( ExtraOutputTypes ) + @property( hlms_gen_normals_gbuffer ) + float4 normals [[ color(@counter(rtv_target)) ]]; + @end + @property( hlms_prepass ) + float2 shadowRoughness [[ color(@counter(rtv_target)) ]]; @end - @end -@end -@property( !emissive_map && emissive_constant ) - @piece( SampleEmissiveMap ) - float3 emissiveCol = material.emissive.xyz; - @end -@end - -@property( !hlms_render_depth_only && !hlms_shadowcaster && hlms_prepass ) - @undefpiece( DeclOutputType ) - @piece( DeclOutputType ) - struct PS_OUTPUT - { - float4 normals [[ color(0) ]]; - float2 shadowRoughness [[ color(1) ]]; - }; @end @end diff --git a/ogre2/src/media/Hlms/Pbs/Metal/VertexShader_vs.metal b/ogre2/src/media/Hlms/Pbs/Metal/VertexShader_vs.metal index 9a726ca1b..65b74965d 100644 --- a/ogre2/src/media/Hlms/Pbs/Metal/VertexShader_vs.metal +++ b/ogre2/src/media/Hlms/Pbs/Metal/VertexShader_vs.metal @@ -1,11 +1,9 @@ -@insertpiece( SetCrossPlatformSettings ) -@insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) -@insertpiece( Common_Matrix_DeclUnpackMatrix3x4 ) +//#include "SyntaxHighlightingMisc.h" -@property( hlms_normal || hlms_qtangent || normal_map ) - @insertpiece( Common_Matrix_Conversions ) -@end +@insertpiece( SetCrossPlatformSettings ) + +@insertpiece( DefaultHeaderVS ) struct VS_INPUT { @@ -34,110 +32,15 @@ struct PS_INPUT { @insertpiece( VStoPS_block ) float4 gl_Position [[position]]; - @foreach( n, hlms_pso_clip_distances ) - float gl_ClipDistance@n [[clip_distance]]; - @end -}; - -// START UNIFORM STRUCT DECLARATION -@insertpiece( PassStructDecl ) -@insertpiece( custom_vs_uniformStructDeclaration ) -// END UNIFORM STRUCT DECLARATION - -@property( hlms_qtangent ) -@insertpiece( DeclQuat_xAxis ) -@property( normal_map ) -@insertpiece( DeclQuat_yAxis ) -@end @end - -@property( !hlms_skeleton ) -@piece( local_vertex )input.position@end -@piece( local_normal )normal@end -@piece( local_tangent )tangent@end -@end -@property( hlms_skeleton ) -@piece( local_vertex )worldPos@end -@piece( local_normal )worldNorm@end -@piece( local_tangent )worldTang@end -@end - -@property( hlms_skeleton )@piece( SkeletonTransform ) - int _idx = int((input.blendIndices[0] << 1u) + input.blendIndices[0]); //blendIndices[0] * 3u; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) - int matStart = int(worldMaterialIdx[drawId].x >> 9u); - float4 worldMat[3]; - worldMat[0] = worldMatBuf[matStart + _idx + 0u]; - worldMat[1] = worldMatBuf[matStart + _idx + 1u]; - worldMat[2] = worldMatBuf[matStart + _idx + 2u]; - float4 worldPos; - worldPos.x = dot( worldMat[0], input.position ); - worldPos.y = dot( worldMat[1], input.position ); - worldPos.z = dot( worldMat[2], input.position ); - worldPos.xyz *= input.blendWeights[0]; - @property( hlms_normal || hlms_qtangent )float3 worldNorm; - worldNorm.x = dot( worldMat[0].xyz, normal ); - worldNorm.y = dot( worldMat[1].xyz, normal ); - worldNorm.z = dot( worldMat[2].xyz, normal ); - worldNorm *= input.blendWeights[0];@end - @property( normal_map )float3 worldTang; - worldTang.x = dot( worldMat[0].xyz, tangent ); - worldTang.y = dot( worldMat[1].xyz, tangent ); - worldTang.z = dot( worldMat[2].xyz, tangent ); - worldTang *= input.blendWeights[0];@end - @psub( NeedsMoreThan1BonePerVertex, hlms_bones_per_vertex, 1 ) - @property( NeedsMoreThan1BonePerVertex )float4 tmp; - tmp.w = 1.0;@end //!NeedsMoreThan1BonePerVertex - @foreach( hlms_bones_per_vertex, n, 1 ) - _idx = (input.blendIndices[@n] << 1u) + input.blendIndices[@n]; //blendIndices[@n] * 3; a 32-bit int multiply is 4 cycles on GCN! (and mul24 is not exposed to GLSL...) - worldMat[0] = worldMatBuf[matStart + _idx + 0u]; - worldMat[1] = worldMatBuf[matStart + _idx + 1u]; - worldMat[2] = worldMatBuf[matStart + _idx + 2u]; - tmp.x = dot( worldMat[0], input.position ); - tmp.y = dot( worldMat[1], input.position ); - tmp.z = dot( worldMat[2], input.position ); - worldPos.xyz += (tmp * input.blendWeights[@n]).xyz; - @property( hlms_normal || hlms_qtangent ) - tmp.x = dot( worldMat[0].xyz, normal ); - tmp.y = dot( worldMat[1].xyz, normal ); - tmp.z = dot( worldMat[2].xyz, normal ); - worldNorm += tmp.xyz * input.blendWeights[@n];@end - @property( normal_map ) - tmp.x = dot( worldMat[0].xyz, tangent ); - tmp.y = dot( worldMat[1].xyz, tangent ); - tmp.z = dot( worldMat[2].xyz, tangent ); - worldTang += tmp.xyz * input.blendWeights[@n];@end + @property( hlms_pso_clip_distances ) + float gl_ClipDistance [[clip_distance]] [@value( hlms_pso_clip_distances )]; @end +}; - worldPos.w = 1.0; -@end @end //SkeletonTransform // !hlms_skeleton - -@property( hlms_skeleton ) - @piece( worldViewMat )passBuf.view@end -@end @property( !hlms_skeleton ) - @piece( worldViewMat )worldView@end -@end - -@piece( CalculatePsPos )( @insertpiece(local_vertex) * @insertpiece( worldViewMat ) ).xyz@end +// START UNIFORM METAL STRUCT DECLARATION +// END UNIFORM METAL STRUCT DECLARATION -@piece( VertexTransform ) -@insertpiece( custom_vs_preTransform ) - //Lighting is in view space - @property( hlms_normal || hlms_qtangent || normal_map )float3x3 mat3x3 = toMat3x3( @insertpiece( worldViewMat ) );@end - @property( hlms_normal || hlms_qtangent )outVs.pos = @insertpiece( CalculatePsPos );@end - @property( hlms_normal || hlms_qtangent )outVs.normal = @insertpiece(local_normal) * mat3x3;@end - @property( normal_map )outVs.tangent = @insertpiece(local_tangent) * mat3x3;@end -@property( !hlms_dual_paraboloid_mapping ) - outVs.gl_Position = worldPos * passBuf.viewProj;@end -@property( hlms_dual_paraboloid_mapping ) - //Dual Paraboloid Mapping - outVs.gl_Position.w = 1.0f; - @property( hlms_normal || hlms_qtangent )outVs.gl_Position.xyz = outVs.pos;@end - @property( !hlms_normal && !hlms_qtangent )outVs.gl_Position.xyz = @insertpiece( CalculatePsPos );@end - float L = length( outVs.gl_Position.xyz ); - outVs.gl_Position.z += 1.0f; - outVs.gl_Position.xy /= outVs.gl_Position.z; - outVs.gl_Position.z = (L - NearPlane) / (FarPlane - NearPlane);@end -@end vertex PS_INPUT main_metal ( @@ -150,62 +53,30 @@ vertex PS_INPUT main_metal @insertpiece( PassDecl ) @insertpiece( InstanceDecl ) , device const float4 *worldMatBuf [[buffer(TEX_SLOT_START+0)]] + @property( hlms_pose ) + @property( !hlms_pose_half ) + , device const float4 *poseBuf [[buffer(TEX_SLOT_START+@value(poseBuf))]] + @else + , device const half4 *poseBuf [[buffer(TEX_SLOT_START+@value(poseBuf))]] + @end + @end + @property( hlms_vertex_id ) + , uint vertexId [[vertex_id]] + , uint baseVertex [[base_vertex]] + @end @insertpiece( custom_vs_uniformDeclaration ) // END UNIFORM DECLARATION ) { - @property( iOS ) - ushort drawId = baseInstance + instanceId; - @end @property( !iOS ) - ushort drawId = input.drawId; - @end - PS_INPUT outVs; - @insertpiece( custom_vs_preExecution ) -@property( !hlms_skeleton ) - float3x4 worldMat = UNPACK_MAT3x4( worldMatBuf, drawId @property( !hlms_shadowcaster )<< 1u@end ); - @property( hlms_normal || hlms_qtangent ) - float4x4 worldView = UNPACK_MAT4( worldMatBuf, (drawId << 1u) + 1u ); - @end - - float4 worldPos = float4( ( input.position * worldMat ).xyz, 1.0f ); -@end - -@property( hlms_qtangent ) - //Decode qTangent to TBN with reflection - float3 normal = xAxis( normalize( input.qtangent ) ); - @property( normal_map ) - float3 tangent = yAxis( input.qtangent ); - outVs.biNormalReflection = sign( input.qtangent.w ); //We ensure in C++ qtangent.w is never 0 - @end -@end @property( !hlms_qtangent && hlms_normal ) +@property( !hlms_qtangent && hlms_normal ) float3 normal = input.normal; @property( normal_map )float3 tangent = input.tangent;@end + @property( hlms_binormal )float3 binormal = input.binormal;@end @end - @insertpiece( SkeletonTransform ) - @insertpiece( VertexTransform ) - - @insertpiece( DoShadowReceiveVS ) - @insertpiece( DoShadowCasterVS ) - - /// hlms_uv_count will be 0 on shadow caster passes w/out alpha test -@foreach( hlms_uv_count, n ) - outVs.uv@n = input.uv@n;@end - -@property( (!hlms_shadowcaster || alpha_test) && !lower_gpu_overhead ) - outVs.materialId = worldMaterialIdx[drawId].x & 0x1FFu;@end - -@property( hlms_fine_light_mask || hlms_forwardplus_fine_light_mask ) - outVs.objLightMask = worldMaterialIdx[drawId].z;@end - -@property( use_planar_reflections ) - outVs.planarReflectionIdx = (ushort)(worldMaterialIdx[drawId].w);@end - -@property( hlms_global_clip_planes ) - outVs.gl_ClipDistance0 = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); -@end - + @insertpiece( custom_vs_preExecution ) + @insertpiece( DefaultBodyVS ) @insertpiece( custom_vs_posExecution ) return outVs; diff --git a/ogre2/src/media/Hlms/Unlit/GLSL/BlendModes_piece_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSL/BlendModes_piece_ps.glsl index f70f16bf7..d44bb0c59 100644 --- a/ogre2/src/media/Hlms/Unlit/GLSL/BlendModes_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Unlit/GLSL/BlendModes_piece_ps.glsl @@ -93,11 +93,6 @@ @foreach( 16, n ) @property( uv_atlas@n ) @piece( atlasOffset@n )* atlasOffsets[@n].z + atlasOffsets[@n].xy @end @end @end -// Get the indexes to the textureMaps[] array using template code. We had to add 1 -// to the actual value otherwise property( diffuse_map ) fails when the index is 0 -@foreach( diffuse_map, n ) - @sub( diffuse_map@n_idx, diffuse_map@n, 1 ) @end - @piece( diffuseIdx0 )material.indices0_3.x & 0x0000FFFFu@end @piece( diffuseIdx1 )material.indices0_3.x >> 16u@end @piece( diffuseIdx2 )material.indices0_3.y & 0x0000FFFFu@end @@ -110,26 +105,26 @@ @foreach( diffuse_map, n ) @property( diffuse_map@n_array ) @piece( SamplerOrigin@n )textureMapsArray[@value(diffuse_map@n_idx)]@end - @end @property( !diffuse_map@n_array ) + @else @piece( SamplerOrigin@n )textureMaps[@value(diffuse_map@n_idx)]@end @end @property( !diffuse_map@n_reflection ) @property( diffuse_map@n_array ) @piece( SamplerUV@n )vec3( inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n ), @insertpiece( diffuseIdx@n ) )@end - @end @property( !diffuse_map@n_array ) + @else @piece( SamplerUV@n )inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n )@end @end - @end @property( diffuse_map@n_reflection ) + @else @property( !hlms_forwardplus_flipY ) @property( diffuse_map@n_array ) @piece( SamplerUV@n )vec3( gl_FragCoord.x * passBuf.invWindowSize.x, 1.0 - gl_FragCoord.y * passBuf.invWindowSize.y, @insertpiece( diffuseIdx@n ) )@end - @end @property( !diffuse_map@n_array ) + @else @piece( SamplerUV@n )vec2( gl_FragCoord.x * passBuf.invWindowSize.x, 1.0 - gl_FragCoord.y * passBuf.invWindowSize.y )@end @end - @end @property( hlms_forwardplus_flipY ) + @else @property( diffuse_map@n_array ) @piece( SamplerUV@n )vec3( gl_FragCoord.xy * passBuf.invWindowSize.xy, @insertpiece( diffuseIdx@n ) )@end - @end @property( !diffuse_map@n_array ) + @else @piece( SamplerUV@n )vec2( gl_FragCoord.xy * passBuf.invWindowSize.xy )@end @end @end diff --git a/ogre2/src/media/Hlms/Unlit/GLSL/PixelShader_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSL/PixelShader_ps.glsl index 74b601be7..0d1e91ebc 100644 --- a/ogre2/src/media/Hlms/Unlit/GLSL/PixelShader_ps.glsl +++ b/ogre2/src/media/Hlms/Unlit/GLSL/PixelShader_ps.glsl @@ -43,7 +43,7 @@ void main() { @insertpiece( custom_ps_preExecution ) @property( diffuse_map || alpha_test || diffuse ) - uint materialId = instance.worldMaterialIdx[inPs.drawId].x; + uint materialId = worldMaterialIdx[inPs.drawId].x; material = materialArray.m[materialId]; @end @insertpiece( custom_ps_posMaterialLoad ) @@ -70,7 +70,7 @@ void main() @insertpiece( custom_ps_preLights ) -@property( alpha_test ) +@property( alpha_test && !alpha_test_shadow_caster_only ) if( material.alpha_test_threshold.x @insertpiece( alpha_test_cmp_func ) outColour.a ) discard;@end diff --git a/ogre2/src/media/Hlms/Unlit/GLSL/Structs_piece_vs_piece_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSL/Structs_piece_vs_piece_ps.glsl index bc96e1a13..71bdf00cc 100644 --- a/ogre2/src/media/Hlms/Unlit/GLSL/Structs_piece_vs_piece_ps.glsl +++ b/ogre2/src/media/Hlms/Unlit/GLSL/Structs_piece_vs_piece_ps.glsl @@ -41,7 +41,7 @@ layout_constbuffer(binding = 2) uniform InstanceBuffer //Contains 0 or 1 to index into passBuf.viewProj[]. Only used //if hlms_identity_viewproj_dynamic is set. uvec4 worldMaterialIdx[4096]; -} instance; +}; @end @piece( VStoPS_block ) diff --git a/ogre2/src/media/Hlms/Unlit/GLSL/VertexShader_vs.glsl b/ogre2/src/media/Hlms/Unlit/GLSL/VertexShader_vs.glsl index cc6589f23..9198e3f4c 100644 --- a/ogre2/src/media/Hlms/Unlit/GLSL/VertexShader_vs.glsl +++ b/ogre2/src/media/Hlms/Unlit/GLSL/VertexShader_vs.glsl @@ -47,7 +47,7 @@ out block @property( !hlms_identity_viewproj_dynamic ) @piece( worldViewProj )passBuf.viewProj[@value(hlms_identity_viewproj)]@end @end @property( hlms_identity_viewproj_dynamic ) - @piece( worldViewProj )passBuf.viewProj[instance.worldMaterialIdx[finalDrawId].z]@end + @piece( worldViewProj )passBuf.viewProj[worldMaterialIdx[finalDrawId].z]@end @end @end @@ -84,7 +84,7 @@ void main() @foreach( out_uv_count, n ) @property( out_uv@n_texture_matrix ) - textureMatrix = UNPACK_MAT4( animationMatrixBuf, (instance.worldMaterialIdx[finalDrawId].x << 4u) + @value( out_uv@n_tex_unit )u ); + textureMatrix = UNPACK_MAT4( animationMatrixBuf, (worldMaterialIdx[finalDrawId].x << 4u) + @value( out_uv@n_tex_unit )u ); outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = (vec4( uv@value( out_uv@n_source_uv ).xy, 0, 1 ) * textureMatrix).xy; @end @property( !out_uv@n_texture_matrix ) outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = uv@value( out_uv@n_source_uv ).xy; diff --git a/ogre2/src/media/Hlms/Unlit/GLSLES/BlendModes_piece_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSLES/BlendModes_piece_ps.glsl new file mode 100644 index 000000000..f70f16bf7 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/GLSLES/BlendModes_piece_ps.glsl @@ -0,0 +1,137 @@ +//Reset t to 0 just in case (values are preserved from previous stages) +@pset( t, 0 ) + +@piece( NormalNonPremul ) + //Normal Non Premultiplied @counter(t) + outColour.xyz = mix( outColour.xyz, topImage@value(t).xyz, topImage@value(t).a ); + outColour.w = mix( outColour.w, 1.0, topImage@value(t).w ); +@end + +@piece( NormalPremul ) + //Normal Premultiplied @counter(t) + outColour.xyz = (1.0 - topImage@value(t).a) * outColour.xyz + topImage@value(t).xyz; + outColour.w = mix( outColour.w, 1.0, topImage@value(t).w ); +@end + +@piece( Add ) + //Add @counter(t) + outColour.xyz = mix( outColour.xyz, + min( outColour.xyz + topImage@value(t).xyz, vec3(1.0) ), + topImage@value(t).a ); +@end + +@piece( Subtract ) + //Subtract @counter(t) + outColour.xyz = mix( outColour.xyz, + max( outColour.xyz - topImage@value(t).xyz, vec3(0.0) ), + topImage@value(t).a ); +@end + +@piece( Multiply ) + //Multiply @counter(t) + outColour.xyz = mix( outColour.xyz, + outColour.xyz * topImage@value(t).xyz, + topImage@value(t).a ); +@end + +@piece( Multiply2x ) + //Multiply2x @counter(t) + outColour.xyz = mix( outColour.xyz, + min( outColour.xyz * topImage@value(t).xyz * 2.0, vec3(1.0) ), + topImage@value(t).a ); +@end + +@piece( Screen ) + //Screen @counter(t) + outColour.xyz = mix( outColour.xyz, + 1.0 - (1.0 - outColour.xyz) * (1.0 - topImage@value(t).xyz), + topImage@value(t).a ); +@end + +@piece( Overlay ) + //Overlay @counter(t) + outColour.xyz = mix( outColour.xyz, + outColour.xyz * ( outColour.xyz + 2.0 * topImage@value(t).xyz * (1.0 - outColour.xyz) ), + topImage@value(t).a ); +@end + +@piece( Lighten ) + //Lighten @counter(t) + outColour.xyz = mix( outColour.xyz, + max( outColour.xyz, topImage@value(t).xyz ), + topImage@value(t).a ); +@end + +@piece( Darken ) + //Darken @counter(t) + outColour.xyz = mix( outColour.xyz, + min( outColour.xyz, topImage@value(t).xyz ), + topImage@value(t).a ); +@end + +@piece( GrainExtract ) + //GrainExtract @counter(t) + outColour.xyz = mix( outColour.xyz, + (outColour.xyz - topImage@value(t).xyz) + 0.5f, + topImage@value(t).a ); +@end + +@piece( GrainMerge ) + //GrainMerge @counter(t) + outColour.xyz = mix( outColour.xyz, + (outColour.xyz + topImage@value(t).xyz) - 0.5f, + topImage@value(t).a ); +@end + +@piece( Difference ) + //Difference @counter(t) + outColour.xyz = mix( outColour.xyz, + abs(outColour.xyz - topImage@value(t).xyz), + topImage@value(t).a ); +@end + +@foreach( 16, n ) +@property( uv_atlas@n ) @piece( atlasOffset@n )* atlasOffsets[@n].z + atlasOffsets[@n].xy @end @end @end + +// Get the indexes to the textureMaps[] array using template code. We had to add 1 +// to the actual value otherwise property( diffuse_map ) fails when the index is 0 +@foreach( diffuse_map, n ) + @sub( diffuse_map@n_idx, diffuse_map@n, 1 ) @end + +@piece( diffuseIdx0 )material.indices0_3.x & 0x0000FFFFu@end +@piece( diffuseIdx1 )material.indices0_3.x >> 16u@end +@piece( diffuseIdx2 )material.indices0_3.y & 0x0000FFFFu@end +@piece( diffuseIdx3 )material.indices0_3.y >> 16u@end +@piece( diffuseIdx4 )material.indices0_3.z & 0x0000FFFFu@end +@piece( diffuseIdx5 )material.indices0_3.z >> 16u@end +@piece( diffuseIdx6 )material.indices0_3.w & 0x0000FFFFu@end +@piece( diffuseIdx7 )material.indices0_3.w >> 16u@end + +@foreach( diffuse_map, n ) + @property( diffuse_map@n_array ) + @piece( SamplerOrigin@n )textureMapsArray[@value(diffuse_map@n_idx)]@end + @end @property( !diffuse_map@n_array ) + @piece( SamplerOrigin@n )textureMaps[@value(diffuse_map@n_idx)]@end + @end + @property( !diffuse_map@n_reflection ) + @property( diffuse_map@n_array ) + @piece( SamplerUV@n )vec3( inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n ), @insertpiece( diffuseIdx@n ) )@end + @end @property( !diffuse_map@n_array ) + @piece( SamplerUV@n )inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n )@end + @end + @end @property( diffuse_map@n_reflection ) + @property( !hlms_forwardplus_flipY ) + @property( diffuse_map@n_array ) + @piece( SamplerUV@n )vec3( gl_FragCoord.x * passBuf.invWindowSize.x, 1.0 - gl_FragCoord.y * passBuf.invWindowSize.y, @insertpiece( diffuseIdx@n ) )@end + @end @property( !diffuse_map@n_array ) + @piece( SamplerUV@n )vec2( gl_FragCoord.x * passBuf.invWindowSize.x, 1.0 - gl_FragCoord.y * passBuf.invWindowSize.y )@end + @end + @end @property( hlms_forwardplus_flipY ) + @property( diffuse_map@n_array ) + @piece( SamplerUV@n )vec3( gl_FragCoord.xy * passBuf.invWindowSize.xy, @insertpiece( diffuseIdx@n ) )@end + @end @property( !diffuse_map@n_array ) + @piece( SamplerUV@n )vec2( gl_FragCoord.xy * passBuf.invWindowSize.xy )@end + @end + @end + @end +@end diff --git a/ogre2/src/media/Hlms/Unlit/GLSLES/PixelShader_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSLES/PixelShader_ps.glsl new file mode 100644 index 000000000..ce64f66e5 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/GLSLES/PixelShader_ps.glsl @@ -0,0 +1,97 @@ +@insertpiece( SetCrossPlatformSettings ) +@insertpiece( SetCompatibilityLayer ) + +layout(std140) uniform; +#define FRAG_COLOR 0 + +@property( hlms_vpos ) +in vec4 gl_FragCoord; +@end + +@property( !hlms_shadowcaster ) +layout(location = FRAG_COLOR) out vec4 outColour; +@end @property( hlms_shadowcaster ) +layout(location = FRAG_COLOR) out float outColour; +@end + +// START UNIFORM DECLARATION +@property( has_planar_reflections ) + @insertpiece( PassDecl ) +@end +@property( !hlms_shadowcaster && (diffuse_map || alpha_test || diffuse) ) +@insertpiece( MaterialDecl ) +@insertpiece( InstanceDecl ) +@end +@insertpiece( custom_ps_uniformDeclaration ) +// END UNIFORM DECLARATION +@property( !hlms_shadowcaster || !hlms_shadow_uses_depth_texture || exponential_shadow_maps ) +in block +{ +@insertpiece( VStoPS_block ) +} inPs; +@end + +@property( !hlms_shadowcaster ) +@property( num_array_textures )uniform sampler2DArray textureMapsArray[@value( num_array_textures )];@end +@property( num_textures )uniform sampler2D textureMaps[@value( num_textures )];@end + +@property( diffuse )@piece( MultiplyDiffuseConst )* material.diffuse@end @end + +@property( diffuse_map || alpha_test || diffuse )Material material;@end + +void main() +{ + @insertpiece( custom_ps_preExecution ) +@property( diffuse_map || alpha_test || diffuse ) + uint materialId = instance.worldMaterialIdx[inPs.drawId].x; + material = materialArray.m[materialId]; +@end + @insertpiece( custom_ps_posMaterialLoad ) + +@property( !diffuse_map && !diffuse_map0 ) +@property( hlms_colour && !diffuse_map ) outColour = inPs.colour @insertpiece( MultiplyDiffuseConst );@end +@property( !hlms_colour && !diffuse ) outColour = vec4(1, 1, 1, 1);@end +@property( !hlms_colour && diffuse ) outColour = material.diffuse;@end +@end + +@property( diffuse_map )@property( diffuse_map0 ) + //Load base image + outColour = texture( @insertpiece( SamplerOrigin0 ), @insertpiece( SamplerUV0 ) ).@insertpiece(diffuse_map0_tex_swizzle);@end + +@foreach( diffuse_map, n, 1 )@property( diffuse_map@n ) + vec4 topImage@n = texture( @insertpiece( SamplerOrigin@n ), @insertpiece( SamplerUV@n ) ).@insertpiece(diffuse_map@n_tex_swizzle);@end @end + +@foreach( diffuse_map, n, 1 )@property( diffuse_map@n ) + @insertpiece( blend_mode_idx@n )@end @end + + @property( hlms_colour )outColour *= inPs.colour @insertpiece( MultiplyDiffuseConst );@end + @property( !hlms_colour && diffuse )outColour *= material.diffuse;@end +@end + + @insertpiece( custom_ps_preLights ) + +@property( alpha_test && !alpha_test_shadow_caster_only ) + if( material.alpha_test_threshold.x @insertpiece( alpha_test_cmp_func ) outColour.a ) + discard;@end + + @insertpiece( custom_ps_posExecution ) +} + +@end @property( hlms_shadowcaster ) + @property( 0 && hlms_render_depth_only && !macOS) + @set( hlms_disable_stage, 1 ) + @end + +@insertpiece( DeclShadowCasterMacros ) + +@property( hlms_shadowcaster_point ) + @insertpiece( PassDecl ) +@end + +void main() +{ + @insertpiece( custom_ps_preExecution ) + @insertpiece( DoShadowCastPS ) + @insertpiece( custom_ps_posExecution ) +} +@end diff --git a/ogre2/src/media/Hlms/Unlit/GLSLES/Structs_piece_vs_piece_ps.glsl b/ogre2/src/media/Hlms/Unlit/GLSLES/Structs_piece_vs_piece_ps.glsl new file mode 100644 index 000000000..5e73a167f --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/GLSLES/Structs_piece_vs_piece_ps.glsl @@ -0,0 +1,66 @@ +@piece( PassDecl ) +//Uniforms that change per pass +layout_constbuffer(binding = 0) uniform PassBuffer +{ + @insertpiece( PassInternalDecl ) +} passBuf; +@end + +@piece( MaterialDecl ) +struct Material +{ + vec4 alpha_test_threshold; + vec4 diffuse; + + uvec4 indices0_3; + uvec4 indices4_7; + + @insertpiece( custom_materialBuffer ) +}; + +layout_constbuffer(binding = 1) uniform MaterialBuf +{ + Material m[@value( materials_per_buffer )]; +} materialArray; +@end + + +@piece( InstanceDecl ) +//Uniforms that change per Item/Entity +layout_constbuffer(binding = 2) uniform InstanceBuffer +{ + //.x = + //Contains the material's start index. + // + //.y = + //shadowConstantBias. Send the bias directly to avoid an + //unnecessary indirection during the shadow mapping pass. + //Must be loaded with uintBitsToFloat + // + //.z = + //Contains 0 or 1 to index into passBuf.viewProj[]. Only used + //if hlms_identity_viewproj_dynamic is set. + uvec4 worldMaterialIdx[1024]; +} instance; +@end + +@piece( VStoPS_block ) + @property( !hlms_shadowcaster ) + flat uint drawId; + @property( hlms_colour )vec4 colour;@end + @foreach( out_uv_half_count, n ) + vec@value( out_uv_half_count@n ) uv@n;@end + @end + @property( hlms_shadowcaster ) + @property( (!hlms_shadow_uses_depth_texture || exponential_shadow_maps) && !hlms_shadowcaster_point ) + float depth; + @end + @property( hlms_shadowcaster_point ) + vec3 toCameraWS; + @property( !exponential_shadow_maps ) + flat float constBias; + @end + @end + @end + @insertpiece( custom_VStoPS ) +@end diff --git a/ogre2/src/media/Hlms/Unlit/GLSLES/VertexShader_vs.glsl b/ogre2/src/media/Hlms/Unlit/GLSLES/VertexShader_vs.glsl new file mode 100644 index 000000000..8d2ff5b8a --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/GLSLES/VertexShader_vs.glsl @@ -0,0 +1,113 @@ +@insertpiece( SetCrossPlatformSettings ) +@insertpiece( SetCompatibilityLayer ) + +@property( GL3+ ) +out gl_PerVertex +{ + vec4 gl_Position; +@property( hlms_pso_clip_distances ) + float gl_ClipDistance[@value(hlms_pso_clip_distances)]; +@end +}; +@end + +layout(std140) uniform; + +@insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) + +in vec4 vertex; +@property( hlms_colour )in vec4 colour;@end + +@foreach( hlms_uv_count, n ) +in vec@value( hlms_uv_count@n ) uv@n;@end + +@property( GL_ARB_base_instance ) + in uint drawId; +@end + +@insertpiece( custom_vs_attributes ) + +@property( !hlms_shadowcaster || !hlms_shadow_uses_depth_texture || exponential_shadow_maps ) +out block +{ +@insertpiece( VStoPS_block ) +} outVs; +@end + +// START UNIFORM DECLARATION +@insertpiece( PassDecl ) +@property( hlms_identity_world && hlms_identity_viewproj_dynamic )@set(VsUseInstanceDecl,1)@end +@foreach( out_uv_count, n )@property( out_uv@n_texture_matrix )@set(VsUseInstanceDecl,1)@end@end +#if @value(VsUseInstanceDecl) // iOS GLSL ES compiler optimizes unused uniform blocks up to the breaking VS/PS layout compatibility +@insertpiece( InstanceDecl ) +#endif +/*layout(binding = 0) */uniform samplerBuffer worldMatBuf; +@property( texture_matrix )/*layout(binding = 1) */uniform samplerBuffer animationMatrixBuf;@end +@insertpiece( custom_vs_uniformDeclaration ) +@property( !GL_ARB_base_instance )uniform uint baseInstance;@end +// END UNIFORM DECLARATION + +@property( !hlms_identity_world ) + @piece( worldViewProj )worldViewProj@end +@end @property( hlms_identity_world ) + @property( !hlms_identity_viewproj_dynamic ) + @piece( worldViewProj )passBuf.viewProj[@value(hlms_identity_viewproj)]@end + @end @property( hlms_identity_viewproj_dynamic ) + @piece( worldViewProj )passBuf.viewProj[instance.worldMaterialIdx[finalDrawId].z]@end + @end +@end + +void main() +{ +@property( !GL_ARB_base_instance ) + uint drawId = baseInstance + uint( gl_InstanceID ); +@end + + @insertpiece( custom_vs_preExecution ) + @property( !hlms_identity_world ) + mat4 worldViewProj; + worldViewProj = UNPACK_MAT4( worldMatBuf, finalDrawId ); + @end + +@property( !hlms_dual_paraboloid_mapping ) + gl_Position = vertex * @insertpiece( worldViewProj ); +@end + +@property( hlms_dual_paraboloid_mapping ) + //Dual Paraboloid Mapping + gl_Position.w = 1.0f; + gl_Position.xyz = (vertex * @insertpiece( worldViewProj )).xyz; + float L = length( gl_Position.xyz ); + gl_Position.z += 1.0f; + gl_Position.xy /= gl_Position.z; + gl_Position.z = (L - NearPlane) / (FarPlane - NearPlane); +@end + +@property( !hlms_shadowcaster ) +@property( hlms_colour ) outVs.colour = colour;@end + +@property( texture_matrix ) mat4 textureMatrix;@end + +@foreach( out_uv_count, n ) + @property( out_uv@n_texture_matrix ) + textureMatrix = UNPACK_MAT4( animationMatrixBuf, (instance.worldMaterialIdx[finalDrawId].x << 4u) + @value( out_uv@n_tex_unit )u ); + outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = (vec4( uv@value( out_uv@n_source_uv ).xy, 0, 1 ) * textureMatrix).xy; + @end @property( !out_uv@n_texture_matrix ) + outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = uv@value( out_uv@n_source_uv ).xy; + @end @end + + outVs.drawId = finalDrawId; + +@end + + @property( hlms_global_clip_planes || (hlms_shadowcaster && (exponential_shadow_maps || hlms_shadowcaster_point)) ) + float3 worldPos = (gl_Position * passBuf.invViewProj).xyz; + @end + @insertpiece( DoShadowCasterVS ) + +@property( hlms_global_clip_planes ) + gl_ClipDistance[0] = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); +@end + + @insertpiece( custom_vs_posExecution ) +} diff --git a/ogre2/src/media/Hlms/Unlit/HLSL/BlendModes_piece_ps.hlsl b/ogre2/src/media/Hlms/Unlit/HLSL/BlendModes_piece_ps.hlsl new file mode 100644 index 000000000..3701eb500 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/HLSL/BlendModes_piece_ps.hlsl @@ -0,0 +1,127 @@ +//Reset t to 0 just in case (values are preserved from previous stages) +@pset( t, 0 ) + +@piece( NormalNonPremul ) + //Normal Non Premultiplied @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, topImage@value(t).xyz, topImage@value(t).a ); + outPs.colour0.w = lerp( outPs.colour0.w, 1.0, topImage@value(t).w ); +@end + +@piece( NormalPremul ) + //Normal Premultiplied @counter(t) + outPs.colour0.xyz = (1.0 - topImage@value(t).a) * outPs.colour0.xyz + topImage@value(t).xyz; + outPs.colour0.w = lerp( outPs.colour0.w, 1.0, topImage@value(t).w ); +@end + +@piece( Add ) + //Add @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + min( outPs.colour0.xyz + topImage@value(t).xyz, float3(1.0,1.0,1.0) ), + topImage@value(t).a ); +@end + +@piece( Subtract ) + //Subtract @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + max( outPs.colour0.xyz - topImage@value(t).xyz, float3(0.0,0.0,0.0) ), + topImage@value(t).a ); +@end + +@piece( Multiply ) + //Multiply @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + outPs.colour0.xyz * topImage@value(t).xyz, + topImage@value(t).a ); +@end + +@piece( Multiply2x ) + //Multiply2x @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + min( outPs.colour0.xyz * topImage@value(t).xyz * 2.0, float3(1.0,1.0,1.0) ), + topImage@value(t).a ); +@end + +@piece( Screen ) + //Screen @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + 1.0 - (1.0 - outPs.colour0.xyz) * (1.0 - topImage@value(t).xyz), + topImage@value(t).a ); +@end + +@piece( Overlay ) + //Overlay @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + outPs.colour0.xyz * ( outPs.colour0.xyz + 2.0 * topImage@value(t).xyz * (1.0 - outPs.colour0.xyz) ), + topImage@value(t).a ); +@end + +@piece( Lighten ) + //Lighten @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + max( outPs.colour0.xyz, topImage@value(t).xyz ), + topImage@value(t).a ); +@end + +@piece( Darken ) + //Darken @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + min( outPs.colour0.xyz, topImage@value(t).xyz ), + topImage@value(t).a ); +@end + +@piece( GrainExtract ) + //GrainExtract @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + (outPs.colour0.xyz - topImage@value(t).xyz) + 0.5f, + topImage@value(t).a ); +@end + +@piece( GrainMerge ) + //GrainMerge @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + (outPs.colour0.xyz + topImage@value(t).xyz) - 0.5f, + topImage@value(t).a ); +@end + +@piece( Difference ) + //Difference @counter(t) + outPs.colour0.xyz = lerp( outPs.colour0.xyz, + abs(outPs.colour0.xyz - topImage@value(t).xyz), + topImage@value(t).a ); +@end + +@foreach( 16, n ) +@property( uv_atlas@n ) @piece( atlasOffset@n )* atlasOffsets[@n].z + atlasOffsets[@n].xy @end @end @end + +@piece( diffuseIdx0 )material.indices0_3.x & 0x0000FFFFu@end +@piece( diffuseIdx1 )material.indices0_3.x >> 16u@end +@piece( diffuseIdx2 )material.indices0_3.y & 0x0000FFFFu@end +@piece( diffuseIdx3 )material.indices0_3.y >> 16u@end +@piece( diffuseIdx4 )material.indices0_3.z & 0x0000FFFFu@end +@piece( diffuseIdx5 )material.indices0_3.z >> 16u@end +@piece( diffuseIdx6 )material.indices0_3.w & 0x0000FFFFu@end +@piece( diffuseIdx7 )material.indices0_3.w >> 16u@end + +@foreach( diffuse_map, n ) + @property( !diffuse_map@n_reflection ) + @property( diffuse_map@n_array ) + @piece( TextureOrigin@n )textureMapsArray@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end + @piece( SamplerUV@n )float3( inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n ), @insertpiece( diffuseIdx@n ) )@end + @else + @piece( TextureOrigin@n )textureMaps@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end + @piece( SamplerUV@n )inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n )@end + @end + @else + @property( diffuse_map@n_array ) + @piece( TextureOrigin@n )textureMapsArray@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end + @piece( SamplerUV@n )float3( gl_FragCoord.xy * passBuf.invWindowSize.xy, @insertpiece( diffuseIdx@n ) )@end + @else + @piece( TextureOrigin@n )textureMaps@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end + @piece( SamplerUV@n )gl_FragCoord.xy * passBuf.invWindowSize.xy@end + @end + @end +@end diff --git a/ogre2/src/media/Hlms/Unlit/HLSL/PixelShader_ps.hlsl b/ogre2/src/media/Hlms/Unlit/HLSL/PixelShader_ps.hlsl new file mode 100644 index 000000000..8f88e45a1 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/HLSL/PixelShader_ps.hlsl @@ -0,0 +1,101 @@ +@insertpiece( SetCrossPlatformSettings ) + +// START UNIFORM DECLARATION +@property( has_planar_reflections ) + @insertpiece( PassDecl ) +@end +@property( !hlms_shadowcaster ) +@insertpiece( MaterialDecl ) +@insertpiece( InstanceDecl ) +@end +@insertpiece( custom_ps_uniformDeclaration ) +// END UNIFORM DECLARATION +struct PS_INPUT +{ +@insertpiece( VStoPS_block ) +}; + +@property( !hlms_shadowcaster ) + +@foreach( num_array_textures, n ) +Texture2DArray textureMapsArray@n : register(t@value(array_texture_bind@n));@end +@foreach( num_textures, n ) +Texture2D textureMaps@n : register(t@value(texture_bind@n));@end + +@pset( samplerStateBind, sampler_unit_slot_start ) + +@foreach( num_samplers, n ) +SamplerState samplerState@n : register(s@counter(samplerStateBind));@end + +@property( diffuse )@piece( MultiplyDiffuseConst )* material.diffuse@end @end + +@insertpiece( DeclOutputType ) + +@insertpiece( output_type ) main( PS_INPUT inPs +@property( hlms_vpos ), float4 gl_FragCoord : SV_Position@end ) +{ + PS_OUTPUT outPs; + @insertpiece( custom_ps_preExecution ) + + @property( diffuse_map || alpha_test || diffuse )Material material;@end + +@property( diffuse_map || alpha_test || diffuse ) + uint materialId = worldMaterialIdx[inPs.drawId].x; + material = materialArray[materialId]; +@end + + @insertpiece( custom_ps_posMaterialLoad ) + +@property( !diffuse_map && !diffuse_map0 ) +@property( hlms_colour && !diffuse_map ) outPs.colour0 = inPs.colour @insertpiece( MultiplyDiffuseConst );@end +@property( !hlms_colour && !diffuse ) outPs.colour0 = float4(1, 1, 1, 1);@end +@property( !hlms_colour && diffuse ) outPs.colour0 = material.diffuse;@end +@end + +@property( diffuse_map )@property( diffuse_map0 ) + //Load base image + outPs.colour0 = @insertpiece( TextureOrigin0 ).Sample( @insertpiece( SamplerOrigin0 ), @insertpiece( SamplerUV0 ) ).@insertpiece(diffuse_map0_tex_swizzle);@end + +@foreach( diffuse_map, n, 1 )@property( diffuse_map@n ) + float4 topImage@n = @insertpiece( TextureOrigin@n ).Sample( @insertpiece( SamplerOrigin@n ), @insertpiece( SamplerUV@n ) ).@insertpiece(diffuse_map@n_tex_swizzle);@end @end + +@foreach( diffuse_map, n, 1 )@property( diffuse_map@n ) + @insertpiece( blend_mode_idx@n )@end @end + + @property( hlms_colour )outPs.colour0 *= inPs.colour @insertpiece( MultiplyDiffuseConst );@end + @property( !hlms_colour && diffuse )outPs.colour0 *= material.diffuse;@end +@end + + @insertpiece( custom_ps_preLights ) + +@property( alpha_test && !alpha_test_shadow_caster_only ) + if( material.alpha_test_threshold.x @insertpiece( alpha_test_cmp_func ) outPs.colour0.a ) + discard;@end + + @insertpiece( custom_ps_posExecution ) + +@property( !hlms_render_depth_only ) + return outPs; +@end +} +@end @property( hlms_shadowcaster ) + @property( hlms_render_depth_only ) + @set( hlms_disable_stage, 1 ) + @end +@insertpiece( DeclShadowCasterMacros ) + +@property( hlms_shadowcaster_point ) + @insertpiece( PassDecl ) +@end + +@insertpiece( DeclOutputType ) +@insertpiece( output_type ) main( PS_INPUT inPs +@property( hlms_vpos ), float4 gl_FragCoord : SV_Position@end ) +{ + PS_OUTPUT outPs; + @insertpiece( custom_ps_preExecution ) + @insertpiece( DoShadowCastPS ) + @insertpiece( custom_ps_posExecution ) + return outPs; +} +@end diff --git a/ogre2/src/media/Hlms/Unlit/HLSL/Structs_piece_vs_piece_ps.hlsl b/ogre2/src/media/Hlms/Unlit/HLSL/Structs_piece_vs_piece_ps.hlsl new file mode 100644 index 000000000..e3e12f929 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/HLSL/Structs_piece_vs_piece_ps.hlsl @@ -0,0 +1,76 @@ +@piece( PassDecl ) +//Uniforms that change per pass +cbuffer PassBuffer : register(b0) +{ + struct PassData + { + @insertpiece( PassInternalDecl ) + } passBuf; +}; +@end + +@piece( MaterialDecl ) +struct Material +{ + float4 alpha_test_threshold; + float4 diffuse; + + uint4 indices0_3; + uint4 indices4_7; + + @insertpiece( custom_materialBuffer ) +}; + +cbuffer materialArray : register(b1) +{ + Material materialArray[@value( materials_per_buffer )]; +}; +@end + + +@piece( InstanceDecl ) +//Uniforms that change per Item/Entity +cbuffer instance : register(b2) +{ + //.x = + //Contains the material's start index. + // + //.y = + //shadowConstantBias. Send the bias directly to avoid an + //unnecessary indirection during the shadow mapping pass. + //Must be loaded with uintBitsToFloat + // + //.z = + //Contains 0 or 1 to index into passBuf.viewProj[]. Only used + //if hlms_identity_viewproj_dynamic is set. + @property( fast_shader_build_hack ) + uint4 worldMaterialIdx[2]; + @end @property( !fast_shader_build_hack ) + uint4 worldMaterialIdx[4096]; + @end +}; +@end + +//Reset texcoord to 0 for every shader stage (since values are preserved). +@pset( texcoord, 0 ) + +@piece( VStoPS_block ) + @property( !hlms_shadowcaster ) + nointerpolation uint drawId : TEXCOORD@counter(texcoord); + @property( hlms_colour )float4 colour : TEXCOORD@counter(texcoord);@end + @foreach( out_uv_half_count, n ) + float@value( out_uv_half_count@n ) uv@n : TEXCOORD@counter(texcoord);@end + @end + @property( hlms_shadowcaster ) + @property( (!hlms_shadow_uses_depth_texture || exponential_shadow_maps) && !hlms_shadowcaster_point ) + float depth : TEXCOORD@counter(texcoord); + @end + @property( hlms_shadowcaster_point ) + float3 toCameraWS : TEXCOORD@counter(texcoord); + @property( !exponential_shadow_maps ) + nointerpolation float constBias : TEXCOORD@counter(texcoord); + @end + @end + @end + @insertpiece( custom_VStoPS ) +@end diff --git a/ogre2/src/media/Hlms/Unlit/HLSL/VertexShader_vs.hlsl b/ogre2/src/media/Hlms/Unlit/HLSL/VertexShader_vs.hlsl new file mode 100644 index 000000000..4000710a2 --- /dev/null +++ b/ogre2/src/media/Hlms/Unlit/HLSL/VertexShader_vs.hlsl @@ -0,0 +1,101 @@ +@insertpiece( SetCrossPlatformSettings ) + +@insertpiece( Common_Matrix_DeclUnpackMatrix4x4 ) + +// START UNIFORM DECLARATION +@insertpiece( PassDecl ) +@insertpiece( InstanceDecl ) +Buffer worldMatBuf : register(t0); +@property( texture_matrix )Buffer animationMatrixBuf : register(t1);@end +@insertpiece( custom_vs_uniformDeclaration ) +// END UNIFORM DECLARATION + +struct VS_INPUT +{ + float4 vertex : POSITION; +@property( hlms_colour ) float4 colour : COLOR0;@end +@foreach( hlms_uv_count, n ) + float@value( hlms_uv_count@n ) uv@n : TEXCOORD@n;@end + uint drawId : DRAWID; + @insertpiece( custom_vs_attributes ) +}; + +struct PS_INPUT +{ +@insertpiece( VStoPS_block ) + float4 gl_Position : SV_Position; + + @pdiv( full_pso_clip_distances, hlms_pso_clip_distances, 4 ) + @pmod( partial_pso_clip_distances, hlms_pso_clip_distances, 4 ) + @foreach( full_pso_clip_distances, n ) + float4 gl_ClipDistance@n : SV_ClipDistance@n; + @end + @property( partial_pso_clip_distances ) + float@value( partial_pso_clip_distances ) gl_ClipDistance@value( full_pso_clip_distances ) : SV_ClipDistance@value( full_pso_clip_distances ); + @end +}; + +@property( !hlms_identity_world ) + @piece( worldViewProj )worldViewProj@end +@end @property( hlms_identity_world ) + @property( !hlms_identity_viewproj_dynamic ) + @piece( worldViewProj )passBuf.viewProj[@value(hlms_identity_viewproj)]@end + @end @property( hlms_identity_viewproj_dynamic ) + @piece( worldViewProj )passBuf.viewProj[worldMaterialIdx[finalDrawId].z]@end + @end +@end + +PS_INPUT main( VS_INPUT input ) +{ + PS_INPUT outVs; + @insertpiece( custom_vs_preExecution ) + + @property( !hlms_identity_world ) + float4x4 worldViewProj; + worldViewProj = UNPACK_MAT4( worldMatBuf, finalDrawId ); + @end + +@property( !hlms_dual_paraboloid_mapping ) + outVs.gl_Position = mul( input.vertex, @insertpiece( worldViewProj ) ); +@end + +@property( hlms_dual_paraboloid_mapping ) + //Dual Paraboloid Mapping + outVs.gl_Position.w = 1.0f; + outVs.gl_Position.xyz = mul( input.vertex, @insertpiece( worldViewProj ) ).xyz; + float L = length( outVs.gl_Position.xyz ); + outVs.gl_Position.z += 1.0f; + outVs.gl_Position.xy /= outVs.gl_Position.z; + outVs.gl_Position.z = (L - NearPlane) / (FarPlane - NearPlane); +@end + +@property( !hlms_shadowcaster ) +@property( hlms_colour ) outVs.colour = input.colour;@end + +@property( texture_matrix ) float4x4 textureMatrix;@end + +@foreach( out_uv_count, n ) + @property( out_uv@n_texture_matrix ) + textureMatrix = UNPACK_MAT4( animationMatrixBuf, (worldMaterialIdx[finalDrawId].x << 4u) + @value( out_uv@n_tex_unit ) ); + outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = mul( float4( input.uv@value( out_uv@n_source_uv ).xy, 0, 1 ), textureMatrix ).xy; + @end @property( !out_uv@n_texture_matrix ) + outVs.uv@value( out_uv@n_out_uv ).@insertpiece( out_uv@n_swizzle ) = input.uv@value( out_uv@n_source_uv ).xy; + @end @end + + outVs.drawId = finalDrawId; + +@end + + @property( hlms_global_clip_planes || (hlms_shadowcaster && (exponential_shadow_maps || hlms_shadowcaster_point)) ) + float3 worldPos = mul(outVs.gl_Position, passBuf.invViewProj).xyz; + @end + @insertpiece( DoShadowCasterVS ) + +@property( hlms_global_clip_planes ) + outVs.gl_ClipDistance0 = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); +@end + + @insertpiece( custom_vs_posExecution ) + + return outVs; +} diff --git a/ogre2/src/media/Hlms/Unlit/Metal/BlendModes_piece_ps.metal b/ogre2/src/media/Hlms/Unlit/Metal/BlendModes_piece_ps.metal index 1ec58fbea..1099ca220 100644 --- a/ogre2/src/media/Hlms/Unlit/Metal/BlendModes_piece_ps.metal +++ b/ogre2/src/media/Hlms/Unlit/Metal/BlendModes_piece_ps.metal @@ -93,30 +93,25 @@ @foreach( 16, n ) @property( uv_atlas@n ) @piece( atlasOffset@n )* atlasOffsets[@n].z + atlasOffsets[@n].xy @end @end @end -// Get the indexes to the textureMaps[] array using template code. We had to add 1 -// to the actual value otherwise property( diffuse_map ) fails when the index is 0 -@foreach( diffuse_map, n ) - @sub( diffuse_map@n_idx, diffuse_map@n, 1 ) @end - @foreach( diffuse_map, n ) @property( !diffuse_map@n_reflection ) @property( diffuse_map@n_array ) @piece( TextureOrigin@n )textureMapsArray@value(diffuse_map@n_idx)@end - @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end @piece( SamplerUV@n )inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n ), material.diffuseIdx@n @end @end @property( !diffuse_map@n_array ) @piece( TextureOrigin@n )textureMaps@value(diffuse_map@n_idx)@end - @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end @piece( SamplerUV@n )inPs.uv@value( uv_diffuse@n ).@insertpiece( uv_diffuse_swizzle@n )@end @end - @end @property( diffuse_map@n_reflection ) + @else @property( diffuse_map@n_array ) @piece( TextureOrigin@n )textureMapsArray@value(diffuse_map@n_idx)@end - @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end @piece( SamplerUV@n )gl_FragCoord.xy * passBuf.invWindowSize.xy, material.diffuseIdx@n@end @end @property( !diffuse_map@n_array ) @piece( TextureOrigin@n )textureMaps@value(diffuse_map@n_idx)@end - @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_idx)@end + @piece( SamplerOrigin@n )samplerState@value(diffuse_map@n_sampler)@end @piece( SamplerUV@n )gl_FragCoord.xy * passBuf.invWindowSize.xy@end @end @end diff --git a/ogre2/src/media/Hlms/Unlit/Metal/PixelShader_ps.metal b/ogre2/src/media/Hlms/Unlit/Metal/PixelShader_ps.metal index e01a6dac7..a980410a0 100644 --- a/ogre2/src/media/Hlms/Unlit/Metal/PixelShader_ps.metal +++ b/ogre2/src/media/Hlms/Unlit/Metal/PixelShader_ps.metal @@ -16,8 +16,7 @@ struct PS_INPUT @property( !hlms_shadowcaster ) -@padd( numSamplerStates, num_array_textures, num_textures ) -@pset( samplerStateBind, 2 ) +@pset( samplerStateBind, sampler_unit_slot_start ) @property( diffuse )@piece( MultiplyDiffuseConst )* material.diffuse@end @end @@ -41,7 +40,7 @@ fragment @insertpiece( output_type ) main_metal , texture2d_array textureMapsArray@n [[texture(@value(array_texture_bind@n))]]@end @foreach( num_textures, n ) , texture2d textureMaps@n [[texture(@value(texture_bind@n))]]@end - @foreach( numSamplerStates, n ) + @foreach( num_samplers, n ) , sampler samplerState@n [[sampler(@counter(samplerStateBind))]]@end ) { @@ -79,9 +78,9 @@ fragment @insertpiece( output_type ) main_metal @insertpiece( custom_ps_preLights ) -@property( alpha_test ) +@property( alpha_test && !alpha_test_shadow_caster_only ) if( material.alpha_test_threshold.x @insertpiece( alpha_test_cmp_func ) outPs.colour0.a ) - discard;@end + discard_fragment();@end @insertpiece( custom_ps_posExecution ) diff --git a/ogre2/src/media/Hlms/Unlit/Metal/VertexShader_vs.metal b/ogre2/src/media/Hlms/Unlit/Metal/VertexShader_vs.metal index c69b1ea63..55413a58e 100644 --- a/ogre2/src/media/Hlms/Unlit/Metal/VertexShader_vs.metal +++ b/ogre2/src/media/Hlms/Unlit/Metal/VertexShader_vs.metal @@ -21,8 +21,9 @@ struct PS_INPUT { @insertpiece( VStoPS_block ) float4 gl_Position [[position]]; - @foreach( n, hlms_pso_clip_distances ) - float gl_ClipDistance@n [[clip_distance]]; + + @property( hlms_pso_clip_distances ) + float gl_ClipDistance [[clip_distance]] [@value( hlms_pso_clip_distances )]; @end }; @@ -103,7 +104,7 @@ vertex PS_INPUT main_metal @insertpiece( DoShadowCasterVS ) @property( hlms_global_clip_planes ) - outVs.gl_ClipDistance0 = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); + outVs.gl_ClipDistance[0] = dot( float4( worldPos.xyz, 1.0 ), passBuf.clipPlane0.xyzw ); @end @insertpiece( custom_vs_posExecution )