From 7def756623029ef168cf159147d4df39e702ae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Wed, 8 Sep 2021 23:26:52 +0100 Subject: [PATCH] From Ogre 2.1 to Ogre 2.2 (#272) * Ogre2.2 Signed-off-by: ahcorde * Added media files Signed-off-by: ahcorde * Added Headless mode Signed-off-by: ahcorde * Added feedback Signed-off-by: ahcorde * Added feedback Signed-off-by: ahcorde * Add OGRE2.2 to dependencies Signed-off-by: Michael Carroll * Fixed GPUray and depthCamera test Co-authored-by: Michael Carroll Signed-off-by: ahcorde * cast based on pf Signed-off-by: Ian Chen * Fix cleanup with packaged debs Signed-off-by: Michael Carroll * fix copy raw data Signed-off-by: Ian Chen * fix material test Signed-off-by: Ian Chen * Lint and compiler warning Signed-off-by: Michael Carroll * Trim whitespace Signed-off-by: Michael Carroll * Apply gamma correction to sky Signed-off-by: ahcorde * Test fixes to Ogre2.2 branch (#279) Signed-off-by: Michael Carroll * Revert gamma correction in the sky Signed-off-by: ahcorde * enable grayscale albedo map to fix red color highlights and disable hardware gamma to fix dark sky color Signed-off-by: Ian Chen * Local updates for Ogre2.2 against main branch (#317) * Local updates for Ogre2.2 against main branch Signed-off-by: Ian Chen Co-authored-by: Ian Chen * Fix merge Signed-off-by: ahcorde * fix shadows in ogre 2.2 Signed-off-by: Ian Chen * Lint Signed-off-by: Michael Carroll * fix toggling sky Signed-off-by: Ian Chen * fix camera test Signed-off-by: Ian Chen * make linters happy Signed-off-by: ahcorde * make linters happy Signed-off-by: ahcorde * Fix small regression from merge Signed-off-by: Michael Carroll * Remove problematic leftover files from 2.1 The mere presence of these files can cause incorrect shader generation or unknown visual bugs. IMPORTANT: The installation folder (i.e. CMAKE_INSTALL_PREFIX) must remove them as well. `make install` won't be enough because it won't remove files, only add new ones or update existing ones. This folder is usually installed in ign/install/share/ignition/ignition-rendering6/ogre2/media/Hlms Signed-off-by: Matias N. Goldberg * Do not crash on shutdown - ogreRoot may be nullptr - Do not destroy textures already scheduled for destruction Signed-off-by: Matias N. Goldberg * Remove problematic leftover files from 2.1 (#354) The mere presence of these files can cause incorrect shader generation or unknown visual bugs. IMPORTANT: The installation folder (i.e. CMAKE_INSTALL_PREFIX) must remove them as well. `make install` won't be enough because it won't remove files, only add new ones or update existing ones. This folder is usually installed in ign/install/share/ignition/ignition-rendering6/ogre2/media/Hlms Signed-off-by: Matias N. Goldberg * Do not crash on shutdown (#355) - ogreRoot may be nullptr - Do not destroy textures already scheduled for destruction Signed-off-by: Matias N. Goldberg * Removed unused variable Signed-off-by: ahcorde * Restore FSAA support in 2.2 branch Signed-off-by: Matias N. Goldberg * Fix changing background color not always taking immediate effect Changed pass_clear in favour of LoadAction::Clear which is more efficient on very modern GPUs and specially TBDR ones. Signed-off-by: Matias N. Goldberg * Changed pass_clear in favour of LoadAction::Clear which is more efficient on very modern GPUs and specially TBDR ones. Signed-off-by: Matias N. Goldberg * Missing public keyword Signed-off-by: Matias N. Goldberg * Save VRAM when FSAA is used and no postprocessing There's an unused texture when these conditions are met (which are fairly common) This memory optimization could not be performed in Ogre 2.1, it needs Ogre 2.2+ Signed-off-by: Matias N. Goldberg * Remove code deprecated in ign-rendering5 Syntax cosmetic changes for consistency Signed-off-by: Matias N. Goldberg * Remove code deprecated in ign-rendering5 Signed-off-by: Matias N. Goldberg * Code style fixes Signed-off-by: Matias N. Goldberg * Undo VRAM saving optimization: It cannot be applied The "Final Composition" node requires both textures to be resident. Thus 2nd texture must always be resident. The optimization could still be applied if we create two Final Composition nodes (one for when 2 textures are needed, another for when only MSAA + 1 texture is needed) but this would: 1. Hurt code readability too much (i.e. what is going on?) 2. Increase debuggability difficulty too much because codepaths taken would differ depending on whether optimization was applied. Also certain bugs could remain hidden until compositors are toggled. This was causing ogre2_demo to fail. Signed-off-by: Matias N. Goldberg * fixing tests Signed-off-by: Ian Chen * add ifdef Signed-off-by: Ian Chen * suppress warnings Signed-off-by: Ian Chen * update syntax Signed-off-by: Ian Chen * update syntax Signed-off-by: Ian Chen * Don't keep DEPTH_CLAMP enabled after it's used (#393) Probably a copy-paste bug, after enabling DEPTH_CLAMP we must disable once we're done; but we call glEnable again instead of disabling it. Signed-off-by: Matias N. Goldberg Co-authored-by: Michael Carroll Co-authored-by: Ian Chen Co-authored-by: Matias N. Goldberg --- .github/ci/packages.apt | 2 +- CMakeLists.txt | 2 +- include/ignition/rendering/Camera.hh | 4 + include/ignition/rendering/RenderEngine.hh | 9 + include/ignition/rendering/base/BaseCamera.hh | 10 + .../rendering/base/BaseRenderEngine.hh | 8 + .../ignition/rendering/ogre2/Ogre2Camera.hh | 14 +- .../rendering/ogre2/Ogre2Conversions.hh | 6 +- .../rendering/ogre2/Ogre2DepthCamera.hh | 28 +- .../ignition/rendering/ogre2/Ogre2Includes.hh | 59 +- .../ignition/rendering/ogre2/Ogre2Material.hh | 2 +- .../rendering/ogre2/Ogre2MaterialSwitcher.hh | 12 +- .../rendering/ogre2/Ogre2RenderEngine.hh | 10 + .../rendering/ogre2/Ogre2RenderTarget.hh | 53 +- .../ogre2/Ogre2RenderTargetMaterial.hh | 29 +- .../rendering/ogre2/Ogre2SelectionBuffer.hh | 10 +- .../ignition/rendering/ogre2/Ogre2Storage.hh | 1 + ogre2/src/CMakeLists.txt | 2 + ogre2/src/Ogre2Camera.cc | 14 +- ogre2/src/Ogre2Conversions.cc | 28 +- ogre2/src/Ogre2DepthCamera.cc | 352 ++++---- ogre2/src/Ogre2DynamicRenderable.cc | 1 + ogre2/src/Ogre2GaussianNoisePass.cc | 2 +- ogre2/src/Ogre2Geometry.cc | 1 - ogre2/src/Ogre2GpuRays.cc | 542 +++++++----- ogre2/src/Ogre2Material.cc | 215 +++-- ogre2/src/Ogre2MaterialSwitcher.cc | 8 +- ogre2/src/Ogre2ParticleNoiseListener.cc | 10 +- ogre2/src/Ogre2ParticleNoiseListener.hh | 27 +- ogre2/src/Ogre2RenderEngine.cc | 148 +++- ogre2/src/Ogre2RenderTarget.cc | 349 ++++---- ogre2/src/Ogre2RenderTargetMaterial.cc | 28 +- ogre2/src/Ogre2Scene.cc | 94 +- ogre2/src/Ogre2SelectionBuffer.cc | 213 +++-- ogre2/src/Ogre2ThermalCamera.cc | 215 ++--- 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 +- .../materials/programs/depth_camera_fs.glsl | 4 +- .../programs/gpu_rays_1st_pass_fs.glsl | 4 +- src/base/BaseRenderEngine.cc | 12 + test/integration/gpu_rays.cc | 28 +- test/integration/lidar_visual.cc | 36 +- 128 files changed, 8964 insertions(+), 4190 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/.github/ci/packages.apt b/.github/ci/packages.apt index b359c4a2c..dab47666b 100644 --- a/.github/ci/packages.apt +++ b/.github/ci/packages.apt @@ -6,7 +6,7 @@ libignition-common4-dev libignition-math6-dev libignition-plugin-dev libogre-1.9-dev -libogre-2.1-dev +libogre-2.2-dev libxi-dev libxmu-dev uuid-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b60a20b3..276a517f1 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/include/ignition/rendering/Camera.hh b/include/ignition/rendering/Camera.hh index 856e9b1a3..33b52efcc 100644 --- a/include/ignition/rendering/Camera.hh +++ b/include/ignition/rendering/Camera.hh @@ -333,6 +333,10 @@ namespace ignition /// \return Render pass at the specified index public: virtual RenderPassPtr RenderPassByIndex(unsigned int _index) const = 0; + + /// \internal + /// \brief Notify that shadows are dirty and need to be regenerated + public: virtual void SetShadowsDirty() = 0; }; } } diff --git a/include/ignition/rendering/RenderEngine.hh b/include/ignition/rendering/RenderEngine.hh index 4fc14ece4..65dc7a8a0 100644 --- a/include/ignition/rendering/RenderEngine.hh +++ b/include/ignition/rendering/RenderEngine.hh @@ -163,6 +163,15 @@ namespace ignition public: virtual ScenePtr CreateScene(unsigned int _id, const std::string &_name) = 0; + /// \brief Set headless mode + /// Only available in OGRE 2.2, which makes use of EGL + /// \param[in] _headless Set to true to enable headless mode. + public: virtual void SetHeadless(bool _headless) = 0; + + /// \brief Get headless mode + /// \return True if headless mode is enable, false otherwise. + public: virtual bool Headless() const = 0; + /// \brief Add path to media resource location /// \param[in] _paths Absolute path to resource location public: virtual void AddResourcePath(const std::string &_path) = 0; diff --git a/include/ignition/rendering/base/BaseCamera.hh b/include/ignition/rendering/base/BaseCamera.hh index 0024f4cb8..7278245d5 100644 --- a/include/ignition/rendering/base/BaseCamera.hh +++ b/include/ignition/rendering/base/BaseCamera.hh @@ -193,6 +193,9 @@ namespace ignition public: virtual RenderPassPtr RenderPassByIndex(unsigned int _index) const override; + // Documentation inherited. + public: virtual void SetShadowsDirty() override; + protected: virtual void *CreateImageBuffer() const; protected: virtual void Load() override; @@ -828,6 +831,13 @@ namespace ignition { return this->RenderTarget()->RenderPassByIndex(_index); } + + ////////////////////////////////////////////////// + template + void BaseCamera::SetShadowsDirty() + { + // no op + } } } } diff --git a/include/ignition/rendering/base/BaseRenderEngine.hh b/include/ignition/rendering/base/BaseRenderEngine.hh index c41fb03a5..36f0f9ef5 100644 --- a/include/ignition/rendering/base/BaseRenderEngine.hh +++ b/include/ignition/rendering/base/BaseRenderEngine.hh @@ -88,6 +88,12 @@ namespace ignition // Documentation Inherited public: virtual void AddResourcePath(const std::string &_path) override; + // Documentation Inherited + public: virtual void SetHeadless(bool _headless) override; + + // Documentation Inherited + public: virtual bool Headless() const override; + // Documentation Inherited public: virtual RenderPassSystemPtr RenderPassSystem() const override; @@ -111,6 +117,8 @@ namespace ignition protected: bool initialized = false; + protected: bool isHeadless = false; + protected: unsigned int nextSceneId; IGN_COMMON_WARN_IGNORE__DLL_INTERFACE_MISSING diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Camera.hh index a485ad4ed..dfb8805e1 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 @@ -114,11 +115,7 @@ namespace ignition public: virtual unsigned int RenderTextureGLId() const override; // Documentation inherited. - // TODO(anyone): this function should be virtual, declared in 'Camera' - // and 'BaseCamera'. We didn't do it to preserve ABI. - // Looks in commit history for '#SetShadowsNodeDefDirtyABI' to - // see changes made and revert - public: void SetShadowsNodeDefDirty(); + public: void SetShadowsDirty() override; // Documentation inherited. public: virtual void Destroy() override; @@ -144,6 +141,13 @@ namespace ignition /// \brief Create internal camera object private: void CreateCamera(); + /// \brief Notifies us that the shadow node definition is about to be + /// updated. This means our compositor workspace must be destroyed + /// because the shadow node definition it's using will become a + /// dangling pointer otherwise + /// \sa SetShadowsDirty + private: void SetShadowsNodeDefDirty(); + /// \brief Pointer to ogre camera object protected: Ogre::Camera *ogreCamera = nullptr; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh index 4db1120d9..b7731db0f 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Conversions.hh @@ -32,7 +32,7 @@ #include #include -#include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -107,10 +107,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/Ogre2DepthCamera.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2DepthCamera.hh index 593d775ab..8c97445fd 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2DepthCamera.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2DepthCamera.hh @@ -123,26 +123,7 @@ namespace ignition public: double FarClipPlane() const override; // Documentation inherited. - // TODO(anyone): this function should be virtual, declared in 'Camera' - // and 'BaseCamera'. We didn't do it to preserve ABI. - // Looks in commit history for '#SetShadowsNodeDefDirtyABI' to - // see changes made and revert - public: void SetShadowsNodeDefDirty(); - - // TODO(anyone): This fixes the pass quad material leaving dangling - // pointers when we remove the workspace, so we have to cleanup the - // material first. - // This bug was fixed in Ogre 2.2 thus the workaround should not be - // necessary there - // - // See https://github.com/ignitionrobotics/ign-rendering/ - // pull/303#pullrequestreview-635228897 - // Repro: - // 1.run the sensors_demo.sdf world: ign gazebo -v 4 -r sensors_demo.sdf - // 2.open Lights plugin, top right menu (3 dots) and select Lights - // 3.insert a spot light into the scene (needs to be spot light) - // 4.ign gazebo crashes - private: void RemoveWorkspaceCrashWorkaround(); + public: void SetShadowsDirty() override; // Documentation inherited. public: void AddRenderPass(const RenderPassPtr &_pass) override; @@ -160,6 +141,13 @@ namespace ignition /// \brief Create the camera. protected: void CreateCamera(); + /// \brief Notifies us that the shadow node definition is about to be + /// updated. This means our compositor workspace must be destroyed + /// because the shadow node definition it's using will become a + /// dangling pointer otherwise + /// \sa SetShadowsDirty + private: void SetShadowsNodeDefDirty(); + /// \brief Pointer to the ogre camera protected: Ogre::Camera *ogreCamera; diff --git a/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2Includes.hh index 1a0bc41fa..27d360bf7 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 @@ -84,7 +92,6 @@ #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 d5578bd1e..31c10b87d 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2Material.hh @@ -246,7 +246,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 a98c48e62..1bd050700 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2MaterialSwitcher.hh @@ -29,8 +29,8 @@ #ifdef _MSC_VER #pragma warning(push, 0) #endif +#include #include -#include #ifdef _MSC_VER #pragma warning(pop) #endif @@ -46,7 +46,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); @@ -65,14 +65,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..605c0be94 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh @@ -34,6 +34,7 @@ namespace Ogre { class LogManager; class Root; + class Window; namespace v1 { class OverlaySystem; @@ -94,6 +95,9 @@ namespace ignition /// \param[in] _uri Resource path in the form of an uri public: void AddResourcePath(const std::string &_uri) override; + /// \brief return the ogre window + public: Ogre::Window * OgreWindow() const; + /// \brief Get the ogre2 root object /// \return ogre2 root object public: virtual Ogre::Root *OgreRoot() const; @@ -138,6 +142,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 +199,9 @@ namespace ignition /// \brief Dummy window Id needed for linux platform private: uint64_t dummyWindowId = 0u; + /// \brief Ogre Window + private: Ogre::Window *window = nullptr; + /// \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 32672db24..439beafac 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh @@ -115,14 +115,19 @@ namespace ignition /// \see Camera::SetShadowsNodeDefDirty public: void SetShadowsNodeDefDirty(); + /// \brief Returns the FSAA to use based on supported specs by HW + /// and value specified in Ogre2RenderTarget::AntiAliasing + /// \return Value in range [1; 256). 1 means no antialiasing. + protected: uint8_t TargetFSAA() const; + /// \brief Get a pointer to the ogre render target containing /// the results of the render (implemented separately /// to avoid breaking ABI of the pure virtual function) - protected: Ogre::RenderTarget *RenderTargetImpl() const; + protected: Ogre::TextureGpu *RenderTargetImpl() const; /// \brief Get a pointer to the ogre render target containing /// the results of the render - public: virtual Ogre::RenderTarget *RenderTarget() const = 0; + public: virtual Ogre::TextureGpu *RenderTarget() const = 0; /// \brief Returns true if this is a render window /// TODO(anyone): this function should be virtual. @@ -150,14 +155,6 @@ namespace ignition /// \param[in] _mask Visibility mask public: virtual void SetVisibilityMask(uint32_t _mask); - /// \brief Deprecated. Use other overloads. - public: static IGN_DEPRECATED(5) void UpdateRenderPassChain( - Ogre::CompositorWorkspace *_workspace, - const std::string &_workspaceDefName, - const std::string &_baseNode, const std::string &_finalNode, - const std::vector &_renderPasses, - bool _recreateNodes); - /// \brief Update the render pass chain public: static void UpdateRenderPassChain( Ogre::CompositorWorkspace *_workspace, @@ -165,7 +162,7 @@ namespace ignition const std::string &_baseNode, const std::string &_finalNode, const std::vector &_renderPasses, bool _recreateNodes, - Ogre::Texture *(*_ogreTextures)[2], + Ogre::TextureGpu *(*_ogreTextures)[2], bool _isRenderWindow); /// \brief Update the background color @@ -177,9 +174,6 @@ namespace ignition /// \brief Update the render pass chain protected: virtual void UpdateRenderPassChain(); - /// \brief Deprecated. Use Ogre2Scene:UpdateShadowNode instead - protected: void IGN_DEPRECATED(5) UpdateShadowNode(); - /// \brief Implementation of the Rebuild function protected: virtual void RebuildImpl() override; @@ -201,10 +195,6 @@ namespace ignition /// \sa BaseRenderTarget::Rebuild() protected: void RebuildMaterial(); - /// Calls Ogre2RenderTexture::SetOgreTexture if appropiate to ensure - /// Ogre2RenderTexture::ogreTexture always has our outputs - protected: void SyncOgreTextureVars(); - /// \brief Pointer to the internal ogre camera protected: Ogre::Camera *ogreCamera = nullptr; @@ -224,11 +214,7 @@ namespace ignition /// \brief a material used by for the render target protected: MaterialPtr material; - /// \brief Unused. Kept for ABI reasons. - /// - /// Just in case we set this value to - /// Ogre2RenderTargetPrivate::materialApplicator[0] which is what - /// most client applications may want. + /// \brief Helper class that applies the material to the render target protected: Ogre2RenderTargetMaterialPtr materialApplicator; /// \brief Flag to indicate if the render target color has changed @@ -273,7 +259,7 @@ namespace ignition // Documentation inherited // TODO(anyone): this function should be removed. // We didn't do it to preserve ABI. - public: virtual Ogre::RenderTarget *RenderTarget() const override; + public: virtual Ogre::TextureGpu *RenderTarget() const override; // Documentation inherited. protected: virtual void RebuildTarget() override; @@ -284,21 +270,6 @@ namespace ignition /// \brief Build the render texture protected: virtual void BuildTarget(); - /// \brief Do not call this function directly. - /// - /// It's used to keep ABI compatibility to sync ogreTexture - /// with the internal pointer from our base class. - /// \param[in] _ogreTexture texture from - /// Ogre2RenderTargetPrivate::ogreTexture[1] - public: void SetOgreTexture(Ogre::Texture *_ogreTexture); - - /// \brief Unused. Kept for ABI reasons. - /// - /// Just in case we set this value to - /// Ogre2RenderTargetPrivate::ogreTexture[1] which is what most client - /// applications may want. - protected: IGN_DEPRECATED(5) Ogre::Texture * ogreTexture = nullptr; - /// \brief Make scene our friend so it can create a ogre2 render texture private: friend class Ogre2Scene; }; @@ -323,7 +294,7 @@ namespace ignition public: bool IsRenderWindow() const; // Documentation inherited. - public: virtual Ogre::RenderTarget *RenderTarget() const override; + public: virtual Ogre::TextureGpu *RenderTarget() const override; // Documentation inherited. protected: virtual void RebuildTarget() override; @@ -332,7 +303,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 57bfaae61..5f586e0d7 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2RenderTargetMaterial.hh @@ -25,7 +25,7 @@ #ifdef _MSC_VER #pragma warning(push, 0) #endif -#include +#include #include #ifdef _MSC_VER #pragma warning(pop) @@ -56,7 +56,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 @@ -64,22 +64,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 @@ -96,14 +94,11 @@ namespace ignition Ogre::Material *_originalMaterial, uint16_t _lodIndex, const Ogre::Renderable *_rend) override; - /// \brief Returns this->renderTarget == _renderTarget - public: bool IsSameRenderTarget(Ogre::RenderTarget *_renderTarget); - /// \brief scene manager responsible for rendering 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/Ogre2SelectionBuffer.hh b/ogre2/include/ignition/rendering/ogre2/Ogre2SelectionBuffer.hh index 35fd51332..34d411fc6 100644 --- a/ogre2/include/ignition/rendering/ogre2/Ogre2SelectionBuffer.hh +++ b/ogre2/include/ignition/rendering/ogre2/Ogre2SelectionBuffer.hh @@ -50,8 +50,11 @@ namespace ignition /// \param[in] _camera Name of the camera to generate a selection /// buffer for. /// \param[in] _scene Pointer to the scene + /// \param[in] _width width of the camera + /// \param[in] _height height of the camera public: Ogre2SelectionBuffer(const std::string &_cameraName, - Ogre2ScenePtr _scene); + Ogre2ScenePtr _scene, unsigned int _width, + unsigned int _height); /// \brief Destructor public: ~Ogre2SelectionBuffer(); @@ -62,6 +65,11 @@ namespace ignition /// \return Returns the Ogre item at the coordinate. public: Ogre::Item *OnSelectionClick(const int _x, const int _y); + /// \brief Set dimension of the selection buffer + /// \param[in] _x X coordinate in pixels. + /// \param[in] _y Y coordinate in pixels. + public: void SetDimensions(unsigned int _width, unsigned int _height); + /// \brief Debug show overlay /// \param[in] _show True to show the selection buffer in an overlay. // public: void ShowOverlay(const bool _show); 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/CMakeLists.txt b/ogre2/src/CMakeLists.txt index 44b8b5a52..9685ecc7d 100644 --- a/ogre2/src/CMakeLists.txt +++ b/ogre2/src/CMakeLists.txt @@ -17,6 +17,8 @@ ign_add_component(${engine_name} SOURCES ${sources} GET_TARGET_NAME ogre2_target find_package(OpenGL) +add_definitions(-DOGRE_IGNORE_UNKNOWN_DEBUG) + set_property( SOURCE Ogre2RenderEngine.cc PROPERTY COMPILE_DEFINITIONS diff --git a/ogre2/src/Ogre2Camera.cc b/ogre2/src/Ogre2Camera.cc index f1eb83e6a..01dd48754 100644 --- a/ogre2/src/Ogre2Camera.cc +++ b/ogre2/src/Ogre2Camera.cc @@ -207,6 +207,12 @@ unsigned int Ogre2Camera::RenderTextureGLId() const return rt->GLId(); } +////////////////////////////////////////////////// +void Ogre2Camera::SetShadowsDirty() +{ + this->SetShadowsNodeDefDirty(); +} + ////////////////////////////////////////////////// void Ogre2Camera::SetShadowsNodeDefDirty() { @@ -223,7 +229,8 @@ void Ogre2Camera::SetShadowsNodeDefDirty() ////////////////////////////////////////////////// void Ogre2Camera::SetSelectionBuffer() { - this->selectionBuffer = new Ogre2SelectionBuffer(this->name, this->scene); + this->selectionBuffer = new Ogre2SelectionBuffer(this->name, this->scene, + this->ImageWidth(), this->ImageHeight()); } ////////////////////////////////////////////////// @@ -240,6 +247,11 @@ VisualPtr Ogre2Camera::VisualAt(const ignition::math::Vector2i &_mousePos) return result; } } + else + { + this->selectionBuffer->SetDimensions( + this->ImageWidth(), this->ImageHeight()); + } float ratio = screenScalingFactor(); ignition::math::Vector2i mousePos( diff --git a/ogre2/src/Ogre2Conversions.cc b/ogre2/src/Ogre2Conversions.cc index de6600c2d..c4d0ec7e1 100644 --- a/ogre2/src/Ogre2Conversions.cc +++ b/ogre2/src/Ogre2Conversions.cc @@ -28,32 +28,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 }; ////////////////////////////////////////////////// @@ -105,7 +105,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]; } diff --git a/ogre2/src/Ogre2DepthCamera.cc b/ogre2/src/Ogre2DepthCamera.cc index 09e17b275..319650a5c 100644 --- a/ogre2/src/Ogre2DepthCamera.cc +++ b/ogre2/src/Ogre2DepthCamera.cc @@ -23,6 +23,14 @@ #include #endif +#ifdef __APPLE__ + #include +#else +#ifndef _WIN32 + #include +#endif +#endif + #include #include @@ -104,7 +112,7 @@ class ignition::rendering::Ogre2DepthCameraPrivate public: Ogre::CompositorWorkspace *ogreCompositorWorkspace = nullptr; /// \brief Output texture with depth and color data - public: Ogre::TexturePtr ogreDepthTexture[2]; + public: Ogre::TextureGpu *ogreDepthTexture[2]; /// \brief Dummy render texture for the depth data public: RenderTexturePtr depthTexture; @@ -225,17 +233,16 @@ void Ogre2DepthGaussianNoisePass::CreateRenderPass() nodeDef->setNumTargetPass(1); Ogre::CompositorTargetDef *inputTargetDef = nodeDef->addTargetPass("rt_output"); - inputTargetDef->setNumPasses(2); + inputTargetDef->setNumPasses(1); { - // clear pass - inputTargetDef->addPass(Ogre::PASS_CLEAR); - // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->mMaterialName = materialName; - passQuad->addQuadTextureSource(0, "rt_input", 0); + passQuad->addQuadTextureSource(0, "rt_input"); } nodeDef->mapOutputChannel(0, "rt_output"); nodeDef->mapOutputChannel(1, "rt_input"); @@ -297,17 +304,17 @@ void Ogre2DepthCamera::Destroy() Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); // remove depth texture, material, compositor - for( size_t i = 0u; i < 2u; ++i ) + for (size_t i = 0u; i < 2u; ++i) { if (this->dataPtr->ogreDepthTexture[i]) { - Ogre::TextureManager::getSingleton().remove( - this->dataPtr->ogreDepthTexture[i]->getName()); + ogreRoot->getRenderSystem()->getTextureGpuManager()->destroyTexture( + this->dataPtr->ogreDepthTexture[i]); + this->dataPtr->ogreDepthTexture[i] = nullptr; } } if (this->dataPtr->ogreCompositorWorkspace) { - this->RemoveWorkspaceCrashWorkaround(); ogreCompMgr->removeWorkspace( this->dataPtr->ogreCompositorWorkspace); } @@ -422,10 +429,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)); @@ -487,7 +493,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 @@ -599,98 +605,95 @@ void Ogre2DepthCamera::CreateDepthTexture() 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; - // Enable gamma write to avoid discretization in the color values + colorTexDef->format = Ogre::PFG_RGBA8_UNORM_SRGB; // 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"); if (validBackground) - colorTargetDef->setNumPasses(3); - else colorTargetDef->setNumPasses(2); + else + colorTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue( - Ogre2Conversions::Convert(this->Scene()->BackgroundColor())); - if (validBackground) { // quad pass @@ -701,6 +704,10 @@ void Ogre2DepthCamera::CreateDepthTexture() + this->Name(); passQuad->mFrustumCorners = Ogre::CompositorPassQuadDef::CAMERA_DIRECTION; + + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue( + Ogre2Conversions::Convert(this->Scene()->BackgroundColor()))); } // scene pass @@ -712,23 +719,28 @@ void Ogre2DepthCamera::CreateDepthTexture() // todo(anyone) PbsMaterialsShadowNode is hardcoded. // Although this may be just fine passScene->mShadowNode = "PbsMaterialsShadowNode"; + + if (!validBackground) + { + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue( + Ogre2Conversions::Convert(this->Scene()->BackgroundColor()))); + } } Ogre::CompositorTargetDef *depthTargetDef = baseNodeDef->addTargetPass("depthTexture"); - depthTargetDef->setNumPasses(2); + depthTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - depthTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); - // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( depthTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); // depth texute does not contain particles passScene->mVisibilityMask = IGN_VISIBILITY_ALL & ~Ogre2ParticleEmitter::kParticleVisibilityFlags; @@ -736,37 +748,31 @@ void Ogre2DepthCamera::CreateDepthTexture() Ogre::CompositorTargetDef *particleTargetDef = baseNodeDef->addTargetPass("particleTexture"); - particleTargetDef->setNumPasses(2); + particleTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - particleTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue::Black; - // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( particleTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue::Black); passScene->mVisibilityMask = Ogre2ParticleEmitter::kParticleVisibilityFlags; } Ogre::CompositorTargetDef *particleDepthTargetDef = baseNodeDef->addTargetPass("particleDepthTexture"); - particleDepthTargetDef->setNumPasses(2); + particleDepthTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - particleDepthTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); - // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( particleDepthTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); passScene->mVisibilityMask = Ogre2ParticleEmitter::kParticleVisibilityFlags; } @@ -774,24 +780,23 @@ void Ogre2DepthCamera::CreateDepthTexture() // rt0 target - converts depth to xyz Ogre::CompositorTargetDef *inTargetDef = baseNodeDef->addTargetPass("rt0"); - inTargetDef->setNumPasses(2); + inTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - inTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); - // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); + 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; } @@ -836,21 +841,20 @@ void Ogre2DepthCamera::CreateDepthTexture() // rt_output target - converts depth to xyz Ogre::CompositorTargetDef *outputTargetDef = finalNodeDef->addTargetPass("rt_output"); - outputTargetDef->setNumPasses(2); + outputTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - outputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->FarClipPlane(), - this->FarClipPlane(), this->FarClipPlane()); - // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( outputTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); + passQuad->mMaterialName = this->dataPtr->depthFinalMaterial->getName(); - passQuad->addQuadTextureSource(0, "rt_input", 0); + passQuad->addQuadTextureSource(0, "rt_input"); } finalNodeDef->mapOutputChannel(0, "rt_output"); @@ -878,19 +882,26 @@ void Ogre2DepthCamera::CreateDepthTexture() << " for " << this->Name(); } + Ogre::TextureGpuManager *textureMgr = + ogreRoot->getRenderSystem()->getTextureGpuManager(); // create render texture - these textures pack the range data - for( size_t i = 0u; i < 2u; ++i ) + for (size_t i = 0u; i < 2u; ++i) { this->dataPtr->ogreDepthTexture[i] = - Ogre::TextureManager::getSingleton().createManual( - this->Name() + "_depth" + std::to_string(i), "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); - - Ogre::RenderTarget *rt = - this->dataPtr->ogreDepthTexture[i]->getBuffer()->getRenderTarget(); - rt->setDepthBufferPool(Ogre::DepthBuffer::POOL_INVALID); + textureMgr->createTexture( + this->Name() + "_depth" + std::to_string(i), + Ogre::GpuPageOutStrategy::SaveToSystemRam, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->dataPtr->ogreDepthTexture[i]->setResolution( + this->ImageWidth(), this->ImageHeight()); + this->dataPtr->ogreDepthTexture[i]->setNumMipmaps(1u); + this->dataPtr->ogreDepthTexture[i]->setPixelFormat( + Ogre::PFG_RGBA32_FLOAT); + + this->dataPtr->ogreDepthTexture[i]->scheduleTransitionTo( + Ogre::GpuResidency::Resident); } CreateWorkspaceInstance(); @@ -904,18 +915,18 @@ void Ogre2DepthCamera::CreateWorkspaceInstance() Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); Ogre::CompositorChannelVec externalTargets(2u); - for( size_t i = 0u; i < 2u; ++i ) - { - externalTargets[i].target = - this->dataPtr->ogreDepthTexture[i]->getBuffer()->getRenderTarget(); - externalTargets[i].textures.push_back(this->dataPtr->ogreDepthTexture[i]); - } + + externalTargets[0] = this->dataPtr->ogreDepthTexture[0]; + externalTargets[1] = this->dataPtr->ogreDepthTexture[1]; // create compositor worksspace this->dataPtr->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - externalTargets, this->ogreCamera, - this->dataPtr->ogreCompositorWorkspaceDef, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + externalTargets, + this->ogreCamera, + this->dataPtr->ogreCompositorWorkspaceDef, + false); // add the listener Ogre::CompositorNode *node = @@ -924,14 +935,15 @@ void Ogre2DepthCamera::CreateWorkspaceInstance() for (auto c : channelsTex) { - if (c.textures[0]->getSrcFormat() == Ogre::PF_L8) + if (c->getPixelFormat() == Ogre::PFG_R8_UNORM) { // add particle noise / scatter effects listener so we can set the // amount of noise based on size of emitter this->dataPtr->particleNoiseListener.reset( new Ogre2ParticleNoiseListener(this->scene, - this->ogreCamera, this->dataPtr->depthMaterial)); - c.target->addListener(this->dataPtr->particleNoiseListener.get()); + this->dataPtr->depthMaterial)); + this->ogreCamera->addListener( + this->dataPtr->particleNoiseListener.get()); break; } } @@ -940,6 +952,12 @@ void Ogre2DepthCamera::CreateWorkspaceInstance() ////////////////////////////////////////////////// void Ogre2DepthCamera::Render() { + // GL_DEPTH_CLAMP was disabled in later version of ogre2.2 + // however our shaders rely on clamped values so enable it for this sensor +#ifndef _WIN32 + glEnable(GL_DEPTH_CLAMP); +#endif + this->scene->StartRendering(); // update the compositors @@ -948,11 +966,15 @@ void Ogre2DepthCamera::Render() this->dataPtr->ogreCompositorWorkspace->_update(); this->dataPtr->ogreCompositorWorkspace->_endUpdate(false); - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); this->dataPtr->ogreCompositorWorkspace->_swapFinalTarget(swappedTargets); this->scene->FlushGpuCommandsAndStartNewFrame(1u, false); + +#ifndef _WIN32 + glDisable(GL_DEPTH_CLAMP); +#endif } ////////////////////////////////////////////////// @@ -964,12 +986,6 @@ void Ogre2DepthCamera::PreRender() if (!this->dataPtr->ogreCompositorWorkspace) this->CreateWorkspaceInstance(); - Ogre::Texture *rawDepthTextures[2] = - { - this->dataPtr->ogreDepthTexture[0].get(), - this->dataPtr->ogreDepthTexture[1].get() - }; - // update depth camera render passes Ogre2RenderTarget::UpdateRenderPassChain( this->dataPtr->ogreCompositorWorkspace, @@ -978,15 +994,9 @@ void Ogre2DepthCamera::PreRender() this->dataPtr->ogreCompositorFinalNodeDef, this->dataPtr->renderPasses, this->dataPtr->renderPassDirty, - &rawDepthTextures, + &this->dataPtr->ogreDepthTexture, false); - if (rawDepthTextures[0] != this->dataPtr->ogreDepthTexture[0].get()) - { - std::swap( this->dataPtr->ogreDepthTexture[0], - this->dataPtr->ogreDepthTexture[1] ); - } - for (auto &pass : this->dataPtr->renderPasses) pass->PreRender(); @@ -1001,14 +1011,15 @@ void Ogre2DepthCamera::PreRender() for (auto c : channelsTex) { - if (c.textures[0]->getSrcFormat() == Ogre::PF_L8) + if (c->getPixelFormat() == Ogre::PFG_RGB8_UNORM) { // add particle noise / scatter effects listener so we can set the // amount of noise based on size of emitter this->dataPtr->particleNoiseListener.reset( new Ogre2ParticleNoiseListener(this->scene, - this->ogreCamera, this->dataPtr->depthMaterial)); - c.target->addListener(this->dataPtr->particleNoiseListener.get()); + this->dataPtr->depthMaterial)); + this->ogreCamera->addListener( + this->dataPtr->particleNoiseListener.get()); break; } } @@ -1024,22 +1035,29 @@ void Ogre2DepthCamera::PostRender() unsigned int height = this->ImageHeight(); PixelFormat format = PF_FLOAT32_RGBA; - Ogre::PixelFormat imageFormat = Ogre2Conversions::Convert(format); - size_t size = Ogre::PixelUtil::getMemorySize(width, height, 1, imageFormat); int len = width * height; unsigned int channelCount = PixelUtil::ChannelCount(format); + unsigned int bytesPerChannel = PixelUtil::BytesPerChannel(format); + Ogre::Image2 image; + image.convertFromTexture(this->dataPtr->ogreDepthTexture[1], 0u, 0u); + Ogre::TextureBox box = image.getData(0); + float *depthBufferTmp = static_cast(box.data); 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[1]->getBuffer()->getRenderTarget(); - rt->copyContentsToMemory(dstBox, Ogre::RenderTarget::FB_AUTO); + // copy data row by row. The texture box may not be a contiguous region of + // a texture + for (unsigned int i = 0; i < height; ++i) + { + unsigned int rawDataRowIdx = i * box.bytesPerRow / bytesPerChannel; + unsigned int rowIdx = i * width * channelCount; + memcpy(&this->dataPtr->depthBuffer[rowIdx], &depthBufferTmp[rawDataRowIdx], + width * channelCount * bytesPerChannel); + } if (!this->dataPtr->depthImage) { @@ -1066,7 +1084,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"); @@ -1175,6 +1194,12 @@ double Ogre2DepthCamera::FarClipPlane() const return BaseDepthCamera::FarClipPlane(); } +////////////////////////////////////////////////// +void Ogre2DepthCamera::SetShadowsDirty() +{ + this->SetShadowsNodeDefDirty(); +} + ////////////////////////////////////////////////// void Ogre2DepthCamera::SetShadowsNodeDefDirty() { @@ -1185,25 +1210,12 @@ void Ogre2DepthCamera::SetShadowsNodeDefDirty() auto ogreRoot = engine->OgreRoot(); Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2(); - this->RemoveWorkspaceCrashWorkaround(); - ogreCompMgr->removeWorkspace( this->dataPtr->ogreCompositorWorkspace ); + ogreCompMgr->removeWorkspace(this->dataPtr->ogreCompositorWorkspace); this->dataPtr->ogreCompositorWorkspace = nullptr; -} - -////////////////////////////////////////////////// -void Ogre2DepthCamera::RemoveWorkspaceCrashWorkaround() -{ - Ogre::MaterialPtr material = - Ogre::MaterialManager::getSingleton(). - getByName (this->dataPtr->depthMaterial->getName()); - - if (!material.isNull()) + if (this->dataPtr->particleNoiseListener) { - for (size_t i = 0; i < 4; ++i) - { - material->getBestTechnique()->getPass(0)-> - getTextureUnitState(i)->setBlank(); - } + this->ogreCamera->removeListener( + this->dataPtr->particleNoiseListener.get()); } } diff --git a/ogre2/src/Ogre2DynamicRenderable.cc b/ogre2/src/Ogre2DynamicRenderable.cc index 90ffbedd6..52be0b32f 100644 --- a/ogre2/src/Ogre2DynamicRenderable.cc +++ b/ogre2/src/Ogre2DynamicRenderable.cc @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/ogre2/src/Ogre2GaussianNoisePass.cc b/ogre2/src/Ogre2GaussianNoisePass.cc index 530d26597..905ae42c1 100644 --- a/ogre2/src/Ogre2GaussianNoisePass.cc +++ b/ogre2/src/Ogre2GaussianNoisePass.cc @@ -177,7 +177,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 3cdfae962..f5d3219cf 100644 --- a/ogre2/src/Ogre2GpuRays.cc +++ b/ogre2/src/Ogre2GpuRays.cc @@ -40,17 +40,13 @@ #endif #include #include -#include #include #include #include -#include #include -#include #include #include #include -#include #ifdef _MSC_VER #pragma warning(pop) #endif @@ -63,7 +59,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 @@ -72,17 +68,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; @@ -133,7 +127,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 @@ -158,10 +152,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; @@ -212,8 +206,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 @@ -246,64 +240,65 @@ void Ogre2LaserRetroMaterialSwitcher::preRenderTargetUpdate( // get laser_retro Variant tempLaserRetro = ogreVisual->UserData(laserRetroKey); - float retroValue = -1.0; + float retroValue = -1.0; + try + { + retroValue = std::get(tempLaserRetro); + } + catch(...) + { try { - retroValue = std::get(tempLaserRetro); + retroValue = std::get(tempLaserRetro); } catch(...) { try { - retroValue = std::get(tempLaserRetro); + retroValue = std::get(tempLaserRetro); } - catch(...) + catch(std::bad_variant_access &e) { - try - { - retroValue = std::get(tempLaserRetro); - } - catch(std::bad_variant_access &e) - { - ignerr << "Error casting user data: " << e.what() << "\n"; - retroValue = -1.0; - } + ignerr << "Error casting user data: " << e.what() << "\n"; + retroValue = -1.0; } } + } - // only accept positive laser retro value - if (retroValue >= 0) + // only accept positive laser retro value + if (retroValue >= 0) + { + // set visibility flag so the camera can see it + item->addVisibilityFlags(0x01000000); + for (unsigned int i = 0; i < item->getNumSubItems(); ++i) { - // set visibility flag so the camera can see it - item->addVisibilityFlags(0x01000000); - for (unsigned int i = 0; i < item->getNumSubItems(); ++i) + Ogre::SubItem *subItem = item->getSubItem(i); + if (!subItem->hasCustomParameter(this->customParamIdx)) { - Ogre::SubItem *subItem = item->getSubItem(i); - if (!subItem->hasCustomParameter(this->customParamIdx)) + // limit laser retro value to 2000 (as in gazebo) + if (retroValue > 2000.0) { - // limit laser retro value to 2000 (as in gazebo) - if (retroValue > 2000.0) - { - retroValue = 2000.0; - } - float color = retroValue / 2000.0; - subItem->setCustomParameter(this->customParamIdx, - Ogre::Vector4(color, color, color, 1.0)); + retroValue = 2000.0; } - Ogre::HlmsDatablock *datablock = subItem->getDatablock(); - this->datablockMap[subItem] = datablock; + float color = retroValue / 2000.0; - subItem->setMaterial(this->laserRetroSourceMaterial); + subItem->setCustomParameter(this->customParamIdx, + Ogre::Vector4(color, color, color, 1.0)); } + Ogre::HlmsDatablock *datablock = subItem->getDatablock(); + this->datablockMap[subItem] = datablock; + + subItem->setMaterial(this->laserRetroSourceMaterial); } } - itor.moveNext(); } + itor.moveNext(); } +} ////////////////////////////////////////////////// -void Ogre2LaserRetroMaterialSwitcher::postRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2LaserRetroMaterialSwitcher::cameraPostRenderScene( + Ogre::Camera * /*_cam*/) { // restore item to use hlms material for (auto it : this->datablockMap) @@ -362,15 +357,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 @@ -378,9 +373,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]) { @@ -408,9 +403,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) @@ -445,7 +440,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; @@ -579,24 +574,42 @@ 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; @@ -614,18 +627,53 @@ 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(); } ///////////////////////////////////////////////////////// @@ -646,10 +694,10 @@ 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)); @@ -676,7 +724,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 @@ -731,110 +779,146 @@ 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_R8_UNORM; + colorTexDef->fsaa = "0"; + 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::TextureDefinitionBase::TextureDefinition *particleDepthTexDef = - nodeDef->addTextureDefinition("particleDepthTexture"); - particleDepthTexDef->textureType = Ogre::TEX_TYPE_2D; - particleDepthTexDef->width = 0; - particleDepthTexDef->height = 0; - particleDepthTexDef->depth = 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->depthBufferId = Ogre::DepthBuffer::POOL_DEFAULT; + Ogre::RenderTargetViewDef *rtv2 = + nodeDef->addRenderTextureView("colorTexture"); + rtv2->setForTextureDefinition("colorTexture", colorTexDef); 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_RGBA8_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); + + Ogre::TextureDefinitionBase::TextureDefinition *particleDepthTexDef = + nodeDef->addTextureDefinition("particleDepthTexture"); + particleDepthTexDef->textureType = Ogre::TextureTypes::Type2D; + particleDepthTexDef->width = 0; + particleDepthTexDef->height = 0; + particleDepthTexDef->depthOrSlices = 1; + particleDepthTexDef->numMipmaps = 0; + particleDepthTexDef->widthFactor = 0.5; + particleDepthTexDef->heightFactor = 0.5; + particleDepthTexDef->format = Ogre::PFG_D32_FLOAT; + particleDepthTexDef->fsaa = "0"; + particleDepthTexDef->depthBufferId = Ogre::DepthBuffer::POOL_NON_SHAREABLE; + particleDepthTexDef->textureFlags &= ~Ogre::TextureFlags::Uav; + particleDepthTexDef->depthBufferFormat = Ogre::PFG_UNKNOWN; + + Ogre::RenderTargetViewDef *rtvparticleDepthTex = + nodeDef->addRenderTextureView("particleDepthTexture"); + rtvparticleDepthTex->setForTextureDefinition( + "particleDepthTexture", particleDepthTexDef); + + nodeDef->setNumTargetPass(5); Ogre::CompositorTargetDef *colorTargetDef = nodeDef->addTargetPass("colorTexture"); - colorTargetDef->setNumPasses(2); + colorTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(0, 0, 0); // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( colorTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue(0, 0, 0)); // set camera custom visibility mask when rendering laser retro passScene->mVisibilityMask = 0x01000000 & ~Ogre2ParticleEmitter::kParticleVisibilityFlags; } + Ogre::CompositorTargetDef *depthTargetDef = + nodeDef->addTargetPass("depthTexture"); + depthTargetDef->setNumPasses(1); + { + // scene pass + Ogre::CompositorPassSceneDef *passScene = + static_cast( + depthTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); + // depth texture does not contain particles + passScene->mVisibilityMask = 0x01000000 & + ~Ogre2ParticleEmitter::kParticleVisibilityFlags; + } + + Ogre::CompositorTargetDef *particleDepthTargetDef = + nodeDef->addTargetPass("particleDepthTexture"); + particleDepthTargetDef->setNumPasses(1); + { + // scene pass + Ogre::CompositorPassSceneDef *passScene = + static_cast( + particleDepthTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue( + this->FarClipPlane(), + this->FarClipPlane(), + this->FarClipPlane())); + // set camera custom visibility mask when rendering laser retro + passScene->mVisibilityMask = + Ogre2ParticleEmitter::kParticleVisibilityFlags; + } + Ogre::CompositorTargetDef *particleTargetDef = nodeDef->addTargetPass("particleTexture"); - particleTargetDef->setNumPasses(2); + particleTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - particleTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue::Black; // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( particleTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue::Black); // set camera custom visibility mask when rendering laser retro passScene->mVisibilityMask = Ogre2ParticleEmitter::kParticleVisibilityFlags; @@ -843,22 +927,21 @@ void Ogre2GpuRays::Setup1stPass() // rt_input target - converts depth to range Ogre::CompositorTargetDef *inputTargetDef = nodeDef->addTargetPass("rt_input"); - inputTargetDef->setNumPasses(2); + inputTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->dataMaxVal, 0, 1.0); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue( + this->dataMaxVal, 0, 1.0)); + 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; } @@ -906,21 +989,34 @@ 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(); - // create compositor worksspace + 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 workspace 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); Ogre::CompositorNode *node = this->dataPtr->ogreCompositorWorkspace1st[i]->getNodeSequence()[0]; @@ -928,22 +1024,23 @@ void Ogre2GpuRays::Setup1stPass() for (auto c : channelsTex) { - if (c.textures[0]->getSrcFormat() == Ogre::PF_R8G8B8) + if (c->getPixelFormat() == Ogre::PFG_R8_UNORM) { // add laser retro material switcher to render target listener // so we can switch to use laser retro material when the camera is being // updated this->dataPtr->laserRetroMaterialSwitcher[i].reset( new Ogre2LaserRetroMaterialSwitcher(this->scene)); - c.target->addListener( + this->dataPtr->cubeCam[i]->addListener( this->dataPtr->laserRetroMaterialSwitcher[i].get()); // add particle noise / scatter effects listener so we can set the // amount of noise based on size of emitter this->dataPtr->particleNoiseListener[i].reset( new Ogre2ParticleNoiseListener(this->scene, - this->dataPtr->cubeCam[i], this->dataPtr->matFirstPass)); - c.target->addListener(this->dataPtr->particleNoiseListener[i].get()); + this->dataPtr->matFirstPass)); + this->dataPtr->cubeCam[i]->addListener( + this->dataPtr->particleNoiseListener[i].get()); break; } } @@ -955,14 +1052,26 @@ 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). @@ -993,8 +1102,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 @@ -1033,16 +1140,15 @@ void Ogre2GpuRays::Setup2ndPass() { Ogre::CompositorTargetDef *inputTargetDef = nodeDef->addTargetPass("rt_input"); - inputTargetDef->setNumPasses(2); - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->dataMaxVal, 0, 1.0); + inputTargetDef->setNumPasses(1); + // quad pass - sample from cubemap textures Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue( + this->dataMaxVal, 0, 1.0)); passQuad->mMaterialName = this->dataPtr->matSecondPass->getName(); } nodeDef->mapOutputChannel(0, "rt_input"); @@ -1060,11 +1166,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); } ///////////////////////////////////////////////////////// @@ -1079,7 +1187,7 @@ void Ogre2GpuRays::CreateGpuRaysTextures() ///////////////////////////////////////////////// void Ogre2GpuRays::UpdateRenderTarget1stPass() { - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); // update the compositors @@ -1108,7 +1216,7 @@ void Ogre2GpuRays::UpdateRenderTarget2ndPass() this->dataPtr->ogreCompositorWorkspace2nd->_update(); this->dataPtr->ogreCompositorWorkspace2nd->_endUpdate(false); - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); this->dataPtr->ogreCompositorWorkspace2nd->_swapFinalTarget(swappedTargets); } @@ -1137,42 +1245,62 @@ 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(); + PixelFormat format = PF_FLOAT32_RGB; + unsigned int channelCount = PixelUtil::ChannelCount(format); + unsigned int bytesPerChannel = PixelUtil::BytesPerChannel(format); + 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); + Ogre::TextureBox box = image.getData(0u); + float *bufferTmp = static_cast(box.data); + + // copy data row by row. The texture box may not be a contiguous region of + // a texture + for (unsigned int i = 0; i < height; ++i) + { + unsigned int rawDataRowIdx = i * box.bytesPerRow / bytesPerChannel; + unsigned int rowIdx = i * width * channelCount; + memcpy(&this->dataPtr->gpuRaysBuffer[rowIdx], &bufferTmp[rawDataRowIdx], + width * channelCount * bytesPerChannel); + } 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"); // Uncomment to debug output - // igndbg << "wxh: " << width << " x " << height << std::endl; + // std::cerr << "wxh: " << width << " x " << height << std::endl; // for (unsigned int i = 0; i < height; ++i) // { // for (unsigned int j = 0; j < width; ++j) // { - // igndbg << "[" << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3] << " "; - // igndbg << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3 + 1] << " "; - // igndbg << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3 + 2] << "] "; + // if (this->dataPtr->gpuRaysBuffer[i*width*3 + j*3] < 20) { + // std::cerr + // << "[" + // << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3] + // << " " + // << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3 + 1] + // << " " + // << this->dataPtr->gpuRaysBuffer[i*width*3 + j*3 + 2] + // << "]\n"; + // } // } - // igndbg << std::endl; + // // igndbg << std::endl; // } } @@ -1188,10 +1316,8 @@ 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 024ac33ef..f3151f332 100644 --- a/ogre2/src/Ogre2Material.cc +++ b/ogre2/src/Ogre2Material.cc @@ -26,7 +26,9 @@ #include #include #include -#include +#include +#include +#include #ifdef _MSC_VER #pragma warning(pop) #endif @@ -92,38 +94,88 @@ void Ogre2Material::Destroy() this->ogreMaterial.reset(); } - auto &textureManager = Ogre::TextureManager::getSingleton(); - auto iend = textureManager.getResourceIterator().end(); - for (auto i = textureManager.getResourceIterator().begin(); i != iend;) + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); + Ogre::TextureGpuManager *textureManager = + root->getRenderSystem()->getTextureGpuManager(); + + textureManager->setStagingTextureMaxBudgetBytes( + 8u * 1024u * 1024u); + textureManager->setWorkerThreadMaxPreloadBytes( + 8u * 1024u * 1024u); + textureManager->setWorkerThreadMaxPerStagingTextureRequestBytes( + 4u * 1024u * 1024u); + + Ogre::TextureGpuManager::BudgetEntryVec budget; + textureManager->setWorkerThreadMinimumBudget( budget ); + Ogre::HlmsManager *hlmsManager = root->getHlmsManager(); + + Ogre::TextureGpu* textureToRemove = nullptr; + bool textureIsUse = false; + // Check each material from each Hlms (except low level) to see if their + // material is currently in use. If it's not, then its textures may be + // not either + for (size_t i = Ogre::HLMS_PBS; i < Ogre::HLMS_MAX; ++i) { - // A use count of 4 means that only RGM, RM and MeshManager have references - // RGM has one (this one) and RM has 2 (by name and by handle) - // and MeshManager keep another one int the template - Ogre::Resource* res = i->second.get(); - if (i->second.useCount() == 5) + Ogre::Hlms *hlms = hlmsManager->getHlms(static_cast(i)); + + if(hlms) { - if (this->dataPtr->hashName == res->getName() && - res->getName().find( - scene->Name() + "::RenderTexture") == std::string::npos) + const Ogre::Hlms::HlmsDatablockMap &datablocks = hlms->getDatablockMap(); + + Ogre::Hlms::HlmsDatablockMap::const_iterator itor = datablocks.begin(); + Ogre::Hlms::HlmsDatablockMap::const_iterator end = datablocks.end(); + + while (itor != end) { - Ogre2ScenePtr s = std::dynamic_pointer_cast(this->Scene()); - s->ClearMaterialsCache(this->textureName); - this->Scene()->UnregisterMaterial(this->name); - if (i->second.useCount() == 4) + if (i == Ogre::HLMS_PBS) { - textureManager.remove(res->getHandle()); - if (!this->textureName.empty()) + Ogre::HlmsPbsDatablock *derivedDatablock = + static_cast(itor->second.datablock); + for (size_t texUnit = 0; texUnit < Ogre::NUM_PBSM_TEXTURE_TYPES; + ++texUnit) { - Ogre::HlmsTextureManager *hlmsTextureManager = - this->ogreHlmsPbs->getHlmsManager()->getTextureManager(); - hlmsTextureManager->destroyTexture(this->textureName); + // Check each texture from the material + Ogre::TextureGpu *tex = derivedDatablock->getTexture(texUnit); + if (tex) + { + // If getLinkedRenderables is empty, then the material is + // not in use, and thus so is potentially the texture + if (!itor->second.datablock->getLinkedRenderables().empty()) + { + if (tex->getNameStr() == this->textureName) + { + textureIsUse = true; + } + } + else + { + if (tex->getNameStr() == this->textureName) + { + textureToRemove = tex; + } + } + } } } - break; + ++itor; } } - ++i; } + + if (textureToRemove && !textureIsUse) + { + Ogre2ScenePtr s = std::dynamic_pointer_cast(this->Scene()); + s->ClearMaterialsCache(this->textureName); + this->Scene()->UnregisterMaterial(this->name); + textureManager->destroyTexture(textureToRemove); + } + + Ogre2ScenePtr s = std::dynamic_pointer_cast(this->Scene()); + Ogre::SceneManager *sceneManager = s->OgreSceneManager(); + sceneManager->shrinkToFitMemoryPools(); + + Ogre::VaoManager *vaoManager = textureManager->getVaoManager(); + vaoManager->cleanupEmptyPools(); } ////////////////////////////////////////////////// @@ -217,7 +269,9 @@ void Ogre2Material::SetAlphaFromTexture(bool _enabled, ////////////////////////////////////////////////// float Ogre2Material::RenderOrder() const { - return this->renderOrder; + Ogre::HlmsMacroblock macroblock( + *this->ogreDatablock->getMacroblock()); + return macroblock.mDepthBiasConstant; } ////////////////////////////////////////////////// @@ -271,7 +325,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); } ////////////////////////////////////////////////// @@ -303,7 +357,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); } ////////////////////////////////////////////////// @@ -335,7 +389,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); } ////////////////////////////////////////////////// @@ -367,7 +421,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); } ////////////////////////////////////////////////// @@ -399,7 +453,8 @@ 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); } ////////////////////////////////////////////////// @@ -431,7 +486,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); } ////////////////////////////////////////////////// @@ -464,16 +519,19 @@ void Ogre2Material::SetLightMap(const std::string &_name, unsigned int _uvSet) this->lightMapName = _name; this->lightMapUvSet = _uvSet; - // reserve detail map 0 for light map - Ogre::PbsTextureTypes type = Ogre::PBSM_DETAIL0; + // in ign-rendering5 + ogre 2.1, we reserved detail map 0 for light map + // and set a blend mode (PBSM_BLEND_OVERLAY AND PBSM_BLEND_MULTIPLY2X + // produces better results) to blend with base albedo map. However, this + // creates unwanted red highlights with ogre 2.2. So switching to use the + // emissive map slot and calling setUseEmissiveAsLightmap(true) + // Ogre::PbsTextureTypes type = Ogre::PBSM_DETAIL0; + // this->ogreDatablock->setDetailMapBlendMode(0, Ogre::PBSM_BLEND_OVERLAY); + Ogre::PbsTextureTypes type = Ogre::PBSM_EMISSIVE; // lightmap usually uses a different tex coord set this->SetTextureMapImpl(this->lightMapName, type); - this->ogreDatablock->setTextureUvSource(type, this->lightMapUvSet); - - // PBSM_BLEND_OVERLAY and PBSM_BLEND_MULTIPLY2X produces better results - this->ogreDatablock->setDetailMapBlendMode(0, Ogre::PBSM_BLEND_OVERLAY); + this->ogreDatablock->setUseEmissiveAsLightmap(true); } ////////////////////////////////////////////////// @@ -481,7 +539,10 @@ void Ogre2Material::ClearLightMap() { this->lightMapName = ""; this->lightMapUvSet = 0u; - this->ogreDatablock->setTexture(Ogre::PBSM_DETAIL0, 0, Ogre::TexturePtr()); + + // in ogre 2.2, we swtiched to use the emissive map slot for light map + this->ogreDatablock->setTexture(Ogre::PBSM_EMISSIVE, this->lightMapName); + this->ogreDatablock->setUseEmissiveAsLightmap(false); } ////////////////////////////////////////////////// @@ -557,6 +618,10 @@ void Ogre2Material::SetTextureMapImpl(const std::string &_texture, } } } + else + { + return; + } // temp workaround check if the model is a OBJ file { @@ -570,43 +635,62 @@ 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)); - this->dataPtr->hashName = texLocation.texture->getName(); - 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); + + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = + root->getRenderSystem()->getTextureGpuManager(); + auto tex = textureMgr->findTextureNoThrow(baseName); + + if (tex) + { + tex->waitForMetadata(); + this->dataPtr->hashName = tex->getName().getFriendlyText(); + } // 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()) + if (this->TextureAlphaEnabled()) { - this->SetAlphaFromTexture(false, this->AlphaThreshold(), - this->TwoSidedEnabled()); + if (tex) + { + tex->scheduleTransitionTo(Ogre::GpuResidency::Resident); + tex->waitForData(); + + // only enable alpha from texture if texture has alpha component + if (!Ogre::PixelFormatGpuUtils::hasAlpha(tex->getPixelFormat())) + { + this->SetAlphaFromTexture(false, this->AlphaThreshold(), + this->TwoSidedEnabled()); + } + + // treat grayscale texture as RGB + if (Ogre::PixelFormatGpuUtils::getNumberOfComponents( + tex->getPixelFormat()) == 1u) + { + this->ogreDatablock->setUseDiffuseMapAsGrayscale(true); + } + } } } } -////////////////////////////////////////////////// -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(); - return texLocation.texture; + auto tex = textureMgr->findTextureNoThrow(_name); + return tex; } ////////////////////////////////////////////////// @@ -711,13 +795,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 3fb96b0d8..d1ae6dee4 100644 --- a/ogre2/src/Ogre2MaterialSwitcher.cc +++ b/ogre2/src/Ogre2MaterialSwitcher.cc @@ -74,8 +74,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 @@ -115,8 +115,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/Ogre2ParticleNoiseListener.cc b/ogre2/src/Ogre2ParticleNoiseListener.cc index 5d510a052..4d0103ab0 100644 --- a/ogre2/src/Ogre2ParticleNoiseListener.cc +++ b/ogre2/src/Ogre2ParticleNoiseListener.cc @@ -30,17 +30,15 @@ using namespace rendering; ////////////////////////////////////////////////// Ogre2ParticleNoiseListener::Ogre2ParticleNoiseListener( - Ogre2ScenePtr _scene, Ogre::Camera *_ogreCamera, - Ogre::MaterialPtr _ogreMaterial) + Ogre2ScenePtr _scene, Ogre::MaterialPtr _ogreMaterial) { this->scene = _scene; - this->ogreCamera = _ogreCamera; this->ogreMaterial = _ogreMaterial; } ////////////////////////////////////////////////// -void Ogre2ParticleNoiseListener::preRenderTargetUpdate( - const Ogre::RenderTargetEvent & /*_evt*/) +void Ogre2ParticleNoiseListener::cameraPreRenderScene( + Ogre::Camera * _cam) { // the code here is responsible for setting the depth variation of readings // returned by sensor in areas where particles are. It does so by adding @@ -75,7 +73,7 @@ void Ogre2ParticleNoiseListener::preRenderTargetUpdate( aabb.getMaximum()); - if (this->ogreCamera->isVisible(box)) + if (_cam->isVisible(box)) { // set stddev to half of size of particle emitter aabb auto hs = box.getHalfSize() * 0.5; diff --git a/ogre2/src/Ogre2ParticleNoiseListener.hh b/ogre2/src/Ogre2ParticleNoiseListener.hh index 889b41a48..eb0f15d19 100644 --- a/ogre2/src/Ogre2ParticleNoiseListener.hh +++ b/ogre2/src/Ogre2ParticleNoiseListener.hh @@ -24,36 +24,39 @@ namespace ignition inline namespace IGNITION_RENDERING_VERSION_NAMESPACE { // /// \brief Helper class for updating particle noise params - class Ogre2ParticleNoiseListener : public Ogre::RenderTargetListener + class Ogre2ParticleNoiseListener : public Ogre::Camera::Listener { /// \brief constructor /// \param[in] _scene the scene manager responsible for rendering public: Ogre2ParticleNoiseListener(Ogre2ScenePtr _scene, - Ogre::Camera *_ogreCamera, Ogre::MaterialPtr _ogreMaterial); + Ogre::MaterialPtr _ogreMaterial); /// \brief destructor public: ~Ogre2ParticleNoiseListener() = 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] _cam Ogre render camara which is about to render. + private: virtual void cameraPreRenderScene( + Ogre::Camera *_cam) override; /// \brief Pointer to scene private: Ogre2ScenePtr scene; - /// \brief Pointer to camera - private: Ogre::Camera *ogreCamera = nullptr; - /// \brief Pointer to ogre matieral with shaders for applying particle /// scattering effect to sensors private: Ogre::MaterialPtr ogreMaterial; + + /// \brief Particle scatter ratio. This is used to determine the ratio of + /// particles that will be detected by sensors. Increasing the ratio + /// increases the scatter of the particles, which means there is a higher + /// chance of particles reflecting and interfering with depth sensing, + /// making the emitter appear more dense. Decreasing the ratio decreases + /// the scatter of the particles, making it appear less dense. This value + /// should be > 0. + private: float particleScatterRatio = 0.65f; }; } } } #endif - - diff --git a/ogre2/src/Ogre2RenderEngine.cc b/ogre2/src/Ogre2RenderEngine.cc index 0008bf5e0..bf15509ba 100644 --- a/ogre2/src/Ogre2RenderEngine.cc +++ b/ogre2/src/Ogre2RenderEngine.cc @@ -94,6 +94,12 @@ Ogre2RenderEngine::Ogre2RenderEngine() : #endif } +////////////////////////////////////////////////// +Ogre::Window * Ogre2RenderEngine::OgreWindow() const +{ + return this->window; +} + ////////////////////////////////////////////////// Ogre2RenderEngine::~Ogre2RenderEngine() { @@ -112,8 +118,19 @@ void Ogre2RenderEngine::Destroy() delete this->ogreOverlaySystem; this->ogreOverlaySystem = nullptr; - if (ogreRoot) + if (this->ogreRoot) { + // Clean up any textures that may still be in flight. + Ogre::TextureGpuManager *mgr = + this->ogreRoot->getRenderSystem()->getTextureGpuManager(); + + auto entries = mgr->getEntries(); + for (auto& [name, entry] : entries) + { + if (entry.resourceGroup == "General" && !entry.destroyRequested) + mgr->destroyTexture(entry.texture); + } + try { // TODO(anyone): do we need to catch segfault on delete? @@ -267,6 +284,10 @@ bool Ogre2RenderEngine::LoadImpl( if (it != _params.end()) std::istringstream(it->second) >> this->useCurrentGLContext; + it = _params.find("headless"); + if (it != _params.end()) + std::istringstream(it->second) >> this->isHeadless; + try { this->LoadAttempt(); @@ -340,6 +361,8 @@ void Ogre2RenderEngine::CreateContext() if (!this->dummyDisplay) { + // Not able to create a Xwindow, try to run in headless mode + this->SetHeadless(true); ignerr << "Unable to open display: " << XDisplayName(0) << std::endl; return; } @@ -524,15 +547,32 @@ void Ogre2RenderEngine::CreateRenderSystem() "and make sure OpenGL is enabled." << std::endl; } - // We operate in windowed mode - renderSys->setConfigOption("Full Screen", "No"); + if (!this->Headless()) + { - /// We used to allow the user to set the RTT mode to PBuffer, FBO, or Copy. - /// Copy is slow, and there doesn't seem to be a good reason to use it - /// PBuffer limits the size of the renderable area of the RTT to the - /// size of the first window created. - /// FBO seem to be the only good option - renderSys->setConfigOption("RTT Preferred Mode", "FBO"); + // We operate in windowed mode + renderSys->setConfigOption("Full Screen", "No"); + + /// We used to allow the user to set the RTT mode to PBuffer, FBO, or Copy. + /// Copy is slow, and there doesn't seem to be a good reason to use it + /// PBuffer limits the size of the renderable area of the RTT to the + /// size of the first window created. + /// FBO seem to be the only good option + renderSys->setConfigOption("RTT Preferred Mode", "FBO"); + } + else + { + try + { + // This may fail if Ogre was *only* build with EGL support, but in that + // case we can ignore the error + renderSys->setConfigOption( "Interface", "Headless EGL / PBuffer" ); + } + catch( Ogre::Exception & ) + { + std::cerr << "Unable to setup EGL (headless mode)" << '\n'; + } + } // get all supported fsaa values Ogre::ConfigOptionMap configMap = renderSys->getConfigOptions(); @@ -570,8 +610,7 @@ void Ogre2RenderEngine::CreateRenderSystem() this->ogreRoot->setRenderSystem(renderSys); } -////////////////////////////////////////////////// -void Ogre2RenderEngine::CreateResources() +void Ogre2RenderEngine::RegisterHlms() { const char *env = std::getenv("IGN_RENDERING_RESOURCE_PATH"); std::string resourcePath = (env) ? std::string(env) : @@ -584,35 +623,6 @@ void Ogre2RenderEngine::CreateResources() mediaPath = common::joinPaths(resourcePath, "ogre2", "src", "media"); } - // register low level materials (ogre v1 materials) - std::vector< std::pair > archNames; - std::string p = mediaPath; - if (common::isDirectory(p)) - { - archNames.push_back( - std::make_pair(p, "General")); - archNames.push_back( - std::make_pair(p + "/materials/programs", "General")); - archNames.push_back( - std::make_pair(p + "/materials/scripts", "General")); - archNames.push_back( - std::make_pair(p + "/materials/textures", "General")); - - for (auto aiter = archNames.begin(); aiter != archNames.end(); ++aiter) - { - try - { - Ogre::ResourceGroupManager::getSingleton().addResourceLocation( - aiter->first, "FileSystem", aiter->second); - } - catch(Ogre::Exception &/*_e*/) - { - ignerr << "Unable to load Ogre Resources. Make sure the resources " - "path in the world file is set correctly." << std::endl; - } - } - } - // register PbsMaterial resources Ogre::String rootHlmsFolder = mediaPath; Ogre::String pbsCompositorFolder = common::joinPaths( @@ -627,6 +637,10 @@ void Ogre2RenderEngine::CreateResources() rootHlmsFolder, "2.0", "scripts", "materials", "Common", "GLSL"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation( commonGLSLMaterialFolder, "FileSystem", "General"); + Ogre::String commonGLSLESMaterialFolder = common::joinPaths( + rootHlmsFolder, "2.0", "scripts", "materials", "Common", "GLSLES"); + Ogre::ResourceGroupManager::getSingleton().addResourceLocation( + commonGLSLESMaterialFolder, "FileSystem", "General"); // The following code is taken from the registerHlms() function in ogre2 // samples framework @@ -703,6 +717,50 @@ void Ogre2RenderEngine::CreateResources() } } +////////////////////////////////////////////////// +void Ogre2RenderEngine::CreateResources() +{ + const char *env = std::getenv("IGN_RENDERING_RESOURCE_PATH"); + std::string resourcePath = (env) ? std::string(env) : + IGN_RENDERING_RESOURCE_PATH; + // install path + std::string mediaPath = common::joinPaths(resourcePath, "ogre2", "media"); + if (!common::exists(mediaPath)) + { + // src path + mediaPath = common::joinPaths(resourcePath, "ogre2", "src", "media"); + } + + // register low level materials (ogre v1 materials) + std::vector< std::pair > archNames; + std::string p = mediaPath; + if (common::isDirectory(p)) + { + archNames.push_back( + std::make_pair(p, "General")); + archNames.push_back( + std::make_pair(p + "/materials/programs", "General")); + archNames.push_back( + std::make_pair(p + "/materials/scripts", "General")); + archNames.push_back( + std::make_pair(p + "/materials/textures", "General")); + + for (auto aiter = archNames.begin(); aiter != archNames.end(); ++aiter) + { + try + { + Ogre::ResourceGroupManager::getSingleton().addResourceLocation( + aiter->first, "FileSystem", aiter->second); + } + catch(Ogre::Exception &/*_e*/) + { + ignerr << "Unable to load Ogre Resources. Make sure the resources " + "path in the world file is set correctly." << std::endl; + } + } + } +} + ////////////////////////////////////////////////// void Ogre2RenderEngine::CreateRenderWindow() { @@ -722,7 +780,7 @@ std::string Ogre2RenderEngine::CreateRenderWindow(const std::string &_handle, { Ogre::StringVector paramsVector; Ogre::NameValuePairList params; - Ogre::RenderWindow *window = nullptr; + window = nullptr; // if use current gl then don't include window handle params if (!this->useCurrentGLContext) @@ -756,7 +814,7 @@ std::string Ogre2RenderEngine::CreateRenderWindow(const std::string &_handle, params["contentScalingFactor"] = std::to_string(_ratio); // Ogre 2 PBS expects gamma correction - params["gamma"] = "true"; + params["gamma"] = "Yes"; if (this->useCurrentGLContext) { @@ -769,8 +827,9 @@ std::string Ogre2RenderEngine::CreateRenderWindow(const std::string &_handle, { try { - window = this->ogreRoot->createRenderWindow( + window = Ogre::Root::getSingleton().createRenderWindow( stream.str(), _width, _height, false, ¶ms); + this->RegisterHlms(); } catch(const std::exception &_e) { @@ -789,8 +848,7 @@ std::string Ogre2RenderEngine::CreateRenderWindow(const std::string &_handle, if (window) { - window->setActive(true); - window->setVisible(true); + window->_setVisible(true); // Windows needs to reposition the render window to 0,0. window->reposition(0, 0); diff --git a/ogre2/src/Ogre2RenderTarget.cc b/ogre2/src/Ogre2RenderTarget.cc index 705a38c27..b2fc62549 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; @@ -101,16 +92,13 @@ class ignition::rendering::Ogre2RenderTargetPrivate /// \brief Name of shadow compositor node public: const std::string kShadowNodeName = "PbsMaterialsShadowNode"; - /// \brief Helper class that applies the material to the render target - Ogre2RenderTargetMaterialPtr materialApplicator[2]; - /// \brief Pointer to the internal ogre render texture objects /// There's two because we ping pong postprocessing effects /// and the final result is always in ogreTexture[1] /// RenderWindows may have a 3rd texture which is the /// actual window /// - Ogre::Texture *ogreTexture[2] = {nullptr, nullptr}; + public: Ogre::TextureGpu *ogreTexture[2] = {nullptr, nullptr}; }; using namespace ignition; @@ -169,21 +157,38 @@ void Ogre2RenderTarget::BuildCompositor() nodeDef->addTextureSourceName( "rt1", 1u, Ogre::TextureDefinitionBase::TEXTURE_INPUT); + { + // Add a manually-defined RTV (based on an automatically generated one) + // so that we can perform an explicit MSAA resolve. + const Ogre::RenderTargetViewDef *rt0Def = + nodeDef->getRenderTargetViewDef( "rt0" ); + Ogre::RenderTargetViewDef *rtvDef = + nodeDef->addRenderTextureView( "rtv" ); + + *rtvDef = *rt0Def; + + const uint8_t fsaa = TargetFSAA(); + if (fsaa > 1u) + { + Ogre::TextureDefinitionBase::TextureDefinition *msaaDef = + nodeDef->addTextureDefinition("rt_fsaa"); + + msaaDef->fsaa = std::to_string(fsaa); + + rtvDef->colourAttachments[0].textureName = "rt_fsaa"; + rtvDef->colourAttachments[0].resolveTextureName = "rt0"; + } + } + nodeDef->setNumTargetPass(2); Ogre::CompositorTargetDef *rt0TargetDef = - nodeDef->addTargetPass("rt0"); + nodeDef->addTargetPass("rtv"); if (validBackground) - rt0TargetDef->setNumPasses(3); - else rt0TargetDef->setNumPasses(2); + else + rt0TargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - rt0TargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = this->ogreBackgroundColor; - if (validBackground) { // quad pass @@ -194,6 +199,9 @@ void Ogre2RenderTarget::BuildCompositor() + this->Name(); passQuad->mFrustumCorners = Ogre::CompositorPassQuadDef::CAMERA_DIRECTION; + + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(this->ogreBackgroundColor); } // scene pass @@ -202,6 +210,12 @@ void Ogre2RenderTarget::BuildCompositor() rt0TargetDef->addPass(Ogre::PASS_SCENE)); passScene->mShadowNode = this->dataPtr->kShadowNodeName; passScene->mIncludeOverlays = true; + + if (!validBackground) + { + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(this->ogreBackgroundColor); + } } nodeDef->mapOutputChannel(0, "rt0"); @@ -227,7 +241,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 = @@ -258,27 +272,24 @@ void Ogre2RenderTarget::BuildCompositor() } } - auto &manager = Ogre::TextureManager::getSingleton(); Ogre::CompositorChannelVec externalTargets(2u); - for( size_t i = 0u; i < 2u; ++i ) + for (size_t i = 0u; i < 2u; ++i) { // Connect them in reverse order const size_t srcIdx = 2u - i - 1u; - externalTargets[i].target = - this->dataPtr->ogreTexture[srcIdx]->getBuffer()->getRenderTarget(); - externalTargets[i].textures.push_back( - manager.getByName(this->dataPtr->ogreTexture[srcIdx]->getName())); + externalTargets[i] = this->dataPtr->ogreTexture[srcIdx]; } - this->SyncOgreTextureVars(); - this->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(), - externalTargets, this->ogreCamera, - this->ogreCompositorWorkspaceDefName, false); + ogreCompMgr->addWorkspace( + this->scene->OgreSceneManager(), + externalTargets, + this->ogreCamera, + this->ogreCompositorWorkspaceDefName, + false); this->dataPtr->rtListener = new Ogre2RenderTargetCompositorListener(this); - this->ogreCompositorWorkspace->setListener(this->dataPtr->rtListener); + this->ogreCompositorWorkspace->addListener(this->dataPtr->rtListener); } ////////////////////////////////////////////////// @@ -291,27 +302,16 @@ void Ogre2RenderTarget::DestroyCompositor() // FSAA (which we need for BuildCompositor to connect correctly) const Ogre::CompositorChannelVec &externalTargets = this->ogreCompositorWorkspace->getExternalRenderTargets(); - for( size_t i = 0u; i < 2u; ++i ) + for (size_t i = 0u; i < 2u; ++i) { const size_t srcIdx = (2u - i - 1u); - this->dataPtr->ogreTexture[srcIdx] = - externalTargets[i].textures.front().get(); - } - this->SyncOgreTextureVars(); - - if (this->dataPtr->materialApplicator[0] && - this->dataPtr->materialApplicator[0]->IsSameRenderTarget( - this->dataPtr->ogreTexture[0]->getBuffer()->getRenderTarget())) - { - std::swap( this->dataPtr->materialApplicator[0], - this->dataPtr->materialApplicator[1] ); + this->dataPtr->ogreTexture[srcIdx] = externalTargets[i]; } - this->materialApplicator = this->dataPtr->materialApplicator[0]; 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 + @@ -334,6 +334,8 @@ void Ogre2RenderTarget::RebuildCompositor() ////////////////////////////////////////////////// void Ogre2RenderTarget::Copy(Image &_image) const { + Ogre::TextureGpu *texture = this->RenderTarget(); + // TODO(anyone) handle Bayer conversions // TODO(anyone) handle ogre version differences @@ -343,10 +345,33 @@ 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); + Ogre::TextureBox box = image2.getData(0); + + auto dataImage = static_cast(_image.Data()); + auto dataImage2 = static_cast(box.data); + + unsigned int channelCount = 3u; + unsigned int rawChannelCount = 4u; + unsigned int bytesPerChannel = 1u; + for (unsigned int row = 0; row < this->height; ++row) + { + // the texture box step size could be larger than our image buffer step + // size + unsigned int rawDataRowIdx = row * box.bytesPerRow / bytesPerChannel; + for (unsigned int column = 0; column < this->width; ++column) + { + unsigned int idx = (row * this->width * channelCount) + + column * channelCount; + unsigned int rawIdx = rawDataRowIdx + + column * rawChannelCount; + + dataImage[idx] = dataImage2[rawIdx]; + dataImage[idx + 1] = dataImage2[rawIdx + 1]; + dataImage[idx + 2] = dataImage2[rawIdx + 2]; + } + } } ////////////////////////////////////////////////// @@ -432,7 +457,7 @@ void Ogre2RenderTarget::Render() this->ogreCompositorWorkspace->_update(); this->ogreCompositorWorkspace->_endUpdate(false); - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); this->ogreCompositorWorkspace->_swapFinalTarget(swappedTargets); @@ -458,43 +483,70 @@ void Ogre2RenderTarget::DestroyTargetImpl() this->DestroyCompositor(); - auto &manager = Ogre::TextureManager::getSingleton(); - - this->materialApplicator.reset(); + Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot(); - for( size_t i = 0u; i < 2u; ++i ) + Ogre::TextureGpuManager *textureManager = + root->getRenderSystem()->getTextureGpuManager(); + for (size_t i = 0u; i < 2u; ++i) { - manager.unload(this->dataPtr->ogreTexture[i]->getName()); - manager.remove(this->dataPtr->ogreTexture[i]->getName()); - - // 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 - - this->dataPtr->materialApplicator[i].reset(); + textureManager->destroyTexture(this->dataPtr->ogreTexture[i]); this->dataPtr->ogreTexture[i] = nullptr; } - this->SyncOgreTextureVars(); + // 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 } ////////////////////////////////////////////////// void Ogre2RenderTarget::BuildTargetImpl() { - Ogre::TextureManager &manager = Ogre::TextureManager::getSingleton(); - Ogre::PixelFormat ogreFormat = Ogre2Conversions::Convert(this->format); + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + Ogre::TextureGpuManager *textureMgr = + ogreRoot->getRenderSystem()->getTextureGpuManager(); + + for (size_t i = 0u; i < 2u; ++i) + { + this->dataPtr->ogreTexture[i] = + textureMgr->createTexture( + this->name + std::to_string(i), + Ogre::GpuPageOutStrategy::Discard, + Ogre::TextureFlags::RenderToTexture, + Ogre::TextureTypes::Type2D); + + this->dataPtr->ogreTexture[i]->setResolution(this->width, this->height); + this->dataPtr->ogreTexture[i]->setNumMipmaps(1u); + this->dataPtr->ogreTexture[i]->setPixelFormat(Ogre::PFG_RGBA8_UNORM_SRGB); + + this->dataPtr->ogreTexture[i]->scheduleTransitionTo( + Ogre::GpuResidency::Resident); + } +} + +////////////////////////////////////////////////// +unsigned int Ogre2RenderTarget::GLIdImpl() const +{ + if (!this->dataPtr->ogreTexture[0]) + return 0; + + unsigned int texId; + this->dataPtr->ogreTexture[1]->getCustomAttribute("msFinalTextureBuffer", + &texId); + + return static_cast(texId); +} +////////////////////////////////////////////////// +uint8_t Ogre2RenderTarget::TargetFSAA() const +{ // check if target fsaa is supported - unsigned int fsaa = 0; std::vector fsaaLevels = Ogre2RenderEngine::Instance()->FSAALevels(); unsigned int targetFSAA = this->antiAliasing; auto const it = std::find(fsaaLevels.begin(), fsaaLevels.end(), targetFSAA); - if (it != fsaaLevels.end()) - { - fsaa = targetFSAA; - } - else + + if (it == fsaaLevels.end()) { // output warning but only do it once static bool ogre2FSAAWarn = false; @@ -506,37 +558,16 @@ void Ogre2RenderTarget::BuildTargetImpl() } } - for( size_t i = 0u; i < 2u; ++i ) - { - // Ogre 2 PBS expects gamma correction to be enabled - // Only the second target uses FSAA. - // Note: It's not guaranteed the 2nd target will remain - // the one using FSAA - this->dataPtr->ogreTexture[i] = (manager.createManual( - this->name + std::to_string(i), "General", - Ogre::TEX_TYPE_2D, this->width, this->height, 0, ogreFormat, - Ogre::TU_RENDERTARGET, 0, true, i == 1u ? fsaa : 0)).get(); - } - - this->SyncOgreTextureVars(); -} - -////////////////////////////////////////////////// -unsigned int Ogre2RenderTarget::GLIdImpl() const -{ - if (!this->dataPtr->ogreTexture[0]) - return 0; - - GLuint texId; - this->dataPtr->ogreTexture[1]->getCustomAttribute("GLID", &texId); + if (targetFSAA == 0u) + targetFSAA = 1u; - return static_cast(texId); + return static_cast(targetFSAA); } ////////////////////////////////////////////////// -Ogre::RenderTarget *Ogre2RenderTarget::RenderTargetImpl() const +Ogre::TextureGpu *Ogre2RenderTarget::RenderTargetImpl() const { - return this->dataPtr->ogreTexture[1]->getBuffer()->getRenderTarget(); + return this->dataPtr->ogreTexture[1]; } ////////////////////////////////////////////////// @@ -556,12 +587,15 @@ void Ogre2RenderTarget::UpdateBackgroundColor() { if (this->colorDirty) { - // set background color in compositor clear pass def + // set background color in the first pass that clears + // the RT (both node and its definition). auto nodeSeq = this->ogreCompositorWorkspace->getNodeSequence(); - auto pass = nodeSeq[0]->_getPasses()[0]->getDefinition(); - auto clearPass = dynamic_cast(pass); - const_cast(clearPass)->mColourValue = - this->ogreBackgroundColor; + auto pass = nodeSeq[0]->_getPasses()[0]; + pass->getRenderPassDesc()->setClearColour(this->ogreBackgroundColor); + + auto passDef = pass->getDefinition(); + const_cast(passDef)->setAllClearColours( + this->ogreBackgroundColor); this->colorDirty = false; } @@ -595,7 +629,8 @@ 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); + texUnit->setHardwareGammaEnabled(false); } this->backgroundMaterialDirty = false; @@ -615,39 +650,15 @@ void Ogre2RenderTarget::UpdateRenderPassChain() &this->dataPtr->ogreTexture, this->IsRenderWindow()); - // this->dataPtr->ogreTexture[0] may have changed - if (this->dataPtr->materialApplicator[0] && - this->dataPtr->materialApplicator[0]->IsSameRenderTarget( - this->dataPtr->ogreTexture[0]->getBuffer()->getRenderTarget())) - { - std::swap( this->dataPtr->materialApplicator[0], - this->dataPtr->materialApplicator[1] ); - } - this->materialApplicator = this->dataPtr->materialApplicator[0]; - - this->SyncOgreTextureVars(); - this->renderPassDirty = false; } -////////////////////////////////////////////////// -void Ogre2RenderTarget::UpdateRenderPassChain( - Ogre::CompositorWorkspace * /*_workspace*/, - const std::string & /*_workspaceDefName*/, - const std::string & /*_baseNode*/, const std::string & /*_finalNode*/, - const std::vector & /*_renderPasses*/, - bool /*_recreateNodes*/) -{ - ignwarn << "Warning: This Ogre2RenderTarget::UpdateRenderPassChain " - << "overload is deprecated" << std::endl; -} - ////////////////////////////////////////////////// void Ogre2RenderTarget::UpdateRenderPassChain( Ogre::CompositorWorkspace *_workspace, const std::string &_workspaceDefName, const std::string &_baseNode, const std::string &_finalNode, const std::vector &_renderPasses, - bool _recreateNodes, Ogre::Texture *(*_ogreTextures)[2], + bool _recreateNodes, Ogre::TextureGpu *(*_ogreTextures)[2], bool _isRenderWindow) { if (!_workspace || _workspaceDefName.empty() || @@ -746,10 +757,10 @@ void Ogre2RenderTarget::UpdateRenderPassChain( const Ogre::CompositorChannelVec &externalTargets = _workspace->getExternalRenderTargets(); - for( size_t i = 0u; i < 2u; ++i ) + for (size_t i = 0u; i < 2u; ++i) { const size_t srcIdx = bMustSwapRts ? (2u - i - 1u) : i; - (*_ogreTextures)[srcIdx] = externalTargets[i].textures.front().get(); + (*_ogreTextures)[srcIdx] = externalTargets[i]; } } else @@ -774,14 +785,6 @@ void Ogre2RenderTarget::UpdateRenderPassChain( } } -////////////////////////////////////////////////// -void Ogre2RenderTarget::UpdateShadowNode() -{ - ignwarn << "Ogre2RenderTarget::UpdateShadowNode() is deprecated and " - "replaced by Ogre2Scene:UpdateShadowNode()" - << std::endl; -} - ////////////////////////////////////////////////// void Ogre2RenderTarget::RebuildImpl() { @@ -795,7 +798,8 @@ void Ogre2RenderTarget::SetMaterial(MaterialPtr _material) { this->material = _material; - // Have to rebuild the target so there is something to apply the applicator to + // Have to rebuild the target so there is something to apply + // the applicator to this->targetDirty = true; } @@ -818,27 +822,11 @@ void Ogre2RenderTarget::RebuildMaterial() Ogre::MaterialPtr matPtr = ogreMaterial->Material(); Ogre::SceneManager *sceneMgr = this->scene->OgreSceneManager(); - for( size_t i = 0u; i < 2u; ++i ) - { - Ogre::RenderTarget *target = - this->dataPtr->ogreTexture[i]->getBuffer()->getRenderTarget(); - this->dataPtr->materialApplicator[i].reset( - new Ogre2RenderTargetMaterial(sceneMgr, target, matPtr.get())); - } - - this->materialApplicator = this->dataPtr->materialApplicator[0]; + this->materialApplicator.reset(new Ogre2RenderTargetMaterial( + sceneMgr, this->ogreCamera, matPtr.get())); } } -////////////////////////////////////////////////// -void Ogre2RenderTarget::SyncOgreTextureVars() -{ - Ogre2RenderTexture *asRenderTexture = - dynamic_cast(this); - if (asRenderTexture) - asRenderTexture->SetOgreTexture(this->dataPtr->ogreTexture[1]); -} - ////////////////////////////////////////////////// // Ogre2RenderTexture ////////////////////////////////////////////////// @@ -898,20 +886,11 @@ void Ogre2RenderTexture::PostRender() } ////////////////////////////////////////////////// -Ogre::RenderTarget *Ogre2RenderTexture::RenderTarget() const +Ogre::TextureGpu *Ogre2RenderTexture::RenderTarget() const { return Ogre2RenderTarget::RenderTargetImpl(); } -////////////////////////////////////////////////// -void Ogre2RenderTexture::SetOgreTexture(Ogre::Texture *_ogreTexture) -{ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - this->ogreTexture = _ogreTexture; -#pragma GCC diagnostic pop -} - ////////////////////////////////////////////////// // Ogre2RenderWindow ////////////////////////////////////////////////// @@ -931,7 +910,7 @@ bool Ogre2RenderWindow::IsRenderWindow() const } ////////////////////////////////////////////////// -Ogre::RenderTarget *Ogre2RenderWindow::RenderTarget() const +Ogre::TextureGpu *Ogre2RenderWindow::RenderTarget() const { return this->ogreRenderWindow; } @@ -951,9 +930,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(); } @@ -961,12 +941,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->OgreWindow()->getTexture(); } diff --git a/ogre2/src/Ogre2RenderTargetMaterial.cc b/ogre2/src/Ogre2RenderTargetMaterial.cc index bcea1ae90..d87645a78 100644 --- a/ogre2/src/Ogre2RenderTargetMaterial.cc +++ b/ogre2/src/Ogre2RenderTargetMaterial.cc @@ -20,7 +20,7 @@ #ifdef _MSC_VER #pragma warning(push, 0) #endif -#include +#include #include #ifdef _MSC_VER #pragma warning(pop) @@ -31,32 +31,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); } @@ -76,9 +78,3 @@ Ogre::Technique *Ogre2RenderTargetMaterial::handleSchemeNotFound( return nullptr; } -////////////////////////////////////////////////// -bool Ogre2RenderTargetMaterial::IsSameRenderTarget( - Ogre::RenderTarget *_renderTarget) -{ - return this->renderTarget == _renderTarget; -} diff --git a/ogre2/src/Ogre2Scene.cc b/ogre2/src/Ogre2Scene.cc index 4100b61a5..428afd97b 100644 --- a/ogre2/src/Ogre2Scene.cc +++ b/ogre2/src/Ogre2Scene.cc @@ -173,22 +173,7 @@ void Ogre2Scene::PreRender() this->SensorByIndex(i)); if (camera) { - // TODO(anyone): this function should rely on virtual functions instead - // of dynamic casts - // Looks in commit history for '#SetShadowsNodeDefDirtyABI' to - // see changes made and revert - { - auto cameraDerived = std::dynamic_pointer_cast( - this->SensorByIndex(i)); - if (cameraDerived) - cameraDerived->SetShadowsNodeDefDirty(); - } - { - auto cameraDerived = std::dynamic_pointer_cast( - this->SensorByIndex(i)); - if (cameraDerived) - cameraDerived->SetShadowsNodeDefDirty(); - } + camera->SetShadowsDirty(); } } @@ -416,7 +401,7 @@ bool Ogre2Scene::InitImpl() this->CreateRootVisual(); this->CreateStores(); this->CreateMeshFactory(); - + UpdateShadowNode(); return true; } @@ -625,17 +610,20 @@ void Ogre2Scene::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 @@ -644,15 +632,18 @@ void Ogre2Scene::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 ); } } @@ -690,7 +681,7 @@ void Ogre2Scene::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; @@ -717,8 +708,8 @@ void Ogre2Scene::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 @@ -772,25 +763,18 @@ void Ogre2Scene::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 = + // 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; + 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; } } @@ -806,7 +790,7 @@ void Ogre2Scene::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 == @@ -1162,8 +1146,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()); @@ -1174,8 +1156,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()); @@ -1191,7 +1172,8 @@ 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 56ef5023d..b68379bdb 100644 --- a/ogre2/src/Ogre2SelectionBuffer.cc +++ b/ogre2/src/Ogre2SelectionBuffer.cc @@ -33,12 +33,10 @@ #include #include #include -#include #include -#include #include #include -#include +#include #include #ifdef _MSC_VER #pragma warning(pop) @@ -68,31 +66,38 @@ 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 compositor manager + public: Ogre::CompositorManager2 *ogreCompMgr = nullptr; + + /// \brief selection buffer width + public: unsigned int width = 0; + + /// \brief selection buffer height + public: unsigned int height = 0; /// \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; }; ///////////////////////////////////////////////// Ogre2SelectionBuffer::Ogre2SelectionBuffer(const std::string &_cameraName, - Ogre2ScenePtr _scene): dataPtr(new Ogre2SelectionBufferPrivate) + Ogre2ScenePtr _scene, unsigned int _width, unsigned int _height): + dataPtr(new Ogre2SelectionBufferPrivate) { this->dataPtr->scene = _scene; this->dataPtr->sceneMgr = _scene->OgreSceneManager(); + auto engine = Ogre2RenderEngine::Instance(); + auto ogreRoot = engine->OgreRoot(); + this->dataPtr->ogreCompMgr = ogreRoot->getCompositorManager2(); + + this->dataPtr->width = _width; + this->dataPtr->height = _height; + this->dataPtr->camera = this->dataPtr->sceneMgr->findCameraNoThrow( _cameraName); if (!this->dataPtr->camera) @@ -105,6 +110,18 @@ Ogre2SelectionBuffer::Ogre2SelectionBuffer(const std::string &_cameraName, this->dataPtr->selectionCamera = this->dataPtr->sceneMgr->createCamera(_cameraName + "_selection_buffer"); + this->dataPtr->selectionCamera->detachFromParent(); + this->dataPtr->sceneMgr->getRootSceneNode()->attachObject( + this->dataPtr->selectionCamera); + + 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->setAspectRatio( + this->dataPtr->camera->getAspectRatio()); + this->dataPtr->materialSwitcher.reset( new Ogre2MaterialSwitcher(this->dataPtr->scene)); this->CreateRTTBuffer(); @@ -130,12 +147,16 @@ void Ogre2SelectionBuffer::Update() this->dataPtr->scene->StartForcedRender(); // manual update + // this->dataPtr->ogreCompositorWorkspace->setEnabled(true); + // auto engine = Ogre2RenderEngine::Instance(); + // engine->OgreRoot()->renderOneFrame(); + // this->dataPtr->ogreCompositorWorkspace->setEnabled(false); this->dataPtr->ogreCompositorWorkspace->_validateFinalTarget(); this->dataPtr->ogreCompositorWorkspace->_beginUpdate(false); this->dataPtr->ogreCompositorWorkspace->_update(); this->dataPtr->ogreCompositorWorkspace->_endUpdate(false); - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); this->dataPtr->ogreCompositorWorkspace->_swapFinalTarget(swappedTargets); @@ -143,146 +164,116 @@ void Ogre2SelectionBuffer::Update() this->dataPtr->scene->EndForcedRender(); - this->dataPtr->renderTexture->copyContentsToMemory(*this->dataPtr->pixelBox, - Ogre::RenderTarget::FB_FRONT); + // 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( + this->dataPtr->width, this->dataPtr->height); + this->dataPtr->renderTexture->setNumMipmaps(1u); + this->dataPtr->renderTexture->setPixelFormat(Ogre::PFG_RGBA8_UNORM); + + 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 selection buffer compositor. const Ogre::String workspaceName = "SelectionBufferWorkspace" + - this->dataPtr->camera->getName(); - ogreCompMgr->createBasicWorkspaceDef(workspaceName, + this->dataPtr->camera->getName(); + this->dataPtr->ogreCompMgr->createBasicWorkspaceDef(workspaceName, Ogre::ColourValue(0.0f, 0.0f, 0.0f, 1.0f)); this->dataPtr->ogreCompositorWorkspace = - ogreCompMgr->addWorkspace(this->dataPtr->scene->OgreSceneManager(), - this->dataPtr->renderTexture, - this->dataPtr->selectionCamera, workspaceName, false); + this->dataPtr->ogreCompMgr->addWorkspace( + this->dataPtr->scene->OgreSceneManager(), + this->dataPtr->renderTexture, + 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. Ensure it's at least 4 bytes - size_t bufferSize = std::max( - Ogre::PixelUtil::getMemorySize(width, height, 1, format), - 4u); - this->dataPtr->buffer = new uint8_t[bufferSize]; - memset(this->dataPtr->buffer, 0, 4u); - this->dataPtr->pixelBox = new Ogre::PixelBox(width, - height, 1, format, this->dataPtr->buffer); } ///////////////////////////////////////////////// -Ogre::Item *Ogre2SelectionBuffer::OnSelectionClick(const int _x, const int _y) +void Ogre2SelectionBuffer::SetDimensions( + unsigned int _width, unsigned int _height) { - if (!this->dataPtr->renderTexture) - return nullptr; + if (this->dataPtr->width == _width && this->dataPtr->height == _height) + return; - if (!this->dataPtr->camera) - return nullptr; + this->dataPtr->width = _width; + this->dataPtr->height = _height; - Ogre::Viewport *vp = this->dataPtr->camera->getLastViewport(); + DeleteRTTBuffer(); - if (!vp) - return nullptr; + if (this->dataPtr->ogreCompositorWorkspace) + { + // TODO(ahcorde): Remove the workspace. Potential leak here + this->dataPtr->ogreCompMgr->removeWorkspace( + this->dataPtr->ogreCompositorWorkspace); + } - Ogre::RenderTarget *rt = vp->getTarget(); + CreateRTTBuffer(); +} - if (!rt) +///////////////////////////////////////////////// +Ogre::Item *Ogre2SelectionBuffer::OnSelectionClick(const int _x, const int _y) +{ + if (!this->dataPtr->renderTexture) return nullptr; - const unsigned int targetWidth = rt->getWidth(); - const unsigned int targetHeight = rt->getHeight(); - - if (_x < 0 || _y < 0 || _x >= static_cast(targetWidth) - || _y >= static_cast(targetHeight)) + if (!this->dataPtr->camera) 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->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 e1002402a..bcc0e99f6 100644 --- a/ogre2/src/Ogre2ThermalCamera.cc +++ b/ogre2/src/Ogre2ThermalCamera.cc @@ -23,6 +23,14 @@ #include #endif +#ifdef __APPLE__ + #include +#else +#ifndef _WIN32 + #include +#endif +#endif + #include #include @@ -57,6 +65,8 @@ #include "ignition/rendering/ogre2/Ogre2ThermalCamera.hh" #include "ignition/rendering/ogre2/Ogre2Visual.hh" +#include + namespace ignition { namespace rendering @@ -65,7 +75,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 +94,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 +155,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 +174,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 +235,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 @@ -421,8 +426,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) @@ -462,12 +467,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; @@ -477,15 +479,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) { @@ -597,15 +598,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(); @@ -656,8 +657,8 @@ void Ogre2ThermalCamera::CreateThermalTexture() // compositor_node ThermalCamera // { // in 0 rt_input - // texture depthTexture target_width target_height PF_D32_FLOAT - // texture colorTexture target_width target_height PF_R8G8B8A8 + // texture depthTexture target_width target_height PFG_D32_FLOAT + // texture colorTexture target_width target_height PFG_RGBA8_UNORM // target colorTexture // { // pass clear @@ -697,57 +698,54 @@ 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 = nodeDef->addTargetPass("colorTexture"); - colorTargetDef->setNumPasses(2); + colorTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - colorTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(0, 0, 0); // scene pass Ogre::CompositorPassSceneDef *passScene = static_cast( colorTargetDef->addPass(Ogre::PASS_SCENE)); + passScene->setAllLoadActions(Ogre::LoadAction::Clear); + passScene->setAllClearColours(Ogre::ColourValue(0, 0, 0)); // thermal camera should not see particles passScene->mVisibilityMask = IGN_VISIBILITY_ALL & ~Ogre2ParticleEmitter::kParticleVisibilityFlags; @@ -756,20 +754,18 @@ void Ogre2ThermalCamera::CreateThermalTexture() // rt_input target - converts to thermal Ogre::CompositorTargetDef *inputTargetDef = nodeDef->addTargetPass("rt_input"); - inputTargetDef->setNumPasses(2); + inputTargetDef->setNumPasses(1); { - // clear pass - Ogre::CompositorPassClearDef *passClear = - static_cast( - inputTargetDef->addPass(Ogre::PASS_CLEAR)); - passClear->mColourValue = Ogre::ColourValue(this->ambient, 0, 1.0); // quad pass Ogre::CompositorPassQuadDef *passQuad = static_cast( inputTargetDef->addPass(Ogre::PASS_QUAD)); + passQuad->setAllLoadActions(Ogre::LoadAction::Clear); + passQuad->setAllClearColours(Ogre::ColourValue(this->ambient, 0, 1.0)); + 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; } @@ -787,37 +783,49 @@ 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); + + this->dataPtr->ogreThermalTexture->setResolution( + this->ImageWidth(), this->ImageHeight()); + this->dataPtr->ogreThermalTexture->setNumMipmaps(1u); + this->dataPtr->ogreThermalTexture->setPixelFormat( + ogrePF); - Ogre::RenderTarget *rt = - this->dataPtr->ogreThermalTexture->getBuffer()->getRenderTarget(); + 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; } } @@ -826,6 +834,12 @@ void Ogre2ThermalCamera::CreateThermalTexture() ////////////////////////////////////////////////// void Ogre2ThermalCamera::Render() { + // GL_DEPTH_CLAMP is disabled in later version of ogre2.2 + // however our shaders rely on clamped values so enable it for this sensor +#ifndef _WIN32 + glEnable(GL_DEPTH_CLAMP); +#endif + // update the compositors this->scene->StartRendering(); @@ -834,11 +848,15 @@ void Ogre2ThermalCamera::Render() this->dataPtr->ogreCompositorWorkspace->_update(); this->dataPtr->ogreCompositorWorkspace->_endUpdate(false); - Ogre::vector::type swappedTargets; + Ogre::vector::type swappedTargets; swappedTargets.reserve(2u); this->dataPtr->ogreCompositorWorkspace->_swapFinalTarget(swappedTargets); this->scene->FlushGpuCommandsAndStartNewFrame(1u, false); + +#ifndef _WIN32 + glDisable(GL_DEPTH_CLAMP); +#endif } ////////////////////////////////////////////////// @@ -857,50 +875,49 @@ 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); if (!this->dataPtr->thermalImage) { this->dataPtr->thermalImage = new uint16_t[len]; } + Ogre::TextureBox box = image.getData(0u); if (format == PF_L8) { - // workaround for populating a 16bit image buffer with 8bit data - // \todo(anyone) add a new ConnectNewThermalFrame function that accepts - // a generic unsigned char array instead of uint16_t so we can do a direct - // memcpy of the data + uint8_t *thermalBuffer = static_cast(box.data); for (unsigned int i = 0u; i < height; ++i) { + // the texture box step size could be larger than our image buffer step + // size + unsigned int rawDataRowIdx = i * box.bytesPerRow / bytesPerChannel; for (unsigned int j = 0u; j < width; ++j) { unsigned int idx = (i * width) + j; - this->dataPtr->thermalImage[idx] = static_cast( - this->dataPtr->thermalBuffer[idx]); + this->dataPtr->thermalImage[idx] = thermalBuffer[rawDataRowIdx + j]; } } } else { // fill thermal data - memcpy(this->dataPtr->thermalImage, this->dataPtr->thermalBuffer, - height * width * channelCount * bytesPerChannel); + // copy data row by row. The texture box may not be a contiguous region of + // a texture + uint16_t * thermalBuffer = static_cast(box.data); + for (unsigned int i = 0; i < height; ++i) + { + unsigned int rawDataRowIdx = i * box.bytesPerRow / bytesPerChannel; + unsigned int rowIdx = i * width * channelCount; + memcpy(&this->dataPtr->thermalImage[rowIdx], + &thermalBuffer[rawDataRowIdx], + width * channelCount * bytesPerChannel); + } } this->dataPtr->newThermalFrame( diff --git a/ogre2/src/Ogre2Visual.cc b/ogre2/src/Ogre2Visual.cc index 8a77bcfee..bbe16a7cb 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" #ifdef _MSC_VER 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 ) diff --git a/ogre2/src/media/materials/programs/depth_camera_fs.glsl b/ogre2/src/media/materials/programs/depth_camera_fs.glsl index 6163b43c3..a28babdb8 100644 --- a/ogre2/src/media/materials/programs/depth_camera_fs.glsl +++ b/ogre2/src/media/materials/programs/depth_camera_fs.glsl @@ -100,17 +100,17 @@ void main() // particle mask - color and depth vec4 particle = texture(particleTexture, inPs.uv0); float particleDepth = texture(particleDepthTexture, inPs.uv0).x; + float pd = projectionParams.y / (particleDepth - projectionParams.x); // return particle depth if it can be seen by the camera and not obstructed // by other objects in the camera view - if (particle.x > 0 && particleDepth < fDepth) + if (particle.x > 0 && pd < d) { // apply scatter effect so that only some of the smoke pixels are visible float r = rand(inPs.uv0 + vec2(time, time)); if (r < particleScatterRatio) { // set point to 3d pos of particle pixel - float pd = projectionParams.y / (particleDepth - projectionParams.x); vec3 particleViewSpacePos = inPs.cameraDir * pd; vec3 particlePoint = vec3(-particleViewSpacePos.z, -particleViewSpacePos.x, particleViewSpacePos.y); diff --git a/ogre2/src/media/materials/programs/gpu_rays_1st_pass_fs.glsl b/ogre2/src/media/materials/programs/gpu_rays_1st_pass_fs.glsl index 6911933bc..739e42364 100644 --- a/ogre2/src/media/materials/programs/gpu_rays_1st_pass_fs.glsl +++ b/ogre2/src/media/materials/programs/gpu_rays_1st_pass_fs.glsl @@ -87,15 +87,15 @@ void main() // particle mask - color and depth vec4 particle = texture(particleTexture, inPs.uv0); float particleDepth = texture(particleDepthTexture, inPs.uv0).x; + float pd = projectionParams.y / (particleDepth - projectionParams.x); // check if need to apply scatter effect - if (particle.x > 0.0 && particleDepth < fDepth) + if (particle.x > 0.0 && pd < d) { // apply scatter effect so that only some of the smoke pixels are visible float r = rand(inPs.uv0 + vec2(time, time)); if (r < particleScatterRatio) { - float pd = projectionParams.y / (particleDepth - projectionParams.x); vec3 point = inPs.cameraDir * pd; float rr = rand(inPs.uv0 + vec2(1.0/time, time)) - 0.5; diff --git a/src/base/BaseRenderEngine.cc b/src/base/BaseRenderEngine.cc index 5a0c26cca..0f61773b6 100644 --- a/src/base/BaseRenderEngine.cc +++ b/src/base/BaseRenderEngine.cc @@ -247,6 +247,18 @@ void BaseRenderEngine::AddResourcePath(const std::string &_path) this->resourcePaths.push_back(_path); } +////////////////////////////////////////////////// +void BaseRenderEngine::SetHeadless(bool _headless) +{ + this->isHeadless = _headless; +} + +////////////////////////////////////////////////// +bool BaseRenderEngine::Headless() const +{ + return this->isHeadless; +} + ////////////////////////////////////////////////// void BaseRenderEngine::PrepareScene(ScenePtr _scene) { diff --git a/test/integration/gpu_rays.cc b/test/integration/gpu_rays.cc index f0774b941..c2b2da25b 100644 --- a/test/integration/gpu_rays.cc +++ b/test/integration/gpu_rays.cc @@ -291,13 +291,13 @@ void GpuRaysTest::RaysUnitBox(const std::string &_renderEngine) // rays caster 1 should see box01 and box02 EXPECT_NEAR(scan[mid], expectedRangeAtMidPointBox1, LASER_TOL); EXPECT_NEAR(scan[0], expectedRangeAtMidPointBox2, LASER_TOL); - EXPECT_DOUBLE_EQ(scan[last], ignition::math::INF_D); + EXPECT_FLOAT_EQ(scan[last], ignition::math::INF_F); // rays cater should see box01 with laser retro value set to laserRetro1 // and box02 with laser retro value set to laserRetro2 EXPECT_NEAR(scan[mid+1], laserRetro1, 5.0); EXPECT_NEAR(scan[0+1], laserRetro2, 5.0); - EXPECT_DOUBLE_EQ(scan[last+1], 0.0); + EXPECT_FLOAT_EQ(scan[last+1], 0.0); // Verify rays caster 2 range readings // listen to new gpu rays frames @@ -308,9 +308,9 @@ void GpuRaysTest::RaysUnitBox(const std::string &_renderEngine) gpuRays2->Copy(scan2); // Only box01 should be visible to rays caster 2 - EXPECT_DOUBLE_EQ(scan2[0], maxRange); + EXPECT_FLOAT_EQ(scan2[0], maxRange); EXPECT_NEAR(scan2[mid], expectedRangeAtMidPointBox1, LASER_TOL); - EXPECT_DOUBLE_EQ(scan2[last], maxRange); + EXPECT_FLOAT_EQ(scan2[last], maxRange); // Move all boxes out of range visualBox1->SetWorldPosition( @@ -325,10 +325,10 @@ void GpuRaysTest::RaysUnitBox(const std::string &_renderEngine) gpuRays2->Copy(scan2); for (int i = 0; i < gpuRays->RayCount(); ++i) - EXPECT_DOUBLE_EQ(scan[i * 3], ignition::math::INF_D); + EXPECT_FLOAT_EQ(scan[i * 3], ignition::math::INF_F); for (int i = 0; i < gpuRays2->RayCount(); ++i) - EXPECT_DOUBLE_EQ(scan2[i * 3], maxRange); + EXPECT_FLOAT_EQ(scan2[i * 3], maxRange); c.reset(); @@ -442,10 +442,10 @@ void GpuRaysTest::LaserVertical(const std::string &_renderEngine) angleStep += vAngleStep; // check that the values in the extremes are infinity - EXPECT_DOUBLE_EQ(scan[i * hRayCount * channels], - ignition::math::INF_D); - EXPECT_DOUBLE_EQ(scan[(i * hRayCount + (hRayCount - 1)) * channels], - ignition::math::INF_D); + EXPECT_FLOAT_EQ(scan[i * hRayCount * channels], + ignition::math::INF_F); + EXPECT_FLOAT_EQ(scan[(i * hRayCount + (hRayCount - 1)) * channels], + ignition::math::INF_F); } // Move box out of range @@ -461,8 +461,8 @@ void GpuRaysTest::LaserVertical(const std::string &_renderEngine) { for (int i = 0; i < gpuRays->RayCount(); ++i) { - EXPECT_DOUBLE_EQ(scan[j * gpuRays->RayCount() * channels+ i * channels], - ignition::math::INF_D); + EXPECT_FLOAT_EQ(scan[j * gpuRays->RayCount() * channels+ i * channels], + ignition::math::INF_F); } } @@ -629,7 +629,7 @@ void GpuRaysTest::RaysParticles(const std::string &_renderEngine) EXPECT_NEAR(expectedRangeAtMidPointBox2, scan[0], LASER_TOL); // sensor should not see box03 as it is out of range - EXPECT_DOUBLE_EQ(ignition::math::INF_D, scan[last]); + EXPECT_DOUBLE_EQ(ignition::math::INF_F, scan[last]); } // there should be at least one hit @@ -667,7 +667,7 @@ void GpuRaysTest::RaysParticles(const std::string &_renderEngine) EXPECT_NEAR(expectedRangeAtMidPointBox2, scan[0], LASER_TOL); // sensor should not see box03 as it is out of range - EXPECT_DOUBLE_EQ(ignition::math::INF_D, scan[last]); + EXPECT_DOUBLE_EQ(ignition::math::INF_F, scan[last]); } // there should be at least one hit diff --git a/test/integration/lidar_visual.cc b/test/integration/lidar_visual.cc index 713c31dab..cc55a9470 100644 --- a/test/integration/lidar_visual.cc +++ b/test/integration/lidar_visual.cc @@ -100,22 +100,22 @@ void LidarVisualTest::Configure(const std::string &_renderEngine) // The following tests all the getters and setters { lidarVis->SetMinVerticalAngle(0.1); - EXPECT_NEAR(lidarVis->MinVerticalAngle(), 0.1, 1e-6); + EXPECT_DOUBLE_EQ(lidarVis->MinVerticalAngle(), 0.1); lidarVis->SetMaxVerticalAngle(251.20); - EXPECT_NEAR(lidarVis->MaxVerticalAngle(), 251.20, 1e-6); + EXPECT_DOUBLE_EQ(lidarVis->MaxVerticalAngle(), 251.20); lidarVis->SetMinRange(0.05); - EXPECT_NEAR(lidarVis->MinRange(), 0.05, 1e-6); + EXPECT_DOUBLE_EQ(lidarVis->MinRange(), 0.05); lidarVis->SetMaxRange(105.20); - EXPECT_NEAR(lidarVis->MaxRange(), 105.20, 1e-6); + EXPECT_DOUBLE_EQ(lidarVis->MaxRange(), 105.20); - lidarVis->SetMinHorizontalAngle(-1.513); - EXPECT_NEAR(lidarVis->MinHorizontalAngle(), -1.513, 1e-6); + lidarVis->SetMinHorizontalAngle(-1.5136); + EXPECT_DOUBLE_EQ(lidarVis->MinHorizontalAngle(), -1.5136); lidarVis->SetMaxHorizontalAngle(2.513); - EXPECT_NEAR(lidarVis->MaxHorizontalAngle(), 2.513, 1e-6); + EXPECT_DOUBLE_EQ(lidarVis->MaxHorizontalAngle(), 2.513); lidarVis->SetHorizontalRayCount(360); EXPECT_EQ(lidarVis->HorizontalRayCount(), 360u); @@ -319,7 +319,7 @@ void LidarVisualTest::RaysUnitBox(const std::string &_renderEngine) // rays caster values received from lidar should see box01 and box02 EXPECT_NEAR(pts_back[mid], expectedRangeAtMidPointBox1, LASER_TOL); EXPECT_NEAR(pts_back[0], expectedRangeAtMidPointBox2, LASER_TOL); - EXPECT_DOUBLE_EQ(pts_back[last], ignition::math::INF_D); + EXPECT_FLOAT_EQ(pts_back[last], ignition::math::INF_F); // Verify rays caster 2 range readings // listen to new gpu rays frames @@ -343,9 +343,9 @@ void LidarVisualTest::RaysUnitBox(const std::string &_renderEngine) std::vector pts_back2 = lidarVis2->Points(); // Only box01 should be visible to rays caster 2 - EXPECT_DOUBLE_EQ(pts_back2[0], maxRange); + EXPECT_FLOAT_EQ(pts_back2[0], maxRange); EXPECT_NEAR(pts_back2[mid], expectedRangeAtMidPointBox1, LASER_TOL); - EXPECT_DOUBLE_EQ(pts_back2[last], maxRange); + EXPECT_FLOAT_EQ(pts_back2[last], maxRange); // Move all boxes out of range visualBox1->SetWorldPosition( @@ -378,10 +378,10 @@ void LidarVisualTest::RaysUnitBox(const std::string &_renderEngine) } for (unsigned int i = 0; i < lidarVis->HorizontalRayCount(); ++i) - EXPECT_DOUBLE_EQ(pts[i], ignition::math::INF_D); + EXPECT_FLOAT_EQ(pts[i], ignition::math::INF_F); for (unsigned int i = 0; i < lidarVis->HorizontalRayCount(); ++i) - EXPECT_DOUBLE_EQ(pts2[i], maxRange); + EXPECT_FLOAT_EQ(pts2[i], maxRange); c.reset(); @@ -518,10 +518,10 @@ void LidarVisualTest::LaserVertical(const std::string &_renderEngine) angleStep += vAngleStep; // check that the values in the extremes are infinity - EXPECT_DOUBLE_EQ(pts[i * hRayCount ], - ignition::math::INF_D); - EXPECT_DOUBLE_EQ(pts[(i * hRayCount + (hRayCount - 1))], - ignition::math::INF_D); + EXPECT_FLOAT_EQ(pts[i * hRayCount ], + ignition::math::INF_F); + EXPECT_FLOAT_EQ(pts[(i * hRayCount + (hRayCount - 1))], + ignition::math::INF_F); } // Move box out of range @@ -548,8 +548,8 @@ void LidarVisualTest::LaserVertical(const std::string &_renderEngine) { for (unsigned int i = 0; i < lidarVis->HorizontalRayCount(); ++i) { - EXPECT_DOUBLE_EQ(pts[j * lidarVis->HorizontalRayCount()+ i], - ignition::math::INF_D); + EXPECT_FLOAT_EQ(pts[j * lidarVis->HorizontalRayCount()+ i], + ignition::math::INF_F); } }