From 353d7680f74c07f13c3b02a0df05869369240e14 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Tue, 21 Jun 2022 16:21:02 +0200 Subject: [PATCH 01/12] CastorViewer: Added a way to speed up the camera movement, using 'E' key. --- tools/CastorViewer/RenderPanel.cpp | 44 +++++++++++++++++++++------- tools/CastorViewer/RenderPanel.hpp | 6 ++-- tools/GuiCommon/System/NodeState.cpp | 10 +++++++ tools/GuiCommon/System/NodeState.hpp | 5 ++++ 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/tools/CastorViewer/RenderPanel.cpp b/tools/CastorViewer/RenderPanel.cpp index b596cbb848..c8711a45b5 100644 --- a/tools/CastorViewer/RenderPanel.cpp +++ b/tools/CastorViewer/RenderPanel.cpp @@ -391,6 +391,14 @@ namespace CastorViewer return *it->second; } + void RenderPanel::doUpdateMaxSpeed( float factor ) + { + for ( auto & nodeState : m_nodesStates ) + { + nodeState.second->multMaxSpeed( factor ); + } + } + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" BEGIN_EVENT_TABLE( RenderPanel, wxPanel ) @@ -408,9 +416,9 @@ namespace CastorViewer EVT_ENTER_WINDOW( RenderPanel::onEnterWindow ) EVT_LEAVE_WINDOW( RenderPanel::onLeaveWindow ) EVT_ERASE_BACKGROUND( RenderPanel::onEraseBackground ) - EVT_SET_FOCUS( RenderPanel::onsetFocus ) + EVT_SET_FOCUS( RenderPanel::onSetFocus ) EVT_KILL_FOCUS( RenderPanel::onKillFocus ) - EVT_KEY_DOWN( RenderPanel::onKeydown ) + EVT_KEY_DOWN( RenderPanel::onKeyDown ) EVT_KEY_UP( RenderPanel::onKeyUp ) EVT_CHAR( RenderPanel::onChar ) EVT_LEFT_DCLICK( RenderPanel::onMouseLDClick ) @@ -430,7 +438,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, 0.0f, m_camSpeed.value() } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, 0.0f, speed } ); } p_event.Skip(); @@ -440,7 +449,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, 0.0f, -m_camSpeed.value() } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, 0.0f, -speed } ); } p_event.Skip(); @@ -450,7 +460,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ m_camSpeed.value(), 0.0f, 0.0f } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ speed, 0.0f, 0.0f } ); } p_event.Skip(); @@ -460,7 +471,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ -m_camSpeed.value(), 0.0f, 0.0f } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ -speed, 0.0f, 0.0f } ); } p_event.Skip(); @@ -470,7 +482,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, m_camSpeed.value(), 0.0f } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, speed, 0.0f } ); } p_event.Skip(); @@ -480,7 +493,8 @@ namespace CastorViewer { if ( m_currentState ) { - m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, -m_camSpeed.value(), 0.0f } ); + auto speed = m_camSpeed.value() * ( m_extraSpeed ? 10.0f : 1.0f ); + m_currentState->addScalarVelocity( castor::Point3f{ 0.0f, -speed, 0.0f } ); } p_event.Skip(); @@ -537,7 +551,7 @@ namespace CastorViewer p_event.Skip(); } - void RenderPanel::onsetFocus( wxFocusEvent & p_event ) + void RenderPanel::onSetFocus( wxFocusEvent & p_event ) { p_event.Skip(); } @@ -548,7 +562,7 @@ namespace CastorViewer p_event.Skip(); } - void RenderPanel::onKeydown( wxKeyEvent & p_event ) + void RenderPanel::onKeyDown( wxKeyEvent & p_event ) { auto inputListener = wxGetApp().getCastor()->getUserInputListener(); @@ -588,6 +602,11 @@ namespace CastorViewer m_altdown = true; break; + case 'E': + m_extraSpeed = true; + doUpdateMaxSpeed( 10.0f ); + break; + case 'L': if ( m_lightsNode ) { @@ -661,6 +680,11 @@ namespace CastorViewer m_altdown = false; break; + case 'E': + m_extraSpeed = false; + doUpdateMaxSpeed( 0.1f ); + break; + case WXK_ESCAPE: if ( m_selectedGeometry ) { diff --git a/tools/CastorViewer/RenderPanel.hpp b/tools/CastorViewer/RenderPanel.hpp index 4ed4d2da5c..50d4f6597e 100644 --- a/tools/CastorViewer/RenderPanel.hpp +++ b/tools/CastorViewer/RenderPanel.hpp @@ -86,6 +86,7 @@ namespace CastorViewer , castor3d::SubmeshSPtr submesh ); GuiCommon::NodeState & doAddNodeState( castor3d::SceneNodeRPtr node , bool camera ); + void doUpdateMaxSpeed( float factor ); DECLARE_EVENT_TABLE() void onTimerFwd( wxTimerEvent & event ); @@ -102,9 +103,9 @@ namespace CastorViewer void onEnterWindow( wxMouseEvent & event ); void onLeaveWindow( wxMouseEvent & event ); void onEraseBackground( wxEraseEvent & event ); - void onsetFocus( wxFocusEvent & event ); + void onSetFocus( wxFocusEvent & event ); void onKillFocus( wxFocusEvent & event ); - void onKeydown( wxKeyEvent & event ); + void onKeyDown( wxKeyEvent & event ); void onChar( wxKeyEvent & event ); void onMouseLDClick( wxMouseEvent & event ); void onMouseLdown( wxMouseEvent & event ); @@ -127,6 +128,7 @@ namespace CastorViewer bool m_mouseRightDown{ false }; bool m_mouseMiddleDown{ false }; bool m_resizeWindow{ true }; + bool m_extraSpeed{ false }; std::atomic_bool m_movementStarted{ false }; std::array< wxTimer *, eTIMER_ID_COUNT > m_timers; castor3d::RenderWindowPtr m_renderWindow; diff --git a/tools/GuiCommon/System/NodeState.cpp b/tools/GuiCommon/System/NodeState.cpp index de4552585d..83d1ce4e8e 100644 --- a/tools/GuiCommon/System/NodeState.cpp +++ b/tools/GuiCommon/System/NodeState.cpp @@ -75,6 +75,16 @@ namespace GuiCommon m_scalarVelocityZ.updateRange( castor::makeRange( -speed, speed ) ); } + void NodeState::multMaxSpeed( float factor ) + { + auto range = m_scalarVelocityX.range(); + m_scalarVelocityX.updateRange( castor::makeRange( range.getMin() * factor, range.getMax() * factor ) ); + range = m_scalarVelocityY.range(); + m_scalarVelocityY.updateRange( castor::makeRange( range.getMin() * factor, range.getMax() * factor ) ); + range = m_scalarVelocityZ.range(); + m_scalarVelocityZ.updateRange( castor::makeRange( range.getMin() * factor, range.getMax() * factor ) ); + } + bool NodeState::update() { auto angles = m_angles; diff --git a/tools/GuiCommon/System/NodeState.hpp b/tools/GuiCommon/System/NodeState.hpp index 15688cf375..f818ba7f31 100644 --- a/tools/GuiCommon/System/NodeState.hpp +++ b/tools/GuiCommon/System/NodeState.hpp @@ -48,6 +48,11 @@ namespace GuiCommon void setMaxSpeed( float speed ); /** *\brief + * Multiplie la vitesse maximale par le facteur donné. + */ + void multMaxSpeed( float factor ); + /** + *\brief * Met à jour l'angle et le zoom en fonction des vitesses. *\return * \p true s'il y a eu du mouvement. From d13bdb5d706ffacad63dc4087ddaf13e320c280a Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Wed, 22 Jun 2022 11:07:54 +0200 Subject: [PATCH 02/12] Castor3D: Fixed background pass with env maps. --- .../EnvironmentMap/EnvironmentMapPass.hpp | 2 +- .../EnvironmentMap/EnvironmentMapPass.cpp | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.hpp b/include/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.hpp index 519c151462..be1cf842b8 100644 --- a/include/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.hpp +++ b/include/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.hpp @@ -120,9 +120,9 @@ namespace castor3d HdrConfigUbo m_hdrConfigUbo; SceneUbo m_sceneUbo; crg::ImageViewId m_colourView; - BackgroundRendererUPtr m_backgroundRenderer; crg::FramePass * m_opaquePassDesc{}; RenderTechniquePass * m_opaquePass{}; + BackgroundRendererUPtr m_backgroundRenderer; crg::FramePass * m_transparentPassDesc{}; RenderTechniquePass * m_transparentPass{}; }; diff --git a/source/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.cpp b/source/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.cpp index e2932b995e..6ec3620e91 100644 --- a/source/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.cpp +++ b/source/Core/Castor3D/Render/EnvironmentMap/EnvironmentMapPass.cpp @@ -69,8 +69,9 @@ namespace castor3d , m_hdrConfigUbo{ m_device } , m_sceneUbo{ m_device } , m_colourView{ environmentMap.getColourViewId( m_index, m_face ) } + , m_opaquePassDesc{ &doCreateOpaquePass( nullptr ) } , m_backgroundRenderer{ castor::makeUnique< BackgroundRenderer >( m_graph - , nullptr + , m_opaquePassDesc , m_device , getName() , m_background @@ -79,8 +80,7 @@ namespace castor3d , m_colourView , false , getOwner()->getDepthViewId( m_index, m_face ) ) } - , m_opaquePassDesc{ &doCreateOpaquePass( &m_backgroundRenderer->getPass() ) } - , m_transparentPassDesc{ &doCreateTransparentPass( m_opaquePassDesc ) } + , m_transparentPassDesc{ &doCreateTransparentPass( &m_backgroundRenderer->getPass() ) } { doCreateGenMipmapsPass( m_transparentPassDesc ); m_matrixUbo.cpuUpdate( m_camera->getView() @@ -159,8 +159,9 @@ namespace castor3d crg::FramePass & EnvironmentMapPass::doCreateOpaquePass( crg::FramePass const * previousPass ) { + auto depthView = getOwner()->getDepthViewId( m_index, m_face ); auto & result = m_graph.createPass( "OpaquePass" - , [this]( crg::FramePass const & framePass + , [this, depthView]( crg::FramePass const & framePass , crg::GraphContext & context , crg::RunnableGraph & graph ) { @@ -175,6 +176,10 @@ namespace castor3d , m_colourView.data->image.data , RenderNodesPassDesc{ getOwner()->getSize(), m_matrixUbo, *m_culler } .meshShading( true ) + .implicitAction( depthView + , crg::RecordContext::clearAttachment( depthView, defaultClearDepthStencil ) ) + .implicitAction( m_colourView + , crg::RecordContext::clearAttachment( m_colourView, transparentBlackClearColor ) ) , RenderTechniquePassDesc{ true, SsaoConfig{} } ); m_node->getScene()->getEngine()->registerTimer( framePass.getFullName() , res->getTimer() ); @@ -187,9 +192,10 @@ namespace castor3d result.addDependency( *previousPass ); } - result.addOutputDepthView( getOwner()->getDepthViewId( m_index, m_face ) + result.addOutputDepthView( depthView , defaultClearDepthStencil ); - result.addInOutColourView( m_colourView ); + result.addOutputColourView( m_colourView + , transparentBlackClearColor ); return result; } From 5249f5fc5bb7c21a6cd09a3be52a05058c174b73 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Wed, 22 Jun 2022 13:00:48 +0200 Subject: [PATCH 03/12] Castor3D: Modified lighting model to support background model. --- .../Pass/PBR/Shaders/GlslPbrLighting.hpp | 23 +- .../Pass/Phong/Shaders/GlslPhongLighting.hpp | 29 +- .../Technique/Opaque/Lighting/LightPass.hpp | 3 +- .../Opaque/Lighting/LightingModule.hpp | 2 +- .../Opaque/Lighting/LightsPipeline.hpp | 8 +- .../Opaque/Lighting/RunnableLightingPass.hpp | 4 +- .../Render/Technique/Opaque/LightingPass.hpp | 2 + .../Castor3D/Scene/Background/Background.hpp | 5 + include/Core/Castor3D/Scene/Scene.hpp | 14 + .../Shader/Shaders/GlslCookTorranceBRDF.hpp | 12 +- .../Castor3D/Shader/Shaders/GlslLighting.hpp | 27 +- .../Castor3D/Shader/Shaders/SdwModule.hpp | 2 + .../Pass/PBR/Shaders/GlslPbrLighting.cpp | 927 ++++---- .../Pass/Phong/Shaders/GlslPhongLighting.cpp | 1065 +++++---- .../Technique/ForwardRenderTechniquePass.cpp | 7 +- .../Technique/Opaque/DeferredRendering.cpp | 1 + .../Technique/Opaque/Lighting/LightPass.cpp | 18 +- .../Opaque/Lighting/LightsPipeline.cpp | 18 +- .../Opaque/Lighting/RunnableLightingPass.cpp | 10 +- .../Render/Technique/Opaque/LightingPass.cpp | 5 +- .../Technique/Transparent/TransparentPass.cpp | 3 +- source/Core/Castor3D/Scene/Scene.cpp | 28 +- source/Core/Castor3D/Shader/ShaderModule.cpp | 8 + .../Shader/Shaders/GlslCookTorranceBRDF.cpp | 37 +- .../Castor3D/Shader/Shaders/GlslLighting.cpp | 53 +- .../FFTOceanRendering/OceanFFTRenderPass.cpp | 5 +- .../OceanRendering/OceanRenderPass.cpp | 3 +- .../ToonMaterial/Shaders/GlslToonLighting.cpp | 1928 ++++++++--------- .../ToonMaterial/Shaders/GlslToonLighting.hpp | 48 +- .../WaterRendering/WaterRenderPass.cpp | 3 +- 30 files changed, 2149 insertions(+), 2149 deletions(-) diff --git a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp index 2b42bb3566..5090f899a1 100644 --- a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp @@ -53,21 +53,22 @@ namespace castor3d::shader C3D_API void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface + , BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void compute( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void compute( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void computeMapContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -99,17 +100,17 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API sdw::Vec3 computeDiffuse( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API sdw::Vec3 computeDiffuse( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API void computeMapDiffuseContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -127,16 +128,6 @@ namespace castor3d::shader , LightMaterial & lightMat )override; //\} - protected: - void doDeclareModel()override; - void doDeclareComputeDirectionalLight()override; - void doDeclareComputePointLight()override; - void doDeclareComputeSpotLight()override; - void doDeclareDiffuseModel()override; - void doDeclareComputeDirectionalLightDiffuse()override; - void doDeclareComputePointLightDiffuse()override; - void doDeclareComputeSpotLightDiffuse()override; - public: CookTorranceBRDF m_cookTorrance; sdw::Function< sdw::Void diff --git a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp index 93b291bbec..f6d40f991a 100644 --- a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp @@ -49,21 +49,22 @@ namespace castor3d::shader C3D_API void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface + , BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void compute( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void compute( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const override; + , OutputComponents & output )override; C3D_API void computeMapContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -95,17 +96,17 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API sdw::Vec3 computeDiffuse( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API sdw::Vec3 computeDiffuse( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; C3D_API void computeMapDiffuseContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -129,29 +130,17 @@ namespace castor3d::shader } protected: - void doDeclareModel()override; - void doDeclareComputeDirectionalLight()override; - void doDeclareComputePointLight()override; - void doDeclareComputeSpotLight()override; - void doDeclareDiffuseModel()override; - void doDeclareComputeDirectionalLightDiffuse()override; - void doDeclareComputePointLightDiffuse()override; - void doDeclareComputeSpotLightDiffuse()override; - - private: - sdw::RetVec3 doComputeLight( Light const & light + C3D_API sdw::RetVec3 doComputeLight( Light const & light , PhongLightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Vec3 const & lightDirection , OutputComponents & output ); - void doDeclareComputeLight(); - sdw::Vec3 doComputeLightDiffuse( Light const & light + C3D_API sdw::Vec3 doComputeLightDiffuse( Light const & light , PhongLightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Vec3 const & lightDirection ); - void doDeclareComputeLightDiffuse(); public: C3D_API static castor::String getName(); diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp index 2dfccdef72..89a47b1e40 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp @@ -44,8 +44,7 @@ namespace castor3d *\param[in] shadows Dit si les ombres sont utilisées. *\return Le source. */ - static ShaderPtr getPixelShaderSource( PassTypeID passType - , RenderSystem const & renderSystem + static ShaderPtr getPixelShaderSource( Scene const & scene , SceneFlags const & sceneFlags , LightType lightType , ShadowType shadowType diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp index 5571868136..0ae50d9e28 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp @@ -43,7 +43,6 @@ namespace castor3d eData2, eData3, eData4, - eData5, }; /** *\~english @@ -61,6 +60,7 @@ namespace castor3d eModelMatrix, eSmLinear, eSmVariance, + eCount, }; /** *\~english diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.hpp index 66245a4eb8..2f69e42583 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.hpp @@ -18,7 +18,8 @@ namespace castor3d { struct LightsPipeline { - LightsPipeline( crg::FramePass const & pass + LightsPipeline( Scene const & scene + , crg::FramePass const & pass , crg::GraphContext & context , crg::RunnableGraph & graph , RenderDevice const & device @@ -26,7 +27,8 @@ namespace castor3d , LightPassResult const & lpResult , ShadowMapResult const & smResult , std::vector< LightRenderPass > const & renderPasses - , std::vector< LightRenderPass > const & stencilRenderPasses ); + , std::vector< LightRenderPass > const & stencilRenderPasses + , crg::ImageId const & targetColourResult ); void clear(); void addLight( Camera const & camera @@ -87,6 +89,7 @@ namespace castor3d ShadowMapResult const & m_smResult; RenderDevice const & m_device; std::vector< LightRenderPass > const & m_renderPasses; + Scene const & m_scene; LightPipelineConfig m_config; ShaderModule m_vertexShader; ShaderModule m_pixelShader; @@ -101,6 +104,7 @@ namespace castor3d std::map< size_t, std::unique_ptr< LightDescriptors > > m_lightDescriptors; std::vector< LightDescriptors const * > m_enabledLights; Viewport m_viewport; + crg::ImageId m_targetColourResult; }; using LightsPipelinePtr = std::unique_ptr< LightsPipeline >; diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.hpp index fe3a430104..9417260272 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.hpp @@ -23,7 +23,8 @@ namespace castor3d , LightPassResult const & lpResult , ShadowMapResult const & smDirectionalResult , ShadowMapResult const & smPointResult - , ShadowMapResult const & smSpotResult ); + , ShadowMapResult const & smSpotResult + , crg::ImageId const & targetColourResult ); void clear(); void enableLight( Camera const & camera @@ -55,6 +56,7 @@ namespace castor3d ShadowMapResult const & m_smDirectionalResult; ShadowMapResult const & m_smPointResult; ShadowMapResult const & m_smSpotResult; + crg::ImageId const & m_targetColourResult; std::vector< LightRenderPass > m_renderPasses; std::vector< LightRenderPass > m_stencilRenderPasses; std::map< size_t, LightsPipelinePtr > m_pipelines; diff --git a/include/Core/Castor3D/Render/Technique/Opaque/LightingPass.hpp b/include/Core/Castor3D/Render/Technique/Opaque/LightingPass.hpp index e2cc502be5..b1594ca0ca 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/LightingPass.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/LightingPass.hpp @@ -61,6 +61,7 @@ namespace castor3d , ShadowMapResult const & smPointResult , ShadowMapResult const & smSpotResult , LightPassResult const & lpResult + , crg::ImageId const & targetColourResult , SceneUbo const & sceneUbo , GpInfoUbo const & gpInfoUbo ); /** @@ -111,6 +112,7 @@ namespace castor3d ShadowMapResult const & m_smPointResult; ShadowMapResult const & m_smSpotResult; LightPassResult const & m_lpResult; + crg::ImageId const & m_targetColourResult; SceneUbo const & m_sceneUbo; GpInfoUbo const & m_gpInfoUbo; crg::FramePassGroup & m_group; diff --git a/include/Core/Castor3D/Scene/Background/Background.hpp b/include/Core/Castor3D/Scene/Background/Background.hpp index e9ab395469..ca279f453a 100644 --- a/include/Core/Castor3D/Scene/Background/Background.hpp +++ b/include/Core/Castor3D/Scene/Background/Background.hpp @@ -284,6 +284,11 @@ namespace castor3d return false; } + virtual bool hasScattering()const + { + return false; + } + Scene const & getScene()const { return m_scene; diff --git a/include/Core/Castor3D/Scene/Scene.hpp b/include/Core/Castor3D/Scene/Scene.hpp index 20ead0ab09..4bd3d69acf 100644 --- a/include/Core/Castor3D/Scene/Scene.hpp +++ b/include/Core/Castor3D/Scene/Scene.hpp @@ -220,6 +220,20 @@ namespace castor3d *\return Le nom du modèle de fond. */ C3D_API castor::String const & getBackgroundModel()const; + /** + *\~english + *\return The lighting model name. + *\~french + *\return Le nom du modèle d'éclairage. + */ + C3D_API castor::String getLightingModel( LightType lightType )const; + /** + *\~english + *\return The lighting model name. + *\~french + *\return Le nom du modèle d'éclairage. + */ + C3D_API castor::String getLightingModel()const; /** *\~english *\brief Creates an animated texture and adds it to animated textures group. diff --git a/include/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.hpp b/include/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.hpp index f4cf3e26df..1d6642b78f 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.hpp @@ -21,6 +21,15 @@ namespace castor3d::shader , sdw::Float const & roughness , Surface surface , OutputComponents & output ); + C3D_API sdw::RetVec3 compute( sdw::Vec3 const & radiance + , sdw::Vec2 const & intensity + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & direction + , sdw::Vec3 const & specular + , sdw::Float const & metalness + , sdw::Float const & roughness + , Surface surface + , OutputComponents & output ); C3D_API void computeAON( Light const & light , sdw::Vec3 const & worldEye , sdw::Vec3 const & direction @@ -84,7 +93,8 @@ namespace castor3d::shader , sdw::InVec3 , sdw::InFloat > m_smith; sdw::Function< sdw::Vec3 - , InLight + , sdw::InVec3 + , sdw::InVec2 , sdw::InVec3 , sdw::InVec3 , sdw::InVec3 diff --git a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp index fee3f7509a..3116bbf6ab 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp @@ -122,10 +122,11 @@ namespace castor3d::shader , uint32_t shadowMapSet ); C3D_API void computeCombined( LightMaterial const & material , SceneData const & sceneData + , BackgroundModel const & background , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const; + , OutputComponents & output ); C3D_API static LightingModelPtr createModel( Utils & utils , castor::String const & name , uint32_t lightsBufBinding @@ -193,7 +194,7 @@ namespace castor3d::shader , SceneData const & sceneData , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const; + , sdw::Int const & receivesShadows ); C3D_API static LightingModelPtr createDiffuseModel( Utils & utils , castor::String const & name , uint32_t lightsBufBinding @@ -251,21 +252,22 @@ namespace castor3d::shader C3D_API virtual void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface + , BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const = 0; + , OutputComponents & output ) = 0; C3D_API virtual void compute( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const = 0; + , OutputComponents & output ) = 0; C3D_API virtual void compute( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & output )const = 0; + , OutputComponents & output ) = 0; C3D_API virtual void computeMapContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -297,17 +299,17 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const = 0; + , sdw::Int const & receivesShadows ) = 0; C3D_API virtual sdw::Vec3 computeDiffuse( PointLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const = 0; + , sdw::Int const & receivesShadows ) = 0; C3D_API virtual sdw::Vec3 computeDiffuse( SpotLight const & light , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const = 0; + , sdw::Int const & receivesShadows ) = 0; C3D_API virtual void computeMapDiffuseContributions( PassFlags const & passFlags , TextureFlagsArray const & textures , TextureConfigurations const & textureConfigs @@ -356,15 +358,6 @@ namespace castor3d::shader C3D_API void doDeclareGetSpotLight(); C3D_API void doDeclareGetCascadeFactors(); - virtual void doDeclareModel() = 0; - virtual void doDeclareComputeDirectionalLight() = 0; - virtual void doDeclareComputePointLight() = 0; - virtual void doDeclareComputeSpotLight() = 0; - virtual void doDeclareDiffuseModel() = 0; - virtual void doDeclareComputeDirectionalLightDiffuse() = 0; - virtual void doDeclareComputePointLightDiffuse() = 0; - virtual void doDeclareComputeSpotLightDiffuse() = 0; - private: C3D_API static LightingModelPtr createModel( Utils & utils , castor::String const & name diff --git a/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp b/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp index 10066c9904..83f9eccc32 100644 --- a/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp +++ b/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp @@ -171,6 +171,8 @@ namespace castor3d::shader C3D_API uint32_t getPointShadowMapCount(); C3D_API uint32_t getBaseLightComponentsCount(); C3D_API uint32_t getMaxLightComponentsCount(); + C3D_API castor::String concatModelNames( castor::String lhs + , castor::String rhs ); //@} //@} diff --git a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp index 96a9896191..7aba77f8a6 100644 --- a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp @@ -143,10 +143,148 @@ namespace castor3d::shader void PbrLightingModel::compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface + , BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computeDirectional ) + { + OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( DirectionalLight const & light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( -light.direction ) ); + m_cookTorrance.compute( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , surface + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + auto maxCount = m_writer.declLocale( "maxCount" + , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF ( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , -lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , -lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + + if ( m_enableVolumetric ) + { + IF( m_writer, light.base.volumetricSteps != 0_u ) + { + m_shadowModel->computeVolumetric( light.base + , surface + , worldEye + , light.transforms[cascadeIndex] + , light.direction + , cascadeIndex + , light.cascadeCount + , output ); + } + FI; + } + +#if C3D_DebugCascades + IF( m_writer, cascadeIndex == 0_u ) + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + } + ELSEIF( cascadeIndex == 1_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + } + ELSEIF( cascadeIndex == 2_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + } + ELSE + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + } + FI; +#endif + } + FI; + } + + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , InDirectionalLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeDirectional( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -160,8 +298,68 @@ namespace castor3d::shader , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computePoint ) + { + OutputComponents outputs{ m_writer }; + m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" + , [this]( PointLight const & light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto vertexToLight = m_writer.declLocale( "vertexToLight" + , light.position - surface.worldPosition ); + auto distance = m_writer.declLocale( "distance" + , length( vertexToLight ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( vertexToLight ) ); + m_cookTorrance.compute( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , surface + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) + && ( light.base.index >= 0_i ) + && ( receivesShadows != 0_i ) ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + output.m_diffuse = output.m_diffuse / attenuation; + output.m_specular = output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , InPointLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computePoint( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -175,8 +373,97 @@ namespace castor3d::shader , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computeSpot ) + { + OutputComponents outputs{ m_writer }; + m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" + , [this]( SpotLight const & light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + auto vertexToLight = m_writer.declLocale( "vertexToLight" + , light.position - surface.worldPosition ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( vertexToLight ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, -light.direction ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( vertexToLight ) ); + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto rawDiffuse = m_writer.declLocale( "rawDiffuse" + , m_cookTorrance.compute( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , surface + , output ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) + && ( light.base.index >= 0_i ) + && ( receivesShadows != 0_i ) ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , -vertexToLight ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + output.m_diffuse = spotFactor * output.m_diffuse / attenuation; + +#if !C3D_DisableSSSTransmittance + if ( m_shadowModel->isEnabled() && m_sssTransmittance ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) + && ( light.base.index >= 0_i ) + && ( receivesShadows != 0_i ) + && ( material.sssProfileIndex != 0.0_f ) ) + { + output.m_diffuse += ( spotFactor * rawDiffuse / attenuation ) + * m_sssTransmittance->compute( material + , light + , surface ); + } + FI; + } +#endif + + output.m_specular = spotFactor * output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + FI; + } + , InSpotLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeSpot( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -277,8 +564,60 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeDirectionalDiffuse ) + { + m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" + , [this]( DirectionalLight light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( -light.direction ) ); + diffuse = m_cookTorrance.computeDiffuse( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , surface ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , light.cascadeCount - 1_u ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , -lightDirection + , cascadeIndex + , light.cascadeCount ) ); + diffuse *= shadowFactor; + } + FI; + } + + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); + } + , InOutDirectionalLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeDirectionalDiffuse( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -290,8 +629,60 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computePointDiffuse ) + { + m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" + , [this]( PointLight light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + diffuse = m_cookTorrance.computeDiffuse( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , surface ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); + } + , InOutPointLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computePointDiffuse( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -303,8 +694,71 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeSpotDiffuse ) + { + m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" + , [this]( SpotLight light + , PbrLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, -light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + diffuse = m_cookTorrance.computeDiffuse( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , surface ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , -lightToVertex ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); + } + FI; + + m_writer.returnStmt( diffuse ); + } + , InOutSpotLight( m_writer, "light" ) + , InPbrLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeSpotDiffuse( light , static_cast< PbrLightMaterial const & >( material ) , surface @@ -387,466 +841,5 @@ namespace castor3d::shader , emissive ); } - void PbrLightingModel::doDeclareModel() - { - } - - void PbrLightingModel::doDeclareComputeDirectionalLight() - { - OutputComponents outputs{ m_writer }; - m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" - , [this]( DirectionalLight const & light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( -light.direction ) ); - m_cookTorrance.compute( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , surface - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) ) - { - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , 0_u ); - auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); - auto maxCount = m_writer.declLocale( "maxCount" - , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); - - // Get cascade index for the current fragment's view position - FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) - { - auto factors = m_writer.declLocale( "factors" - , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } - , light.splitDepths - , i ) ); - - IF( m_writer, factors.x() != 0.0_f ) - { - cascadeFactors = factors; - } - FI; - } - ROF; - - cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); - - IF ( m_writer, receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , cascadeFactors.y() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , -lightDirection - , cascadeIndex - , light.cascadeCount ) ); - - IF( m_writer, cascadeIndex > 0_u ) - { - shadowFactor += cascadeFactors.z() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex - 1u] - , -lightDirection - , cascadeIndex - 1u - , light.cascadeCount ); - } - FI; - - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - - if ( m_enableVolumetric ) - { - IF( m_writer, light.base.volumetricSteps != 0_u ) - { - m_shadowModel->computeVolumetric( light.base - , surface - , worldEye - , light.transforms[cascadeIndex] - , light.direction - , cascadeIndex - , light.cascadeCount - , output ); - } - FI; - } - -#if C3D_DebugCascades - IF( m_writer, cascadeIndex == 0_u ) - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - } - ELSEIF( cascadeIndex == 1_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - } - ELSEIF( cascadeIndex == 2_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - } - ELSE - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - } - FI; -#endif - } - FI; - } - - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , InDirectionalLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PbrLightingModel::doDeclareComputePointLight() - { - OutputComponents outputs{ m_writer }; - m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" - , [this]( PointLight const & light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto vertexToLight = m_writer.declLocale( "vertexToLight" - , light.position - surface.worldPosition ); - auto distance = m_writer.declLocale( "distance" - , length( vertexToLight ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( vertexToLight ) ); - m_cookTorrance.compute( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , surface - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) - && ( light.base.index >= 0_i ) - && ( receivesShadows != 0_i ) ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - output.m_diffuse = output.m_diffuse / attenuation; - output.m_specular = output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , InPointLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PbrLightingModel::doDeclareComputeSpotLight() - { - OutputComponents outputs{ m_writer }; - m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" - , [this]( SpotLight const & light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - auto vertexToLight = m_writer.declLocale( "vertexToLight" - , light.position - surface.worldPosition ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( vertexToLight ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, -light.direction ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( vertexToLight ) ); - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto rawDiffuse = m_writer.declLocale( "rawDiffuse" - , m_cookTorrance.compute( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , surface - , output ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) - && ( light.base.index >= 0_i ) - && ( receivesShadows != 0_i ) ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , -vertexToLight ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - output.m_diffuse = spotFactor * output.m_diffuse / attenuation; - -#if !C3D_DisableSSSTransmittance - if ( m_shadowModel->isEnabled() && m_sssTransmittance ) - { - IF( m_writer - , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) - && ( light.base.index >= 0_i ) - && ( receivesShadows != 0_i ) - && ( material.sssProfileIndex != 0.0_f ) ) - { - output.m_diffuse += ( spotFactor * rawDiffuse / attenuation ) - * m_sssTransmittance->compute( material - , light - , surface ); - } - FI; - } -#endif - - output.m_specular = spotFactor * output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - FI; - } - , InSpotLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PbrLightingModel::doDeclareDiffuseModel() - { - } - - void PbrLightingModel::doDeclareComputeDirectionalLightDiffuse() - { - m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" - , [this]( DirectionalLight light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( -light.direction ) ); - diffuse = m_cookTorrance.computeDiffuse( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , surface ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , light.cascadeCount - 1_u ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , -lightDirection - , cascadeIndex - , light.cascadeCount ) ); - diffuse *= shadowFactor; - } - FI; - } - - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); - } - , InOutDirectionalLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void PbrLightingModel::doDeclareComputePointLightDiffuse() - { - m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" - , [this]( PointLight light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - diffuse = m_cookTorrance.computeDiffuse( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , surface ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); - } - , InOutPointLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void PbrLightingModel::doDeclareComputeSpotLightDiffuse() - { - m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" - , [this]( SpotLight light - , PbrLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, -light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - diffuse = m_cookTorrance.computeDiffuse( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , surface ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , -lightToVertex ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); - } - FI; - - m_writer.returnStmt( diffuse ); - } - , InOutSpotLight( m_writer, "light" ) - , InPbrLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - //*********************************************************************************************** } diff --git a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp index 94f2738ed5..8f8528ad9d 100644 --- a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp @@ -124,10 +124,146 @@ namespace castor3d::shader void PhongLightingModel::compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface + , BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computeDirectional ) + { + OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( DirectionalLight const & light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( light.direction ) ); + doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + auto maxCount = m_writer.declLocale( "maxCount" + , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + + if ( m_enableVolumetric ) + { + IF( m_writer, light.base.volumetricSteps != 0_u ) + { + m_shadowModel->computeVolumetric( light.base + , surface + , worldEye + , light.transforms[cascadeIndex] + , light.direction + , cascadeIndex + , light.cascadeCount + , output ); + } + FI; + } + +#if C3D_DebugCascades + IF( m_writer, cascadeIndex == 0_u ) + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + } + ELSEIF( cascadeIndex == 1_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + } + ELSEIF( cascadeIndex == 2_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + } + ELSE + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + } + FI; +#endif + } + FI; + } + + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , InDirectionalLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeDirectional( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -141,8 +277,66 @@ namespace castor3d::shader , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computePoint ) + { + OutputComponents outputs{ m_writer }; + m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" + , [this]( PointLight const & light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + output.m_diffuse = output.m_diffuse / attenuation; + output.m_specular = output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , InPointLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computePoint( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -156,8 +350,95 @@ namespace castor3d::shader , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { + if ( !m_computeSpot ) + { + OutputComponents outputs{ m_writer }; + m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" + , [this]( SpotLight const & light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , OutputComponents & parentOutput ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, light.direction ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distLightToVertex" + , length( lightToVertex ) ); + OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto rawDiffuse = m_writer.declLocale( "rawDiffuse" + , doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , lightToVertex ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + output.m_diffuse = spotFactor * output.m_diffuse / attenuation; + +#if !C3D_DisableSSSTransmittance + if ( m_shadowModel->isEnabled() && m_sssTransmittance ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) + && ( light.base.index >= 0_i ) + && ( receivesShadows != 0_i ) + && ( material.sssProfileIndex != 0.0_f ) ) + { + output.m_diffuse += ( spotFactor * rawDiffuse / attenuation ) + * m_sssTransmittance->compute( material + , light + , surface ); + } + FI; + } +#endif + + output.m_specular = spotFactor * output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + FI; + } + , InSpotLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeSpot( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -258,8 +539,56 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeDirectionalDiffuse ) + { + m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" + , [this]( DirectionalLight light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , light.cascadeCount - 1_u ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , lightDirection + , cascadeIndex + , light.cascadeCount ) ); + diffuse *= shadowFactor; + } + FI; + } + + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); + } + , InOutDirectionalLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeDirectionalDiffuse( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -271,8 +600,58 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computePointDiffuse ) + { + m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" + , [this]( PointLight light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); + } + , InOutPointLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computePointDiffuse( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -284,8 +663,70 @@ namespace castor3d::shader , LightMaterial const & material , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeSpotDiffuse ) + { + m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" + , [this]( SpotLight light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + diffuse = doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , lightToVertex ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); + } + FI; + + m_writer.returnStmt( diffuse ); + } + , InOutSpotLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeSpotDiffuse( light , static_cast< PhongLightMaterial const & >( material ) , surface @@ -368,349 +809,6 @@ namespace castor3d::shader , emissive ); } - void PhongLightingModel::doDeclareModel() - { - doDeclareComputeLight(); - } - - void PhongLightingModel::doDeclareComputeDirectionalLight() - { - OutputComponents outputs{ m_writer }; - m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" - , [this]( DirectionalLight const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( light.direction ) ); - doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) - { - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , 0_u ); - auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); - auto maxCount = m_writer.declLocale( "maxCount" - , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); - - // Get cascade index for the current fragment's view position - FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) - { - auto factors = m_writer.declLocale( "factors" - , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } - , light.splitDepths - , i ) ); - - IF( m_writer, factors.x() != 0.0_f ) - { - cascadeFactors = factors; - } - FI; - } - ROF; - - cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); - - IF( m_writer, receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , cascadeFactors.y() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , lightDirection - , cascadeIndex - , light.cascadeCount ) ); - - IF( m_writer, cascadeIndex > 0_u ) - { - shadowFactor += cascadeFactors.z() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex - 1u] - , lightDirection - , cascadeIndex - 1u - , light.cascadeCount ); - } - FI; - - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - - if ( m_enableVolumetric ) - { - IF( m_writer, light.base.volumetricSteps != 0_u ) - { - m_shadowModel->computeVolumetric( light.base - , surface - , worldEye - , light.transforms[cascadeIndex] - , light.direction - , cascadeIndex - , light.cascadeCount - , output ); - } - FI; - } - -#if C3D_DebugCascades - IF( m_writer, cascadeIndex == 0_u ) - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - } - ELSEIF( cascadeIndex == 1_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - } - ELSEIF( cascadeIndex == 2_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - } - ELSE - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - } - FI; -#endif - } - FI; - } - - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , InDirectionalLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PhongLightingModel::doDeclareComputePointLight() - { - OutputComponents outputs{ m_writer }; - m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" - , [this]( PointLight const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - output.m_diffuse = output.m_diffuse / attenuation; - output.m_specular = output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , InPointLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PhongLightingModel::doDeclareComputeSpotLight() - { - OutputComponents outputs{ m_writer }; - m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" - , [this]( SpotLight const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, light.direction ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distLightToVertex" - , length( lightToVertex ) ); - OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto rawDiffuse = m_writer.declLocale( "rawDiffuse" - , doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , lightToVertex ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - output.m_diffuse = spotFactor * output.m_diffuse / attenuation; - -#if !C3D_DisableSSSTransmittance - if ( m_shadowModel->isEnabled() && m_sssTransmittance ) - { - IF( m_writer - , ( light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) ) - && ( light.base.index >= 0_i ) - && ( receivesShadows != 0_i ) - && ( material.sssProfileIndex != 0.0_f ) ) - { - output.m_diffuse += ( spotFactor * rawDiffuse / attenuation ) - * m_sssTransmittance->compute( material - , light - , surface ); - } - FI; - } -#endif - - output.m_specular = spotFactor * output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - FI; - } - , InSpotLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void PhongLightingModel::doDeclareComputeLight() - { - OutputComponents outputs{ m_writer }; - m_computeLight = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" - , [this]( Light const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection - , OutputComponents & output ) - { - // Diffuse term. - auto diffuseFactor = m_writer.declLocale( "diffuseFactor" - , dot( surface.worldNormal, -lightDirection ) ); - auto isLit = m_writer.declLocale( "isLit" - , 1.0_f - step( diffuseFactor, 0.0_f ) ); - auto result = m_writer.declLocale( "result" - , light.colour - * light.intensity.x() ); - output.m_diffuse = isLit - * result - * diffuseFactor; - - // Specular term. - auto vertexToEye = m_writer.declLocale( "vertexToEye" - , normalize( worldEye - surface.worldPosition ) ); - - if ( m_isBlinnPhong ) - { - auto halfwayDir = m_writer.declLocale( "halfwayDir" - , normalize( vertexToEye - lightDirection ) ); - m_writer.declLocale( "specularFactor" - , max( dot( surface.worldNormal, halfwayDir ), 0.0_f ) ); - } - else - { - auto lightReflect = m_writer.declLocale( "lightReflect" - , normalize( reflect( lightDirection, surface.worldNormal ) ) ); - m_writer.declLocale( "specularFactor" - , max( dot( vertexToEye, lightReflect ), 0.0_f ) ); - } - - auto specularFactor = m_writer.getVariable< sdw::Float >( "specularFactor" ); - output.m_specular = isLit - * light.colour - * light.intensity.y() - * pow( specularFactor, clamp( material.shininess, 1.0_f, 256.0_f ) ); - - m_writer.returnStmt( result ); - } - , InLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InVec3( m_writer, "lightDirection" ) - , outputs ); - } - sdw::RetVec3 PhongLightingModel::doComputeLight( Light const & light , PhongLightMaterial const & material , Surface const & surface @@ -718,203 +816,70 @@ namespace castor3d::shader , sdw::Vec3 const & lightDirection , OutputComponents & parentOutput ) { - return m_computeLight( light - , material - , surface - , worldEye - , lightDirection - , parentOutput ); - } - - void PhongLightingModel::doDeclareDiffuseModel() - { - doDeclareComputeLightDiffuse(); - } - - void PhongLightingModel::doDeclareComputeDirectionalLightDiffuse() - { - m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" - , [this]( DirectionalLight light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ) ); - - if ( m_shadowModel->isEnabled() ) + if ( !m_computeLight ) + { + OutputComponents outputs{ m_writer }; + m_computeLight = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" + , [this]( Light const & light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection + , OutputComponents & output ) { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && receivesShadows != 0_i ) + // Diffuse term. + auto diffuseFactor = m_writer.declLocale( "diffuseFactor" + , dot( surface.worldNormal, -lightDirection ) ); + auto isLit = m_writer.declLocale( "isLit" + , 1.0_f - step( diffuseFactor, 0.0_f ) ); + auto result = m_writer.declLocale( "result" + , light.colour + * light.intensity.x() ); + output.m_diffuse = isLit + * result + * diffuseFactor; + + // Specular term. + auto vertexToEye = m_writer.declLocale( "vertexToEye" + , normalize( worldEye - surface.worldPosition ) ); + + if ( m_isBlinnPhong ) { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , light.cascadeCount - 1_u ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , lightDirection - , cascadeIndex - , light.cascadeCount ) ); - diffuse *= shadowFactor; + auto halfwayDir = m_writer.declLocale( "halfwayDir" + , normalize( vertexToEye - lightDirection ) ); + m_writer.declLocale( "specularFactor" + , max( dot( surface.worldNormal, halfwayDir ), 0.0_f ) ); } - FI; - } - - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); - } - , InOutDirectionalLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void PhongLightingModel::doDeclareComputePointLightDiffuse() - { - m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" - , [this]( PointLight light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) + else { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - diffuse *= shadowFactor; + auto lightReflect = m_writer.declLocale( "lightReflect" + , normalize( reflect( lightDirection, surface.worldNormal ) ) ); + m_writer.declLocale( "specularFactor" + , max( dot( vertexToEye, lightReflect ), 0.0_f ) ); } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); - } - , InOutPointLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void PhongLightingModel::doDeclareComputeSpotLightDiffuse() - { - m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" - , [this]( SpotLight light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - diffuse = doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ); - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , lightToVertex ) ); - diffuse *= shadowFactor; - } - FI; - } + auto specularFactor = m_writer.getVariable< sdw::Float >( "specularFactor" ); + output.m_specular = isLit + * light.colour + * light.intensity.y() + * pow( specularFactor, clamp( material.shininess, 1.0_f, 256.0_f ) ); - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); + m_writer.returnStmt( result ); } - FI; - - m_writer.returnStmt( diffuse ); - } - , InOutSpotLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } + , InLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InVec3( m_writer, "lightDirection" ) + , outputs ); + } - void PhongLightingModel::doDeclareComputeLightDiffuse() - { - m_computeLightDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" - , [this]( Light const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection ) - { - // Diffuse term. - auto diffuseFactor = m_writer.declLocale( "diffuseFactor" - , dot( surface.worldNormal, -lightDirection ) ); - auto isLit = m_writer.declLocale( "isLit" - , 1.0_f - step( diffuseFactor, 0.0_f ) ); - m_writer.returnStmt( isLit - * light.colour - * light.intensity.x() - * diffuseFactor ); - } - , InLight( m_writer, "light" ) - , InPhongLightMaterial{ m_writer, "material" } - , InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InVec3( m_writer, "lightDirection" ) ); + return m_computeLight( light + , material + , surface + , worldEye + , lightDirection + , parentOutput ); } sdw::Vec3 PhongLightingModel::doComputeLightDiffuse( Light const & light @@ -923,6 +888,32 @@ namespace castor3d::shader , sdw::Vec3 const & worldEye , sdw::Vec3 const & lightDirection ) { + if ( !m_computeLightDiffuse ) + { + m_computeLightDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" + , [this]( Light const & light + , PhongLightMaterial const & material + , Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection ) + { + // Diffuse term. + auto diffuseFactor = m_writer.declLocale( "diffuseFactor" + , dot( surface.worldNormal, -lightDirection ) ); + auto isLit = m_writer.declLocale( "isLit" + , 1.0_f - step( diffuseFactor, 0.0_f ) ); + m_writer.returnStmt( isLit + * light.colour + * light.intensity.x() + * diffuseFactor ); + } + , InLight( m_writer, "light" ) + , InPhongLightMaterial{ m_writer, "material" } + , InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InVec3( m_writer, "lightDirection" ) ); + } + return m_computeLightDiffuse( light , material , surface diff --git a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp index a3ec33a677..62f395ae5c 100644 --- a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp @@ -83,8 +83,6 @@ namespace castor3d ShaderPtr ForwardRenderTechniquePass::doGetPixelShaderSource( PipelineFlags const & flags )const { - auto & renderSystem = *getEngine()->getRenderSystem(); - using namespace sdw; FragmentWriter writer; auto textureFlags = filterTexturesFlags( flags.textures ); @@ -93,7 +91,7 @@ namespace castor3d || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer, *getEngine() }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; C3D_Matrix( writer @@ -126,7 +124,7 @@ namespace castor3d , index++ , RenderPipeline::eBuffers ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *getEngine(), flags.passType ) + , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers , shader::ShadowOptions{ flags.sceneFlags, true, false } @@ -252,6 +250,7 @@ namespace castor3d surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), normal); lightingModel->computeCombined( *lightMat , c3d_sceneData + , *backgroundModel , surface , worldEye , modelData.isShadowReceiver() diff --git a/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp b/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp index ae2af0067b..020ff02ce4 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp @@ -68,6 +68,7 @@ namespace castor3d , smPointResult , smSpotResult , m_lightPassResult + , resultTexture.imageId , sceneUbo , m_lightingGpInfoUbo ) } , m_indirectLightingPass{ castor::makeUnique< IndirectLightingPass >( m_device diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp index dcaf47c3d1..63a235ac42 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp @@ -6,9 +6,11 @@ #include "Castor3D/Render/Technique/Opaque/Lighting/DirectionalLightPass.hpp" #include "Castor3D/Render/Technique/Opaque/Lighting/LightPassResult.hpp" #include "Castor3D/Render/Technique/Opaque/Lighting/MeshLightPass.hpp" +#include "Castor3D/Scene/Scene.hpp" #include "Castor3D/Scene/Light/Light.hpp" #include "Castor3D/Shader/Program.hpp" #include "Castor3D/Shader/ShaderBuffers/PassBuffer.hpp" +#include "Castor3D/Shader/Shaders/GlslBackground.hpp" #include "Castor3D/Shader/Shaders/GlslFog.hpp" #include "Castor3D/Shader/Shaders/GlslLight.hpp" #include "Castor3D/Shader/Shaders/GlslLighting.hpp" @@ -99,8 +101,7 @@ namespace castor3d } } - ShaderPtr LightPass::getPixelShaderSource( PassTypeID passType - , RenderSystem const & renderSystem + ShaderPtr LightPass::getPixelShaderSource( Scene const & scene , SceneFlags const & sceneFlags , LightType lightType , ShadowType shadowType @@ -108,7 +109,7 @@ namespace castor3d { using namespace sdw; FragmentWriter writer; - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer, *scene.getEngine() }; // Shader outputs auto pxl_diffuse = writer.declOutput< Vec3 >( "pxl_diffuse", 0 ); @@ -124,7 +125,6 @@ namespace castor3d C3D_ModelsData( writer, LightPassIdx::eModels, 0u ); C3D_GpInfo( writer, LightPassIdx::eGpInfo, 0u ); C3D_Scene( writer, LightPassIdx::eScene, 0u ); - uint32_t index = uint32_t( LightPassIdx::eData5 ) + 1u; auto c3d_mapData0 = writer.declCombinedImg< FImg2DRgba32 >( getTextureName( DsTexture::eData0 ), uint32_t( LightPassIdx::eData0 ), 0u ); auto c3d_mapData1 = writer.declCombinedImg< FImg2DRgba32 >( getTextureName( DsTexture::eData1 ), uint32_t( LightPassIdx::eData1 ), 0u ); @@ -137,9 +137,9 @@ namespace castor3d : ShadowType::eNone; // Utility functions - index = uint32_t( LightPassLgtIdx::eSmLinear ); + auto index = uint32_t( LightPassLgtIdx::eSmLinear ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *renderSystem.getEngine(), passType ) + , scene.getLightingModel( lightType ) , lightType , uint32_t( LightPassLgtIdx::eLight ) , 1u @@ -148,6 +148,11 @@ namespace castor3d , &sssProfiles , index , 1u ); + auto backgroundModel = shader::BackgroundModel::createModel( scene + , writer + , utils + , index + , 1u ); writer.implementMainT< VoidT, VoidT >( [&]( FragmentIn in , FragmentOut out ) @@ -224,6 +229,7 @@ namespace castor3d lightingModel->compute( light , *lightMat , surface + , *backgroundModel , eye , shadowReceiver , output ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp index 87f0578dc8..62763d3ceb 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp @@ -11,6 +11,7 @@ #include "Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp" #include "Castor3D/Scene/Camera.hpp" #include "Castor3D/Scene/Scene.hpp" +#include "Castor3D/Scene/Background/Background.hpp" #include "Castor3D/Scene/Light/Light.hpp" #include "Castor3D/Scene/Light/PointLight.hpp" #include "Castor3D/Scene/Light/SpotLight.hpp" @@ -39,7 +40,8 @@ namespace castor3d //********************************************************************************************* - LightsPipeline::LightsPipeline( crg::FramePass const & pass + LightsPipeline::LightsPipeline( Scene const & scene + , crg::FramePass const & pass , crg::GraphContext & context , crg::RunnableGraph & graph , RenderDevice const & device @@ -47,19 +49,20 @@ namespace castor3d , LightPassResult const & lpResult , ShadowMapResult const & smResult , std::vector< LightRenderPass > const & renderPasses - , std::vector< LightRenderPass > const & stencilRenderPasses ) + , std::vector< LightRenderPass > const & stencilRenderPasses + , crg::ImageId const & targetColourResult ) : m_context{ context } , m_smResult{ smResult } , m_device{ device } , m_renderPasses{ renderPasses } + , m_scene{ scene } , m_config{ config } , m_vertexShader{ VK_SHADER_STAGE_VERTEX_BIT , castor::string::snakeToCamelCase( getName( m_config.lightType ) ) , LightPass::getVertexShaderSource( m_config.lightType ) } , m_pixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT , castor::string::snakeToCamelCase( getName( m_config.lightType ) ) - , LightPass::getPixelShaderSource( m_config.passType - , m_device.renderSystem + , LightPass::getPixelShaderSource( m_scene , m_config.sceneFlags , m_config.lightType , m_config.shadowType @@ -77,6 +80,7 @@ namespace castor3d ? GpuBufferOffsetT< float >{} : doCreateVertexBuffer( nullptr ) } , m_viewport{ *device.renderSystem.getEngine() } + , m_targetColourResult{ targetColourResult } { m_viewport.setOrtho( -1, 1, -1, 1, -1, 1 ); } @@ -188,6 +192,9 @@ namespace castor3d , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT ) ); + auto index = uint32_t( LightPassLgtIdx::eCount ); + m_scene.getBackground()->addBindings( setLayoutBindings, index ); + return m_device->createDescriptorSetLayout( std::move( setLayoutBindings ) ); } @@ -226,6 +233,9 @@ namespace castor3d , m_smResult[SmTexture::eVariance].wholeView , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } } ); + auto index = uint32_t( LightPassLgtIdx::eCount ); + m_scene.getBackground()->addDescriptors( writes, *m_targetColourResult.data, index ); + result.descriptorSet = m_descriptorPool->createDescriptorSet( 1u ); result.descriptorSet->setBindings( writes ); result.descriptorSet->update(); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp index 6e0e63d2fe..ecd83f86c3 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp @@ -18,7 +18,8 @@ namespace castor3d , LightPassResult const & lpResult , ShadowMapResult const & smDirectionalResult , ShadowMapResult const & smPointResult - , ShadowMapResult const & smSpotResult ) + , ShadowMapResult const & smSpotResult + , crg::ImageId const & targetColourResult ) : crg::RunnablePass{ pass , context , graph @@ -38,6 +39,7 @@ namespace castor3d , m_smDirectionalResult{ smDirectionalResult } , m_smPointResult{ smPointResult } , m_smSpotResult{ smSpotResult } + , m_targetColourResult{ targetColourResult } { } @@ -328,7 +330,8 @@ namespace castor3d if ( it == m_pipelines.end() ) { it = m_pipelines.emplace( hash - , std::make_unique< LightsPipeline >( m_pass + , std::make_unique< LightsPipeline >( m_scene + , m_pass , m_context , m_graph , m_device @@ -340,7 +343,8 @@ namespace castor3d ? m_smPointResult : m_smSpotResult ) ) , m_renderPasses - , m_stencilRenderPasses ) ).first; + , m_stencilRenderPasses + , m_targetColourResult ) ).first; } return *it->second; diff --git a/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp index 1e2aeeb294..e42d1d5665 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp @@ -36,6 +36,7 @@ namespace castor3d , ShadowMapResult const & smPointResult , ShadowMapResult const & smSpotResult , LightPassResult const & lpResult + , crg::ImageId const & targetColourResult , SceneUbo const & sceneUbo , GpInfoUbo const & gpInfoUbo ) : m_device{ device } @@ -45,6 +46,7 @@ namespace castor3d , m_smPointResult{ smPointResult } , m_smSpotResult{ smSpotResult } , m_lpResult{ lpResult } + , m_targetColourResult{ targetColourResult } , m_sceneUbo{ sceneUbo } , m_gpInfoUbo{ gpInfoUbo } , m_group{ graph.createPassGroup( "DirectLighting" ) } @@ -175,7 +177,8 @@ namespace castor3d , m_lpResult , m_smDirectionalResult , m_smPointResult - , m_smSpotResult ); + , m_smSpotResult + , m_targetColourResult ); engine.registerTimer( framePass.getFullName() , result->getTimer() ); m_lightPass = result.get(); diff --git a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp index 387fed4e06..e2801e0e03 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp @@ -179,7 +179,7 @@ namespace castor3d , index++ , RenderPipeline::eBuffers ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *getEngine(), flags.passType ) + , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers , shader::ShadowOptions{ flags.sceneFlags, true, false } @@ -296,6 +296,7 @@ namespace castor3d surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), normal ); lightingModel->computeCombined( *lightMat , c3d_sceneData + , *backgroundModel , surface , worldEye , modelData.isShadowReceiver() diff --git a/source/Core/Castor3D/Scene/Scene.cpp b/source/Core/Castor3D/Scene/Scene.cpp index e1a7e5a4bd..a06e0ed895 100644 --- a/source/Core/Castor3D/Scene/Scene.cpp +++ b/source/Core/Castor3D/Scene/Scene.cpp @@ -36,7 +36,7 @@ #include "Castor3D/Scene/Light/Light.hpp" #include "Castor3D/Scene/Light/LightFactory.hpp" #include "Castor3D/Scene/ParticleSystem/ParticleSystem.hpp" -#include "Castor3D/Shader/Shaders/SdwModule.hpp" +#include "Castor3D/Shader/Shaders/GlslLighting.hpp" #include "Castor3D/Shader/ShaderBuffers/PassBuffer.hpp" #include @@ -586,6 +586,32 @@ namespace castor3d return m_background->getModelName(); } + castor::String Scene::getLightingModel( LightType lightType )const + { + auto result = shader::getLightingModelName( *getEngine(), getPassesType() ); + + if ( m_background->hasScattering() && lightType == LightType::eDirectional ) + { + result = shader::concatModelNames( result + , m_background->getModelName() ); + } + + return result; + } + + castor::String Scene::getLightingModel()const + { + auto result = shader::getLightingModelName( *getEngine(), getPassesType() ); + + if ( m_background->hasScattering() ) + { + result = shader::concatModelNames( result + , m_background->getModelName() ); + } + + return result; + } + AnimatedObjectSPtr Scene::addAnimatedTexture( TextureSourceInfo const & sourceInfo , TextureConfiguration const & config , Pass & pass ) diff --git a/source/Core/Castor3D/Shader/ShaderModule.cpp b/source/Core/Castor3D/Shader/ShaderModule.cpp index 2a93bf4cfe..f31ece24dc 100644 --- a/source/Core/Castor3D/Shader/ShaderModule.cpp +++ b/source/Core/Castor3D/Shader/ShaderModule.cpp @@ -98,6 +98,14 @@ namespace castor3d { return std::make_unique< Materials >( writer ); } + + castor::String concatModelNames( castor::String lhs + , castor::String rhs ) + { + castor::string::replace( lhs, cuT( "c3d." ), castor::cuEmptyString ); + castor::string::replace( rhs, cuT( "c3d." ), castor::cuEmptyString ); + return cuT( "c3d." ) + lhs + cuT( "." ) + rhs; + } } //************************************************************************* diff --git a/source/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.cpp b/source/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.cpp index 1faad47d1f..5761bb88e5 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslCookTorranceBRDF.cpp @@ -33,7 +33,30 @@ namespace castor3d::shader , OutputComponents & output ) { declareComputeCookTorrance(); - return m_computeCookTorrance( light + return m_computeCookTorrance( light.colour + , light.intensity + , worldEye + , direction + , specular + , metalness + , roughness + , surface + , output ); + } + + sdw::RetVec3 CookTorranceBRDF::compute( sdw::Vec3 const & radiance + , sdw::Vec2 const & intensity + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & direction + , sdw::Vec3 const & specular + , sdw::Float const & metalness + , sdw::Float const & roughness + , Surface surface + , OutputComponents & output ) + { + declareComputeCookTorrance(); + return m_computeCookTorrance( radiance + , intensity , worldEye , direction , specular @@ -230,7 +253,8 @@ namespace castor3d::shader declareGeometry(); OutputComponents outputs{ m_writer }; m_computeCookTorrance = m_writer.implementFunction< sdw::Vec3 >( "c3d_computeCookTorrance" - , [this]( Light const & light + , [this]( sdw::Vec3 const & radiance + , sdw::Vec2 const & intensity , sdw::Vec3 const & worldEye , sdw::Vec3 const & direction , sdw::Vec3 const & specular @@ -248,8 +272,6 @@ namespace castor3d::shader , normalize( L + V ) ); auto N = m_writer.declLocale( "N" , normalize( surface.worldNormal ) ); - auto radiance = m_writer.declLocale( "radiance" - , light.colour ); auto NdotL = m_writer.declLocale( "NdotL" , max( 0.0_f, dot( N, L ) ) ); @@ -285,12 +307,13 @@ namespace castor3d::shader kD *= 1.0_f - metalness; auto result = m_writer.declLocale( "result" - , max( radiance * light.intensity.r() * kD, vec3( 0.0_f ) ) / sdw::Float{ castor::Pi< float > } ); + , max( radiance * intensity.r() * kD, vec3( 0.0_f ) ) / sdw::Float{ castor::Pi< float > } ); output.m_diffuse = NdotL * result; - output.m_specular = max( specReflectance * radiance * light.intensity.g() * NdotL, vec3( 0.0_f ) ); + output.m_specular = max( specReflectance * radiance * intensity.g() * NdotL, vec3( 0.0_f ) ); m_writer.returnStmt( result ); } - , InLight( m_writer, "light" ) + , sdw::InVec3( m_writer, "radiance" ) + , sdw::InVec2( m_writer, "intensity" ) , sdw::InVec3( m_writer, "worldEye" ) , sdw::InVec3( m_writer, "direction" ) , sdw::InVec3{ m_writer, "specular" } diff --git a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp index ee840cb181..1b7595c6c7 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp @@ -118,30 +118,21 @@ namespace castor3d::shader , uint32_t shadowMapSet ) { m_shadowModel->declare( shadowMapBinding, shadowMapSet ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTS" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); doDeclareLightsBuffer( lightsBufBinding, lightsBufSet ); doDeclareGetCascadeFactors(); doDeclareGetBaseLight(); doDeclareGetDirectionalLight(); doDeclareGetPointLight(); doDeclareGetSpotLight(); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTING" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - doDeclareModel(); - doDeclareComputeDirectionalLight(); - doDeclareComputePointLight(); - doDeclareComputeSpotLight(); } void LightingModel::computeCombined( LightMaterial const & material , SceneData const & sceneData + , BackgroundModel const & background , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , OutputComponents & parentOutput )const + , OutputComponents & parentOutput ) { auto begin = m_writer.declLocale( "c3d_begin" , 0_u ); @@ -153,6 +144,7 @@ namespace castor3d::shader compute( getDirectionalLight( dir ) , material , surface + , background , worldEye , receivesShadows , parentOutput ); @@ -265,29 +257,19 @@ namespace castor3d::shader , uint32_t shadowMapSet ) { m_shadowModel->declare( shadowMapBinding, shadowMapSet ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTS" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); doDeclareLightsBuffer( lightsBufBinding, lightsBufSet ); doDeclareGetCascadeFactors(); doDeclareGetBaseLight(); doDeclareGetDirectionalLight(); doDeclareGetPointLight(); doDeclareGetSpotLight(); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// DIFFUSE LIGHTING" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - doDeclareDiffuseModel(); - doDeclareComputeDirectionalLightDiffuse(); - doDeclareComputePointLightDiffuse(); - doDeclareComputeSpotLightDiffuse(); } sdw::Vec3 LightingModel::computeCombinedDiffuse( LightMaterial const & material , SceneData const & sceneData , Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { auto begin = m_writer.declLocale( "c3d_begin" , 0_u ); @@ -362,9 +344,6 @@ namespace castor3d::shader , uint32_t shadowMapSet ) { m_shadowModel->declareDirectional( shadowMapBinding, shadowMapSet ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTS" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); doDeclareGetCascadeFactors(); if ( lightUbo ) @@ -377,12 +356,6 @@ namespace castor3d::shader doDeclareGetBaseLight(); doDeclareGetDirectionalLight(); } - - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTING" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - doDeclareModel(); - doDeclareComputeDirectionalLight(); } void LightingModel::declarePointModel( bool lightUbo @@ -392,9 +365,6 @@ namespace castor3d::shader , uint32_t shadowMapSet ) { m_shadowModel->declarePoint( shadowMapBinding, shadowMapSet ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTS" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); if ( lightUbo ) { @@ -406,12 +376,6 @@ namespace castor3d::shader doDeclareGetBaseLight(); doDeclareGetPointLight(); } - - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTING" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - doDeclareModel(); - doDeclareComputePointLight(); } void LightingModel::declareSpotModel( bool lightUbo @@ -421,9 +385,6 @@ namespace castor3d::shader , uint32_t shadowMapSet ) { m_shadowModel->declareSpot( shadowMapBinding, shadowMapSet ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTS" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); if ( lightUbo ) { @@ -435,12 +396,6 @@ namespace castor3d::shader doDeclareGetBaseLight(); doDeclareGetSpotLight(); } - - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - m_writer.inlineComment( "// LIGHTING" ); - m_writer.inlineComment( "//////////////////////////////////////////////////////////////////////////////" ); - doDeclareModel(); - doDeclareComputeSpotLight(); } DirectionalLight LightingModel::getDirectionalLight( sdw::UInt const & index )const diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp index b377d264fa..2e268c503c 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp @@ -634,6 +634,8 @@ namespace ocean_fft castor3d::SubmeshFlags OceanRenderPass::doAdjustSubmeshFlags( castor3d::SubmeshFlags flags )const { + remFlag( flags, castor3d::SubmeshFlag::eNormals ); + remFlag( flags, castor3d::SubmeshFlag::eTangents ); remFlag( flags, castor3d::SubmeshFlag::eTexcoords0 ); remFlag( flags, castor3d::SubmeshFlag::eTexcoords1 ); remFlag( flags, castor3d::SubmeshFlag::eTexcoords2 ); @@ -1142,7 +1144,7 @@ namespace ocean_fft , index++ , RenderPipeline::eBuffers ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *getEngine(), flags.passType ) + , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers , shader::ShadowOptions{ flags.sceneFlags, true, false } @@ -1257,6 +1259,7 @@ namespace ocean_fft , finalNormal ); lightingModel->computeCombined( *lightMat , c3d_sceneData + , *backgroundModel , surface , worldEye , modelData.isShadowReceiver() diff --git a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp index 4a14f5cf06..aad693e44e 100644 --- a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp @@ -1122,7 +1122,7 @@ namespace ocean , index++ , RenderPipeline::eBuffers ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *getEngine(), flags.passType ) + , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers , shader::ShadowOptions{ flags.sceneFlags, true, false } @@ -1215,6 +1215,7 @@ namespace ocean surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), finalNormal ); lightingModel->computeCombined( *lightMat , c3d_sceneData + , *backgroundModel , surface , worldEye , modelData.isShadowReceiver() diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp index d637e2490b..5db475cba0 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp @@ -128,10 +128,122 @@ namespace toon::shader void ToonPhongLightingModel::compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface + , c3d::BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computeDirectional ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( light.direction ) ); + doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + auto maxCount = m_writer.declLocale( "maxCount" + , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , -lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + + if ( m_enableVolumetric ) + { + IF( m_writer, light.base.volumetricSteps != 0_u ) + { + m_shadowModel->computeVolumetric( light.base + , surface + , worldEye + , light.transforms[cascadeIndex] + , light.direction + , cascadeIndex + , light.cascadeCount + , output ); + } + FI; + } + } + FI; + } + + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , c3d::InDirectionalLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeDirectional( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -145,8 +257,66 @@ namespace toon::shader , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computePoint ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" + , [this]( c3d::PointLight const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + output.m_diffuse = output.m_diffuse / attenuation; + output.m_specular = output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , c3d::InPointLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computePoint( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -160,8 +330,75 @@ namespace toon::shader , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computeSpot ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" + , [this]( c3d::SpotLight const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, light.direction ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + doComputeLight( light.base + , material + , surface + , worldEye + , lightDirection + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , lightToVertex ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = ( spotFactor - light.outerCutOff ) / light.cutOffsDiff; + output.m_diffuse = spotFactor * output.m_diffuse / attenuation; + output.m_specular = spotFactor * output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + FI; + } + , c3d::InSpotLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeSpot( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -262,8 +499,56 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeDirectionalDiffuse ) + { + m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , light.cascadeCount - 1_u ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , lightDirection + , cascadeIndex + , light.cascadeCount ) ); + diffuse *= shadowFactor; + } + FI; + } + + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); + } + , c3d::InOutDirectionalLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeDirectionalDiffuse( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -275,8 +560,58 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computePointDiffuse ) + { + m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" + , [this]( c3d::PointLight light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); + } + , c3d::InOutPointLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computePointDiffuse( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -288,8 +623,70 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeSpotDiffuse ) + { + m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" + , [this]( c3d::SpotLight light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , surface.worldPosition - light.position ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + diffuse = doComputeLightDiffuse( light.base + , material + , surface + , worldEye + , lightDirection ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , lightToVertex ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = ( spotFactor - light.outerCutOff ) / light.cutOffsDiff; + diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); + } + FI; + + m_writer.returnStmt( diffuse ); + } + , c3d::InOutSpotLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeSpotDiffuse( light , static_cast< ToonPhongLightMaterial const & >( material ) , surface @@ -372,536 +769,130 @@ namespace toon::shader , emissive ); } - void ToonPhongLightingModel::doDeclareModel() - { - doDeclareComputeLight(); - } - - void ToonPhongLightingModel::doDeclareComputeDirectionalLight() + void ToonPhongLightingModel::doComputeLight( c3d::Light const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection + , c3d::OutputComponents & parentOutput ) { - c3d::OutputComponents outputs{ m_writer }; - m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" - , [this]( c3d::DirectionalLight const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( light.direction ) ); - doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ); - - if ( m_shadowModel->isEnabled() ) + if ( !m_computeLight ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeLight = m_writer.implementFunction< sdw::Void >( m_prefix + "doComputeLight" + , [this]( c3d::Light const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection + , c3d::OutputComponents & output ) { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) + // Diffuse term. + auto diffuseFactor = m_writer.declLocale( "diffuseFactor" + , dot( surface.worldNormal, -lightDirection ) ); + auto delta = m_writer.declLocale( "delta" + , fwidth( diffuseFactor ) * material.smoothBand ); + diffuseFactor = smoothStep( 0.0_f, delta, diffuseFactor ); + output.m_diffuse = light.colour + * light.intensity.x() + * diffuseFactor; + + // Specular term. + auto vertexToEye = m_writer.declLocale( "vertexToEye" + , normalize( worldEye - surface.worldPosition ) ); + + if ( m_isBlinnPhong ) { - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , 0_u ); - auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); - auto maxCount = m_writer.declLocale( "maxCount" - , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); - - // Get cascade index for the current fragment's view position - FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) - { - auto factors = m_writer.declLocale( "factors" - , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } - , light.splitDepths - , i ) ); - - IF( m_writer, factors.x() != 0.0_f ) - { - cascadeFactors = factors; - } - FI; - } - ROF; - - cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); - - IF( m_writer, receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , cascadeFactors.y() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , lightDirection - , cascadeIndex - , light.cascadeCount ) ); - - IF( m_writer, cascadeIndex > 0_u ) - { - shadowFactor += cascadeFactors.z() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex - 1u] - , -lightDirection - , cascadeIndex - 1u - , light.cascadeCount ); - } - FI; - - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - - if ( m_enableVolumetric ) - { - IF( m_writer, light.base.volumetricSteps != 0_u ) - { - m_shadowModel->computeVolumetric( light.base - , surface - , worldEye - , light.transforms[cascadeIndex] - , light.direction - , cascadeIndex - , light.cascadeCount - , output ); - } - FI; - } + auto halfwayDir = m_writer.declLocale( "halfwayDir" + , normalize( vertexToEye - lightDirection ) ); + m_writer.declLocale( "specularFactor" + , max( dot( surface.worldNormal, halfwayDir ), 0.0_f ) ); } - FI; + else + { + auto lightReflect = m_writer.declLocale( "lightReflect" + , normalize( reflect( lightDirection, surface.worldNormal ) ) ); + m_writer.declLocale( "specularFactor" + , max( dot( vertexToEye, lightReflect ), 0.0_f ) ); + } + + auto specularFactor = m_writer.getVariable< sdw::Float >( "specularFactor" ); + specularFactor = pow( specularFactor * diffuseFactor, clamp( material.shininess, 1.0_f, 256.0_f ) ); + specularFactor = smoothStep( 0.0_f, 0.01_f * material.smoothBand, specularFactor ); + output.m_specular = specularFactor + * light.colour + * light.intensity.y(); } + , c3d::InLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InVec3( m_writer, "lightDirection" ) + , outputs ); + } - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , c3d::InDirectionalLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); + m_computeLight( light + , material + , surface + , worldEye + , lightDirection + , parentOutput ); } - void ToonPhongLightingModel::doDeclareComputePointLight() + sdw::Vec3 ToonPhongLightingModel::doComputeLightDiffuse( c3d::Light const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection ) { - c3d::OutputComponents outputs{ m_writer }; - m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" - , [this]( c3d::PointLight const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ); - - if ( m_shadowModel->isEnabled() ) + if ( !m_computeLightDiffuse ) + { + m_computeLightDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" + , [this]( c3d::Light const & light + , ToonPhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Vec3 const & lightDirection ) { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; + // Diffuse term. + auto diffuseFactor = m_writer.declLocale( "diffuseFactor" + , dot( surface.worldNormal, -lightDirection ) ); + auto delta = m_writer.declLocale( "delta" + , fwidth( diffuseFactor ) * material.smoothBand ); + diffuseFactor = smoothStep( 0.0_f, delta, diffuseFactor ); + m_writer.returnStmt( diffuseFactor + * light.colour + * light.intensity.x() ); } + , c3d::InLight( m_writer, "light" ) + , InToonPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InVec3( m_writer, "lightDirection" ) ); + } - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - output.m_diffuse = output.m_diffuse / attenuation; - output.m_specular = output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , c3d::InPointLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); + return m_computeLightDiffuse( light + , material + , surface + , worldEye + , lightDirection ); } - void ToonPhongLightingModel::doDeclareComputeSpotLight() + //********************************************************************************************* + + ToonBlinnPhongLightingModel::ToonBlinnPhongLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + : ToonPhongLightingModel{ writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric + , true } { - c3d::OutputComponents outputs{ m_writer }; - m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" - , [this]( c3d::SpotLight const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, light.direction ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - doComputeLight( light.base - , material - , surface - , worldEye - , lightDirection - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , lightToVertex ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = ( spotFactor - light.outerCutOff ) / light.cutOffsDiff; - output.m_diffuse = spotFactor * output.m_diffuse / attenuation; - output.m_specular = spotFactor * output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - FI; - } - , c3d::InSpotLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void ToonPhongLightingModel::doDeclareComputeLight() - { - c3d::OutputComponents outputs{ m_writer }; - m_computeLight = m_writer.implementFunction< sdw::Void >( m_prefix + "doComputeLight" - , [this]( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection - , c3d::OutputComponents & output ) - { - // Diffuse term. - auto diffuseFactor = m_writer.declLocale( "diffuseFactor" - , dot( surface.worldNormal, -lightDirection ) ); - auto delta = m_writer.declLocale( "delta" - , fwidth( diffuseFactor ) * material.smoothBand ); - diffuseFactor = smoothStep( 0.0_f, delta, diffuseFactor ); - output.m_diffuse = light.colour - * light.intensity.x() - * diffuseFactor; - - // Specular term. - auto vertexToEye = m_writer.declLocale( "vertexToEye" - , normalize( worldEye - surface.worldPosition ) ); - - if ( m_isBlinnPhong ) - { - auto halfwayDir = m_writer.declLocale( "halfwayDir" - , normalize( vertexToEye - lightDirection ) ); - m_writer.declLocale( "specularFactor" - , max( dot( surface.worldNormal, halfwayDir ), 0.0_f ) ); - } - else - { - auto lightReflect = m_writer.declLocale( "lightReflect" - , normalize( reflect( lightDirection, surface.worldNormal ) ) ); - m_writer.declLocale( "specularFactor" - , max( dot( vertexToEye, lightReflect ), 0.0_f ) ); - } - - auto specularFactor = m_writer.getVariable< sdw::Float >( "specularFactor" ); - specularFactor = pow( specularFactor * diffuseFactor, clamp( material.shininess, 1.0_f, 256.0_f ) ); - specularFactor = smoothStep( 0.0_f, 0.01_f * material.smoothBand, specularFactor ); - output.m_specular = specularFactor - * light.colour - * light.intensity.y(); - } - , c3d::InLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InVec3( m_writer, "lightDirection" ) - , outputs ); - } - - void ToonPhongLightingModel::doComputeLight( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection - , c3d::OutputComponents & parentOutput ) - { - m_computeLight( light - , material - , surface - , worldEye - , lightDirection - , parentOutput ); - } - - void ToonPhongLightingModel::doDeclareDiffuseModel() - { - doDeclareComputeLightDiffuse(); - } - - void ToonPhongLightingModel::doDeclareComputeDirectionalLightDiffuse() - { - m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" - , [this]( c3d::DirectionalLight light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , light.cascadeCount - 1_u ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , lightDirection - , cascadeIndex - , light.cascadeCount ) ); - diffuse *= shadowFactor; - } - FI; - } - - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); - } - , c3d::InOutDirectionalLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void ToonPhongLightingModel::doDeclareComputePointLightDiffuse() - { - m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" - , [this]( c3d::PointLight light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); - } - , c3d::InOutPointLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void ToonPhongLightingModel::doDeclareComputeSpotLightDiffuse() - { - m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" - , [this]( c3d::SpotLight light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , surface.worldPosition - light.position ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - diffuse = doComputeLightDiffuse( light.base - , material - , surface - , worldEye - , lightDirection ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , lightToVertex ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = ( spotFactor - light.outerCutOff ) / light.cutOffsDiff; - diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); - } - FI; - - m_writer.returnStmt( diffuse ); - } - , c3d::InOutSpotLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void ToonPhongLightingModel::doDeclareComputeLightDiffuse() - { - m_computeLightDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "doComputeLight" - , [this]( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection ) - { - // Diffuse term. - auto diffuseFactor = m_writer.declLocale( "diffuseFactor" - , dot( surface.worldNormal, -lightDirection ) ); - auto delta = m_writer.declLocale( "delta" - , fwidth( diffuseFactor ) * material.smoothBand ); - diffuseFactor = smoothStep( 0.0_f, delta, diffuseFactor ); - m_writer.returnStmt( diffuseFactor - * light.colour - * light.intensity.x() ); - } - , c3d::InLight( m_writer, "light" ) - , InToonPhongLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InVec3( m_writer, "lightDirection" ) ); - } - - sdw::Vec3 ToonPhongLightingModel::doComputeLightDiffuse( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection ) - { - return m_computeLightDiffuse( light - , material - , surface - , worldEye - , lightDirection ); - } - - //********************************************************************************************* - - ToonBlinnPhongLightingModel::ToonBlinnPhongLightingModel( sdw::ShaderWriter & writer - , c3d::Utils & utils - , c3d::ShadowOptions shadowOptions - , c3d::SssProfiles const * sssProfiles - , bool enableVolumetric ) - : ToonPhongLightingModel{ writer - , utils - , std::move( shadowOptions ) - , sssProfiles - , enableVolumetric - , true } - { - } + } c3d::LightingModelPtr ToonBlinnPhongLightingModel::create( sdw::ShaderWriter & writer , c3d::Utils & utils @@ -1059,10 +1050,149 @@ namespace toon::shader void ToonPbrLightingModel::compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface + , c3d::BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computeDirectional ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight const & light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( -light.direction ) ); + m_cookTorrance.computeAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , material.smoothBand + , surface + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + auto maxCount = m_writer.declLocale( "maxCount" + , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , -lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , -lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + + if ( m_enableVolumetric ) + { + IF( m_writer, light.base.volumetricSteps != 0_u ) + { + m_shadowModel->computeVolumetric( light.base + , surface + , worldEye + , light.transforms[cascadeIndex] + , light.direction + , cascadeIndex + , light.cascadeCount + , output ); + } + FI; + } + +#if C3D_DebugCascades + IF( m_writer, cascadeIndex == 0_u ) + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); + } + ELSEIF( cascadeIndex == 1_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); + } + ELSEIF( cascadeIndex == 2_u ) + { + output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); + } + ELSE + { + output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); + } + FI; +#endif + } + FI; + } + + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , c3d::InDirectionalLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeDirectional( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1076,8 +1206,69 @@ namespace toon::shader , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computePoint ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" + , [this]( c3d::PointLight const & light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + m_cookTorrance.computeAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , material.smoothBand + , surface + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + output.m_diffuse = output.m_diffuse / attenuation; + output.m_specular = output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + , c3d::InPointLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computePoint( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1091,8 +1282,78 @@ namespace toon::shader , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput )const + , c3d::OutputComponents & parentOutput ) { + if ( !m_computeSpot ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" + , [this]( c3d::SpotLight const & light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, -light.direction ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + m_cookTorrance.computeAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , material.smoothBand + , surface + , output ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , -lightToVertex ) ); + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + output.m_diffuse = spotFactor * output.m_diffuse / attenuation; + output.m_specular = spotFactor * output.m_specular / attenuation; + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + } + FI; + } + , c3d::InSpotLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + m_computeSpot( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1197,8 +1458,60 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeDirectionalDiffuse ) + { + m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( -light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , m_cookTorrance.computeDiffuseAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.smoothBand + , surface ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , light.cascadeCount - 1_u ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , -lightDirection + , cascadeIndex + , light.cascadeCount ) ); + diffuse *= shadowFactor; + } + FI; + } + + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); + } + , c3d::InOutDirectionalLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeDirectionalDiffuse( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1210,8 +1523,60 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if (!m_computePointDiffuse ) + { + m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" + , [this]( c3d::PointLight light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , m_cookTorrance.computeDiffuseAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.smoothBand + , surface ) ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computePoint( light.base + , surface + , light.position ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); + } + , c3d::InOutPointLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computePointDiffuse( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1223,8 +1588,72 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const + , sdw::Int const & receivesShadows ) { + if ( !m_computeSpotDiffuse ) + { + m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" + , [this]( c3d::SpotLight light + , ToonPbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows ) + { + auto lightToVertex = m_writer.declLocale( "lightToVertex" + , light.position - surface.worldPosition ); + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( lightToVertex ) ); + auto spotFactor = m_writer.declLocale( "spotFactor" + , dot( lightDirection, -light.direction ) ); + auto diffuse = m_writer.declLocale( "diffuse" + , vec3( 0.0_f ) ); + + IF( m_writer, spotFactor > light.outerCutOff ) + { + auto distance = m_writer.declLocale( "distance" + , length( lightToVertex ) ); + diffuse = m_cookTorrance.computeDiffuseAON( light.base + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.smoothBand + , surface ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) + && light.base.index >= 0_i + && receivesShadows != 0_i ) + { + light.base.updateShadowType( castor3d::ShadowType::eRaw ); + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , m_shadowModel->computeSpot( light.base + , surface + , light.transform + , -lightToVertex ) ); + diffuse *= shadowFactor; + } + FI; + } + + auto attenuation = m_writer.declLocale( "attenuation" + , light.getAttenuationFactor( distance ) ); + spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); + diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); + } + FI; + + m_writer.returnStmt( diffuse ); + } + , c3d::InOutSpotLight( m_writer, "light" ) + , InToonPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) ); + } + return m_computeSpotDiffuse( light , static_cast< ToonPbrLightMaterial const & >( material ) , surface @@ -1311,450 +1740,5 @@ namespace toon::shader , emissive ); } - void ToonPbrLightingModel::doDeclareModel() - { - } - - void ToonPbrLightingModel::doDeclareComputeDirectionalLight() - { - c3d::OutputComponents outputs{ m_writer }; - m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" - , [this]( c3d::DirectionalLight const & light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( -light.direction ) ); - m_cookTorrance.computeAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , material.smoothBand - , surface - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) - { - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , 0_u ); - auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); - auto maxCount = m_writer.declLocale( "maxCount" - , m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ) ); - - // Get cascade index for the current fragment's view position - FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) - { - auto factors = m_writer.declLocale( "factors" - , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } - , light.splitDepths - , i ) ); - - IF( m_writer, factors.x() != 0.0_f ) - { - cascadeFactors = factors; - } - FI; - } - ROF; - - cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); - - IF( m_writer, receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , cascadeFactors.y() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , -lightDirection - , cascadeIndex - , light.cascadeCount ) ); - - IF( m_writer, cascadeIndex > 0_u ) - { - shadowFactor += cascadeFactors.z() - * m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex - 1u] - , -lightDirection - , cascadeIndex - 1u - , light.cascadeCount ); - } - FI; - - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - - if ( m_enableVolumetric ) - { - IF( m_writer, light.base.volumetricSteps != 0_u ) - { - m_shadowModel->computeVolumetric( light.base - , surface - , worldEye - , light.transforms[cascadeIndex] - , light.direction - , cascadeIndex - , light.cascadeCount - , output ); - } - FI; - } - -#if C3D_DebugCascades - IF( m_writer, cascadeIndex == 0_u ) - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 0.25f, 0.25f ); - } - ELSEIF( cascadeIndex == 1_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 0.25_f, 1.0f, 0.25f ); - } - ELSEIF( cascadeIndex == 2_u ) - { - output.m_diffuse.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - output.m_specular.rgb() *= vec3( 0.25_f, 0.25f, 1.0f ); - } - ELSE - { - output.m_diffuse.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - output.m_specular.rgb() *= vec3( 1.0_f, 1.0f, 0.25f ); - } - FI; -#endif - } - FI; - } - - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , c3d::InDirectionalLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void ToonPbrLightingModel::doDeclareComputePointLight() - { - c3d::OutputComponents outputs{ m_writer }; - m_computePoint = m_writer.implementFunction< sdw::Void >( m_prefix + "computePointLight" - , [this]( c3d::PointLight const & light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - m_cookTorrance.computeAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , material.smoothBand - , surface - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - output.m_diffuse = output.m_diffuse / attenuation; - output.m_specular = output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - , c3d::InPointLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void ToonPbrLightingModel::doDeclareComputeSpotLight() - { - c3d::OutputComponents outputs{ m_writer }; - m_computeSpot = m_writer.implementFunction< sdw::Void >( m_prefix + "computeSpotLight" - , [this]( c3d::SpotLight const & light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, -light.direction ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; - m_cookTorrance.computeAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.getRoughness() - , material.smoothBand - , surface - , output ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , -lightToVertex ) ); - output.m_diffuse *= shadowFactor; - output.m_specular *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - output.m_diffuse = spotFactor * output.m_diffuse / attenuation; - output.m_specular = spotFactor * output.m_specular / attenuation; - parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); - parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); - } - FI; - } - , c3d::InSpotLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) - , outputs ); - } - - void ToonPbrLightingModel::doDeclareDiffuseModel() - { - } - - void ToonPbrLightingModel::doDeclareComputeDirectionalLightDiffuse() - { - m_computeDirectionalDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeDirectionalLight" - , [this]( c3d::DirectionalLight light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( -light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , m_cookTorrance.computeDiffuseAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.smoothBand - , surface ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto cascadeFactors = m_writer.declLocale( "cascadeFactors" - , vec3( 0.0_f, 1.0_f, 0.0_f ) ); - auto cascadeIndex = m_writer.declLocale( "cascadeIndex" - , light.cascadeCount - 1_u ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeDirectional( light.base - , surface - , light.transforms[cascadeIndex] - , -lightDirection - , cascadeIndex - , light.cascadeCount ) ); - diffuse *= shadowFactor; - } - FI; - } - - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse ) ); - } - , c3d::InOutDirectionalLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void ToonPbrLightingModel::doDeclareComputePointLightDiffuse() - { - m_computePointDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computePointLight" - , [this]( c3d::PointLight light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , m_cookTorrance.computeDiffuseAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.smoothBand - , surface ) ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computePoint( light.base - , surface - , light.position ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - m_writer.returnStmt( max( vec3( 0.0_f ), diffuse / attenuation ) ); - } - , c3d::InOutPointLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - - void ToonPbrLightingModel::doDeclareComputeSpotLightDiffuse() - { - m_computeSpotDiffuse = m_writer.implementFunction< sdw::Vec3 >( m_prefix + "computeSpotLight" - , [this]( c3d::SpotLight light - , ToonPbrLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) - { - auto lightToVertex = m_writer.declLocale( "lightToVertex" - , light.position - surface.worldPosition ); - auto lightDirection = m_writer.declLocale( "lightDirection" - , normalize( lightToVertex ) ); - auto spotFactor = m_writer.declLocale( "spotFactor" - , dot( lightDirection, -light.direction ) ); - auto diffuse = m_writer.declLocale( "diffuse" - , vec3( 0.0_f ) ); - - IF( m_writer, spotFactor > light.outerCutOff ) - { - auto distance = m_writer.declLocale( "distance" - , length( lightToVertex ) ); - diffuse = m_cookTorrance.computeDiffuseAON( light.base - , worldEye - , lightDirection - , material.specular - , material.getMetalness() - , material.smoothBand - , surface ); - - if ( m_shadowModel->isEnabled() ) - { - IF( m_writer - , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) - && light.base.index >= 0_i - && receivesShadows != 0_i ) - { - light.base.updateShadowType( castor3d::ShadowType::eRaw ); - auto shadowFactor = m_writer.declLocale( "shadowFactor" - , m_shadowModel->computeSpot( light.base - , surface - , light.transform - , -lightToVertex ) ); - diffuse *= shadowFactor; - } - FI; - } - - auto attenuation = m_writer.declLocale( "attenuation" - , light.getAttenuationFactor( distance ) ); - spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); - diffuse = max( vec3( 0.0_f ), spotFactor * diffuse / attenuation ); - } - FI; - - m_writer.returnStmt( diffuse ); - } - , c3d::InOutSpotLight( m_writer, "light" ) - , InToonPbrLightMaterial{ m_writer, "material" } - , c3d::InSurface{ m_writer, "surface" } - , sdw::InVec3( m_writer, "worldEye" ) - , sdw::InInt( m_writer, "receivesShadows" ) ); - } - //********************************************************************************************* } diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp index f15e37df57..18a99f9f49 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp @@ -55,21 +55,22 @@ namespace toon::shader void compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface + , c3d::BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void compute( c3d::PointLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void compute( c3d::SpotLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void computeMapContributions( castor3d::PassFlags const & passFlags , castor3d::TextureFlagsArray const & textures , c3d::TextureConfigurations const & textureConfigs @@ -101,17 +102,17 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; sdw::Vec3 computeDiffuse( c3d::PointLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; sdw::Vec3 computeDiffuse( c3d::SpotLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; void computeMapDiffuseContributions( castor3d::PassFlags const & passFlags , castor3d::TextureFlagsArray const & textures , c3d::TextureConfigurations const & textureConfigs @@ -129,16 +130,6 @@ namespace toon::shader , c3d::LightMaterial & lightMat )override; //\} - protected: - void doDeclareModel()override; - void doDeclareComputeDirectionalLight()override; - void doDeclareComputePointLight()override; - void doDeclareComputeSpotLight()override; - void doDeclareDiffuseModel()override; - void doDeclareComputeDirectionalLightDiffuse()override; - void doDeclareComputePointLightDiffuse()override; - void doDeclareComputeSpotLightDiffuse()override; - private: void doComputeLight( c3d::Light const & light , ToonPhongLightMaterial const & material @@ -146,13 +137,11 @@ namespace toon::shader , sdw::Vec3 const & worldEye , sdw::Vec3 const & lightDirection , c3d::OutputComponents & output ); - void doDeclareComputeLight(); sdw::Vec3 doComputeLightDiffuse( c3d::Light const & light , ToonPhongLightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Vec3 const & lightDirection ); - void doDeclareComputeLightDiffuse(); public: static const castor::String getName(); @@ -270,21 +259,22 @@ namespace toon::shader void compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface + , c3d::BackgroundModel const & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void compute( c3d::PointLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void compute( c3d::SpotLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows - , c3d::OutputComponents & output )const override; + , c3d::OutputComponents & output )override; void computeMapContributions( castor3d::PassFlags const & passFlags , castor3d::TextureFlagsArray const & textures , c3d::TextureConfigurations const & textureConfigs @@ -316,17 +306,17 @@ namespace toon::shader , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; sdw::Vec3 computeDiffuse( c3d::PointLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; sdw::Vec3 computeDiffuse( c3d::SpotLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows )const override; + , sdw::Int const & receivesShadows )override; void computeMapDiffuseContributions( castor3d::PassFlags const & passFlags , castor3d::TextureFlagsArray const & textures , c3d::TextureConfigurations const & textureConfigs @@ -344,16 +334,6 @@ namespace toon::shader , c3d::LightMaterial & lightMat )override; //\} - protected: - void doDeclareModel()override; - void doDeclareComputeDirectionalLight()override; - void doDeclareComputePointLight()override; - void doDeclareComputeSpotLight()override; - void doDeclareDiffuseModel()override; - void doDeclareComputeDirectionalLightDiffuse()override; - void doDeclareComputePointLightDiffuse()override; - void doDeclareComputeSpotLightDiffuse()override; - public: c3d::CookTorranceBRDF m_cookTorrance; sdw::Function< sdw::Void diff --git a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp index bfa48f2c73..1031d3214b 100644 --- a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp @@ -600,7 +600,7 @@ namespace water , index++ , RenderPipeline::eBuffers ); auto lightingModel = shader::LightingModel::createModel( utils - , shader::getLightingModelName( *getEngine(), flags.passType ) + , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers , shader::ShadowOptions{ flags.sceneFlags, true, false } @@ -697,6 +697,7 @@ namespace water surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), finalNormal ); lightingModel->computeCombined( *lightMat , c3d_sceneData + , *backgroundModel , surface , worldEye , modelData.isShadowReceiver() From 931e865caadb27abc970a7a5677d4a13a358adee Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Wed, 22 Jun 2022 18:29:06 +0200 Subject: [PATCH 04/12] Castor3D: Removed Engine param from shader::Utils ctor. --- .../Castor3D/Shader/Shaders/GlslLighting.hpp | 27 ++++++++++++------- .../Castor3D/Shader/Shaders/GlslUtils.hpp | 7 +++-- .../Core/Castor3D/Overlay/OverlayRenderer.cpp | 3 +-- .../GeometryInjectionPass.cpp | 20 ++++++++------ .../LightInjectionPass.cpp | 20 ++++++++------ .../VoxelConeTracing/VoxelBufferToTexture.cpp | 7 +++-- .../VoxelConeTracing/VoxelSecondaryBounce.cpp | 2 +- .../VoxelConeTracing/VoxelizePass.cpp | 5 ++-- .../Render/Passes/ComputeDepthRange.cpp | 6 ++--- .../Core/Castor3D/Render/Passes/DepthPass.cpp | 3 +-- .../Castor3D/Render/Passes/PickingPass.cpp | 3 +-- source/Core/Castor3D/Render/RenderTarget.cpp | 2 +- .../ShadowMap/ShadowMapPassDirectional.cpp | 5 ++-- .../Render/ShadowMap/ShadowMapPassPoint.cpp | 5 ++-- .../Render/ShadowMap/ShadowMapPassSpot.cpp | 5 ++-- .../Technique/ForwardRenderTechniquePass.cpp | 5 ++-- .../Technique/Opaque/IndirectLightingPass.cpp | 5 ++-- .../Technique/Opaque/Lighting/LightPass.cpp | 5 ++-- .../Lighting/SubsurfaceScatteringPass.cpp | 15 +++++------ .../Render/Technique/Opaque/OpaquePass.cpp | 5 ++-- .../Technique/Opaque/OpaqueResolvePass.cpp | 5 ++-- .../Technique/Transparent/TransparentPass.cpp | 5 ++-- .../Transparent/WeightedBlendRendering.cpp | 6 ++--- .../ToTexture/EquirectangularToCube.cpp | 2 +- .../Render/ToTexture/Texture3DTo2D.cpp | 2 +- .../Castor3D/Scene/Background/Background.cpp | 2 +- .../Castor3D/Shader/Shaders/GlslLighting.cpp | 18 ++++++++----- .../Castor3D/Shader/Shaders/GlslUtils.cpp | 9 +++---- .../FFTOceanRendering/OceanFFTRenderPass.cpp | 7 ++--- .../OceanRendering/OceanRenderPass.cpp | 7 ++--- .../WaterRendering/WaterRenderPass.cpp | 5 ++-- .../SmaaPostEffect/DepthEdgeDetection.cpp | 2 +- 32 files changed, 127 insertions(+), 98 deletions(-) diff --git a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp index 3116bbf6ab..e6463cca79 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp @@ -127,7 +127,8 @@ namespace castor3d::shader , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & output ); - C3D_API static LightingModelPtr createModel( Utils & utils + C3D_API static LightingModelPtr createModel( Engine const & engine + , Utils & utils , castor::String const & name , uint32_t lightsBufBinding , uint32_t lightsBufSet @@ -137,7 +138,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ); template< typename LightsBufBindingT > - static LightingModelPtr createModelT( Utils & utils + static LightingModelPtr createModelT( Engine const & engine + , Utils & utils , castor::String const & name , LightsBufBindingT lightsBufBinding , uint32_t lightsBufSet @@ -147,7 +149,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ) { - return createModel( utils + return createModel( engine + , utils , name , uint32_t( lightsBufBinding ) , lightsBufSet @@ -158,7 +161,8 @@ namespace castor3d::shader , enableVolumetric ); } template< typename LightBindingT > - static LightingModelPtr createModel( Utils & utils + static LightingModelPtr createModel( Engine const & engine + , Utils & utils , castor::String const & name , LightType light , LightBindingT lightBinding @@ -169,7 +173,8 @@ namespace castor3d::shader , uint32_t & shadowMapBinding , uint32_t shadowMapSet ) { - return createModel( utils + return createModel( engine + , utils , name , light , lightUbo @@ -195,7 +200,8 @@ namespace castor3d::shader , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows ); - C3D_API static LightingModelPtr createDiffuseModel( Utils & utils + C3D_API static LightingModelPtr createDiffuseModel( Engine const & engine + , Utils & utils , castor::String const & name , uint32_t lightsBufBinding , uint32_t lightsBufSet @@ -204,7 +210,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ); template< typename LightsBufBindingT > - static LightingModelPtr createDiffuseModelT( Utils & utils + static LightingModelPtr createDiffuseModelT( Engine const & engine + , Utils & utils , castor::String const & name , LightsBufBindingT lightsBufBinding , uint32_t lightsBufSet @@ -213,7 +220,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ) { - return createDiffuseModel( utils + return createDiffuseModel( engine + , utils , name , uint32_t( lightsBufBinding ) , lightsBufSet @@ -359,7 +367,8 @@ namespace castor3d::shader C3D_API void doDeclareGetCascadeFactors(); private: - C3D_API static LightingModelPtr createModel( Utils & utils + C3D_API static LightingModelPtr createModel( Engine const & engine + , Utils & utils , castor::String const & name , LightType light , bool lightUbo diff --git a/include/Core/Castor3D/Shader/Shaders/GlslUtils.hpp b/include/Core/Castor3D/Shader/Shaders/GlslUtils.hpp index 0ff0f8a567..9dd7e89d1a 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslUtils.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslUtils.hpp @@ -15,10 +15,10 @@ namespace castor3d::shader class Utils { public: - C3D_API explicit Utils( sdw::ShaderWriter & writer - , Engine const & engine ); + C3D_API explicit Utils( sdw::ShaderWriter & writer ); - C3D_API LightingModelPtr createLightingModel( castor::String const & name + C3D_API LightingModelPtr createLightingModel( Engine const & engine + , castor::String const & name , ShadowOptions shadowsOptions , SssProfiles const * sssProfiles , bool enableVolumetric ); @@ -170,7 +170,6 @@ namespace castor3d::shader private: sdw::ShaderWriter & m_writer; - Engine const & m_engine; sdw::Function< sdw::Void , sdw::InOutFloat , sdw::InOutFloat > m_swap1F; diff --git a/source/Core/Castor3D/Overlay/OverlayRenderer.cpp b/source/Core/Castor3D/Overlay/OverlayRenderer.cpp index 911d49bbd0..0d1e8cb338 100644 --- a/source/Core/Castor3D/Overlay/OverlayRenderer.cpp +++ b/source/Core/Castor3D/Overlay/OverlayRenderer.cpp @@ -987,7 +987,6 @@ namespace castor3d // Pixel shader ShaderModule pxl{ VK_SHADER_STAGE_FRAGMENT_BIT, "Overlay" }; { - auto & renderSystem = *getRenderSystem(); FragmentWriter writer; auto materials = std::make_unique< shader::Materials >( writer @@ -1016,7 +1015,7 @@ namespace castor3d , std::max( 1u, texturesCount ) , hasTexture ) ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; // Shader outputs auto pxl_fragColor = writer.declOutput< Vec4 >( "pxl_fragColor", 0 ); diff --git a/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/GeometryInjectionPass.cpp b/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/GeometryInjectionPass.cpp index 41884ec813..89e0bd91e8 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/GeometryInjectionPass.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/GeometryInjectionPass.cpp @@ -127,9 +127,10 @@ namespace castor3d C3D_LpvLightConfig( writer, GeometryInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eDirectional , GeometryInjectionPass::LightsIdx @@ -188,9 +189,10 @@ namespace castor3d C3D_LpvLightConfig( writer, GeometryInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eDirectional , GeometryInjectionPass::LightsIdx @@ -254,9 +256,10 @@ namespace castor3d C3D_LpvLightConfig( writer, GeometryInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eSpot , GeometryInjectionPass::LightsIdx @@ -320,9 +323,10 @@ namespace castor3d C3D_LpvLightConfig( writer, GeometryInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::ePoint , GeometryInjectionPass::LightsIdx diff --git a/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/LightInjectionPass.cpp b/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/LightInjectionPass.cpp index d80dc14747..8a5db58112 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/LightInjectionPass.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/LightPropagationVolumes/LightInjectionPass.cpp @@ -130,9 +130,10 @@ namespace castor3d C3D_LpvLightConfig( writer, LightInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eDirectional , uint32_t( LightInjectionPass::LightsIdx ) @@ -183,9 +184,10 @@ namespace castor3d C3D_LpvLightConfig( writer, LightInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eDirectional , uint32_t( LightInjectionPass::LightsIdx ) @@ -239,9 +241,10 @@ namespace castor3d C3D_LpvLightConfig( writer, LightInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::ePoint , uint32_t( LightInjectionPass::LightsIdx ) @@ -294,9 +297,10 @@ namespace castor3d C3D_LpvLightConfig( writer, LightInjectionPass::LpvLightUboIdx, 0u ); // Utility functions - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; uint32_t index = 0u; - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , renderSystem.getEngine()->getPassFactory().getLightingModelName( 1u ) , LightType::eSpot , uint32_t( LightInjectionPass::LightsIdx ) diff --git a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelBufferToTexture.cpp b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelBufferToTexture.cpp index bd774acbf0..e3e934cd27 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelBufferToTexture.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelBufferToTexture.cpp @@ -92,8 +92,7 @@ namespace castor3d } static ShaderPtr createShader( bool temporalSmoothing - , uint32_t voxelGridSize - , RenderSystem const & renderSystem ) + , uint32_t voxelGridSize ) { using namespace sdw; ComputeWriter writer; @@ -108,7 +107,7 @@ namespace castor3d , eResult , 0u ) ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; writer.implementMainT< VoidT >( 256u , [&]( ComputeIn in ) @@ -148,7 +147,7 @@ namespace castor3d auto temporalSmoothing = ( ( index >> 0 ) % 2 ) == 1u; VoxelBufferToTexture::Pipeline result{ { VK_SHADER_STAGE_COMPUTE_BIT , "VoxelBufferToTexture" - , createShader( temporalSmoothing, voxelGridSize, device.renderSystem ) } }; + , createShader( temporalSmoothing, voxelGridSize ) } }; result.pipeline = createPipeline( device, pipelineLayout, result.shader ); return result; } diff --git a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelSecondaryBounce.cpp b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelSecondaryBounce.cpp index 02b0c8c657..e7019a0931 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelSecondaryBounce.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelSecondaryBounce.cpp @@ -142,7 +142,7 @@ namespace castor3d , eResult , 0u ) ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; shader::GlobalIllumination indirect{ writer, utils }; writer.implementMainT< VoidT >( 64u, [&]( ComputeIn in ) diff --git a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp index e2d88dd211..db742768a8 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp @@ -576,7 +576,7 @@ namespace castor3d FragmentWriter writer; auto textureFlags = filterTexturesFlags( flags.textures ); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; C3D_Scene( writer , GlobalBuffersIdx::eScene @@ -604,7 +604,8 @@ namespace castor3d auto output( writer.declArrayStorageBuffer< shader::Voxel >( "voxels" , addIndex++ , RenderPipeline::eBuffers ) ); - auto lightingModel = shader::LightingModel::createDiffuseModel( utils + auto lightingModel = shader::LightingModel::createDiffuseModel( *getEngine() + , utils , shader::getLightingModelName( *getEngine(), flags.passType ) , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Core/Castor3D/Render/Passes/ComputeDepthRange.cpp b/source/Core/Castor3D/Render/Passes/ComputeDepthRange.cpp index b23545dba8..df9a9bcd02 100644 --- a/source/Core/Castor3D/Render/Passes/ComputeDepthRange.cpp +++ b/source/Core/Castor3D/Render/Passes/ComputeDepthRange.cpp @@ -83,7 +83,7 @@ namespace castor3d , pipelineLayout ) ); } - static ShaderPtr createShader( RenderSystem const & renderSystem ) + static ShaderPtr createShader() { using namespace sdw; ComputeWriter writer; @@ -100,7 +100,7 @@ namespace castor3d auto minmax = output.declMember< sdw::Int >( "minmax", 2u ); output.end(); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; writer.implementMainT< VoidT >( 32u, 32u, [&]( ComputeIn in ) { @@ -148,7 +148,7 @@ namespace castor3d , m_device{ device } , m_descriptorSetLayout{ passcompdr::createDescriptorLayout( m_device ) } , m_pipelineLayout{ passcompdr::createPipelineLayout( m_device, *m_descriptorSetLayout ) } - , m_shader{ VK_SHADER_STAGE_COMPUTE_BIT, "ComputeDepthRange", passcompdr::createShader( device.renderSystem ) } + , m_shader{ VK_SHADER_STAGE_COMPUTE_BIT, "ComputeDepthRange", passcompdr::createShader() } , m_pipeline{ passcompdr::createPipeline( device, *m_pipelineLayout, m_shader ) } , m_descriptorSetPool{ m_descriptorSetLayout->createPool( 1u ) } , m_descriptorSet{ passcompdr::createDescriptorSet( m_graph, *m_descriptorSetPool, m_pass ) } diff --git a/source/Core/Castor3D/Render/Passes/DepthPass.cpp b/source/Core/Castor3D/Render/Passes/DepthPass.cpp index 794943a9a7..7ab1a6bb4d 100644 --- a/source/Core/Castor3D/Render/Passes/DepthPass.cpp +++ b/source/Core/Castor3D/Render/Passes/DepthPass.cpp @@ -110,7 +110,6 @@ namespace castor3d using namespace sdw; FragmentWriter writer; auto textureFlags = filterTexturesFlags( flags.textures ); - auto & renderSystem = *getEngine()->getRenderSystem(); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); C3D_Scene( writer @@ -141,7 +140,7 @@ namespace castor3d auto data1 = writer.declOutput< Vec4 >( "data1", 1u ); auto velocity = writer.declOutput< Vec4 >( "velocity", 2u ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; writer.implementMainT< shader::FragmentSurfaceT, VoidT >( sdw::FragmentInT< shader::FragmentSurfaceT >{ writer , flags.submeshFlags diff --git a/source/Core/Castor3D/Render/Passes/PickingPass.cpp b/source/Core/Castor3D/Render/Passes/PickingPass.cpp index 177475d5ee..fe4a304604 100644 --- a/source/Core/Castor3D/Render/Passes/PickingPass.cpp +++ b/source/Core/Castor3D/Render/Passes/PickingPass.cpp @@ -124,8 +124,7 @@ namespace castor3d auto textureFlags = filterTexturesFlags( flags.textures ); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); - auto & renderSystem = *getEngine()->getRenderSystem(); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; // UBOs C3D_ModelsData( writer diff --git a/source/Core/Castor3D/Render/RenderTarget.cpp b/source/Core/Castor3D/Render/RenderTarget.cpp index 2a5677f577..535c8a5b06 100644 --- a/source/Core/Castor3D/Render/RenderTarget.cpp +++ b/source/Core/Castor3D/Render/RenderTarget.cpp @@ -922,7 +922,7 @@ namespace castor3d auto vtx_textureLhs = writer.declOutput< Vec2 >( "vtx_textureLhs", rendtgt::CombineLhsIdx ); auto vtx_textureRhs = writer.declOutput< Vec2 >( "vtx_textureRhs", rendtgt::CombineRhsIdx ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; auto getSafeBandedCoord = [&]( Vec2 const & texcoord ) { diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp index 79335a99cd..8164cfbe92 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp @@ -284,7 +284,7 @@ namespace castor3d auto textureFlags = filterTexturesFlags( flags.textures ); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; C3D_ModelsData( writer , GlobalBuffersIdx::eModelsData @@ -308,7 +308,8 @@ namespace castor3d C3D_ShadowMap( writer , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , shader::getLightingModelName( *getEngine(), flags.passType ) , LightType::eDirectional , lightsIndex diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp index 6888a11fb2..29512661fd 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp @@ -281,7 +281,7 @@ namespace castor3d auto textureFlags = filterTexturesFlags( flags.textures ); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; C3D_ModelsData( writer , GlobalBuffersIdx::eModelsData @@ -305,7 +305,8 @@ namespace castor3d C3D_ShadowMap( writer , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , shader::getLightingModelName( *getEngine(), flags.passType ) , LightType::ePoint , lightsIndex diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp index a8f2c9541f..6ef250a4d7 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp @@ -269,7 +269,7 @@ namespace castor3d auto textureFlags = filterTexturesFlags( flags.textures ); bool hasTextures = flags.hasTextures() && !textureFlags.empty(); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; C3D_ModelsData( writer , GlobalBuffersIdx::eModelsData @@ -293,7 +293,8 @@ namespace castor3d C3D_ShadowMap( writer , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *renderSystem.getEngine() + , utils , shader::getLightingModelName( *getEngine(), flags.passType ) , LightType::eSpot , lightsIndex diff --git a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp index 62f395ae5c..ed48f6cf75 100644 --- a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp @@ -91,7 +91,7 @@ namespace castor3d || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; C3D_Matrix( writer @@ -123,7 +123,8 @@ namespace castor3d auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf" , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp index 5bff984103..ed12b680f1 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp @@ -54,7 +54,7 @@ namespace castor3d { using namespace sdw; FragmentWriter writer; - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; // Shader outputs auto pxl_indirectDiffuse = writer.declOutput< Vec3 >( "pxl_indirectDiffuse", 0 ); @@ -76,7 +76,8 @@ namespace castor3d , llpvIndex , 0u , config.sceneFlags ); - auto lightingModel = utils.createLightingModel( shader::getLightingModelName( *renderSystem.getEngine(), passType ) + auto lightingModel = utils.createLightingModel( *renderSystem.getEngine() + , shader::getLightingModelName( *renderSystem.getEngine(), passType ) , {} , nullptr , true ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp index 63a235ac42..24b7de30a0 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp @@ -109,7 +109,7 @@ namespace castor3d { using namespace sdw; FragmentWriter writer; - shader::Utils utils{ writer, *scene.getEngine() }; + shader::Utils utils{ writer}; // Shader outputs auto pxl_diffuse = writer.declOutput< Vec3 >( "pxl_diffuse", 0 ); @@ -138,7 +138,8 @@ namespace castor3d // Utility functions auto index = uint32_t( LightPassLgtIdx::eSmLinear ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *scene.getEngine() + , utils , scene.getLightingModel( lightType ) , lightType , uint32_t( LightPassLgtIdx::eLight ) diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/SubsurfaceScatteringPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/SubsurfaceScatteringPass.cpp index 850d8bbbe0..7953a9aa19 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/SubsurfaceScatteringPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/SubsurfaceScatteringPass.cpp @@ -94,8 +94,7 @@ namespace castor3d return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); } - static ShaderPtr getBlurProgram( RenderSystem const & renderSystem - , bool isVertic ) + static ShaderPtr getBlurProgram( bool isVertic ) { using namespace sdw; FragmentWriter writer; @@ -116,7 +115,7 @@ namespace castor3d auto vtx_texture = writer.declInput< Vec2 >( "vtx_texture", 0u ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; // Shader outputs auto pxl_fragColor = writer.declOutput< Vec4 >( "pxl_fragColor", 0 ); @@ -222,7 +221,7 @@ namespace castor3d return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); } - static ShaderPtr getCombineProgram( RenderSystem const & renderSystem ) + static ShaderPtr getCombineProgram() { using namespace sdw; FragmentWriter writer; @@ -244,7 +243,7 @@ namespace castor3d // Shader outputs auto pxl_fragColor = writer.declOutput< Vec4 >( "pxl_fragColor", 0 ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; writer.implementMainT< VoidT, VoidT >( [&]( FragmentIn in , FragmentOut out ) @@ -380,15 +379,15 @@ namespace castor3d , m_blurCfgUbo{ m_device.uboPool->getBuffer< BlurConfiguration >( 0u ) } , m_blurWgtUbo{ m_device.uboPool->getBuffer< BlurWeights >( 0u ) } , m_blurHorizVertexShader{ VK_SHADER_STAGE_VERTEX_BIT, "SSSBlurX", sssss::getVertexProgram() } - , m_blurHorizPixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSBlurX", sssss::getBlurProgram( m_device.renderSystem, false ) } + , m_blurHorizPixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSBlurX", sssss::getBlurProgram( false ) } , m_blurXShader{ makeShaderState( m_device, m_blurHorizVertexShader ) , makeShaderState( m_device, m_blurHorizPixelShader ) } , m_blurVerticVertexShader{ VK_SHADER_STAGE_VERTEX_BIT, "SSSBlurY", sssss::getVertexProgram() } - , m_blurVerticPixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSBlurY", sssss::getBlurProgram( m_device.renderSystem, true ) } + , m_blurVerticPixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSBlurY", sssss::getBlurProgram( true ) } , m_blurYShader{ makeShaderState( m_device, m_blurVerticVertexShader ) , makeShaderState( m_device, m_blurVerticPixelShader ) } , m_combineVertexShader{ VK_SHADER_STAGE_VERTEX_BIT, "SSSCombine", sssss::getVertexProgram() } - , m_combinePixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSCombine", sssss::getCombineProgram( m_device.renderSystem ) } + , m_combinePixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "SSSCombine", sssss::getCombineProgram() } , m_combineShader{ makeShaderState( m_device, m_combineVertexShader ) , makeShaderState( m_device, m_combinePixelShader ) } { diff --git a/source/Core/Castor3D/Render/Technique/Opaque/OpaquePass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/OpaquePass.cpp index 86d67ce3a7..1de6d5ec14 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/OpaquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/OpaquePass.cpp @@ -159,8 +159,9 @@ namespace castor3d auto outData4 = writer.declOutput< Vec4 >( dropqpass::Output4, index++ ); auto outData5 = writer.declOutput< Vec4 >( dropqpass::Output5, index++ ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; - auto lightingModel = utils.createLightingModel( shader::getLightingModelName( *getEngine(), flags.passType ) + shader::Utils utils{ writer }; + auto lightingModel = utils.createLightingModel( *renderSystem.getEngine() + , shader::getLightingModelName( *getEngine(), flags.passType ) , {} , nullptr , true ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp index d288d6596e..716e4f58f4 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp @@ -166,10 +166,11 @@ namespace castor3d auto vtx_texture = writer.declInput< Vec2 >( "vtx_texture", 0u ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; - auto lightingModel = utils.createLightingModel( shader::getLightingModelName( *renderSystem.getEngine(), passType ) + auto lightingModel = utils.createLightingModel( *renderSystem.getEngine() + , shader::getLightingModelName( *renderSystem.getEngine(), passType ) , {} , nullptr , true ); diff --git a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp index e2801e0e03..4315d06bf4 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp @@ -146,7 +146,7 @@ namespace castor3d || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; C3D_Matrix( writer @@ -178,7 +178,8 @@ namespace castor3d auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf" , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Core/Castor3D/Render/Technique/Transparent/WeightedBlendRendering.cpp b/source/Core/Castor3D/Render/Technique/Transparent/WeightedBlendRendering.cpp index 44119d13f7..0e0b78504c 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/WeightedBlendRendering.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/WeightedBlendRendering.cpp @@ -53,7 +53,7 @@ namespace castor3d return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); } - static ShaderPtr getPixelProgram( RenderSystem const & renderSystem ) + static ShaderPtr getPixelProgram() { using namespace sdw; FragmentWriter writer; @@ -69,7 +69,7 @@ namespace castor3d // Shader outputs auto pxl_fragColor = writer.declOutput< Vec4 >( "pxl_fragColor", 0u ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; shader::Fog fog{ writer }; auto maxComponent = writer.implementFunction< Float >( "maxComponent" @@ -146,7 +146,7 @@ namespace castor3d , m_depthOnlyView{ m_transparentPassResult[WbTexture::eDepth].sampledViewId } , m_size{ size } , m_vertexShader{ VK_SHADER_STAGE_VERTEX_BIT, "TransparentCombine", wboit::getVertexProgram() } - , m_pixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "TransparentCombine", wboit::getPixelProgram( device.renderSystem ) } + , m_pixelShader{ VK_SHADER_STAGE_FRAGMENT_BIT, "TransparentCombine", wboit::getPixelProgram() } , m_stages{ makeShaderState( device, m_vertexShader ) , makeShaderState( device, m_pixelShader ) } , m_finalCombinePassDesc{ doCreateFinalCombine( graph diff --git a/source/Core/Castor3D/Render/ToTexture/EquirectangularToCube.cpp b/source/Core/Castor3D/Render/ToTexture/EquirectangularToCube.cpp index d04f002190..24b29c56d2 100644 --- a/source/Core/Castor3D/Render/ToTexture/EquirectangularToCube.cpp +++ b/source/Core/Castor3D/Render/ToTexture/EquirectangularToCube.cpp @@ -66,7 +66,7 @@ namespace castor3d // Outputs auto pxl_colour = writer.declOutput< sdw::Vec4 >( "pxl_colour", 0u ); - shader::Utils utils{ writer, *device.renderSystem.getEngine() }; + shader::Utils utils{ writer }; auto sampleSphericalMap = writer.implementFunction< sdw::Vec2 >( "sampleSphericalMap" , [&]( sdw::Vec3 const & v ) diff --git a/source/Core/Castor3D/Render/ToTexture/Texture3DTo2D.cpp b/source/Core/Castor3D/Render/ToTexture/Texture3DTo2D.cpp index 1b7eb7f62f..ff21f3e119 100644 --- a/source/Core/Castor3D/Render/ToTexture/Texture3DTo2D.cpp +++ b/source/Core/Castor3D/Render/ToTexture/Texture3DTo2D.cpp @@ -347,7 +347,7 @@ namespace castor3d , eSource , 0u ) ); - shader::Utils utils{ writer, *renderSystem.getEngine() }; + shader::Utils utils{ writer }; writer.implementMainT< VoidT, SurfaceT >( [&]( VertexIn in , VertexOutT< SurfaceT > out ) diff --git a/source/Core/Castor3D/Scene/Background/Background.cpp b/source/Core/Castor3D/Scene/Background/Background.cpp index 52a0a1f910..9c06cbe0b4 100644 --- a/source/Core/Castor3D/Scene/Background/Background.cpp +++ b/source/Core/Castor3D/Scene/Background/Background.cpp @@ -216,7 +216,7 @@ namespace castor3d C3D_HdrConfig( writer, Bindings::eHdrConfig, 0u ); auto vtx_texture = writer.declInput< Vec3 >( "vtx_texture", 0u ); auto c3d_mapSkybox = writer.declCombinedImg< FImgCubeRgba32 >( "c3d_mapSkybox", Bindings::eSkybox, 0u ); - shader::Utils utils{ writer, *m_device.renderSystem.getEngine() }; + shader::Utils utils{ writer }; // Outputs auto pxl_FragColor = writer.declOutput< Vec4 >( "pxl_FragColor", 0u ); diff --git a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp index 1b7595c6c7..0dcce9806b 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp @@ -180,7 +180,8 @@ namespace castor3d::shader ROF; } - LightingModelPtr LightingModel::createModel( Utils & utils + LightingModelPtr LightingModel::createModel( Engine const & engine + , Utils & utils , castor::String const & name , uint32_t lightsBufBinding , uint32_t lightsBufSet @@ -190,7 +191,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ) { - auto result = utils.createLightingModel( name + auto result = utils.createLightingModel( engine + , name , shadows , sssProfiles , enableVolumetric ); @@ -201,7 +203,8 @@ namespace castor3d::shader return result; } - LightingModelPtr LightingModel::createModel( Utils & utils + LightingModelPtr LightingModel::createModel( Engine const & engine + , Utils & utils , castor::String const & name , LightType lightType , bool lightUbo @@ -212,7 +215,8 @@ namespace castor3d::shader , uint32_t & shadowMapBinding , uint32_t shadowMapSet ) { - auto result = utils.createLightingModel( name + auto result = utils.createLightingModel( engine + , name , shadows , sssProfiles , true ); @@ -317,7 +321,8 @@ namespace castor3d::shader return result; } - LightingModelPtr LightingModel::createDiffuseModel( Utils & utils + LightingModelPtr LightingModel::createDiffuseModel( Engine const & engine + , Utils & utils , castor::String const & name , uint32_t lightsBufBinding , uint32_t lightsBufSet @@ -326,7 +331,8 @@ namespace castor3d::shader , uint32_t shadowMapSet , bool enableVolumetric ) { - auto result = utils.createLightingModel( name + auto result = utils.createLightingModel( engine + , name , shadows , nullptr , enableVolumetric ); diff --git a/source/Core/Castor3D/Shader/Shaders/GlslUtils.cpp b/source/Core/Castor3D/Shader/Shaders/GlslUtils.cpp index b829c52aae..89dbb8c3d1 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslUtils.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslUtils.cpp @@ -12,19 +12,18 @@ namespace castor3d::shader { - Utils::Utils( sdw::ShaderWriter & writer - , Engine const & engine ) + Utils::Utils( sdw::ShaderWriter & writer ) : m_writer{ writer } - , m_engine{ engine } { } - LightingModelPtr Utils::createLightingModel( castor::String const & name + LightingModelPtr Utils::createLightingModel( Engine const & engine + , castor::String const & name , ShadowOptions shadowsOptions , SssProfiles const * sssProfiles , bool enableVolumetric ) { - return m_engine.getLightingModelFactory().create( name + return engine.getLightingModelFactory().create( name , m_writer , *this , std::move( shadowsOptions ) diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp index 2e268c503c..2688946cd2 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp @@ -955,7 +955,7 @@ namespace ocean_fft TessellationEvaluationWriter writer; auto textureFlags = filterTexturesFlags( flags.textures ); - castor3d::shader::Utils utils{ writer, *getEngine() }; + castor3d::shader::Utils utils{ writer }; C3D_Matrix( writer , GlobalBuffersIdx::eMatrix @@ -1095,7 +1095,7 @@ namespace ocean_fft || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; shader::Fog fog{ writer }; @@ -1143,7 +1143,8 @@ namespace ocean_fft auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf" , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp index aad693e44e..244a3c4da9 100644 --- a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp @@ -873,7 +873,7 @@ namespace ocean TessellationEvaluationWriter writer; auto textureFlags = filterTexturesFlags( flags.textures ); - castor3d::shader::Utils utils{ writer, *getEngine() }; + castor3d::shader::Utils utils{ writer }; C3D_Matrix( writer , GlobalBuffersIdx::eMatrix @@ -1076,7 +1076,7 @@ namespace ocean || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; shader::Fog fog{ writer }; @@ -1121,7 +1121,8 @@ namespace ocean auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf" , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp index 1031d3214b..def8febec9 100644 --- a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp @@ -549,7 +549,7 @@ namespace water || checkFlag( flags.sceneFlags, SceneFlag::eLpvGI ) || checkFlag( flags.sceneFlags, SceneFlag::eLayeredLpvGI ); - shader::Utils utils{ writer, *getEngine() }; + shader::Utils utils{ writer }; shader::CookTorranceBRDF cookTorrance{ writer, utils }; shader::Fog fog{ writer }; @@ -599,7 +599,8 @@ namespace water auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf" , index++ , RenderPipeline::eBuffers ); - auto lightingModel = shader::LightingModel::createModel( utils + auto lightingModel = shader::LightingModel::createModel( *getEngine() + , utils , getScene().getLightingModel() , lightsIndex , RenderPipeline::eBuffers diff --git a/source/Plugins/PostEffects/SmaaPostEffect/DepthEdgeDetection.cpp b/source/Plugins/PostEffects/SmaaPostEffect/DepthEdgeDetection.cpp index 335b333cdc..108f4f49b9 100644 --- a/source/Plugins/PostEffects/SmaaPostEffect/DepthEdgeDetection.cpp +++ b/source/Plugins/PostEffects/SmaaPostEffect/DepthEdgeDetection.cpp @@ -35,7 +35,7 @@ namespace smaa { using namespace sdw; FragmentWriter writer; - castor3d::shader::Utils utils{ writer, engine }; + castor3d::shader::Utils utils{ writer }; // Shader inputs auto vtx_texture = writer.declInput< Vec2 >( "vtx_texture", 0u ); From d9f81d5f00b5914d3722df821016929c58605f22 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Wed, 22 Jun 2022 18:33:25 +0200 Subject: [PATCH 05/12] Castor3D: Added target size to shader background model. --- .../Material/Pass/PBR/Shaders/GlslPbrLighting.hpp | 2 +- .../Material/Pass/Phong/Shaders/GlslPhongLighting.hpp | 2 +- .../Render/Technique/Opaque/Lighting/LightPass.hpp | 3 ++- .../Scene/Background/Shaders/GlslIblBackground.hpp | 2 ++ .../Scene/Background/Shaders/GlslImgBackground.hpp | 2 ++ .../Scene/Background/Shaders/GlslNoIblBackground.hpp | 2 ++ .../Core/Castor3D/Shader/Shaders/GlslBackground.hpp | 10 +++++++++- include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp | 4 ++-- include/Core/Castor3D/Shader/Shaders/SdwModule.hpp | 1 + .../Material/Pass/PBR/Shaders/GlslPbrLighting.cpp | 2 +- .../Material/Pass/Phong/Shaders/GlslPhongLighting.cpp | 2 +- .../Render/Technique/ForwardRenderTechniquePass.cpp | 1 + .../Render/Technique/Opaque/Lighting/LightPass.cpp | 4 +++- .../Technique/Opaque/Lighting/LightsPipeline.cpp | 3 ++- .../Render/Technique/Opaque/OpaqueResolvePass.cpp | 1 + .../Render/Technique/Transparent/TransparentPass.cpp | 1 + .../Scene/Background/Shaders/GlslIblBackground.cpp | 5 ++++- .../Scene/Background/Shaders/GlslImgBackground.cpp | 5 ++++- .../Scene/Background/Shaders/GlslNoIblBackground.cpp | 5 ++++- source/Core/Castor3D/Shader/Shaders/GlslBackground.cpp | 6 +++++- source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp | 2 +- .../AtmosphereScattering/AtmosphereBackgroundModel.cpp | 10 ++++++++-- .../AtmosphereScattering/AtmosphereBackgroundModel.hpp | 2 ++ .../Generic/FFTOceanRendering/OceanFFTRenderPass.cpp | 1 + .../Plugins/Generic/OceanRendering/OceanRenderPass.cpp | 1 + .../Generic/ToonMaterial/Shaders/GlslToonLighting.cpp | 4 ++-- .../Generic/ToonMaterial/Shaders/GlslToonLighting.hpp | 4 ++-- .../Plugins/Generic/WaterRendering/WaterRenderPass.cpp | 1 + 28 files changed, 67 insertions(+), 21 deletions(-) diff --git a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp index 5090f899a1..6a907b1bb7 100644 --- a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp @@ -53,7 +53,7 @@ namespace castor3d::shader C3D_API void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface - , BackgroundModel const & background + , BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & output )override; diff --git a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp index f6d40f991a..b9c3d3a25c 100644 --- a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp @@ -49,7 +49,7 @@ namespace castor3d::shader C3D_API void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface - , BackgroundModel const & background + , BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & output )override; diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp index 89a47b1e40..0b7ddcabd9 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.hpp @@ -48,7 +48,8 @@ namespace castor3d , SceneFlags const & sceneFlags , LightType lightType , ShadowType shadowType - , bool shadows ); + , bool shadows + , VkExtent2D const & targetSize ); }; } diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp index 8b55d76925..f843e6174b 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp @@ -14,11 +14,13 @@ namespace castor3d::shader public: C3D_API IblBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); C3D_API static BackgroundModelPtr create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp index ccd22558ce..9f18e52f80 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp @@ -14,11 +14,13 @@ namespace castor3d::shader public: C3D_API ImgBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); C3D_API static BackgroundModelPtr create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp index f9a5fb2a71..abfaf18186 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp @@ -14,11 +14,13 @@ namespace castor3d::shader public: C3D_API NoIblBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); C3D_API static BackgroundModelPtr create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); diff --git a/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp b/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp index 704d4842c6..45eeb74ff1 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp @@ -12,12 +12,14 @@ namespace castor3d::shader { public: C3D_API BackgroundModel( sdw::ShaderWriter & writer - , Utils & utils ); + , Utils & utils + , VkExtent2D targetSize ); C3D_API virtual ~BackgroundModel() = default; C3D_API static std::unique_ptr< BackgroundModel > createModel( Scene const & scene , sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); @@ -41,9 +43,15 @@ namespace castor3d::shader , sdw::Vec2 const & fragSize , sdw::Float const & fragDepth ) = 0; + VkExtent2D const & getTargetSize()const + { + return m_targetSize; + } + protected: sdw::ShaderWriter & m_writer; Utils & m_utils; + VkExtent2D m_targetSize; }; } diff --git a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp index e6463cca79..efc3a0d6fa 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp @@ -122,7 +122,7 @@ namespace castor3d::shader , uint32_t shadowMapSet ); C3D_API void computeCombined( LightMaterial const & material , SceneData const & sceneData - , BackgroundModel const & background + , BackgroundModel & background , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows @@ -260,7 +260,7 @@ namespace castor3d::shader C3D_API virtual void compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface - , BackgroundModel const & background + , BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & output ) = 0; diff --git a/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp b/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp index 83f9eccc32..96f251e8a0 100644 --- a/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp +++ b/include/Core/Castor3D/Shader/Shaders/SdwModule.hpp @@ -135,6 +135,7 @@ namespace castor3d::shader using BackgroundModelPtr = std::unique_ptr< BackgroundModel >; using BackgroundModelCreator = std::function< BackgroundModelPtr( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) >; using BackgroundModelFactory = castor::Factory< BackgroundModel diff --git a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp index 7aba77f8a6..f19565f693 100644 --- a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp @@ -143,7 +143,7 @@ namespace castor3d::shader void PbrLightingModel::compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface - , BackgroundModel const & background + , BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & parentOutput ) diff --git a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp index 8f8528ad9d..fb2e8e555e 100644 --- a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp @@ -124,7 +124,7 @@ namespace castor3d::shader void PhongLightingModel::compute( DirectionalLight const & light , LightMaterial const & material , Surface const & surface - , BackgroundModel const & background + , BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , OutputComponents & parentOutput ) diff --git a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp index ed48f6cf75..6ce99f1b36 100644 --- a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp @@ -138,6 +138,7 @@ namespace castor3d auto backgroundModel = shader::BackgroundModel::createModel( getScene() , writer , utils + , makeExtent2D( m_size ) , index , RenderPipeline::eBuffers ); shader::GlobalIllumination indirect{ writer, utils }; diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp index 24b7de30a0..e82637dc61 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp @@ -105,7 +105,8 @@ namespace castor3d , SceneFlags const & sceneFlags , LightType lightType , ShadowType shadowType - , bool shadows ) + , bool shadows + , VkExtent2D const & targetSize ) { using namespace sdw; FragmentWriter writer; @@ -152,6 +153,7 @@ namespace castor3d auto backgroundModel = shader::BackgroundModel::createModel( scene , writer , utils + , targetSize , index , 1u ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp index 62763d3ceb..f248e893df 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightsPipeline.cpp @@ -66,7 +66,8 @@ namespace castor3d , m_config.sceneFlags , m_config.lightType , m_config.shadowType - , m_config.shadows ) } + , m_config.shadows + , makeExtent2D( getExtent( targetColourResult ) ) ) } , m_stages{ makeShaderState( m_device, m_vertexShader ) , makeShaderState( m_device, m_pixelShader ) } , m_descriptorLayout{ doCreateDescriptorLayout() } diff --git a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp index 716e4f58f4..1a83f9c6ff 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp @@ -180,6 +180,7 @@ namespace castor3d auto backgroundModel = shader::BackgroundModel::createModel( scene , writer , utils + , makeExtent2D( size ) , index , 0u ); shader::Fog fog{ writer }; diff --git a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp index 4315d06bf4..ad09d1dc3a 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp @@ -193,6 +193,7 @@ namespace castor3d auto backgroundModel = shader::BackgroundModel::createModel( getScene() , writer , utils + , makeExtent2D( m_size ) , index , RenderPipeline::eBuffers ); shader::GlobalIllumination indirect{ writer, utils }; diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp index 82487d9489..1e54237d43 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp @@ -12,9 +12,10 @@ namespace castor3d::shader IblBackgroundModel::IblBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) - : BackgroundModel{ writer, utils } + : BackgroundModel{ writer, utils, std::move( targetSize ) } { m_writer.declCombinedImg< FImgCubeRgba32 >( "c3d_mapBackground" , binding++ @@ -29,11 +30,13 @@ namespace castor3d::shader BackgroundModelPtr IblBackgroundModel::create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) { return std::make_unique< IblBackgroundModel >( writer , utils + , std::move( targetSize ) , binding , set ); } diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp index 6403016dd8..3a86471502 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp @@ -14,9 +14,10 @@ namespace castor3d::shader ImgBackgroundModel::ImgBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) - : BackgroundModel{ writer, utils } + : BackgroundModel{ writer, utils, std::move( targetSize ) } { m_writer.declCombinedImg< FImgCubeRgba32 >( "c3d_mapBackground" , binding++ @@ -25,11 +26,13 @@ namespace castor3d::shader BackgroundModelPtr ImgBackgroundModel::create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) { return std::make_unique< ImgBackgroundModel >( writer , utils + , std::move( targetSize ) , binding , set ); } diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp index 284997d90b..110d8ce6ad 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp @@ -12,9 +12,10 @@ namespace castor3d::shader NoIblBackgroundModel::NoIblBackgroundModel( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) - : BackgroundModel{ writer, utils } + : BackgroundModel{ writer, utils, std::move( targetSize ) } { m_writer.declCombinedImg< FImgCubeRgba32 >( "c3d_mapBackground" , binding++ @@ -23,11 +24,13 @@ namespace castor3d::shader BackgroundModelPtr NoIblBackgroundModel::create( sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) { return std::make_unique< NoIblBackgroundModel >( writer , utils + , std::move( targetSize ) , binding , set ); } diff --git a/source/Core/Castor3D/Shader/Shaders/GlslBackground.cpp b/source/Core/Castor3D/Shader/Shaders/GlslBackground.cpp index 61f2dfdd73..8987b42db2 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslBackground.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslBackground.cpp @@ -6,21 +6,25 @@ namespace castor3d::shader { BackgroundModel::BackgroundModel( sdw::ShaderWriter & writer - , Utils & utils ) + , Utils & utils + , VkExtent2D targetSize ) : m_writer{ writer } , m_utils{ utils } + , m_targetSize{ std::move( targetSize ) } { } std::unique_ptr< BackgroundModel > BackgroundModel::createModel( Scene const & scene , sdw::ShaderWriter & writer , Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) { return scene.getEngine()->getBackgroundModelFactory().create( scene.getBackgroundModel() , writer , utils + , std::move( targetSize ) , binding , set ); } diff --git a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp index 0dcce9806b..83f6af81b8 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslLighting.cpp @@ -128,7 +128,7 @@ namespace castor3d::shader void LightingModel::computeCombined( LightMaterial const & material , SceneData const & sceneData - , BackgroundModel const & background + , BackgroundModel & background , Surface const & surface , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp index 93fef52170..a9e1b1bfc0 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp @@ -21,9 +21,10 @@ namespace atmosphere_scattering AtmosphereBackgroundModel::AtmosphereBackgroundModel( sdw::ShaderWriter & writer , castor3d::shader::Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) - : castor3d::shader::BackgroundModel{ writer, utils } + : castor3d::shader::BackgroundModel{ writer, utils, std::move( targetSize ) } , m_cameraBuffer{ writer.declUniformBuffer<>( CameraUbo::Buffer , binding++ , set ) } @@ -56,10 +57,15 @@ namespace atmosphere_scattering castor3d::shader::BackgroundModelPtr AtmosphereBackgroundModel::create( sdw::ShaderWriter & writer , castor3d::shader::Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ) { - return std::make_unique< AtmosphereBackgroundModel >( writer, utils, binding, set ); + return std::make_unique< AtmosphereBackgroundModel >( writer + , utils + , std::move( targetSize ) + , binding + , set ); } sdw::Vec3 AtmosphereBackgroundModel::computeReflections( sdw::Vec3 const & wsIncident diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp index 3f1ac4fa17..834e66c7ec 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp @@ -21,11 +21,13 @@ namespace atmosphere_scattering public: AtmosphereBackgroundModel( sdw::ShaderWriter & writer , castor3d::shader::Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); static castor3d::shader::BackgroundModelPtr create( sdw::ShaderWriter & writer , castor3d::shader::Utils & utils + , VkExtent2D targetSize , uint32_t & binding , uint32_t set ); diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp index 2688946cd2..2c1d190611 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp @@ -1158,6 +1158,7 @@ namespace ocean_fft auto backgroundModel = shader::BackgroundModel::createModel( getScene() , writer , utils + , castor3d::makeExtent2D( m_size ) , index , RenderPipeline::eBuffers ); shader::GlobalIllumination indirect{ writer, utils }; diff --git a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp index 244a3c4da9..dedbc9e3dc 100644 --- a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp @@ -1136,6 +1136,7 @@ namespace ocean auto backgroundModel = shader::BackgroundModel::createModel( getScene() , writer , utils + , castor3d::makeExtent2D( m_size ) , index , RenderPipeline::eBuffers ); shader::GlobalIllumination indirect{ writer, utils }; diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp index 5db475cba0..688ddc6fe0 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp @@ -128,7 +128,7 @@ namespace toon::shader void ToonPhongLightingModel::compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface - , c3d::BackgroundModel const & background + , c3d::BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & parentOutput ) @@ -1050,7 +1050,7 @@ namespace toon::shader void ToonPbrLightingModel::compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface - , c3d::BackgroundModel const & background + , c3d::BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & parentOutput ) diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp index 18a99f9f49..f70ff2db9b 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp @@ -55,7 +55,7 @@ namespace toon::shader void compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface - , c3d::BackgroundModel const & background + , c3d::BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & output )override; @@ -259,7 +259,7 @@ namespace toon::shader void compute( c3d::DirectionalLight const & light , c3d::LightMaterial const & material , c3d::Surface const & surface - , c3d::BackgroundModel const & background + , c3d::BackgroundModel & background , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & output )override; diff --git a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp index def8febec9..e8693bb4a9 100644 --- a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp @@ -614,6 +614,7 @@ namespace water auto backgroundModel = shader::BackgroundModel::createModel( getScene() , writer , utils + , castor3d::makeExtent2D( m_size ) , index , RenderPipeline::eBuffers ); shader::GlobalIllumination indirect{ writer, utils }; From da9c935fefe14824bfa51a23d3532d90c844fb97 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Wed, 22 Jun 2022 18:34:19 +0200 Subject: [PATCH 06/12] Castor3D: Added a more generic function to compute directional shadow. --- .../Castor3D/Shader/Shaders/GlslShadow.hpp | 10 ++++- .../Castor3D/Shader/Shaders/GlslShadow.cpp | 38 ++++++++++++++----- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/Core/Castor3D/Shader/Shaders/GlslShadow.hpp b/include/Core/Castor3D/Shader/Shaders/GlslShadow.hpp index ce2913b2f6..6238cac527 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslShadow.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslShadow.hpp @@ -52,6 +52,13 @@ namespace castor3d , sdw::Vec3 const & lightDirection , sdw::UInt const & cascadeIndex , sdw::UInt const & maxCascade ); + C3D_API sdw::Float computeDirectional( shader::Light const & light + , sdw::Vec3 const & wsPosition + , sdw::Vec3 const & wsNormal + , sdw::Mat4 const & lightMatrix + , sdw::Vec3 const & lightDirection + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade ); C3D_API sdw::Float computeSpot( shader::Light const & light , Surface const & surface , sdw::Mat4 const & lightMatrix @@ -142,7 +149,8 @@ namespace castor3d , sdw::InVec3 > m_getLightSpacePosition; sdw::Function< sdw::Float , InLight - , InSurface + , sdw::InVec3 + , sdw::InVec3 , sdw::InMat4 , sdw::InVec3 , sdw::InUInt diff --git a/source/Core/Castor3D/Shader/Shaders/GlslShadow.cpp b/source/Core/Castor3D/Shader/Shaders/GlslShadow.cpp index 39faa78976..6ebb0faab7 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslShadow.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslShadow.cpp @@ -166,10 +166,28 @@ namespace castor3d , sdw::Vec3 const & lightDirection , sdw::UInt const & cascadeIndex , sdw::UInt const & maxCascade ) + { + return computeDirectional( light + , surface.worldPosition + , surface.worldNormal + , lightMatrix + , lightDirection + , cascadeIndex + , maxCascade ); + } + + sdw::Float Shadow::computeDirectional( shader::Light const & light + , sdw::Vec3 const & wsPosition + , sdw::Vec3 const & wsNormal + , sdw::Mat4 const & lightMatrix + , sdw::Vec3 const & lightDirection + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade ) { doDeclareComputeDirectionalShadow(); return m_computeDirectional( light - , surface + , wsPosition + , wsNormal , lightMatrix , lightDirection , cascadeIndex @@ -605,7 +623,8 @@ namespace castor3d doDeclareChebyshevUpperBound(); m_computeDirectional = m_writer.implementFunction< sdw::Float >( "c3d_shdComputeDirectional" , [this]( shader::Light const & light - , Surface const & surface + , sdw::Vec3 const & wsPosition + , sdw::Vec3 const & wsNormal , sdw::Mat4 const & lightMatrix , sdw::Vec3 const & lightToVertex , sdw::UInt cascadeIndex @@ -621,7 +640,7 @@ namespace castor3d auto c3d_mapNormalDepthDirectional = m_writer.getVariable< sdw::CombinedImage2DArrayR32 >( Shadow::MapDepthDirectional ); auto c3d_mapVarianceDirectional = m_writer.getVariable< sdw::CombinedImage2DArrayRg32 >( Shadow::MapVarianceDirectional ); auto lightSpacePosition = m_writer.declLocale( "lightSpacePosition" - , getLightSpacePosition( lightMatrix, surface.worldPosition ) ); + , getLightSpacePosition( lightMatrix, wsPosition ) ); IF( m_writer, light.shadowType == sdw::Int( int( ShadowType::eVariance ) ) ) { @@ -640,7 +659,7 @@ namespace castor3d IF( m_writer, light.shadowType == sdw::Int( int( ShadowType::ePCF ) ) ) { auto bias = m_writer.declLocale( "bias" - , m_getShadowOffset( surface.worldNormal + , m_getShadowOffset( wsNormal , normalize( lightToVertex ) , light.pcfShadowOffsets.x() , light.pcfShadowOffsets.y() ) ); @@ -653,7 +672,7 @@ namespace castor3d ELSE { auto bias = m_writer.declLocale( "bias" - , m_getShadowOffset( surface.worldNormal + , m_getShadowOffset( wsNormal , normalize( lightToVertex ) , light.rawShadowOffsets.x() , light.rawShadowOffsets.y() ) ); @@ -671,7 +690,7 @@ namespace castor3d auto c3d_mapNormalDepthDirectional = m_writer.getVariable< sdw::CombinedImage2DR32 >( Shadow::MapDepthDirectional ); auto c3d_mapVarianceDirectional = m_writer.getVariable< sdw::CombinedImage2DRg32 >( Shadow::MapVarianceDirectional ); auto lightSpacePosition = m_writer.declLocale( "lightSpacePosition" - , getLightSpacePosition( lightMatrix, surface.worldPosition ) ); + , getLightSpacePosition( lightMatrix, wsNormal ) ); IF( m_writer, light.shadowType == sdw::Int( int( ShadowType::eVariance ) ) ) { @@ -688,7 +707,7 @@ namespace castor3d IF( m_writer, light.shadowType == sdw::Int( int( ShadowType::ePCF ) ) ) { auto bias = m_writer.declLocale( "bias" - , m_getShadowOffset( surface.worldNormal + , m_getShadowOffset( wsNormal , normalize( lightToVertex ) , light.pcfShadowOffsets.x() , light.pcfShadowOffsets.y() ) ); @@ -700,7 +719,7 @@ namespace castor3d ELSE { auto bias = m_writer.declLocale( "bias" - , m_getShadowOffset( surface.worldNormal + , m_getShadowOffset( wsNormal , normalize( lightToVertex ) , light.rawShadowOffsets.x() , light.rawShadowOffsets.y() ) ); @@ -721,7 +740,8 @@ namespace castor3d } } , InLight{ m_writer, "light" } - , InSurface{ m_writer, "surface" } + , sdw::InVec3{ m_writer, "wsPosition" } + , sdw::InVec3{ m_writer, "wsNormal" } , sdw::InMat4{ m_writer, "lightMatrix" } , sdw::InVec3{ m_writer, "lightToVertex" } , sdw::InUInt{ m_writer, "cascadeIndex" } From 7c2736d32aea15ed7f4054f56127198f545074e0 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 10:01:54 +0200 Subject: [PATCH 07/12] Castor3D: shader::Surface's clipPosition now also holds depth. --- include/Core/Castor3D/Shader/Shaders/GlslSurface.hpp | 6 +++--- include/Core/Castor3D/Shader/Shaders/GlslSurface.inl | 10 +++++----- .../VoxelConeTracing/VoxelizePass.cpp | 5 ++++- .../Render/Technique/ForwardRenderTechniquePass.cpp | 5 ++++- .../Render/Technique/Opaque/IndirectLightingPass.cpp | 5 ++++- .../Render/Technique/Opaque/Lighting/LightPass.cpp | 6 +++++- .../Render/Technique/Opaque/OpaqueResolvePass.cpp | 8 +++++--- .../Render/Technique/Transparent/TransparentPass.cpp | 5 ++++- .../Generic/FFTOceanRendering/OceanFFTRenderPass.cpp | 3 ++- .../Plugins/Generic/OceanRendering/OceanRenderPass.cpp | 5 ++++- .../Plugins/Generic/WaterRendering/WaterRenderPass.cpp | 5 ++++- 11 files changed, 44 insertions(+), 19 deletions(-) diff --git a/include/Core/Castor3D/Shader/Shaders/GlslSurface.hpp b/include/Core/Castor3D/Shader/Shaders/GlslSurface.hpp index fdafda07af..485e672174 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslSurface.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslSurface.hpp @@ -23,11 +23,11 @@ namespace castor3d::shader , bool enabled ); SDW_DeclStructInstance( , SurfaceT ); - void create( sdw::Vec2 clip + void create( sdw::Vec3 clip , sdw::Vec3 view , sdw::Vec3 world , sdw::Vec3 normal ); - void create( sdw::Vec2 clip + void create( sdw::Vec3 clip , sdw::Vec3 view , sdw::Vec3 world , sdw::Vec3 normal @@ -38,7 +38,7 @@ namespace castor3d::shader static ast::type::BaseStructPtr makeType( ast::type::TypesCache & cache ); static std::unique_ptr< sdw::Struct > declare( sdw::ShaderWriter & writer ); - sdw::Vec2 clipPosition; + sdw::Vec3 clipPosition; sdw::Vec3 viewPosition; sdw::Vec3 worldPosition; sdw::Vec3 worldNormal; diff --git a/include/Core/Castor3D/Shader/Shaders/GlslSurface.inl b/include/Core/Castor3D/Shader/Shaders/GlslSurface.inl index d3ae753f94..54c9e53e5d 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslSurface.inl +++ b/include/Core/Castor3D/Shader/Shaders/GlslSurface.inl @@ -16,7 +16,7 @@ namespace castor3d::shader , ast::expr::ExprPtr expr , bool enabled ) : StructInstance{ writer, std::move( expr ), enabled } - , clipPosition{ getMember< sdw::Vec2 >( "clipPosition" ) } + , clipPosition{ getMember< sdw::Vec3 >( "clipPosition" ) } , viewPosition{ getMember< sdw::Vec3 >( "viewPosition" ) } , worldPosition{ getMember< sdw::Vec3 >( "worldPosition" ) } , worldNormal{ getMember< sdw::Vec3 >( "worldNormal" ) } @@ -25,7 +25,7 @@ namespace castor3d::shader } template< ast::var::Flag FlagT > - void SurfaceT< FlagT >::create( sdw::Vec2 clip + void SurfaceT< FlagT >::create( sdw::Vec3 clip , sdw::Vec3 view , sdw::Vec3 world , sdw::Vec3 normal ) @@ -37,7 +37,7 @@ namespace castor3d::shader } template< ast::var::Flag FlagT > - void SurfaceT< FlagT >::create( sdw::Vec2 clip + void SurfaceT< FlagT >::create( sdw::Vec3 clip , sdw::Vec3 view , sdw::Vec3 world , sdw::Vec3 normal @@ -54,7 +54,7 @@ namespace castor3d::shader void SurfaceT< FlagT >::create( sdw::Vec3 world , sdw::Vec3 normal ) { - create( sdw::vec2( 0.0_f ) + create( sdw::vec3( 0.0_f ) , sdw::vec3( 0.0_f ) , world , normal @@ -69,7 +69,7 @@ namespace castor3d::shader if ( result->empty() ) { - result->declMember( "clipPosition", ast::type::Kind::eVec2F ); + result->declMember( "clipPosition", ast::type::Kind::eVec3F ); result->declMember( "viewPosition", ast::type::Kind::eVec3F ); result->declMember( "worldPosition", ast::type::Kind::eVec3F ); result->declMember( "worldNormal", ast::type::Kind::eVec3F ); diff --git a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp index db742768a8..93d6e0dda1 100644 --- a/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp +++ b/source/Core/Castor3D/Render/GlobalIllumination/VoxelConeTracing/VoxelizePass.cpp @@ -685,7 +685,10 @@ namespace castor3d auto worldEye = writer.declLocale( "worldEye" , c3d_sceneData.cameraPosition ); auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition, in.worldPosition, normal ); + surface.create( in.fragCoord.xyz() + , in.viewPosition + , in.worldPosition + , normal ); color += occlusion * lightMat->albedo * lightingModel->computeCombinedDiffuse( *lightMat diff --git a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp index 6ce99f1b36..05ed2a2c3e 100644 --- a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp @@ -249,7 +249,10 @@ namespace castor3d , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), normal); + surface.create( in.fragCoord.xyz() + , in.viewPosition.xyz() + , in.worldPosition.xyz() + , normal ); lightingModel->computeCombined( *lightMat , c3d_sceneData , *backgroundModel diff --git a/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp index ed12b680f1..252ddd5b58 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/IndirectLightingPass.cpp @@ -132,7 +132,10 @@ namespace castor3d auto wsNormal = writer.declLocale( "wsNormal" , data1.xyz() ); auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), vsPosition, wsPosition, wsNormal ); + surface.create( vec3( in.fragCoord.xy(), depth ) + , vsPosition + , wsPosition + , wsNormal ); //auto occlusion = indirect.computeOcclusion( sceneFlags // , lightType diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp index e82637dc61..8b28c1769d 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp @@ -221,7 +221,11 @@ namespace castor3d , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), vsPosition, wsPosition, wsNormal, vec3( texCoord, 0.0_f ) ); + surface.create( vec3( in.fragCoord.xy(), data0.x() ) + , vsPosition + , wsPosition + , wsNormal + , vec3( texCoord, 0.0_f ) ); switch ( lightType ) { diff --git a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp index 1a83f9c6ff..ac24367a07 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp @@ -221,9 +221,11 @@ namespace castor3d auto albedo = writer.declLocale( "albedo" , data2.rgb() ); auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( c3d_gpInfoData.projToWorld( utils, vtx_texture, depth ) - , data1.rgb() ); - surface.texCoord.xy() = vtx_texture; + surface.create( vec3( in.fragCoord.xy(), depth ) + , vec3( 0.0_f ) + , c3d_gpInfoData.projToWorld( utils, vtx_texture, depth ) + , data1.rgb() + , vec3( vtx_texture, 0.0_f ) ); IF( writer, lighting ) { diff --git a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp index ad09d1dc3a..716ae6733d 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp @@ -295,7 +295,10 @@ namespace castor3d , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), normal ); + surface.create( in.fragCoord.xyz() + , in.viewPosition.xyz() + , in.worldPosition.xyz() + , normal ); lightingModel->computeCombined( *lightMat , c3d_sceneData , *backgroundModel diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp index 2c1d190611..4da54ef0c6 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp @@ -1256,7 +1256,8 @@ namespace ocean_fft , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition.xyz() + surface.create( in.fragCoord.xyz() + , in.viewPosition.xyz() , in.worldPosition.xyz() , finalNormal ); lightingModel->computeCombined( *lightMat diff --git a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp index dedbc9e3dc..5e1f733489 100644 --- a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp @@ -1214,7 +1214,10 @@ namespace ocean , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), finalNormal ); + surface.create( in.fragCoord.xyz() + , in.viewPosition.xyz() + , in.worldPosition.xyz() + , finalNormal ); lightingModel->computeCombined( *lightMat , c3d_sceneData , *backgroundModel diff --git a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp index e8693bb4a9..2990e816b3 100644 --- a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp @@ -696,7 +696,10 @@ namespace water , vec3( 0.0_f ) ); shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto surface = writer.declLocale< shader::Surface >( "surface" ); - surface.create( in.fragCoord.xy(), in.viewPosition.xyz(), in.worldPosition.xyz(), finalNormal ); + surface.create( in.fragCoord.xyz() + , in.viewPosition.xyz() + , in.worldPosition.xyz() + , finalNormal ); lightingModel->computeCombined( *lightMat , c3d_sceneData , *backgroundModel From 873c79af0176d0ded32d7444db394c79f6fb1baa Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 11:21:45 +0200 Subject: [PATCH 08/12] Castor3D: Added a scattering image to direct lighting result. --- .../Pass/PBR/Shaders/GlslPbrLighting.hpp | 1 + .../Pass/Phong/Shaders/GlslPhongLighting.hpp | 1 + .../Opaque/Lighting/LightingModule.hpp | 1 + .../Technique/Opaque/OpaqueResolvePass.hpp | 2 ++ .../Background/Shaders/GlslIblBackground.hpp | 3 -- .../Background/Shaders/GlslImgBackground.hpp | 3 -- .../Shaders/GlslNoIblBackground.hpp | 3 -- .../Shader/Shaders/GlslBackground.hpp | 3 -- .../Castor3D/Shader/Shaders/GlslLighting.hpp | 1 + .../Shader/Shaders/GlslOutputComponents.hpp | 4 ++- .../Pass/PBR/Shaders/GlslPbrLighting.cpp | 18 +++++++--- .../Pass/Phong/Shaders/GlslPhongLighting.cpp | 18 +++++++--- .../ShadowMap/ShadowMapPassDirectional.cpp | 5 --- .../Render/ShadowMap/ShadowMapPassPoint.cpp | 5 --- .../Render/ShadowMap/ShadowMapPassSpot.cpp | 5 --- .../Technique/ForwardRenderTechniquePass.cpp | 11 +++--- .../Technique/Opaque/DeferredRendering.cpp | 1 + .../Technique/Opaque/Lighting/LightPass.cpp | 8 ++++- .../Opaque/Lighting/LightPassResult.cpp | 8 ++++- .../Opaque/Lighting/LightPipeline.cpp | 1 + .../Opaque/Lighting/RunnableLightingPass.cpp | 26 +++++++++++--- .../Render/Technique/Opaque/LightingPass.cpp | 5 +++ .../Technique/Opaque/OpaqueResolvePass.cpp | 15 ++++---- .../Technique/Transparent/TransparentPass.cpp | 5 ++- .../Background/Shaders/GlslIblBackground.cpp | 7 ---- .../Background/Shaders/GlslImgBackground.cpp | 7 ---- .../Shaders/GlslNoIblBackground.cpp | 7 ---- .../Shader/Shaders/GlslOutputComponents.cpp | 20 ++++++++--- .../FFTOceanRendering/OceanFFTRenderPass.cpp | 12 +++---- .../Generic/FFTOceanRendering/OceanFFTUbo.cpp | 1 + .../Generic/FFTOceanRendering/OceanFFTUbo.hpp | 1 + .../OceanRendering/OceanRenderPass.cpp | 16 ++++----- .../Generic/OceanRendering/OceanUbo.cpp | 1 + .../Generic/OceanRendering/OceanUbo.hpp | 1 + .../ToonMaterial/Shaders/GlslToonLighting.cpp | 36 ++++++++++++++----- .../ToonMaterial/Shaders/GlslToonLighting.hpp | 2 ++ .../WaterRendering/WaterRenderPass.cpp | 14 ++++---- .../Generic/WaterRendering/WaterUbo.cpp | 1 + .../Generic/WaterRendering/WaterUbo.hpp | 1 + 39 files changed, 167 insertions(+), 113 deletions(-) diff --git a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp index 6a907b1bb7..bf3eb25ef1 100644 --- a/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.hpp @@ -35,6 +35,7 @@ namespace castor3d::shader C3D_API sdw::Vec3 combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient diff --git a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp index b9c3d3a25c..dbd4bc80a5 100644 --- a/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp +++ b/include/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.hpp @@ -29,6 +29,7 @@ namespace castor3d::shader C3D_API sdw::Vec3 combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient diff --git a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp index 0ae50d9e28..666020cf49 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/Lighting/LightingModule.hpp @@ -76,6 +76,7 @@ namespace castor3d eDepth, eDiffuse, eSpecular, + eScattering, eIndirectDiffuse, eIndirectSpecular, CU_ScopedEnumBounds( eDepth ), diff --git a/include/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.hpp b/include/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.hpp index 3f0946dc65..ba88fb8e0b 100644 --- a/include/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.hpp +++ b/include/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.hpp @@ -92,6 +92,7 @@ namespace castor3d , Texture const & subsurfaceScattering , Texture const & lightDiffuse , Texture const & lightSpecular + , Texture const & lightScattering , Texture const & lightIndirectDiffuse , Texture const & lightIndirectSpecular , Texture const & result @@ -130,6 +131,7 @@ namespace castor3d Texture const & m_ssaoResult; Texture const & m_subsurfaceScattering; Texture const & m_lightSpecular; + Texture const & m_lightScattering; Texture const & m_lightIndirectDiffuse; Texture const & m_lightIndirectSpecular; std::vector< ProgramPtr > m_programs; diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp index f843e6174b..5655a15112 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.hpp @@ -40,9 +40,6 @@ namespace castor3d::shader , LightMaterial const & material , sdw::Vec3 & reflection , sdw::Vec3 & refraction )override; - C3D_API sdw::Vec4 scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth )override; private: sdw::Vec3 doComputeRefractions( sdw::Vec3 const & wsIncident diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp index 9f18e52f80..c06192ec20 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.hpp @@ -40,9 +40,6 @@ namespace castor3d::shader , LightMaterial const & material , sdw::Vec3 & reflection , sdw::Vec3 & refraction )override; - C3D_API sdw::Vec4 scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth )override; public: static castor::String const Name; diff --git a/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp b/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp index abfaf18186..a0d4cb009d 100644 --- a/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp +++ b/include/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.hpp @@ -40,9 +40,6 @@ namespace castor3d::shader , LightMaterial const & material , sdw::Vec3 & reflection , sdw::Vec3 & refraction )override; - C3D_API sdw::Vec4 scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth )override; private: sdw::Vec3 doComputeRefractions( sdw::Vec3 const & wsIncident diff --git a/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp b/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp index 45eeb74ff1..a8aeb086c6 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslBackground.hpp @@ -39,9 +39,6 @@ namespace castor3d::shader , LightMaterial const & material , sdw::Vec3 & reflection , sdw::Vec3 & refraction ) = 0; - C3D_API virtual sdw::Vec4 scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth ) = 0; VkExtent2D const & getTargetSize()const { diff --git a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp index efc3a0d6fa..c39d467a3a 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslLighting.hpp @@ -94,6 +94,7 @@ namespace castor3d::shader C3D_API virtual sdw::Vec3 combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient diff --git a/include/Core/Castor3D/Shader/Shaders/GlslOutputComponents.hpp b/include/Core/Castor3D/Shader/Shaders/GlslOutputComponents.hpp index 244c98324c..d5efa9cee9 100644 --- a/include/Core/Castor3D/Shader/Shaders/GlslOutputComponents.hpp +++ b/include/Core/Castor3D/Shader/Shaders/GlslOutputComponents.hpp @@ -16,7 +16,8 @@ namespace castor3d { C3D_API explicit OutputComponents( sdw::ShaderWriter & writer ); C3D_API OutputComponents( sdw::InOutVec3 const & diffuse - , sdw::InOutVec3 const & specular ); + , sdw::InOutVec3 const & specular + , sdw::InOutVec3 const & scattering ); C3D_API ast::expr::Expr * getExpr()const; C3D_API sdw::ShaderWriter * getWriter()const; @@ -29,6 +30,7 @@ namespace castor3d sdw::InOutVec3 m_diffuse; sdw::InOutVec3 m_specular; + sdw::InOutVec3 m_scattering; private: ast::expr::ExprPtr m_expr; diff --git a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp index f19565f693..15bfd8df36 100644 --- a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp @@ -115,6 +115,7 @@ namespace castor3d::shader sdw::Vec3 PbrLightingModel::combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient @@ -128,7 +129,8 @@ namespace castor3d::shader + directSpecular + ( indirectSpecular * ambientOcclusion ) + emissive + refracted - + ( reflected * ambient * indirectAmbient * ambientOcclusion ); + + ( reflected * ambient * indirectAmbient * ambientOcclusion ) + + directScattering; } ReflectionModelPtr PbrLightingModel::getReflectionModel( uint32_t & envMapBinding @@ -160,7 +162,8 @@ namespace castor3d::shader , OutputComponents & parentOutput ) { OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightDirection = m_writer.declLocale( "lightDirection" , normalize( -light.direction ) ); m_cookTorrance.compute( light.base @@ -276,6 +279,7 @@ namespace castor3d::shader parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , InDirectionalLight( m_writer, "light" ) , InPbrLightMaterial{ m_writer, "material" } @@ -312,7 +316,8 @@ namespace castor3d::shader , OutputComponents & parentOutput ) { OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto vertexToLight = m_writer.declLocale( "vertexToLight" , light.position - surface.worldPosition ); auto distance = m_writer.declLocale( "distance" @@ -349,8 +354,10 @@ namespace castor3d::shader , light.getAttenuationFactor( distance ) ); output.m_diffuse = output.m_diffuse / attenuation; output.m_specular = output.m_specular / attenuation; + output.m_scattering = output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , InPointLight( m_writer, "light" ) , InPbrLightMaterial{ m_writer, "material" } @@ -398,7 +405,8 @@ namespace castor3d::shader auto distance = m_writer.declLocale( "distance" , length( vertexToLight ) ); OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto rawDiffuse = m_writer.declLocale( "rawDiffuse" , m_cookTorrance.compute( light.base , worldEye @@ -451,8 +459,10 @@ namespace castor3d::shader #endif output.m_specular = spotFactor * output.m_specular / attenuation; + output.m_scattering = spotFactor * output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } FI; } diff --git a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp index fb2e8e555e..2f8465958c 100644 --- a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp @@ -89,6 +89,7 @@ namespace castor3d::shader sdw::Vec3 PhongLightingModel::combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient @@ -103,7 +104,8 @@ namespace castor3d::shader + ( ambient * indirectAmbient * ambientOcclusion ) + emissive + refracted - + reflected * ambientOcclusion; + + reflected * ambientOcclusion + + directScattering; } std::unique_ptr< LightMaterial > PhongLightingModel::declMaterial( std::string const & name @@ -141,7 +143,8 @@ namespace castor3d::shader , OutputComponents & parentOutput ) { OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightDirection = m_writer.declLocale( "lightDirection" , normalize( light.direction ) ); doComputeLight( light.base @@ -255,6 +258,7 @@ namespace castor3d::shader parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , InDirectionalLight( m_writer, "light" ) , InPhongLightMaterial{ m_writer, "material" } @@ -291,7 +295,8 @@ namespace castor3d::shader , OutputComponents & parentOutput ) { OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightToVertex = m_writer.declLocale( "lightToVertex" , surface.worldPosition - light.position ); auto distance = m_writer.declLocale( "distance" @@ -326,8 +331,10 @@ namespace castor3d::shader , light.getAttenuationFactor( distance ) ); output.m_diffuse = output.m_diffuse / attenuation; output.m_specular = output.m_specular / attenuation; + output.m_scattering = output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , InPointLight( m_writer, "light" ) , InPhongLightMaterial{ m_writer, "material" } @@ -375,7 +382,8 @@ namespace castor3d::shader auto distance = m_writer.declLocale( "distLightToVertex" , length( lightToVertex ) ); OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto rawDiffuse = m_writer.declLocale( "rawDiffuse" , doComputeLight( light.base , material @@ -426,8 +434,10 @@ namespace castor3d::shader #endif output.m_specular = spotFactor * output.m_specular / attenuation; + output.m_scattering = spotFactor * output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } FI; } diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp index 8164cfbe92..f415716f72 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassDirectional.cpp @@ -454,11 +454,6 @@ namespace castor3d if ( m_needsRsm ) { - auto lightDiffuse = writer.declLocale( "lightDiffuse" - , vec3( 0.0_f ) ); - auto lightSpecular = writer.declLocale( "lightSpecular" - , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto light = writer.declLocale( "light" , c3d_shadowMapData.getDirectionalLight( *lightingModel ) ); pxl_flux.rgb() = lightMat->albedo diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp index 29512661fd..9d0d66faca 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassPoint.cpp @@ -451,11 +451,6 @@ namespace castor3d if ( m_needsRsm ) { - auto lightDiffuse = writer.declLocale( "lightDiffuse" - , vec3( 0.0_f ) ); - auto lightSpecular = writer.declLocale( "lightSpecular" - , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto light = writer.declLocale( "light" , c3d_shadowMapData.getPointLight( *lightingModel ) ); auto lightToVertex = writer.declLocale( "lightToVertex" diff --git a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp index 6ef250a4d7..c47ae3be65 100644 --- a/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp +++ b/source/Core/Castor3D/Render/ShadowMap/ShadowMapPassSpot.cpp @@ -439,11 +439,6 @@ namespace castor3d if ( m_needsRsm ) { - auto lightDiffuse = writer.declLocale( "lightDiffuse" - , vec3( 0.0_f ) ); - auto lightSpecular = writer.declLocale( "lightSpecular" - , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; auto light = writer.declLocale( "light" , c3d_shadowMapData.getSpotLight( *lightingModel ) ); auto lightToVertex = writer.declLocale( "lightToVertex" diff --git a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp index 05ed2a2c3e..6a6e517d41 100644 --- a/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp +++ b/source/Core/Castor3D/Render/Technique/ForwardRenderTechniquePass.cpp @@ -247,7 +247,9 @@ namespace castor3d , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( in.fragCoord.xyz() , in.viewPosition.xyz() @@ -309,6 +311,7 @@ namespace castor3d pxl_fragColor = vec4( lightingModel->combine( lightDiffuse , indirectDiffuse , lightSpecular + , lightScattering , lightIndirectSpecular , ambient , indirectAmbient @@ -331,12 +334,6 @@ namespace castor3d , in.worldPosition.xyz() , c3d_sceneData ); } - else - { - pxl_fragColor += backgroundModel->scatter( in.fragCoord.xy() - , vec2( sdw::Float{ float( m_size.getWidth() ) }, float( m_size.getHeight() ) ) - , in.fragCoord.z() ); - } pxl_velocity.xy() = in.getVelocity(); } ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp b/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp index 020ff02ce4..ba26dc9406 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/DeferredRendering.cpp @@ -108,6 +108,7 @@ namespace castor3d , m_subsurfaceScattering->getResult() , m_lightPassResult[LpTexture::eDiffuse] , m_lightPassResult[LpTexture::eSpecular] + , m_lightPassResult[LpTexture::eScattering] , m_lightPassResult[LpTexture::eIndirectDiffuse] , m_lightPassResult[LpTexture::eIndirectSpecular] , resultTexture diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp index 8b28c1769d..cf95760d07 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPass.cpp @@ -115,6 +115,7 @@ namespace castor3d // Shader outputs auto pxl_diffuse = writer.declOutput< Vec3 >( "pxl_diffuse", 0 ); auto pxl_specular = writer.declOutput< Vec3 >( "pxl_specular", 1 ); + auto pxl_scattering = writer.declOutput< Vec3 >( "pxl_scattering", 2 ); // Shader inputs shader::Materials materials{ writer @@ -150,6 +151,7 @@ namespace castor3d , &sssProfiles , index , 1u ); + index = uint32_t( LightPassLgtIdx::eCount ); auto backgroundModel = shader::BackgroundModel::createModel( scene , writer , utils @@ -219,7 +221,9 @@ namespace castor3d , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( vec3( in.fragCoord.xy(), data0.x() ) , vsPosition @@ -275,11 +279,13 @@ namespace castor3d pxl_diffuse = lightDiffuse; pxl_specular = lightSpecular; + pxl_scattering = lightScattering; } ELSE { pxl_diffuse = albedo; pxl_specular = vec3( 0.0_f, 0.0_f, 0.0_f ); + pxl_scattering = vec3( 0.0_f, 0.0_f, 0.0_f ); } FI; } ); diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPassResult.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPassResult.cpp index a4ef05c6f0..389f48804f 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPassResult.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPassResult.cpp @@ -24,6 +24,7 @@ namespace castor3d cuT( "Depth" ), cuT( "Diffuse" ), cuT( "Specular" ), + cuT( "Scattering" ), cuT( "IndirectDiffuse" ), cuT( "IndirectSpecular" ), } @@ -45,6 +46,8 @@ namespace castor3d | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ), device.selectSmallestFormatRGBUFloatFormat( VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ), + device.selectSmallestFormatRGBUFloatFormat( VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT + | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ), } }; return Values[size_t( texture )]; @@ -60,6 +63,7 @@ namespace castor3d opaqueBlackClearColor, opaqueBlackClearColor, opaqueBlackClearColor, + opaqueBlackClearColor, } }; return Values[size_t( texture )]; @@ -75,6 +79,7 @@ namespace castor3d VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, } }; return Values[size_t( texture )]; @@ -88,6 +93,7 @@ namespace castor3d VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, + VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, } @@ -103,7 +109,7 @@ namespace castor3d : GBufferT< LpTexture >{ handler , device , cuT( "LPResult" ) - , { nullptr, nullptr, nullptr, nullptr, nullptr } + , { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } , 0u , size } { diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPipeline.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPipeline.cpp index 829b895000..7d83b5a9f9 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPipeline.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/LightPipeline.cpp @@ -251,6 +251,7 @@ namespace castor3d , defaultColorWriteMask } ); } + attachs.push_back( attachs.back() ); attachs.push_back( attachs.back() ); return { 0u diff --git a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp index ecd83f86c3..d5e8d4f1ad 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/Lighting/RunnableLightingPass.cpp @@ -32,7 +32,9 @@ namespace castor3d .implicitAction( lpResult[LpTexture::eDiffuse].targetViewId , crg::RecordContext::clearAttachment( lpResult[LpTexture::eDiffuse].targetViewId, getClearValue( LpTexture::eDiffuse ) ) ) .implicitAction( lpResult[LpTexture::eSpecular].targetViewId - , crg::RecordContext::clearAttachment( lpResult[LpTexture::eSpecular].targetViewId, getClearValue( LpTexture::eSpecular ) ) ) } + , crg::RecordContext::clearAttachment( lpResult[LpTexture::eSpecular].targetViewId, getClearValue( LpTexture::eSpecular ) ) ) + .implicitAction( lpResult[LpTexture::eScattering].targetViewId + , crg::RecordContext::clearAttachment( lpResult[LpTexture::eScattering].targetViewId, getClearValue( LpTexture::eScattering ) ) ) } , m_device{ device } , m_scene{ scene } , m_lpResult{ lpResult } @@ -125,7 +127,8 @@ namespace castor3d castor::String name = blend ? castor::String{ cuT( "Blend" ) } : castor::String{ cuT( "First" ) }; - std::array< VkImageLayout, 3u > layouts{ ( ( blend || hasStencil ) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ) + std::array< VkImageLayout, 4u > layouts{ ( ( blend || hasStencil ) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ) + , ( blend ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED ) , ( blend ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED ) , ( blend ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED ) }; VkAttachmentLoadOp loadOp = blend @@ -162,9 +165,19 @@ namespace castor3d , VK_ATTACHMENT_LOAD_OP_DONT_CARE , VK_ATTACHMENT_STORE_OP_DONT_CARE , layouts[2u] + , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } + , { 0u + , lpResult[LpTexture::eScattering].getFormat() + , VK_SAMPLE_COUNT_1_BIT + , loadOp + , VK_ATTACHMENT_STORE_OP_STORE + , VK_ATTACHMENT_LOAD_OP_DONT_CARE + , VK_ATTACHMENT_STORE_OP_DONT_CARE + , layouts[3u] , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } }; ashes::VkAttachmentReferenceArray references{ { 1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } - , { 2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } }; + , { 2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } + , { 3u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } }; ashes::SubpassDescriptionArray subpasses; subpasses.emplace_back( ashes::SubpassDescription{ 0u @@ -203,7 +216,8 @@ namespace castor3d std::vector< VkImageView > viewAttaches{ lpResult[LpTexture::eDepth].targetView , lpResult[LpTexture::eDiffuse].targetView - , lpResult[LpTexture::eSpecular].targetView }; + , lpResult[LpTexture::eSpecular].targetView + , lpResult[LpTexture::eScattering].targetView }; auto fbCreateInfo = makeVkStruct< VkFramebufferCreateInfo >( 0u , VkRenderPass{} , uint32_t{} @@ -223,6 +237,7 @@ namespace castor3d result.clearValues.push_back( getClearValue( LpTexture::eDepth ) ); result.clearValues.push_back( getClearValue( LpTexture::eDiffuse ) ); result.clearValues.push_back( getClearValue( LpTexture::eSpecular ) ); + result.clearValues.push_back( getClearValue( LpTexture::eScattering ) ); result.attaches.push_back( { lpResult[LpTexture::eDepth].targetViewId , layouts[0] @@ -233,6 +248,9 @@ namespace castor3d result.attaches.push_back( { lpResult[LpTexture::eSpecular].targetViewId , layouts[2] , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } ); + result.attaches.push_back( { lpResult[LpTexture::eScattering].targetViewId + , layouts[3] + , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } ); return result; } diff --git a/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp index e42d1d5665..4852412888 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/LightingPass.cpp @@ -96,6 +96,10 @@ namespace castor3d , m_lpResult[LpTexture::eSpecular] , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL , TextureFactors{}.invert( true ) ); + visitor.visit( "Light Scattering" + , m_lpResult[LpTexture::eScattering] + , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + , TextureFactors{}.invert( true ) ); } void LightingPass::doUpdateLightPasses( CpuUpdater & updater @@ -211,6 +215,7 @@ namespace castor3d pass.addInOutDepthStencilView( m_lpResult[LpTexture::eDepth].targetViewId ); pass.addOutputColourView( m_lpResult[LpTexture::eDiffuse].targetViewId ); pass.addOutputColourView( m_lpResult[LpTexture::eSpecular].targetViewId ); + pass.addOutputColourView( m_lpResult[LpTexture::eScattering].targetViewId ); return pass; } } diff --git a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp index ac24367a07..d682514b3e 100644 --- a/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp +++ b/source/Core/Castor3D/Render/Technique/Opaque/OpaqueResolvePass.cpp @@ -126,6 +126,7 @@ namespace castor3d eBrdf, eDirectDiffuse, eDirectSpecular, + eDirectScattering, eIndirectDiffuse, eIndirectSpecular, eEnvironment, @@ -161,6 +162,7 @@ namespace castor3d auto c3d_mapBrdf = writer.declCombinedImg< FImg2DRg32 >( "c3d_mapBrdf", uint32_t( ResolveBind::eBrdf ), 0u ); auto c3d_mapLightDiffuse = writer.declCombinedImg< FImg2DRgba32 >( "c3d_mapLightDiffuse", uint32_t( ResolveBind::eDirectDiffuse ), 0u ); auto c3d_mapLightSpecular = writer.declCombinedImg< FImg2DRgba32 >( "c3d_mapLightSpecular", uint32_t( ResolveBind::eDirectSpecular ), 0u ); + auto c3d_mapLightScattering = writer.declCombinedImg< FImg2DRgba32 >( "c3d_mapLightScattering", uint32_t( ResolveBind::eDirectScattering ), 0u ); auto c3d_mapLightIndirectDiffuse = writer.declCombinedImg< FImg2DRgba32 >( "c3d_mapLightIndirectDiffuse", uint32_t( ResolveBind::eIndirectDiffuse ), 0u, config.hasDiffuseGi ); auto c3d_mapLightIndirectSpecular = writer.declCombinedImg< FImg2DRgba32 >( "c3d_mapLightIndirectSpecular", uint32_t( ResolveBind::eIndirectSpecular ), 0u, config.hasSpecularGi ); @@ -252,6 +254,8 @@ namespace castor3d , c3d_mapLightDiffuse.lod( vtx_texture, 0.0_f ).xyz() ); auto lightSpecular = writer.declLocale( "lightSpecular" , c3d_mapLightSpecular.lod( vtx_texture, 0.0_f ).xyz() ); + auto lightScattering = writer.declLocale( "lightScattering" + , c3d_mapLightScattering.lod( vtx_texture, 0.0_f ).xyz() ); auto lightIndirectDiffuse = writer.declLocale( "lightIndirectDiffuse" , c3d_mapLightIndirectDiffuse.lod( vtx_texture, 0.0_f ).rgb() , config.hasDiffuseGi ); @@ -295,6 +299,7 @@ namespace castor3d pxl_fragColor = vec4( lightingModel->combine( lightDiffuse , indirectDiffuse , lightSpecular + , lightScattering , config.hasSpecularGi ? lightIndirectSpecular : vec3( 0.0_f ) , ambient , indirectAmbient @@ -321,12 +326,6 @@ namespace castor3d , surface.worldPosition , c3d_sceneData ); } - ELSE - { - pxl_fragColor += backgroundModel->scatter( in.fragCoord.xy() - , vec2( sdw::Float{ float( size.width ) }, float( size.height ) ) - , depth ); - } FI; } ); return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); @@ -346,6 +345,7 @@ namespace castor3d , Texture const & subsurfaceScattering , Texture const & lightDiffuse , Texture const & lightSpecular + , Texture const & lightScattering , Texture const & lightIndirectDiffuse , Texture const & lightIndirectSpecular , Texture const & result @@ -364,6 +364,7 @@ namespace castor3d , m_ssaoResult{ ssaoResult } , m_subsurfaceScattering{ subsurfaceScattering } , m_lightSpecular{ lightSpecular } + , m_lightScattering{ lightScattering } , m_lightIndirectDiffuse{ lightIndirectDiffuse } , m_lightIndirectSpecular{ lightIndirectSpecular } { @@ -459,6 +460,8 @@ namespace castor3d , uint32_t( dropqrslv::ResolveBind::eDirectDiffuse ) ); pass.addSampledView( m_lightSpecular.sampledViewId , uint32_t( dropqrslv::ResolveBind::eDirectSpecular ) ); + pass.addSampledView( m_lightScattering.sampledViewId + , uint32_t( dropqrslv::ResolveBind::eDirectScattering ) ); pass.addSampledView( m_lightIndirectDiffuse.sampledViewId , uint32_t( dropqrslv::ResolveBind::eIndirectDiffuse ) ); pass.addSampledView( m_lightIndirectSpecular.sampledViewId diff --git a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp index 716ae6733d..75452c6612 100644 --- a/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp +++ b/source/Core/Castor3D/Render/Technique/Transparent/TransparentPass.cpp @@ -293,7 +293,9 @@ namespace castor3d , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( in.fragCoord.xyz() , in.viewPosition.xyz() @@ -356,6 +358,7 @@ namespace castor3d , lightingModel->combine( lightDiffuse , indirectDiffuse , lightSpecular + , lightScattering , lightIndirectSpecular , ambient , indirectAmbient diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp index 1e54237d43..0b94cb042f 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslIblBackground.cpp @@ -201,13 +201,6 @@ namespace castor3d::shader , prefraction ); } - sdw::Vec4 IblBackgroundModel::scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth ) - { - return vec4( 0.0_f ); - } - sdw::Vec3 IblBackgroundModel::doComputeRefractions( sdw::Vec3 const & pwsIncident , sdw::Vec3 const & pwsNormal , sdw::CombinedImageCubeRgba32 const & pprefiltered diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp index 3a86471502..42b6b9fbe2 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslImgBackground.cpp @@ -45,13 +45,6 @@ namespace castor3d::shader return vec3( 0.0_f ); } - sdw::Vec4 ImgBackgroundModel::scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth ) - { - return vec4( 0.0_f ); - } - sdw::Vec3 ImgBackgroundModel::computeRefractions( sdw::Vec3 const & pwsIncident , sdw::Vec3 const & pwsNormal , sdw::Float const & prefractionRatio diff --git a/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp b/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp index 110d8ce6ad..92358123ef 100644 --- a/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp +++ b/source/Core/Castor3D/Scene/Background/Shaders/GlslNoIblBackground.cpp @@ -154,13 +154,6 @@ namespace castor3d::shader , prefraction ); } - sdw::Vec4 NoIblBackgroundModel::scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth ) - { - return vec4( 0.0_f ); - } - sdw::Vec3 NoIblBackgroundModel::doComputeRefractions( sdw::Vec3 const & pwsIncident , sdw::Vec3 const & pwsNormal , sdw::CombinedImageCubeRgba32 const & pbackgroundMap diff --git a/source/Core/Castor3D/Shader/Shaders/GlslOutputComponents.cpp b/source/Core/Castor3D/Shader/Shaders/GlslOutputComponents.cpp index fe4545846c..c6e935391c 100644 --- a/source/Core/Castor3D/Shader/Shaders/GlslOutputComponents.cpp +++ b/source/Core/Castor3D/Shader/Shaders/GlslOutputComponents.cpp @@ -27,21 +27,32 @@ namespace castor3d result.emplace_back( std::move( expr ) ); } + args = sdw::makeFnArg( writer, value.m_scattering ); + + for ( auto & expr : args ) + { + result.emplace_back( std::move( expr ) ); + } + return result; } //*********************************************************************************************** OutputComponents::OutputComponents( sdw::ShaderWriter & writer ) - : OutputComponents{ { writer, "outDiffuse" }, { writer, "outSpecular" } } + : OutputComponents{ { writer, "outDiffuse" }, { writer, "outSpecular" }, { writer, "outScattering" } } { } OutputComponents::OutputComponents( sdw::InOutVec3 const & diffuse - , sdw::InOutVec3 const & specular ) + , sdw::InOutVec3 const & specular + , sdw::InOutVec3 const & scattering ) : m_diffuse{ diffuse } , m_specular{ specular } - , m_expr{ sdw::expr::makeComma( makeExpr( m_diffuse ), makeExpr( m_specular ) ) } + , m_scattering{ scattering } + , m_expr{ sdw::expr::makeComma( makeExpr( m_diffuse ) + , sdw::expr::makeComma( makeExpr( m_specular ) + , makeExpr( m_scattering ) ) ) } { } @@ -52,13 +63,14 @@ namespace castor3d sdw::ShaderWriter * OutputComponents::getWriter()const { - return findWriter( m_diffuse, m_specular ); + return findWriter( m_diffuse, m_specular, m_scattering ); } void OutputComponents::setVar( sdw::var::VariableList::const_iterator & var ) { m_diffuse.setVar( var ); m_specular.setVar( var ); + m_scattering.setVar( var ); } } } diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp index 4da54ef0c6..777fb2f02f 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTRenderPass.cpp @@ -1254,7 +1254,9 @@ namespace ocean_fft , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( in.fragCoord.xyz() , in.viewPosition.xyz() @@ -1270,6 +1272,7 @@ namespace ocean_fft lightMat->adjustDirectSpecular( lightSpecular ); displayDebugData( eLightDiffuse, lightDiffuse, 1.0_f ); displayDebugData( eLightSpecular, lightSpecular, 1.0_f ); + displayDebugData( eLightScattering, lightScattering, 1.0_f ); // Indirect Lighting @@ -1398,6 +1401,7 @@ namespace ocean_fft + emissive + refractionResult * colorMod + ( reflectionResult * colorMod * indirectAmbient ) + + lightScattering , depthSoftenedAlpha ); } else @@ -1412,12 +1416,6 @@ namespace ocean_fft , in.worldPosition.xyz() , c3d_sceneData ); } - else - { - pxl_colour += backgroundModel->scatter( in.fragCoord.xy() - , vec2( sdw::Float{ float( m_size.getWidth() ) }, float( m_size.getHeight() ) ) - , in.fragCoord.z() ); - } } ); return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.cpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.cpp index def1932833..32515ba9db 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.cpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.cpp @@ -24,6 +24,7 @@ namespace ocean_fft , "MatSpecular" , "LightDiffuse" , "LightSpecular" + , "LightScattering" , "IndirectOcclusion" , "LightIndirectDiffuse" , "LightIndirectSpecular" diff --git a/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.hpp b/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.hpp index 204a1ea5f8..994677a88f 100644 --- a/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.hpp +++ b/source/Plugins/Generic/FFTOceanRendering/OceanFFTUbo.hpp @@ -34,6 +34,7 @@ namespace ocean_fft eMatSpecular, eLightDiffuse, eLightSpecular, + eLightScattering, eIndirectOcclusion, eLightIndirectDiffuse, eLightIndirectSpecular, diff --git a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp index 5e1f733489..6df337e48d 100644 --- a/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanRenderPass.cpp @@ -1212,7 +1212,9 @@ namespace ocean , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( in.fragCoord.xyz() , in.viewPosition.xyz() @@ -1228,6 +1230,7 @@ namespace ocean lightMat->adjustDirectSpecular( lightSpecular ); displayDebugData( eLightDiffuse, lightDiffuse, 1.0_f ); displayDebugData( eLightSpecular, lightSpecular, 1.0_f ); + displayDebugData( eLightScattering, lightScattering, 1.0_f ); // Standard lighting models don't necessarily translate all that well to water. // It can end up looking very glossy and plastic-like, having much more form than it really should. // So here, I'm sampling some noise with three different sets of texture coordinates to try and achieve @@ -1321,7 +1324,7 @@ namespace ocean auto waterSurfacePosition = writer.declLocale( "waterSurfacePosition" , writer.ternary( distortedPosition.y() < in.worldPosition.y(), distortedPosition, scenePosition ) ); auto waterTransmission = writer.declLocale( "waterTransmission" - , material.transmission.rgb() * ( indirectAmbient + indirectDiffuse ) ); + , material.transmission.rgb() * ( indirectAmbient + indirectDiffuse ) * lightDiffuse ); auto heightFactor = writer.declLocale( "heightFactor" , c3d_oceanData.refractionHeightFactor * ( c3d_sceneData.farPlane - c3d_sceneData.nearPlane ) ); refractionResult = mix( refractionResult @@ -1344,7 +1347,7 @@ namespace ocean , utils.saturate( ( in.worldPosition.w() - c3d_oceanData.foamHeightStart ) / c3d_oceanData.foamFadeDistance ) * pow( utils.saturate( dot( in.normal.xyz(), vec3( 0.0_f, 1.0_f, 0.0_f ) ) ), c3d_oceanData.foamAngleExponent ) * foamNoise ); foamAmount += pow( ( 1.0_f - depthSoftenedAlpha ), 3.0_f ); auto foamResult = writer.declLocale( "foamResult" - , mix( vec3( 0.0_f ) + , lightDiffuse * mix( vec3( 0.0_f ) , foamColor * c3d_oceanData.foamBrightness , vec3( utils.saturate( foamAmount ) * depthSoftenedAlpha ) ) ); @@ -1366,6 +1369,7 @@ namespace ocean + refractionResult + ( reflectionResult * indirectAmbient ) + foamResult + + lightScattering , depthSoftenedAlpha ); } else @@ -1380,12 +1384,6 @@ namespace ocean , in.worldPosition.xyz() , c3d_sceneData ); } - else - { - pxl_colour += backgroundModel->scatter( in.fragCoord.xy() - , vec2( sdw::Float{ float( m_size.getWidth() ) }, float( m_size.getHeight() ) ) - , in.fragCoord.z() ); - } } ); return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); diff --git a/source/Plugins/Generic/OceanRendering/OceanUbo.cpp b/source/Plugins/Generic/OceanRendering/OceanUbo.cpp index 8542b6af6e..8ec5043c7c 100644 --- a/source/Plugins/Generic/OceanRendering/OceanUbo.cpp +++ b/source/Plugins/Generic/OceanRendering/OceanUbo.cpp @@ -17,6 +17,7 @@ namespace ocean , "MatSpecular" , "LightDiffuse" , "LightSpecular" + , "LightScattering" , "NoisedSpecular" , "SpecularNoise" , "IndirectOcclusion" diff --git a/source/Plugins/Generic/OceanRendering/OceanUbo.hpp b/source/Plugins/Generic/OceanRendering/OceanUbo.hpp index afb79e77c4..b9dcef351b 100644 --- a/source/Plugins/Generic/OceanRendering/OceanUbo.hpp +++ b/source/Plugins/Generic/OceanRendering/OceanUbo.hpp @@ -27,6 +27,7 @@ namespace ocean eMatSpecular, eLightDiffuse, eLightSpecular, + eLightScattering, eNoisedSpecular, eSpecularNoise, eIndirectOcclusion, diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp index 688ddc6fe0..8a94deddaf 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp @@ -93,6 +93,7 @@ namespace toon::shader sdw::Vec3 ToonPhongLightingModel::combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient @@ -107,7 +108,8 @@ namespace toon::shader + ( ambient * indirectAmbient * ambientOcclusion ) + emissive + refracted - + reflected * ambientOcclusion; + + reflected * ambientOcclusion + + directScattering; } std::unique_ptr< c3d::LightMaterial > ToonPhongLightingModel::declMaterial( std::string const & name @@ -145,7 +147,8 @@ namespace toon::shader , c3d::OutputComponents & parentOutput ) { c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightDirection = m_writer.declLocale( "lightDirection" , normalize( light.direction ) ); doComputeLight( light.base @@ -235,6 +238,7 @@ namespace toon::shader parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , c3d::InDirectionalLight( m_writer, "light" ) , InToonPhongLightMaterial{ m_writer, "material" } @@ -271,7 +275,8 @@ namespace toon::shader , c3d::OutputComponents & parentOutput ) { c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightToVertex = m_writer.declLocale( "lightToVertex" , surface.worldPosition - light.position ); auto distance = m_writer.declLocale( "distance" @@ -306,8 +311,10 @@ namespace toon::shader , light.getAttenuationFactor( distance ) ); output.m_diffuse = output.m_diffuse / attenuation; output.m_specular = output.m_specular / attenuation; + output.m_scattering = output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , c3d::InPointLight( m_writer, "light" ) , InToonPhongLightMaterial{ m_writer, "material" } @@ -355,7 +362,8 @@ namespace toon::shader auto distance = m_writer.declLocale( "distance" , length( lightToVertex ) ); c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; doComputeLight( light.base , material , surface @@ -386,8 +394,10 @@ namespace toon::shader spotFactor = ( spotFactor - light.outerCutOff ) / light.cutOffsDiff; output.m_diffuse = spotFactor * output.m_diffuse / attenuation; output.m_specular = spotFactor * output.m_specular / attenuation; + output.m_scattering = spotFactor * output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } FI; } @@ -1022,6 +1032,7 @@ namespace toon::shader sdw::Vec3 ToonPbrLightingModel::combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient @@ -1035,7 +1046,8 @@ namespace toon::shader + directSpecular + ( indirectSpecular * ambientOcclusion ) + emissive + refracted - + ( reflected * ambient * indirectAmbient * ambientOcclusion ); + + ( reflected * ambient * indirectAmbient * ambientOcclusion ) + + directScattering; } c3d::ReflectionModelPtr ToonPbrLightingModel::getReflectionModel( uint32_t & envMapBinding @@ -1067,7 +1079,8 @@ namespace toon::shader , c3d::OutputComponents & parentOutput ) { c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightDirection = m_writer.declLocale( "lightDirection" , normalize( -light.direction ) ); m_cookTorrance.computeAON( light.base @@ -1184,6 +1197,7 @@ namespace toon::shader parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , c3d::InDirectionalLight( m_writer, "light" ) , InToonPbrLightMaterial{ m_writer, "material" } @@ -1220,7 +1234,8 @@ namespace toon::shader , c3d::OutputComponents & parentOutput ) { c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; auto lightToVertex = m_writer.declLocale( "lightToVertex" , light.position - surface.worldPosition ); auto distance = m_writer.declLocale( "distance" @@ -1258,8 +1273,10 @@ namespace toon::shader , light.getAttenuationFactor( distance ) ); output.m_diffuse = output.m_diffuse / attenuation; output.m_specular = output.m_specular / attenuation; + output.m_scattering = output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } , c3d::InPointLight( m_writer, "light" ) , InToonPbrLightMaterial{ m_writer, "material" } @@ -1307,7 +1324,8 @@ namespace toon::shader auto distance = m_writer.declLocale( "distance" , length( lightToVertex ) ); c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) - , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) }; + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; m_cookTorrance.computeAON( light.base , worldEye , lightDirection @@ -1341,8 +1359,10 @@ namespace toon::shader spotFactor = clamp( ( spotFactor - light.outerCutOff ) / light.cutOffsDiff, 0.0_f, 1.0_f ); output.m_diffuse = spotFactor * output.m_diffuse / attenuation; output.m_specular = spotFactor * output.m_specular / attenuation; + output.m_scattering = spotFactor * output.m_scattering / attenuation; parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); } FI; } diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp index f70ff2db9b..89f09cdec0 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.hpp @@ -35,6 +35,7 @@ namespace toon::shader sdw::Vec3 combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient @@ -241,6 +242,7 @@ namespace toon::shader sdw::Vec3 combine( sdw::Vec3 const & directDiffuse , sdw::Vec3 const & indirectDiffuse , sdw::Vec3 const & directSpecular + , sdw::Vec3 const & directScattering , sdw::Vec3 const & indirectSpecular , sdw::Vec3 const & ambient , sdw::Vec3 const & indirectAmbient diff --git a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp index 2990e816b3..a57d0a21fe 100644 --- a/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterRenderPass.cpp @@ -694,7 +694,9 @@ namespace water , vec3( 0.0_f ) ); auto lightSpecular = writer.declLocale( "lightSpecular" , vec3( 0.0_f ) ); - shader::OutputComponents output{ lightDiffuse, lightSpecular }; + auto lightScattering = writer.declLocale( "lightScattering" + , vec3( 0.0_f ) ); + shader::OutputComponents output{ lightDiffuse, lightSpecular, lightScattering }; auto surface = writer.declLocale< shader::Surface >( "surface" ); surface.create( in.fragCoord.xyz() , in.viewPosition.xyz() @@ -710,6 +712,7 @@ namespace water lightMat->adjustDirectSpecular( lightSpecular ); displayDebugData( eLightDiffuse, lightDiffuse, 1.0_f ); displayDebugData( eLightSpecular, lightSpecular, 1.0_f ); + displayDebugData( eLightScattering, lightScattering, 1.0_f ); // Standard lighting models don't necessarily translate all that well to water. // It can end up looking very glossy and plastic-like, having much more form than it really should. // So here, I'm sampling some noise with three different sets of texture coordinates to try and achieve @@ -803,7 +806,7 @@ namespace water auto waterSurfacePosition = writer.declLocale( "waterSurfacePosition" , writer.ternary( distortedPosition.y() < in.worldPosition.y(), distortedPosition, scenePosition ) ); auto waterTransmission = writer.declLocale( "waterTransmission" - , material.transmission.rgb() * ( indirectAmbient + indirectDiffuse ) ); + , material.transmission.rgb() * ( indirectAmbient + indirectDiffuse ) * lightDiffuse ); auto heightFactor = writer.declLocale( "heightFactor" , c3d_waterData.refractionHeightFactor * ( c3d_sceneData.farPlane - c3d_sceneData.nearPlane ) ); refractionResult = mix( refractionResult @@ -834,6 +837,7 @@ namespace water + emissive + ( refractionResult ) + ( reflectionResult * indirectAmbient ) + + lightScattering , depthSoftenedAlpha ); } @@ -849,12 +853,6 @@ namespace water , in.worldPosition.xyz() , c3d_sceneData ); } - else - { - pxl_colour += backgroundModel->scatter( in.fragCoord.xy() - , vec2( sdw::Float{ float( m_size.getWidth() ) }, float( m_size.getHeight() ) ) - , in.fragCoord.z() ); - } } ); return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); diff --git a/source/Plugins/Generic/WaterRendering/WaterUbo.cpp b/source/Plugins/Generic/WaterRendering/WaterUbo.cpp index bcc361f82c..e973149e19 100644 --- a/source/Plugins/Generic/WaterRendering/WaterUbo.cpp +++ b/source/Plugins/Generic/WaterRendering/WaterUbo.cpp @@ -17,6 +17,7 @@ namespace water , "MatSpecular" , "LightDiffuse" , "LightSpecular" + , "LightScattering" , "NoisedSpecular" , "SpecularNoise" , "IndirectOcclusion" diff --git a/source/Plugins/Generic/WaterRendering/WaterUbo.hpp b/source/Plugins/Generic/WaterRendering/WaterUbo.hpp index 49425d7d2e..8fab40cdf9 100644 --- a/source/Plugins/Generic/WaterRendering/WaterUbo.hpp +++ b/source/Plugins/Generic/WaterRendering/WaterUbo.hpp @@ -27,6 +27,7 @@ namespace water eMatSpecular, eLightDiffuse, eLightSpecular, + eLightScattering, eNoisedSpecular, eSpecularNoise, eIndirectOcclusion, From dbe4b62f655cf7a7ea168a2e24ef54e97343161d Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 11:23:55 +0200 Subject: [PATCH 09/12] AtmosphereScattering: Implemented lighting model. --- .../AtmosphereScattering/Atmosphere.cpp | 897 ++++++++++++------ .../AtmosphereScattering/Atmosphere.hpp | 141 ++- .../AtmosphereBackground.hpp | 5 + .../AtmosphereBackgroundModel.cpp | 29 +- .../AtmosphereBackgroundModel.hpp | 5 +- .../AtmosphereBackgroundPass.cpp | 12 +- .../AtmosphereLightingModel.cpp | 444 +++++++++ .../AtmosphereLightingModel.hpp | 122 +++ .../AtmosphereMultiScatteringPass.cpp | 2 +- .../AtmosphereScatteringPlugin.cpp | 10 + .../AtmosphereSkyViewPass.cpp | 2 +- .../AtmosphereTransmittancePass.cpp | 2 +- .../AtmosphereVolumePass.cpp | 2 +- .../AtmosphereScattering/CMakeLists.txt | 2 + .../AtmosphereScattering/Scattering.cpp | 402 +++++--- .../AtmosphereScattering/Scattering.hpp | 55 +- 16 files changed, 1659 insertions(+), 473 deletions(-) create mode 100644 source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp create mode 100644 source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp diff --git a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp index ea04448421..fd6d3a7325 100644 --- a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp @@ -1,5 +1,8 @@ #include "AtmosphereScattering/Atmosphere.hpp" +#include +#include + #include #define NONLINEARSKYVIEWLUT 1 @@ -145,7 +148,42 @@ namespace atmosphere_scattering sdw::Vec3 AtmosphereConfig::getClipSpace( sdw::Vec2 const & uv , sdw::Float const & fragDepth ) { - return vec3( uv * vec2( 2.0_f ) - vec2( 1.0_f ), fragDepth ); + return vec3( fma( uv, vec2( 2.0_f ), vec2( -1.0_f ) ), fragDepth ); + } + + sdw::Vec3 AtmosphereConfig::getMultipleScattering( sdw::Vec3 const & pscattering + , sdw::Vec3 const & pextinction + , sdw::Vec3 const & pworldPos + , sdw::Float const & pviewZenithCosAngle ) + { + if ( !m_getMultipleScattering ) + { + m_getMultipleScattering = writer.implementFunction< sdw::Vec3 >( "getMultipleScattering" + , [&]( sdw::Vec3 const & scattering + , sdw::Vec3 const & extinction + , sdw::Vec3 const & worldPos + , sdw::Float const & viewZenithCosAngle ) + { + auto uv = writer.declLocale( "uv" + , clamp( vec2( viewZenithCosAngle * 0.5_f + 0.5_f + , ( length( worldPos ) - atmosphereData.bottomRadius ) / ( atmosphereData.topRadius - atmosphereData.bottomRadius ) ) + , vec2( 0.0_f ) + , vec2( 1.0_f ) ) ); + uv = vec2( fromUnitToSubUvs( uv.x(), atmosphereData.multiScatteringLUTRes ) + , fromUnitToSubUvs( uv.y(), atmosphereData.multiScatteringLUTRes ) ); + + writer.returnStmt( multiScatTexture->lod( uv, 0.0_f ).rgb() ); + } + , sdw::InVec3{ writer, "scattering" } + , sdw::InVec3{ writer, "extinction" } + , sdw::InVec3{ writer, "worldPos" } + , sdw::InFloat{ writer, "viewZenithCosAngle" } ); + } + + return m_getMultipleScattering( pscattering + , pextinction + , pworldPos + , pviewZenithCosAngle ); } SingleScatteringResult AtmosphereConfig::integrateScatteredLuminance( sdw::Vec2 const & ppixPos @@ -154,72 +192,67 @@ namespace atmosphere_scattering , sdw::Vec3 const & psunDir , sdw::Float const & psampleCountIni , sdw::Float const & pdepthBufferValue + , castor3d::shader::Light const & plight + , sdw::Vec3 const & psurfaceWorldNormal + , sdw::Mat4 const & plightMatrix + , sdw::UInt const & pcascadeIndex + , sdw::UInt const & pmaxCascade , sdw::Float const & ptMaxMax ) { - if ( !m_integrateScatteredLuminance ) + if ( shadows && shadows->isEnabled() ) { - if ( luminanceSettings.multiScatApproxEnabled ) - { - CU_Require( multiScatTexture ); - m_getMultipleScattering = writer.implementFunction< sdw::Vec3 >( "getMultipleScattering" - , [&]( sdw::Vec3 const & scattering - , sdw::Vec3 const & extinction - , sdw::Vec3 const & worldPos - , sdw::Float const & viewZenithCosAngle ) - { - auto uv = writer.declLocale( "uv" - , clamp( vec2( viewZenithCosAngle * 0.5_f + 0.5_f - , ( length( worldPos ) - atmosphereData.bottomRadius ) / ( atmosphereData.topRadius - atmosphereData.bottomRadius ) ) - , vec2( 0.0_f ) - , vec2( 1.0_f ) ) ); - uv = vec2( fromUnitToSubUvs( uv.x(), atmosphereData.multiScatteringLUTRes ) - , fromUnitToSubUvs( uv.y(), atmosphereData.multiScatteringLUTRes ) ); - - writer.returnStmt( multiScatTexture->lod( uv, 0.0_f ).rgb() ); - } - , sdw::InVec3{ writer, "scattering" } - , sdw::InVec3{ writer, "extinction" } - , sdw::InVec3{ writer, "worldPos" } - , sdw::InFloat{ writer, "viewZenithCosAngle" } ); - } - - if ( luminanceSettings.shadowMapEnabled ) - { - CU_Require( shadowMapTexture ); - CU_Require( shadowmapViewProjMat ); - m_getShadow = writer.implementFunction< sdw::Float >( "getShadow" - , [&]( sdw::Vec3 const & P ) - { - // First evaluate opaque shadow - auto shadowUv = writer.declLocale( "shadowUv" - , ( *shadowmapViewProjMat ) * vec4( P + vec3( 0.0_f, 0.0_f, -atmosphereData.bottomRadius ), 1.0_f ) ); - //shadowUv /= shadowUv.w; // not be needed as it is an ortho projection - shadowUv.x() = shadowUv.x() * 0.5_f + 0.5_f; - shadowUv.y() = -shadowUv.y() * 0.5_f + 0.5_f; - - IF( writer, all( shadowUv.xyz() >= vec3( 0.0_f ) ) && all( shadowUv.xyz() < vec3( 1.0_f ) ) ) - { - writer.returnStmt( shadowMapTexture->lod( shadowUv.xy(), shadowUv.z(), 0.0_f ) ); - } - FI; + return integrateScatteredLuminanceShadow( ppixPos + , pworldPos + , pworldDir + , psunDir + , psampleCountIni + , pdepthBufferValue + , plight + , psurfaceWorldNormal + , plightMatrix + , pcascadeIndex + , pmaxCascade + , ptMaxMax ); + } - writer.returnStmt( 1.0_f ); - } - , sdw::InVec3{ writer, "P" } ); - } + return integrateScatteredLuminanceNoShadow( ppixPos + , pworldPos + , pworldDir + , psunDir + , psampleCountIni + , pdepthBufferValue + , ptMaxMax ); + } - m_integrateScatteredLuminance = writer.implementFunction< SingleScatteringResult >( "integrateScatteredLuminance" + SingleScatteringResult AtmosphereConfig::integrateScatteredLuminanceShadow( sdw::Vec2 const & ppixPos + , sdw::Vec3 const & pworldPos + , sdw::Vec3 const & pworldDir + , sdw::Vec3 const & psunDir + , sdw::Float const & psampleCountIni + , sdw::Float const & pdepthBufferValue + , castor3d::shader::Light const & plight + , sdw::Vec3 const & psurfaceWorldNormal + , sdw::Mat4 const & plightMatrix + , sdw::UInt const & pcascadeIndex + , sdw::UInt const & pmaxCascade + , sdw::Float const & ptMaxMax ) + { + if ( !m_integrateScatteredLuminanceShadow ) + { + m_integrateScatteredLuminanceShadow = writer.implementFunction< SingleScatteringResult >( "integrateScatteredLuminanceShadow" + ( shadows ? std::string{ "Shadow" } : std::string{} ) , [&]( sdw::Vec2 const & pixPos , sdw::Vec3 const & worldPos , sdw::Vec3 const & worldDir , sdw::Vec3 const & sunDir , sdw::Float const & sampleCountIni , sdw::Float const & depthBufferValue + , castor3d::shader::Light const & light + , sdw::Vec3 const & surfaceWorldNormal + , sdw::Mat4 const & lightMatrix + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade , sdw::Float const & tMaxMax ) { - auto planetRadiusOffset = 0.01_f; - auto transmittanceLutExtent = vec2( sdw::Float{ float( transmittanceExtent.width ) }, float( transmittanceExtent.height ) ); - auto result = writer.declLocale< SingleScatteringResult >( "result" ); result.luminance = vec3( 0.0_f ); result.opticalDepth = vec3( 0.0_f ); @@ -233,59 +266,9 @@ namespace atmosphere_scattering , vec3( 0.0_f, 0.0f, 0.0f ) ); auto tBottom = writer.declLocale( "tBottom" , raySphereIntersectNearest( worldPos, worldDir, earthO, atmosphereData.bottomRadius ) ); - auto tTop = writer.declLocale( "tTop" - , raySphereIntersectNearest( worldPos, worldDir, earthO, atmosphereData.topRadius ) ); auto tMax = writer.declLocale( "tMax" , 0.0_f ); - - IF( writer, tBottom < 0.0f ) - { - IF( writer, tTop < 0.0f ) - { - tMax = 0.0f; // No intersection with earth nor atmosphere: stop right away - writer.returnStmt( result ); - } - ELSE - { - tMax = tTop; - } - FI; - } - ELSE - { - IF( writer, tTop > 0.0f ) - { - tMax = min( tTop, tBottom ); - } - FI; - } - FI; - - if ( luminanceSettings.cameraData ) - { - IF( writer, depthBufferValue >= 0.0_f ) - { - IF( writer, depthBufferValue < 1.0f ) - { - auto depthBufferWorldPos = writer.declLocale( "depthBufferWorldPos" - , getWorldPos( depthBufferValue - , pixPos - , transmittanceLutExtent ) ); - auto tDepth = writer.declLocale( "tDepth" - , length( depthBufferWorldPos - ( worldPos + vec3( 0.0_f, -atmosphereData.bottomRadius, 0.0_f ) ) ) ); // apply earth offset to go back to origin as top of earth mode. - - IF( writer, tDepth < tMax ) - { - tMax = tDepth; - } - FI; - } - FI; - } - FI; - } - - tMax = min( tMax, tMaxMax ); + doInitRay( depthBufferValue, pixPos, worldPos, worldDir, tMaxMax, earthO, tBottom, result, tMax ); // Sample count auto sampleCount = writer.declLocale( "sampleCount" @@ -294,32 +277,11 @@ namespace atmosphere_scattering , sampleCountIni ); auto tMaxFloor = writer.declLocale( "tMaxFloor" , tMax ); - - if ( luminanceSettings.variableSampleCount ) - { - sampleCount = mix( atmosphereData.rayMarchMinMaxSPP.x() - , atmosphereData.rayMarchMinMaxSPP.y() - , clamp( tMax * 0.01_f, 0.0_f, 1.0_f ) ); - sampleCountFloor = floor( sampleCount ); - tMaxFloor = tMax * sampleCountFloor / sampleCount; // rescale tMax to map to the last entire step segment. - } - auto dt = writer.declLocale( "dt" - , tMax / sampleCount ); + , doInitSampleCount( tMax, sampleCount, sampleCountFloor, tMaxFloor ) ); // Phase functions - auto uniformPhase = writer.declLocale( "uniformPhase" - , 1.0_f / ( 4.0_f * sdw::Float{ castor::Pi< float > } ) ); - auto wi = writer.declLocale( "wi" - , sunDir ); - auto wo = writer.declLocale( "wo" - , worldDir ); - auto cosTheta = writer.declLocale( "cosTheta" - , dot( wi, wo ) ); - auto miePhaseValue = writer.declLocale( "miePhaseValue" - , hgPhase( atmosphereData.miePhaseFunctionG, -cosTheta ) ); // negate cosTheta because due to worldDir being a "in" direction. - auto rayleighPhaseValue = writer.declLocale( "rayleighPhaseValue" - , rayleighPhase( cosTheta ) ); + auto [miePhaseValue, rayleighPhaseValue] = doInitPhaseFunctions( sunDir, worldDir ); if ( luminanceSettings.illuminanceIsOne ) { @@ -351,182 +313,203 @@ namespace atmosphere_scattering FOR( writer, sdw::Float, s, 0.0_f, s < sampleCount, s += 1.0_f ) { - if ( luminanceSettings.variableSampleCount ) - { - // More expenssive but artefact free - auto t0 = writer.declLocale( "t0" - , ( s ) / sampleCountFloor ); - auto t1 = writer.declLocale( "t1" - , ( s + 1.0_f ) / sampleCountFloor ); - // Non linear distribution of sample within the range. - t0 = t0 * t0; - t1 = t1 * t1; - // Make t0 and t1 world space distances. - t0 = tMaxFloor * t0; - - IF( writer, t1 > 1.0_f ) - { - t1 = tMax; - // t1 = tMaxFloor; // this reveal depth slices - } - ELSE - { - t1 = tMaxFloor * t1; - } - FI; - - //t = t0 + (t1 - t0) * (whangHashNoise(pixPos.x, pixPos.y, gFrameId * 1920 * 1080)); // With dithering required to hide some sampling artefact relying on TAA later? This may even allow volumetric shadow? - t = t0 + ( t1 - t0 ) * sampleSegmentT; - dt = t1 - t0; - } - else - { - //t = tMax * (s + sampleSegmentT) / sampleCount; - // Exact difference, important for accuracy of multiple scattering - auto newT = writer.declLocale( "newT" - , tMax * ( s + sampleSegmentT ) / sampleCount ); - dt = newT - t; - t = newT; - } - - auto P = writer.declLocale( "P" - , worldPos + t * worldDir ); - - auto medium = writer.declLocale( "medium" - , sampleMediumRGB( P ) ); - auto sampleOpticalDepth = writer.declLocale( "sampleOpticalDepth" - , medium.extinction * dt ); - auto sampleTransmittance = writer.declLocale( "sampleTransmittance" - , exp( -sampleOpticalDepth ) ); - opticalDepth += sampleOpticalDepth; - - auto pHeight = writer.declLocale( "pHeight" - , length( P ) ); - auto upVector = writer.declLocale( "upVector" - , P / pHeight ); - auto sunZenithCosAngle = writer.declLocale( "sunZenithCosAngle" - , dot( sunDir, upVector ) ); - auto uv = writer.declLocale< sdw::Vec2 >( "uv" ); - lutTransmittanceParamsToUv( pHeight, sunZenithCosAngle, uv ); - auto transmittanceToSun = writer.declLocale( "transmittanceToSun" - , vec3( 0.0_f ) ); - - if ( transmittanceTexture ) - { - transmittanceToSun = transmittanceTexture->lod( uv, 0.0_f ).rgb(); - } - - auto phaseTimesScattering = writer.declLocale< sdw::Vec3 >( "phaseTimesScattering" ); - - if ( luminanceSettings.mieRayPhase ) - { - phaseTimesScattering = medium.scatteringMie * miePhaseValue + medium.scatteringRay * rayleighPhaseValue; - } - else - { - phaseTimesScattering = medium.scattering * uniformPhase; - } - - // Earth shadow - auto tEarth = writer.declLocale( "tEarth" - , raySphereIntersectNearest( P, sunDir, earthO + planetRadiusOffset * upVector, atmosphereData.bottomRadius ) ); - auto earthShadow = writer.declLocale( "earthShadow" - , writer.ternary( tEarth >= 0.0_f, 0.0_f, 1.0_f ) ); - - // Dual scattering for multi scattering - - auto multiScatteredLuminance = writer.declLocale( "multiScatteredLuminance" - , vec3( 0.0_f ) ); - - if ( luminanceSettings.multiScatApproxEnabled ) - { - multiScatteredLuminance = m_getMultipleScattering( medium.scattering, medium.extinction, P, sunZenithCosAngle ); - } - + doStepRay( s, sampleCount, sampleCountFloor, tMaxFloor, tMax, sampleSegmentT, t, dt ); + auto P = writer.declLocale( "P", worldPos + t * worldDir ); + auto medium = writer.declLocale( "medium", sampleMediumRGB( P ) ); + auto [upVector, sunZenithCosAngle, uv, sampleTransmittance, transmittanceToSun] = doGetSunTransmittance( sunDir + , medium + , P + , dt + , opticalDepth ); + auto [phaseTimesScattering, earthShadow, multiScatteredLuminance] = doGetScatteredLuminance( sunDir + , medium + , P + , earthO + , upVector + , sunZenithCosAngle + , miePhaseValue + , rayleighPhaseValue ); auto shadow = writer.declLocale( "shadow" , 1.0_f ); - if ( luminanceSettings.shadowMapEnabled ) + if ( shadows || luminanceSettings.shadowMapEnabled ) { // First evaluate opaque shadow - shadow = m_getShadow( P ); + shadow = shadows->computeDirectional( light + , P * vec3( 1000.0_f ) + , surfaceWorldNormal + , lightMatrix + , -sunDir + , cascadeIndex + , maxCascade ); } auto S = writer.declLocale( "S" , globalL * ( earthShadow * shadow * transmittanceToSun * phaseTimesScattering + multiScatteredLuminance * medium.scattering ) ); + doComputeStep( medium + , dt + , sampleTransmittance + , earthShadow + , transmittanceToSun + , multiScatteredLuminance + , S + , t + , tPrev + , throughput + , L + , result ); + } + ROF; - // When using the power serie to accumulate all sattering order, serie r must be <1 for a serie to converge. - // Under extreme coefficient, MultiScatAs1 can grow larger and thus result in broken visuals. - // The way to fix that is to use a proper analytical integration as proposed in slide 28 of http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/ - // However, it is possible to disable as it can also work using simple power serie sum unroll up to 5th order. The rest of the orders has a really low contribution. - if ( luminanceSettings.multiScatteringPowerSerie == 0u ) - { - // 1 is the integration of luminance over the 4pi of a sphere, and assuming an isotropic phase function of 1.0/(4*PI) - result.multiScatAs1 += throughput * medium.scattering /** 1 */* dt; - } - else - { - auto MS = writer.declLocale( "MS" - , medium.scattering ); - auto MSint = writer.declLocale( "MSint" - , ( MS - MS * sampleTransmittance ) / medium.extinction ); - result.multiScatAs1 += throughput * MSint; - } + doProcessGround( worldPos, worldDir, sunDir, tMax, tBottom, globalL, throughput, L ); + result.luminance = L; + result.opticalDepth = opticalDepth; + result.transmittance = throughput; + writer.returnStmt( result ); + } + , sdw::InVec2{ writer, "pixPos" } + , sdw::InVec3{ writer, "worldPos" } + , sdw::InVec3{ writer, "worldDir" } + , sdw::InVec3{ writer, "sunDir" } + , sdw::InFloat{ writer, "sampleCountIni" } + , sdw::InFloat{ writer, "depthBufferValue" } + , castor3d::shader::InLight{ writer, "light" } + , sdw::InVec3{ writer, "surfaceWorldNormal" } + , sdw::InMat4{ writer, "lightMatrix" } + , sdw::InUInt{ writer, "cascadeIndex" } + , sdw::InUInt{ writer, "maxCascade" } + , sdw::InFloat{ writer, "tMaxMax" } ); + } - // Evaluate input to multi scattering - { - auto newMS = writer.declLocale< sdw::Vec3 >( "newMS" ); + return m_integrateScatteredLuminanceShadow( ppixPos + , pworldPos + , pworldDir + , psunDir + , psampleCountIni + , pdepthBufferValue + , plight + , psurfaceWorldNormal + , plightMatrix + , pcascadeIndex + , pmaxCascade + , ptMaxMax ); + } - newMS = earthShadow * transmittanceToSun * medium.scattering * uniformPhase; - result.newMultiScatStep0Out += throughput * ( newMS - newMS * sampleTransmittance ) / medium.extinction; - //result.newMultiScatStep0Out += sampleTransmittance * throughput * newMS * dt; + SingleScatteringResult AtmosphereConfig::integrateScatteredLuminanceNoShadow( sdw::Vec2 const & ppixPos + , sdw::Vec3 const & pworldPos + , sdw::Vec3 const & pworldDir + , sdw::Vec3 const & psunDir + , sdw::Float const & psampleCountIni + , sdw::Float const & pdepthBufferValue + , sdw::Float const & ptMaxMax ) + { + if ( !m_integrateScatteredLuminance ) + { + m_integrateScatteredLuminance = writer.implementFunction< SingleScatteringResult >( "integrateScatteredLuminance" + ( shadows ? std::string{ "Shadow" } : std::string{} ) + , [&]( sdw::Vec2 const & pixPos + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Vec3 const & sunDir + , sdw::Float const & sampleCountIni + , sdw::Float const & depthBufferValue + , sdw::Float const & tMaxMax ) + { + auto planetRadiusOffset = 0.01_f; - newMS = medium.scattering * uniformPhase * multiScatteredLuminance; - result.newMultiScatStep1Out += throughput * ( newMS - newMS * sampleTransmittance ) / medium.extinction; - //result.newMultiScatStep1Out += sampleTransmittance * throughput * newMS * dt; - } + auto result = writer.declLocale< SingleScatteringResult >( "result" ); + result.luminance = vec3( 0.0_f ); + result.opticalDepth = vec3( 0.0_f ); + result.transmittance = vec3( 0.0_f ); + result.multiScatAs1 = vec3( 0.0_f ); + result.newMultiScatStep0Out = vec3( 0.0_f ); + result.newMultiScatStep1Out = vec3( 0.0_f ); - // See slide 28 at http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/ - auto Sint = writer.declLocale( "Sint" - , ( S - S * sampleTransmittance ) / medium.extinction ); // integrate along the current step segment - L += throughput * Sint; // accumulate and also take into account the transmittance from previous steps - throughput *= sampleTransmittance; + // Compute next intersection with atmosphere or ground + auto earthO = writer.declLocale( "earthO" + , vec3( 0.0_f, 0.0f, 0.0f ) ); + auto tBottom = writer.declLocale( "tBottom" + , raySphereIntersectNearest( worldPos, worldDir, earthO, atmosphereData.bottomRadius ) ); + auto tMax = writer.declLocale( "tMax" + , 0.0_f ); + doInitRay( depthBufferValue, pixPos, worldPos, worldDir, tMaxMax, earthO, tBottom, result, tMax ); - tPrev = t; - } - ROF; + // Sample count + auto sampleCount = writer.declLocale( "sampleCount" + , sampleCountIni ); + auto sampleCountFloor = writer.declLocale( "sampleCountFloor" + , sampleCountIni ); + auto tMaxFloor = writer.declLocale( "tMaxFloor" + , tMax ); + auto dt = writer.declLocale( "dt" + , doInitSampleCount( tMax, sampleCount, sampleCountFloor, tMaxFloor ) ); - if ( luminanceSettings.useGround ) + // Phase functions + auto [miePhaseValue, rayleighPhaseValue] = doInitPhaseFunctions( sunDir, worldDir ); + + if ( luminanceSettings.illuminanceIsOne ) { - IF( writer, tMax == tBottom && tBottom > 0.0_f ) - { - // Account for bounced light off the earth - auto P = writer.declLocale( "P" - , worldPos + tBottom * worldDir ); - auto pHeight = writer.declLocale( "pHeight" - , length( P ) ); + // When building the scattering factor, we assume light illuminance is 1 to compute a transfert function relative to identity illuminance of 1. + // This make the scattering factor independent of the light. It is now only linked to the atmosphere properties. + auto globalL = writer.declLocale( "globalL" + , vec3( 1.0_f ) ); + } + else + { + auto globalL = writer.declLocale( "globalL" + , atmosphereData.sunIlluminance ); + } - auto upVector = writer.declLocale( "upVector" - , P / pHeight ); - auto sunZenithCosAngle = writer.declLocale( "sunZenithCosAngle" - , dot( sunDir, upVector ) ); - auto uv = writer.declLocale< sdw::Vec2 >( "uv" ); - lutTransmittanceParamsToUv( pHeight, sunZenithCosAngle, uv ); - auto transmittanceToSun = writer.declLocale( "transmittanceToSun" - , vec3( 0.0_f ) ); - - if ( transmittanceTexture ) - { - transmittanceToSun = transmittanceTexture->lod( uv, 0.0_f ).rgb(); - } - - auto NdotL = writer.declLocale( "NdotL" - , clamp( dot( normalize( upVector ), normalize( sunDir ) ), 0.0_f, 1.0_f ) ); - L += globalL * transmittanceToSun * throughput * NdotL * atmosphereData.groundAlbedo / castor::Pi< float >; - } - FI; + auto globalL = writer.getVariable< sdw::Vec3 >( "globalL" ); + // Ray march the atmosphere to integrate optical depth + auto L = writer.declLocale( "L" + , vec3( 0.0_f ) ); + auto throughput = writer.declLocale( "throughput" + , vec3( 1.0_f ) ); + auto opticalDepth = writer.declLocale( "opticalDepth" + , vec3( 0.0_f ) ); + auto t = writer.declLocale( "t" + , 0.0_f ); + auto tPrev = writer.declLocale( "tPrev" + , 0.0_f ); + auto sampleSegmentT = writer.declLocale( "sampleSegmentT" + , 0.3_f ); + + FOR( writer, sdw::Float, s, 0.0_f, s < sampleCount, s += 1.0_f ) + { + doStepRay( s, sampleCount, sampleCountFloor, tMaxFloor, tMax, sampleSegmentT, t, dt ); + auto P = writer.declLocale( "P", worldPos + t * worldDir ); + auto medium = writer.declLocale( "medium", sampleMediumRGB( P ) ); + auto [upVector, sunZenithCosAngle, uv, sampleTransmittance, transmittanceToSun] = doGetSunTransmittance( sunDir + , medium + , P + , dt + , opticalDepth ); + auto [phaseTimesScattering, earthShadow, multiScatteredLuminance] = doGetScatteredLuminance( sunDir + , medium + , P + , earthO + , upVector + , sunZenithCosAngle + , miePhaseValue + , rayleighPhaseValue ); + auto S = writer.declLocale( "S" + , globalL * ( earthShadow * transmittanceToSun * phaseTimesScattering + multiScatteredLuminance * medium.scattering ) ); + doComputeStep( medium + , dt + , sampleTransmittance + , earthShadow + , transmittanceToSun + , multiScatteredLuminance + , S + , t + , tPrev + , throughput + , L + , result ); } + ROF; + doProcessGround( worldPos, worldDir, sunDir, tMax , tBottom, globalL, throughput, L ); result.luminance = L; result.opticalDepth = opticalDepth; result.transmittance = throughput; @@ -597,6 +580,40 @@ namespace atmosphere_scattering return m_moveToTopAtmosphere( pworldPos, pworldDir ); } + sdw::Vec3 AtmosphereConfig::getSunRadiance( sdw::Vec3 const & pcameraPosition + , sdw::Vec3 const & psunDir + , sdw::CombinedImage2DRgba32 const & ptransmittanceMap ) + { + if ( !m_getSunRadiance ) + { + m_getSunRadiance = writer.implementFunction< sdw::Vec3 >( "getSunRadiance" + , [&]( sdw::Vec3 const & cameraPosition + , sdw::Vec3 const & sunDir + , sdw::CombinedImage2DRgba32 const & transmittanceMap ) + { + auto worldPos = writer.declLocale( "worldPos" + , cameraPosition + vec3( 0.0_f, atmosphereData.bottomRadius, 0.0_f ) ); + auto pHeight = writer.declLocale( "pHeight" + , length( worldPos ) ); + auto upVector = writer.declLocale( "upVector" + , worldPos / pHeight ); + auto sunZenithCosAngle = writer.declLocale( "sunZenithCosAngle" + , dot( sunDir, upVector ) ); + + auto uv = writer.declLocale< sdw::Vec2 >( "uv" ); + lutTransmittanceParamsToUv( atmosphereData.bottomRadius, sunZenithCosAngle, uv ); + writer.returnStmt( transmittanceMap.lod( uv, 0.0_f ).rgb() ); + } + , sdw::InVec3{ writer, "cameraPosition" } + , sdw::InVec3{ writer, "sunDir" } + , sdw::InCombinedImage2DRgba32{ writer, "transmittanceMap" } ); + } + + return m_getSunRadiance( pcameraPosition + , psunDir + , ptransmittanceMap ); + } + sdw::Float AtmosphereConfig::raySphereIntersectNearest( sdw::Vec3 const & pr0 , sdw::Vec3 const & prd , sdw::Vec3 const & ps0 @@ -963,5 +980,317 @@ namespace atmosphere_scattering , psize ); } + void AtmosphereConfig::doInitRay( sdw::Float const & depthBufferValue + , sdw::Vec2 const & pixPos + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Float const & tMaxMax + , sdw::Vec3 const & earthO + , sdw::Float const & tBottom + , SingleScatteringResult const & result + , sdw::Float & tMax ) + { + auto tTop = writer.declLocale( "tTop" + , raySphereIntersectNearest( worldPos, worldDir, earthO, atmosphereData.topRadius ) ); + + IF( writer, tBottom < 0.0f ) + { + IF( writer, tTop < 0.0f ) + { + tMax = 0.0f; // No intersection with earth nor atmosphere: stop right away + writer.returnStmt( result ); + } + ELSE + { + tMax = tTop; + } + FI; + } + ELSE + { + IF( writer, tTop > 0.0f ) + { + tMax = min( tTop, tBottom ); + } + FI; + } + FI; + + if ( luminanceSettings.cameraData ) + { + IF( writer, depthBufferValue >= 0.0_f ) + { + IF( writer, depthBufferValue < 1.0f ) + { + auto transmittanceLutExtent = vec2( sdw::Float{ float( transmittanceExtent.width ) } + , float( transmittanceExtent.height ) ); + auto depthBufferWorldPos = writer.declLocale( "depthBufferWorldPos" + , getWorldPos( depthBufferValue + , pixPos + , transmittanceLutExtent ) ); + auto tDepth = writer.declLocale( "tDepth" + , length( depthBufferWorldPos - ( worldPos + vec3( 0.0_f, -atmosphereData.bottomRadius, 0.0_f ) ) ) ); // apply earth offset to go back to origin as top of earth mode. + + IF( writer, tDepth < tMax ) + { + tMax = tDepth; + } + FI; + } + FI; + } + FI; + } + + tMax = min( tMax, tMaxMax ); + } + + sdw::Float AtmosphereConfig::doInitSampleCount( sdw::Float const & tMax + , sdw::Float & sampleCount + , sdw::Float & sampleCountFloor + , sdw::Float & tMaxFloor ) + { + if ( luminanceSettings.variableSampleCount ) + { + sampleCount = mix( atmosphereData.rayMarchMinMaxSPP.x() + , atmosphereData.rayMarchMinMaxSPP.y() + , clamp( tMax * 0.01_f, 0.0_f, 1.0_f ) ); + sampleCountFloor = floor( sampleCount ); + tMaxFloor = tMax * sampleCountFloor / sampleCount; // rescale tMax to map to the last entire step segment. + } + + return tMax / sampleCount; + } + + std::pair< sdw::Float, sdw::Float > AtmosphereConfig::doInitPhaseFunctions( sdw::Vec3 const & sunDir + , sdw::Vec3 const & worldDir ) + { + auto wi = writer.declLocale( "wi" + , sunDir ); + auto wo = writer.declLocale( "wo" + , worldDir ); + auto cosTheta = writer.declLocale( "cosTheta" + , dot( wi, wo ) ); + return { writer.declLocale( "miePhaseValue" + , hgPhase( atmosphereData.miePhaseFunctionG, -cosTheta ) ) // negate cosTheta because due to worldDir being a "in" direction. + , writer.declLocale( "rayleighPhaseValue" + , rayleighPhase( cosTheta ) ) }; + } + + void AtmosphereConfig::doStepRay( sdw::Float const & s + , sdw::Float const & sampleCount + , sdw::Float const & sampleCountFloor + , sdw::Float const & tMaxFloor + , sdw::Float const & tMax + , sdw::Float const & sampleSegmentT + , sdw::Float & t + , sdw::Float & dt ) + { + if ( luminanceSettings.variableSampleCount ) + { + // More expenssive but artefact free + auto t0 = writer.declLocale( "t0" + , ( s ) / sampleCountFloor ); + auto t1 = writer.declLocale( "t1" + , ( s + 1.0_f ) / sampleCountFloor ); + // Non linear distribution of sample within the range. + t0 = t0 * t0; + t1 = t1 * t1; + // Make t0 and t1 world space distances. + t0 = tMaxFloor * t0; + + IF( writer, t1 > 1.0_f ) + { + t1 = tMax; + // t1 = tMaxFloor; // this reveal depth slices + } + ELSE + { + t1 = tMaxFloor * t1; + } + FI; + + //t = t0 + (t1 - t0) * (whangHashNoise(pixPos.x, pixPos.y, gFrameId * 1920 * 1080)); // With dithering required to hide some sampling artefact relying on TAA later? This may even allow volumetric shadow? + t = t0 + ( t1 - t0 ) * sampleSegmentT; + dt = t1 - t0; + } + else + { + //t = tMax * (s + sampleSegmentT) / sampleCount; + // Exact difference, important for accuracy of multiple scattering + auto newT = writer.declLocale( "newT" + , tMax * ( s + sampleSegmentT ) / sampleCount ); + dt = newT - t; + t = newT; + } + } + + std::tuple< sdw::Vec3, sdw::Float, sdw::Vec2, sdw::Vec3, sdw::Vec3 > AtmosphereConfig::doGetSunTransmittance( sdw::Vec3 const & sunDir + , MediumSampleRGB const & medium + , sdw::Vec3 const & P + , sdw::Float const & dt + , sdw::Vec3 & opticalDepth ) + { + auto sampleOpticalDepth = writer.declLocale( "sampleOpticalDepth" + , medium.extinction * dt ); + auto sampleTransmittance = writer.declLocale( "sampleTransmittance" + , exp( -sampleOpticalDepth ) ); + opticalDepth += sampleOpticalDepth; + + auto pHeight = writer.declLocale( "pHeight" + , length( P ) ); + auto upVector = writer.declLocale( "upVector" + , P / pHeight ); + auto sunZenithCosAngle = writer.declLocale( "sunZenithCosAngle" + , dot( sunDir, upVector ) ); + auto uv = writer.declLocale< sdw::Vec2 >( "uv" ); + lutTransmittanceParamsToUv( pHeight, sunZenithCosAngle, uv ); + auto transmittanceToSun = writer.declLocale( "transmittanceToSun" + , vec3( 0.0_f ) ); + + if ( transmittanceTexture ) + { + transmittanceToSun = transmittanceTexture->lod( uv, 0.0_f ).rgb(); + } + + return { upVector, sunZenithCosAngle, uv, sampleTransmittance, transmittanceToSun }; + } + + std::tuple< sdw::Vec3, sdw::Float, sdw::Vec3 > AtmosphereConfig::doGetScatteredLuminance( sdw::Vec3 const & sunDir + , MediumSampleRGB const & medium + , sdw::Vec3 const & P + , sdw::Vec3 const & earthO + , sdw::Vec3 const & upVector + , sdw::Float const & sunZenithCosAngle + , sdw::Float const & miePhaseValue + , sdw::Float const & rayleighPhaseValue ) + { + auto uniformPhase = 1.0_f / ( 4.0_f * sdw::Float{ castor::Pi< float > } ); + auto planetRadiusOffset = 0.01_f; + + auto phaseTimesScattering = writer.declLocale< sdw::Vec3 >( "phaseTimesScattering" ); + + if ( luminanceSettings.mieRayPhase ) + { + phaseTimesScattering = medium.scatteringMie * miePhaseValue + medium.scatteringRay * rayleighPhaseValue; + } + else + { + phaseTimesScattering = medium.scattering * uniformPhase; + } + + // Earth shadow + auto tEarth = writer.declLocale( "tEarth" + , raySphereIntersectNearest( P, sunDir, earthO + planetRadiusOffset * upVector, atmosphereData.bottomRadius ) ); + auto earthShadow = writer.declLocale( "earthShadow" + , writer.ternary( tEarth >= 0.0_f, 0.0_f, 1.0_f ) ); + + // Dual scattering for multi scattering + auto multiScatteredLuminance = writer.declLocale( "multiScatteredLuminance" + , vec3( 0.0_f ) ); + + if ( luminanceSettings.multiScatApproxEnabled ) + { + multiScatteredLuminance = getMultipleScattering( medium.scattering, medium.extinction, P, sunZenithCosAngle ); + } + + return { phaseTimesScattering, earthShadow, multiScatteredLuminance }; + } + + void AtmosphereConfig::doComputeStep( MediumSampleRGB const & medium + , sdw::Float const & dt + , sdw::Vec3 const & sampleTransmittance + , sdw::Float const & earthShadow + , sdw::Vec3 const & transmittanceToSun + , sdw::Vec3 const & multiScatteredLuminance + , sdw::Vec3 const & S + , sdw::Float const & t + , sdw::Float & tPrev + , sdw::Vec3 & throughput + , sdw::Vec3 & L + , SingleScatteringResult & result ) + { + auto uniformPhase = 1.0_f / ( 4.0_f * sdw::Float{ castor::Pi< float > } ); + // When using the power serie to accumulate all sattering order, serie r must be <1 for a serie to converge. + // Under extreme coefficient, MultiScatAs1 can grow larger and thus result in broken visuals. + // The way to fix that is to use a proper analytical integration as proposed in slide 28 of http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/ + // However, it is possible to disable as it can also work using simple power serie sum unroll up to 5th order. The rest of the orders has a really low contribution. + if ( luminanceSettings.multiScatteringPowerSerie == 0u ) + { + // 1 is the integration of luminance over the 4pi of a sphere, and assuming an isotropic phase function of 1.0/(4*PI) + result.multiScatAs1 += throughput * medium.scattering /** 1 */ * dt; + } + else + { + auto MS = writer.declLocale( "MS" + , medium.scattering ); + auto MSint = writer.declLocale( "MSint" + , ( MS - MS * sampleTransmittance ) / medium.extinction ); + result.multiScatAs1 += throughput * MSint; + } + + // Evaluate input to multi scattering + { + auto newMS = writer.declLocale< sdw::Vec3 >( "newMS" ); + + newMS = earthShadow * transmittanceToSun * medium.scattering * uniformPhase; + result.newMultiScatStep0Out += throughput * ( newMS - newMS * sampleTransmittance ) / medium.extinction; + //result.newMultiScatStep0Out += sampleTransmittance * throughput * newMS * dt; + + newMS = medium.scattering * uniformPhase * multiScatteredLuminance; + result.newMultiScatStep1Out += throughput * ( newMS - newMS * sampleTransmittance ) / medium.extinction; + //result.newMultiScatStep1Out += sampleTransmittance * throughput * newMS * dt; + } + + // See slide 28 at http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/ + auto Sint = writer.declLocale( "Sint" + , ( S - S * sampleTransmittance ) / medium.extinction ); // integrate along the current step segment + L += throughput * Sint; // accumulate and also take into account the transmittance from previous steps + throughput *= sampleTransmittance; + + tPrev = t; + } + + void AtmosphereConfig::doProcessGround( sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Vec3 const & sunDir + , sdw::Float const & tMax + , sdw::Float const & tBottom + , sdw::Vec3 const & globalL + , sdw::Vec3 const & throughput + , sdw::Vec3 & L ) + { + if ( luminanceSettings.useGround ) + { + IF( writer, tMax == tBottom && tBottom > 0.0_f ) + { + // Account for bounced light off the earth + auto P = writer.declLocale( "P" + , worldPos + tBottom * worldDir ); + auto pHeight = writer.declLocale( "pHeight" + , length( P ) ); + + auto upVector = writer.declLocale( "upVector" + , P / pHeight ); + auto sunZenithCosAngle = writer.declLocale( "sunZenithCosAngle" + , dot( sunDir, upVector ) ); + auto uv = writer.declLocale< sdw::Vec2 >( "uv" ); + lutTransmittanceParamsToUv( pHeight, sunZenithCosAngle, uv ); + auto transmittanceToSun = writer.declLocale( "transmittanceToSun" + , vec3( 0.0_f ) ); + + if ( transmittanceTexture ) + { + transmittanceToSun = transmittanceTexture->lod( uv, 0.0_f ).rgb(); + } + + auto NdotL = writer.declLocale( "NdotL" + , clamp( dot( normalize( upVector ), normalize( sunDir ) ), 0.0_f, 1.0_f ) ); + L += globalL * transmittanceToSun * throughput * NdotL * atmosphereData.groundAlbedo / castor::Pi< float >; + } + FI; + } + } + //************************************************************************************************ } diff --git a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.hpp b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.hpp index 600e25ab9f..05f0903ed3 100644 --- a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.hpp @@ -17,6 +17,8 @@ See LICENSE file in root folder #include #include +#include + namespace atmosphere_scattering { struct SingleScatteringResult @@ -80,21 +82,21 @@ namespace atmosphere_scattering using sdw::StructInstance::getMemberArray; }; - struct AtmosphereConfig + struct LuminanceSettings { - struct LuminanceSettings - { - bool useGround{}; - CameraData const * cameraData; - bool variableSampleCount{}; - bool mieRayPhase{}; - - bool illuminanceIsOne{}; - bool multiScatApproxEnabled{}; - bool shadowMapEnabled{}; - uint32_t multiScatteringPowerSerie{ 1u }; - }; + bool useGround{}; + CameraData const * cameraData; + bool variableSampleCount{}; + bool mieRayPhase{}; + bool illuminanceIsOne{}; + bool multiScatApproxEnabled{}; + bool shadowMapEnabled{}; + uint32_t multiScatteringPowerSerie{ 1u }; + }; + + struct AtmosphereConfig + { AtmosphereConfig( sdw::ShaderWriter & writer , AtmosphereData const & atmosphereData , LuminanceSettings luminanceSettings ); @@ -109,7 +111,35 @@ namespace atmosphere_scattering , sdw::Float const & fragDepth ); sdw::Vec3 getClipSpace( sdw::Vec2 const & uv , sdw::Float const & fragDepth ); + sdw::Vec3 getMultipleScattering( sdw::Vec3 const & scattering + , sdw::Vec3 const & extinction + , sdw::Vec3 const & worldPos + , sdw::Float const & viewZenithCosAngle ); SingleScatteringResult integrateScatteredLuminance( sdw::Vec2 const & pixPos + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Vec3 const & sunDir + , sdw::Float const & sampleCountIni + , sdw::Float const & depthBufferValue + , castor3d::shader::Light const & light + , sdw::Vec3 const & surfaceWorldNormal + , sdw::Mat4 const & lightMatrix + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade + , sdw::Float const & tMaxMax = sdw::Float{ 9000000.0_f } ); + SingleScatteringResult integrateScatteredLuminanceShadow( sdw::Vec2 const & pixPos + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Vec3 const & sunDir + , sdw::Float const & sampleCountIni + , sdw::Float const & depthBufferValue + , castor3d::shader::Light const & light + , sdw::Vec3 const & surfaceWorldNormal + , sdw::Mat4 const & lightMatrix + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade + , sdw::Float const & tMaxMax = sdw::Float{ 9000000.0_f } ); + SingleScatteringResult integrateScatteredLuminanceNoShadow( sdw::Vec2 const & pixPos , sdw::Vec3 const & worldPos , sdw::Vec3 const & worldDir , sdw::Vec3 const & sunDir @@ -118,6 +148,9 @@ namespace atmosphere_scattering , sdw::Float const & tMaxMax = sdw::Float{ 9000000.0_f } ); sdw::Boolean moveToTopAtmosphere( sdw::Vec3 & worldPos , sdw::Vec3 const & worldDir ); + sdw::Vec3 getSunRadiance( sdw::Vec3 const & cameraPosition + , sdw::Vec3 const & sunDir + , sdw::CombinedImage2DRgba32 const & transmittanceMap ); // - r0: ray origin // - rd: normalized ray direction @@ -171,15 +204,74 @@ namespace atmosphere_scattering , sdw::Vec2 & uv , sdw::Vec2 const & size ); + private: + void doInitRay( sdw::Float const & depthBufferValue + , sdw::Vec2 const & pixPos + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Float const & tMaxMax + , sdw::Vec3 const & earthO + , sdw::Float const & tBottom + , SingleScatteringResult const & result + , sdw::Float & tMax ); + sdw::Float doInitSampleCount( sdw::Float const & tMax + , sdw::Float & sampleCount + , sdw::Float & sampleCountFloor + , sdw::Float & tMaxFloor ); + std::pair< sdw::Float, sdw::Float > doInitPhaseFunctions( sdw::Vec3 const & sunDir + , sdw::Vec3 const & worldDir ); + void doStepRay( sdw::Float const & s + , sdw::Float const & sampleCount + , sdw::Float const & sampleCountFloor + , sdw::Float const & tMaxFloor + , sdw::Float const & tMax + , sdw::Float const & sampleSegmentT + , sdw::Float & t + , sdw::Float & dt ); + std::tuple< sdw::Vec3, sdw::Float, sdw::Vec2, sdw::Vec3, sdw::Vec3 > doGetSunTransmittance( sdw::Vec3 const & sunDir + , MediumSampleRGB const & medium + , sdw::Vec3 const & P + , sdw::Float const & dt + , sdw::Vec3 & opticalDepth ); + std::tuple< sdw::Vec3, sdw::Float, sdw::Vec3 > doGetScatteredLuminance( sdw::Vec3 const & sunDir + , MediumSampleRGB const & medium + , sdw::Vec3 const & P + , sdw::Vec3 const & earthO + , sdw::Vec3 const & upVector + , sdw::Float const & sunZenithCosAngle + , sdw::Float const & miePhaseValue + , sdw::Float const & rayleighPhaseValue ); + void doComputeStep( MediumSampleRGB const & medium + , sdw::Float const & dt + , sdw::Vec3 const & sampleTransmittance + , sdw::Float const & earthShadow + , sdw::Vec3 const & transmittanceToSun + , sdw::Vec3 const & multiScatteredLuminance + , sdw::Vec3 const & S + , sdw::Float const & t + , sdw::Float & tPrev + , sdw::Vec3 & throughput + , sdw::Vec3 & L + , SingleScatteringResult & result ); + void doProcessGround( sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::Vec3 const & sunDir + , sdw::Float const & tMax + , sdw::Float const & tBottom + , sdw::Vec3 const & globalL + , sdw::Vec3 const & throughput + , sdw::Vec3 & L ); + private: sdw::ShaderWriter & writer; + + public: AtmosphereData const & atmosphereData; LuminanceSettings luminanceSettings{}; VkExtent2D transmittanceExtent{}; sdw::CombinedImage2DRgba32 const * transmittanceTexture{}; sdw::CombinedImage2DRgba32 const * multiScatTexture{}; - sdw::CombinedImage2DShadowR32 const * shadowMapTexture{}; - sdw::Mat4 const * shadowmapViewProjMat; + std::shared_ptr< castor3d::shader::Shadow > shadows; private: sdw::Function< SingleScatteringResult @@ -190,6 +282,19 @@ namespace atmosphere_scattering , sdw::InFloat , sdw::InFloat , sdw::InFloat > m_integrateScatteredLuminance; + sdw::Function< SingleScatteringResult + , sdw::InVec2 + , sdw::InVec3 + , sdw::InVec3 + , sdw::InVec3 + , sdw::InFloat + , sdw::InFloat + , castor3d::shader::InLight + , sdw::InVec3 + , sdw::InMat4 + , sdw::InUInt + , sdw::InUInt + , sdw::InFloat > m_integrateScatteredLuminanceShadow; sdw::Function< sdw::Boolean , sdw::InOutVec3 , sdw::InVec3 > m_moveToTopAtmosphere; @@ -229,12 +334,14 @@ namespace atmosphere_scattering , sdw::InVec3 , sdw::InVec3 , sdw::InFloat > m_getMultipleScattering; - sdw::Function< sdw::Float - , sdw::InVec3 > m_getShadow; sdw::Function< sdw::Vec3 , sdw::InFloat , sdw::InVec2 , sdw::InVec2 > m_getWorldPos; + sdw::Function< sdw::Vec3 + , sdw::InVec3 + , sdw::InVec3 + , sdw::InCombinedImage2DRgba32 > m_getSunRadiance; }; } diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackground.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackground.hpp index c123a19025..bfcffe5ff4 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackground.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackground.hpp @@ -78,6 +78,11 @@ namespace atmosphere_scattering void loadAtmosphereVolume( uint32_t dimension ); void loadSkyView( castor::Point2ui const & dimensions ); + bool hasScattering()const override + { + return true; + } + bool isDepthSampled()const override { return true; diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp index a9e1b1bfc0..ee7a482b66 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.cpp @@ -45,7 +45,7 @@ namespace atmosphere_scattering , m_atmosphere , m_cameraData , m_atmosphereData - , false, true, true, false } + , false, true, true, true } { m_writer.declCombinedImg< sdw::CombinedImage2DRgba32 >( "c3d_mapSkyView" , binding++ @@ -96,29 +96,10 @@ namespace atmosphere_scattering return sdw::Void{}; } - sdw::Vec4 AtmosphereBackgroundModel::scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth ) + sdw::Vec3 AtmosphereBackgroundModel::getSunRadiance( sdw::Vec3 const & psunDir ) { - auto luminance = m_writer.declLocale< sdw::Vec4 >( "luminance" ); - auto transmittance = m_writer.declLocale< sdw::Vec4 >( "transmittance" ); - m_scattering.getPixelTransLum( fragPos - , fragSize - , fragDepth - , m_transmittanceMap - , m_writer.getVariable< sdw::CombinedImage2DRgba32 >( "c3d_mapSkyView" ) - , m_writer.getVariable< sdw::CombinedImage3DRgba32 >( "c3d_mapVolume" ) - , transmittance - , luminance ); - - luminance.xyz() /= luminance.a(); // Normalise according to sample count when path tracing - - // Similar setup to the Bruneton demo - auto whitePoint = m_writer.declLocale( "whitePoint" - , vec3( 1.08241_f, 0.96756_f, 0.95003_f ) ); - auto exposure = m_writer.declLocale( "exposure" - , 10.0_f ); - auto hdr = vec3( 1.0_f ) - exp( -luminance.rgb() / whitePoint * exposure ); - return vec4( hdr, luminance.a() ); + return m_atmosphere.getSunRadiance( m_cameraData.position + , psunDir + , m_transmittanceMap ); } } diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp index 834e66c7ec..4429fa38e1 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundModel.hpp @@ -10,6 +10,7 @@ See LICENSE file in root folder #include "AtmosphereScattering/Scattering.hpp" #include +#include #include @@ -47,9 +48,7 @@ namespace atmosphere_scattering , castor3d::shader::LightMaterial const & material , sdw::Vec3 & reflection , sdw::Vec3 & refraction )override; - sdw::Vec4 scatter( sdw::Vec2 const & fragPos - , sdw::Vec2 const & fragSize - , sdw::Float const & fragDepth )override; + sdw::Vec3 getSunRadiance( sdw::Vec3 const & sunDir ); public: static castor::String const Name; diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundPass.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundPass.cpp index 544f53b252..dbff764260 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundPass.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereBackgroundPass.cpp @@ -107,18 +107,8 @@ namespace atmosphere_scattering , volumeMap , transmittance , luminance ); - outLuminance = luminance; + outLuminance = scatteringConfig.rescaleLuminance( luminance ); outTransmittance = transmittance; - - outLuminance.xyz() /= outLuminance.a(); // Normalise according to sample count when path tracing - - // Similar setup to the Bruneton demo - auto whitePoint = writer.declLocale( "whitePoint" - , vec3( 1.08241_f, 0.96756_f, 0.95003_f ) ); - auto exposure = writer.declLocale( "exposure" - , 10.0_f ); - auto hdr = vec3( 1.0_f ) - exp( -outLuminance.rgb() / whitePoint * exposure ); - outLuminance = vec4( hdr, outLuminance.a() ); } ); return std::make_unique< ast::Shader >( std::move( writer.getShader() ) ); diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp new file mode 100644 index 0000000000..51bb44405d --- /dev/null +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp @@ -0,0 +1,444 @@ +#include "AtmosphereScattering/AtmosphereLightingModel.hpp" + +#include "AtmosphereScattering/AtmosphereBackgroundModel.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace atmosphere_scattering +{ + //********************************************************************************************* + + AtmospherePhongLightingModel::AtmospherePhongLightingModel( sdw::ShaderWriter & m_writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric + , bool isBlinnPhong ) + : c3d::PhongLightingModel{ m_writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric + , isBlinnPhong } + { + m_prefix = m_prefix + "atmosphere_"; + } + + const castor::String AtmospherePhongLightingModel::getName() + { + return c3d::concatModelNames( c3d::PhongLightingModel::getName(), AtmosphereBackgroundModel::Name ); + } + + c3d::LightingModelPtr AtmospherePhongLightingModel::create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + { + return std::make_unique< AtmospherePhongLightingModel >( writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric + , false ); + } + + void AtmospherePhongLightingModel::compute( c3d::DirectionalLight const & light + , c3d::LightMaterial const & material + , c3d::Surface const & surface + , c3d::BackgroundModel & background + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + if ( !m_atmosphereBackground ) + { + m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( background ); + m_atmosphereBackground->m_atmosphere.shadows = m_shadowModel; + } + + if ( !m_computeDirectional ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight const & light + , c3d::PhongLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( light.direction ) ); + auto radiance = m_writer.declLocale( "lightSpecular" + , m_atmosphereBackground->getSunRadiance( light.direction ) ); + // Diffuse term. + auto diffuseFactor = m_writer.declLocale( "diffuseFactor" + , dot( surface.worldNormal, -lightDirection ) ); + auto isLit = m_writer.declLocale( "isLit" + , 1.0_f - step( diffuseFactor, 0.0_f ) ); + auto result = m_writer.declLocale( "result" + , radiance * light.base.intensity.x() ); + output.m_diffuse = isLit + * result + * diffuseFactor; + + // Specular term. + auto vertexToEye = m_writer.declLocale( "vertexToEye" + , normalize( worldEye - surface.worldPosition ) ); + + if ( m_isBlinnPhong ) + { + auto halfwayDir = m_writer.declLocale( "halfwayDir" + , normalize( vertexToEye - lightDirection ) ); + m_writer.declLocale( "specularFactor" + , max( dot( surface.worldNormal, halfwayDir ), 0.0_f ) ); + } + else + { + auto lightReflect = m_writer.declLocale( "lightReflect" + , normalize( reflect( lightDirection, surface.worldNormal ) ) ); + m_writer.declLocale( "specularFactor" + , max( dot( vertexToEye, lightReflect ), 0.0_f ) ); + } + + auto specularFactor = m_writer.getVariable< sdw::Float >( "specularFactor" ); + output.m_specular = isLit + * radiance + * light.base.intensity.y() + * pow( specularFactor, clamp( material.shininess, 1.0_f, 256.0_f ) ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto maxCount = m_writer.declLocale( "maxCount" + , 1_u ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + maxCount = m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + FI; + } + + auto luminance = m_writer.declLocale< sdw::Vec4 >( "luminance" ); + auto transmittance = m_writer.declLocale< sdw::Vec4 >( "transmittance" ); + auto targetSize = vec2( sdw::Float{ float( m_atmosphereBackground->getTargetSize().width ) } + , float( m_atmosphereBackground->getTargetSize().height ) ); + m_atmosphereBackground->m_scattering.getPixelTransLum( vec2( surface.clipPosition.x(), 1.0_f - surface.clipPosition.y() ) + , targetSize + , surface.clipPosition.z() + , m_atmosphereBackground->m_transmittanceMap + , m_writer.getVariable< sdw::CombinedImage2DRgba32 >( "c3d_mapSkyView" ) + , m_writer.getVariable< sdw::CombinedImage3DRgba32 >( "c3d_mapVolume" ) + //, light.base + //, surface.worldNormal + //, light.transforms[cascadeIndex - 1u] + //, cascadeIndex + //, maxCount + , transmittance + , luminance ); + output.m_scattering = luminance.xyz() / luminance.a();// m_atmosphereBackground->m_scattering.rescaleLuminance( luminance ).xyz(); + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); + } + , c3d::InDirectionalLight( m_writer, "light" ) + , c3d::InPhongLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + + m_computeDirectional( light + , static_cast< c3d::PhongLightMaterial const & >( material ) + , surface + , worldEye + , receivesShadows + , parentOutput ); + } + + //********************************************************************************************* + + AtmosphereBlinnPhongLightingModel::AtmosphereBlinnPhongLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + : AtmospherePhongLightingModel{ writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric + , true } + { + } + + c3d::LightingModelPtr AtmosphereBlinnPhongLightingModel::create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + { + return std::make_unique< AtmosphereBlinnPhongLightingModel >( writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric ); + } + + castor::String AtmosphereBlinnPhongLightingModel::getName() + { + return c3d::concatModelNames( c3d::BlinnPhongLightingModel::getName(), AtmosphereBackgroundModel::Name ); + } + + //********************************************************************************************* + + AtmospherePbrLightingModel::AtmospherePbrLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + : c3d::PbrLightingModel{ writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric } + { + m_prefix = "c3d_pbr_atmosphere_"; + } + + const castor::String AtmospherePbrLightingModel::getName() + { + return c3d::concatModelNames( c3d::PbrLightingModel::getName(), AtmosphereBackgroundModel::Name ); + } + + c3d::LightingModelPtr AtmospherePbrLightingModel::create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ) + { + return std::make_unique< AtmospherePbrLightingModel >( writer + , utils + , std::move( shadowOptions ) + , sssProfiles + , enableVolumetric ); + } + + void AtmospherePbrLightingModel::compute( c3d::DirectionalLight const & light + , c3d::LightMaterial const & material + , c3d::Surface const & surface + , c3d::BackgroundModel & background + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + if ( !m_atmosphereBackground ) + { + m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( background ); + m_atmosphereBackground->m_atmosphere.shadows = m_shadowModel; + } + + if ( !m_computeDirectional ) + { + c3d::OutputComponents outputs{ m_writer }; + m_computeDirectional = m_writer.implementFunction< sdw::Void >( m_prefix + "computeDirectionalLight" + , [this]( c3d::DirectionalLight const & light + , c3d::PbrLightMaterial const & material + , c3d::Surface const & surface + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & parentOutput ) + { + c3d::OutputComponents output{ m_writer.declLocale( "lightDiffuse", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightSpecular", vec3( 0.0_f ) ) + , m_writer.declLocale( "lightScattering", vec3( 0.0_f ) ) }; + auto lightDirection = m_writer.declLocale( "lightDirection" + , normalize( -light.direction ) ); + auto radiance = m_writer.declLocale( "lightSpecular" + , m_atmosphereBackground->getSunRadiance( lightDirection ) ); + + //Direct lighting + m_cookTorrance.compute( radiance + , light.base.intensity + , worldEye + , lightDirection + , material.specular + , material.getMetalness() + , material.getRoughness() + , surface + , output ); + auto cascadeIndex = m_writer.declLocale( "cascadeIndex" + , 0_u ); + auto maxCount = m_writer.declLocale( "maxCount" + , 1_u ); + + if ( m_shadowModel->isEnabled() ) + { + IF( m_writer + , ( light.base.shadowType != sdw::Int( int( castor3d::ShadowType::eNone ) ) ) ) + { + auto cascadeFactors = m_writer.declLocale( "cascadeFactors" + , vec3( 0.0_f, 1.0_f, 0.0_f ) ); + auto c3d_maxCascadeCount = m_writer.getVariable< sdw::UInt >( "c3d_maxCascadeCount" ); + maxCount = m_writer.cast< sdw::UInt >( clamp( light.cascadeCount, 1_u, c3d_maxCascadeCount ) - 1_u ); + + // Get cascade index for the current fragment's view position + FOR( m_writer, sdw::UInt, i, 0u, i < maxCount, ++i ) + { + auto factors = m_writer.declLocale( "factors" + , m_getCascadeFactors( sdw::Vec3{ surface.viewPosition } + , light.splitDepths + , i ) ); + + IF( m_writer, factors.x() != 0.0_f ) + { + cascadeFactors = factors; + } + FI; + } + ROF; + + cascadeIndex = m_writer.cast< sdw::UInt >( cascadeFactors.x() ); + + IF( m_writer, receivesShadows != 0_i ) + { + auto shadowFactor = m_writer.declLocale( "shadowFactor" + , cascadeFactors.y() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex] + , -lightDirection + , cascadeIndex + , light.cascadeCount ) ); + + IF( m_writer, cascadeIndex > 0_u ) + { + shadowFactor += cascadeFactors.z() + * m_shadowModel->computeDirectional( light.base + , surface + , light.transforms[cascadeIndex - 1u] + , -lightDirection + , cascadeIndex - 1u + , light.cascadeCount ); + } + FI; + + output.m_diffuse *= shadowFactor; + output.m_specular *= shadowFactor; + } + FI; + } + FI; + } + + auto luminance = m_writer.declLocale< sdw::Vec4 >( "luminance" ); + auto transmittance = m_writer.declLocale< sdw::Vec4 >( "transmittance" ); + auto targetSize = vec2( sdw::Float{ float( m_atmosphereBackground->getTargetSize().width ) } + , float( m_atmosphereBackground->getTargetSize().height ) ); + m_atmosphereBackground->m_scattering.getPixelTransLum( vec2( surface.clipPosition.x(), 1.0_f - surface.clipPosition.y() ) + , targetSize + , surface.clipPosition.z() + , m_atmosphereBackground->m_transmittanceMap + , m_writer.getVariable< sdw::CombinedImage2DRgba32 >( "c3d_mapSkyView" ) + , m_writer.getVariable< sdw::CombinedImage3DRgba32 >( "c3d_mapVolume" ) + //, light.base + //, surface.worldNormal + //, light.transforms[cascadeIndex - 1u] + //, cascadeIndex + //, maxCount + , transmittance + , luminance ); + output.m_scattering = luminance.xyz() / luminance.a();// m_atmosphereBackground->m_scattering.rescaleLuminance( luminance ).xyz(); + parentOutput.m_diffuse += max( vec3( 0.0_f ), output.m_diffuse ); + parentOutput.m_specular += max( vec3( 0.0_f ), output.m_specular ); + parentOutput.m_scattering += max( vec3( 0.0_f ), output.m_scattering ); + } + , c3d::InDirectionalLight( m_writer, "light" ) + , c3d::InPbrLightMaterial{ m_writer, "material" } + , c3d::InSurface{ m_writer, "surface" } + , sdw::InVec3( m_writer, "worldEye" ) + , sdw::InInt( m_writer, "receivesShadows" ) + , outputs ); + } + + m_computeDirectional( light + , static_cast< c3d::PbrLightMaterial const & >( material ) + , surface + , worldEye + , receivesShadows + , parentOutput ); + } + + //********************************************************************************************* +} diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp new file mode 100644 index 0000000000..d1fae49d31 --- /dev/null +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp @@ -0,0 +1,122 @@ +/* +See LICENSE file in root folder +*/ +#ifndef ___C3D_GlslToonLightingModel_H___ +#define ___C3D_GlslToonLightingModel_H___ + +#include "AtmosphereScatteringPrerequisites.hpp" + +#include +#include +#include +#include + +#include + +namespace atmosphere_scattering +{ + namespace c3d = castor3d::shader; + + class AtmospherePhongLightingModel + : public c3d::PhongLightingModel + { + public: + AtmospherePhongLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric + , bool isBlinnPhong ); + + static const castor::String getName(); + static c3d::LightingModelPtr create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ); + /** + *\name + * Diffuse + Specular + */ + //\{ + void compute( c3d::DirectionalLight const & light + , c3d::LightMaterial const & material + , c3d::Surface const & surface + , c3d::BackgroundModel & background + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & output )override; + //\} + + public: + AtmosphereBackgroundModel * m_atmosphereBackground{}; + sdw::Function< sdw::Void + , c3d::InDirectionalLight + , c3d::InPhongLightMaterial + , c3d::InSurface + , sdw::InVec3 + , sdw::InInt + , c3d::OutputComponents & > m_computeDirectional; + }; + + class AtmosphereBlinnPhongLightingModel + : public AtmospherePhongLightingModel + { + public: + AtmosphereBlinnPhongLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ); + + static castor::String getName(); + static c3d::LightingModelPtr create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ); + }; + + class AtmospherePbrLightingModel + : public c3d::PbrLightingModel + { + public: + explicit AtmospherePbrLightingModel( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ); + + static const castor::String getName(); + static c3d::LightingModelPtr create( sdw::ShaderWriter & writer + , c3d::Utils & utils + , c3d::ShadowOptions shadowOptions + , c3d::SssProfiles const * sssProfiles + , bool enableVolumetric ); + /** + *\name + * Diffuse + Specular + */ + //\{ + void compute( c3d::DirectionalLight const & light + , c3d::LightMaterial const & material + , c3d::Surface const & surface + , c3d::BackgroundModel & background + , sdw::Vec3 const & worldEye + , sdw::Int const & receivesShadows + , c3d::OutputComponents & output )override; + //\} + + public: + AtmosphereBackgroundModel * m_atmosphereBackground{}; + sdw::Function< sdw::Void + , c3d::InDirectionalLight + , c3d::InPbrLightMaterial + , c3d::InSurface + , sdw::InVec3 + , sdw::InInt + , c3d::OutputComponents & > m_computeDirectional; + }; + } + +#endif diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereMultiScatteringPass.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereMultiScatteringPass.cpp index caa1c89c85..0d0ac06f4e 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereMultiScatteringPass.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereMultiScatteringPass.cpp @@ -131,7 +131,7 @@ namespace atmosphere_scattering , PI * randB ); worldDir = getSphericalDir( theta, phi ); auto result = writer.declLocale( "result" - , atmosphereConfig.integrateScatteredLuminance( pixPos + , atmosphereConfig.integrateScatteredLuminanceNoShadow( pixPos , worldPos , worldDir , sunDir diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPlugin.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPlugin.cpp index 4fe859716d..20a4cb136c 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPlugin.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPlugin.cpp @@ -2,6 +2,7 @@ #include "AtmosphereScattering/AtmosphereBackground.hpp" #include "AtmosphereScattering/AtmosphereBackgroundModel.hpp" +#include "AtmosphereScattering/AtmosphereLightingModel.hpp" #include "AtmosphereScattering/AtmosphereScattering_Parsers.hpp" #include @@ -262,6 +263,12 @@ extern "C" C3D_AtmosphereScattering_API void OnLoad( castor3d::Engine * engine, castor3d::Plugin * plugin ) { + engine->registerLightingModel( atmosphere_scattering::AtmospherePhongLightingModel::getName() + , &atmosphere_scattering::AtmospherePhongLightingModel::create ); + engine->registerLightingModel( atmosphere_scattering::AtmosphereBlinnPhongLightingModel::getName() + , &atmosphere_scattering::AtmosphereBlinnPhongLightingModel::create ); + engine->registerLightingModel( atmosphere_scattering::AtmospherePbrLightingModel::getName() + , &atmosphere_scattering::AtmospherePbrLightingModel::create ); engine->registerParsers( atmosphere_scattering::PluginType , atmosphere_scattering::parser::createParsers() , atmosphere_scattering::parser::createSections() @@ -274,5 +281,8 @@ extern "C" { engine->unregisterBackgroundModel( atmosphere_scattering::AtmosphereBackgroundModel::Name ); engine->unregisterParsers( atmosphere_scattering::PluginType ); + engine->unregisterLightingModel( atmosphere_scattering::AtmospherePhongLightingModel::getName() ); + engine->unregisterLightingModel( atmosphere_scattering::AtmosphereBlinnPhongLightingModel::getName() ); + engine->unregisterLightingModel( atmosphere_scattering::AtmospherePbrLightingModel::getName() ); } } diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereSkyViewPass.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereSkyViewPass.cpp index b25408645c..a5d8edb8ae 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereSkyViewPass.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereSkyViewPass.cpp @@ -136,7 +136,7 @@ namespace atmosphere_scattering ELSE { auto ss = writer.declLocale( "ss" - , atmosphereConfig.integrateScatteredLuminance( pixPos + , atmosphereConfig.integrateScatteredLuminanceNoShadow( pixPos , worldPos , worldDir , sunDir diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereTransmittancePass.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereTransmittancePass.cpp index bef6694289..8c70c69c40 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereTransmittancePass.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereTransmittancePass.cpp @@ -87,7 +87,7 @@ namespace atmosphere_scattering , vec3( 0.0_f, viewZenithCosAngle, -viewZenithSinAngle ) ); auto transmittance = writer.declLocale( "transmittance" - , exp( -atmosphereConfig.integrateScatteredLuminance( pixPos + , exp( -atmosphereConfig.integrateScatteredLuminanceNoShadow( pixPos , worldPos , worldDir , c3d_atmosphereData.sunDirection diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereVolumePass.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereVolumePass.cpp index 02893ae96d..f8552d9f9b 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereVolumePass.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereVolumePass.cpp @@ -231,7 +231,7 @@ namespace atmosphere_scattering FI; SingleScatteringResult ss = writer.declLocale( "ss" - , atmosphereConfig.integrateScatteredLuminance( pixPos + , atmosphereConfig.integrateScatteredLuminanceNoShadow( pixPos , worldPos , worldDir , c3d_atmosphereData.sunDirection diff --git a/source/Plugins/Generic/AtmosphereScattering/CMakeLists.txt b/source/Plugins/Generic/AtmosphereScattering/CMakeLists.txt index b49073704c..e02b6b2288 100644 --- a/source/Plugins/Generic/AtmosphereScattering/CMakeLists.txt +++ b/source/Plugins/Generic/AtmosphereScattering/CMakeLists.txt @@ -21,6 +21,7 @@ set( ${PROJECT_NAME}_HDR_FILES ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereBackgroundModel.hpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereBackgroundPass.hpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereCameraUbo.hpp + ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereLightingModel.hpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereMultiScatteringPass.hpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereScattering_Parsers.hpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereScatteringConfig.hpp @@ -37,6 +38,7 @@ set( ${PROJECT_NAME}_SRC_FILES ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereBackgroundModel.cpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereBackgroundPass.cpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereCameraUbo.cpp + ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereLightingModel.cpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereMultiScatteringPass.cpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereScattering_Parsers.cpp ${CASTOR_SOURCE_DIR}/source/Plugins/Generic/${FOLDER_NAME}/AtmosphereScatteringPlugin.cpp diff --git a/source/Plugins/Generic/AtmosphereScattering/Scattering.cpp b/source/Plugins/Generic/AtmosphereScattering/Scattering.cpp index bade496e46..09519e53b8 100644 --- a/source/Plugins/Generic/AtmosphereScattering/Scattering.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/Scattering.cpp @@ -1,6 +1,7 @@ #include "AtmosphereScattering/Scattering.hpp" #include +#include #include @@ -29,28 +30,8 @@ namespace atmosphere_scattering , sdw::Vec3 const & pworldDir , sdw::CombinedImage2DRgba32 const & ptransmittanceMap ) { - if ( !m_getPixelTransLum ) + if ( !m_getSunLuminance ) { - m_getValFromTLUT = m_writer.implementFunction< sdw::Vec3 >( "getValFromTLUT" - , [&]( sdw::Vec3 const & pos - , sdw::Vec3 const & sunDir - , sdw::CombinedImage2DRgba32 const & transmittanceMap ) - { - auto height = m_writer.declLocale( "height" - , length( pos ) ); - auto up = m_writer.declLocale( "up" - , pos / height ); - auto sunCosZenithAngle = m_writer.declLocale( "sunCosZenithAngle" - , dot( sunDir, up ) ); - auto uv = m_writer.declLocale( "uv" - , vec2( clamp( 0.5_f + 0.5_f * sunCosZenithAngle, 0.0_f, 1.0_f ) - , max( 0.0_f, min( 1.0_f, ( height - m_atmosphereData.bottomRadius ) / ( m_atmosphereData.topRadius - m_atmosphereData.bottomRadius ) ) ) ) ); - m_writer.returnStmt( transmittanceMap.lod( uv, 0.0_f ).rgb() ); - } - , sdw::InVec3{ m_writer, "pos" } - , sdw::InVec3{ m_writer, "sunDir" } - , sdw::InCombinedImage2DRgba32{ m_writer, "transmittanceMap" } ); - m_getSunLuminance = m_writer.implementFunction< sdw::Vec3 >( "getSunLuminance" , [&]( sdw::Vec3 const & worldPos , sdw::Vec3 const & worldDir @@ -59,13 +40,13 @@ namespace atmosphere_scattering if ( m_renderSunDisk ) { auto sunSolidAngle = m_writer.declLocale( "sunSolidAngle" - , 0.53_f * sdw::Float{ castor::Pi< float > } / 180.0_f ); + , 0.053_f * sdw::Float{ castor::Pi< float > } / 180.0_f ); auto minSunCosTheta = m_writer.declLocale( "minSunCosTheta" , cos( sunSolidAngle ) ); auto cosTheta = m_writer.declLocale( "cosTheta" , dot( worldDir, m_atmosphereData.sunDirection ) ); auto sunLuminance = m_writer.declLocale( "sunLuminance" - , vec3( 1000000.0_f ) ); // arbitrary. But fine, not use when comparing the models + , vec3( 1.0_f ) ); // arbitrary. But fine, not use when comparing the models IF( m_writer, cosTheta < minSunCosTheta ) { @@ -91,7 +72,9 @@ namespace atmosphere_scattering ELSE { // If the sun value is applied to this pixel, we need to calculate the transmittance to obscure it. - sunLuminance *= m_getValFromTLUT( worldPos, m_atmosphereData.sunDirection, transmittanceMap ); + sunLuminance *= vec3( 2.0_f ) * m_atmosphereConfig.getSunRadiance( m_cameraData.position + , m_atmosphereData.sunDirection + , transmittanceMap ); } FI; } @@ -134,123 +117,168 @@ namespace atmosphere_scattering , sdw::Float const & pfragDepth , sdw::CombinedImage2DRgba32 const & ptransmittanceMap , sdw::CombinedImage2DRgba32 const & pskyViewMap - , sdw::CombinedImage3DRgba32 const & pvolumMap + , sdw::CombinedImage3DRgba32 const & pvolumeMap + , castor3d::shader::Light const & plight + , sdw::Vec3 const & psurfaceWorldNormal + , sdw::Mat4 const & plightMatrix + , sdw::UInt const & pcascadeIndex + , sdw::UInt const & pmaxCascade , sdw::Vec4 & ptransmittance , sdw::Vec4 & pluminance ) { - if ( !m_getPixelTransLum ) + if ( !m_getPixelTransLumShadow ) { - m_getPixelTransLum = m_writer.implementFunction< sdw::Void >( "getPixelTransLum" + m_getPixelTransLumShadow = m_writer.implementFunction< sdw::Void >( "getPixelTransLumShadow" , [&]( sdw::Vec2 const & fragPos , sdw::Vec2 const & fragSize , sdw::Float const & fragDepth , sdw::CombinedImage2DRgba32 const & transmittanceMap , sdw::CombinedImage2DRgba32 const & skyViewMap , sdw::CombinedImage3DRgba32 const & volumeMap + , castor3d::shader::Light const & light + , sdw::Vec3 const & surfaceWorldNormal + , sdw::Mat4 const & lightMatrix + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade , sdw::Vec4 transmittance , sdw::Vec4 luminance ) { - auto sampleCountIni = 0.0_f; // Can go a low as 10 sample but energy lost starts to be visible. - auto planetRadiusOffset = 0.01_f; - auto apSliceCount = 32.0_f; - auto clipSpace = m_writer.declLocale( "clipSpace" , m_atmosphereConfig.getClipSpace( fragPos, fragSize, 1.0_f ) ); - auto hPos = m_writer.declLocale( "hPos" , m_cameraData.camProjToWorld( vec4( clipSpace, 1.0_f ) ) ); - auto worldDir = m_writer.declLocale( "worldDir" , normalize( hPos.xyz() / hPos.w() - m_cameraData.position ) ); auto worldPos = m_writer.declLocale( "worldPos" , m_cameraData.position + vec3( 0.0_f, m_atmosphereData.bottomRadius, 0.0_f ) ); - - auto viewHeight = m_writer.declLocale( "viewHeight" - , length( worldPos ) ); auto L = m_writer.declLocale( "L" , vec3( 0.0_f ) ); + doRenderSky( fragSize + , fragDepth + , worldPos + , worldDir + , transmittanceMap + , skyViewMap + , L + , luminance ); - if ( m_fastSky ) + if ( m_fastAerialPerspective ) { - IF( m_writer, viewHeight < m_atmosphereData.topRadius && fragDepth >= 1.0_f ) - { - auto uv = m_writer.declLocale< sdw::Vec2 >( "uv" ); - auto upVector = m_writer.declLocale( "upVector" - , normalize( worldPos ) ); - auto viewZenithCosAngle = m_writer.declLocale( "viewZenithCosAngle" - , dot( worldDir, upVector ) ); - - auto sideVector = m_writer.declLocale( "sideVector" - , normalize( cross( upVector, worldDir ) ) ); // assumes non parallel vectors - auto forwardVector = m_writer.declLocale( "forwardVector" - , normalize( cross( sideVector, upVector ) ) ); // aligns toward the sun light but perpendicular to up vector - auto lightOnPlane = m_writer.declLocale( "lightOnPlane" - , vec2( dot( m_atmosphereData.sunDirection, forwardVector ) - , dot( m_atmosphereData.sunDirection, sideVector ) ) ); - lightOnPlane = normalize( lightOnPlane ); - auto lightViewCosAngle = m_writer.declLocale( "lightViewCosAngle" - , lightOnPlane.x() ); - - auto intersectGround = m_writer.declLocale( "intersectGround" - , m_atmosphereConfig.raySphereIntersectNearest( worldPos - , worldDir - , vec3( 0.0_f ) - , m_atmosphereData.bottomRadius ) >= 0.0_f ); - - m_atmosphereConfig.skyViewLutParamsToUv( intersectGround, viewZenithCosAngle, lightViewCosAngle, viewHeight, uv, fragSize ); - - luminance = vec4( skyViewMap.lod( uv, 0.0_f ).rgb() + getSunLuminance( worldPos, worldDir, transmittanceMap ), 1.0_f ); - m_writer.returnStmt(); - } - FI; + doRenderFastAerial( fragPos + , fragSize + , fragDepth + , worldPos + , volumeMap + , L + , luminance ); } else { - IF( m_writer, fragDepth >= 1.0_f ) + // Move to top atmosphere as the starting point for ray marching. + // This is critical to be after the above to not disrupt above atmosphere tests and voxel selection. + IF( m_writer, !m_atmosphereConfig.moveToTopAtmosphere( worldPos, worldDir ) ) { - L += getSunLuminance( worldPos, worldDir, transmittanceMap ); + // Ray is not intersecting the atmosphere + luminance = vec4( getSunLuminance( worldPos, worldDir, transmittanceMap ), 1.0_f ); + m_writer.returnStmt(); } FI; - } - if ( m_fastAerialPerspective ) - { - if ( m_colorTransmittance ) - { - castor3d::log::error << "The fastAerialPerspective path does not support colorTransmittance." << std::endl; - } - else - { - auto depthBufferWorldPos = m_writer.declLocale( "depthBufferWorldPos" - , m_atmosphereConfig.getWorldPos( fragDepth - , fragPos - , fragSize ) ); - auto tDepth = m_writer.declLocale( "tDepth" - , length( depthBufferWorldPos - ( worldPos + vec3( 0.0_f, -m_atmosphereData.bottomRadius, 0.0_f ) ) ) ); - auto slice = m_writer.declLocale( "slice" - , aerialPerspectiveDepthToSlice( tDepth ) ); - auto weight = m_writer.declLocale( "weight" - , 1.0_f ); - - IF( m_writer, slice < 0.5_f ) - { - // We multiply by weight to fade to 0 at depth 0. That works for luminance and opacity. - weight = clamp( slice * 2.0_f, 0.0_f, 1.0_f ); - slice = 0.5_f; - } - FI; + auto sampleCountIni = 0.0_f; + auto ss = m_writer.declLocale( "ss" + , m_atmosphereConfig.integrateScatteredLuminance( fragPos + , worldPos + , worldDir + , m_atmosphereData.sunDirection + , sampleCountIni + , fragDepth + , light + , surfaceWorldNormal + , lightMatrix + , cascadeIndex + , maxCascade ) ); + doRegisterOutputs( ss, L, luminance, transmittance ); + } + } + , sdw::InVec2{ m_writer, "fragPos" } + , sdw::InVec2{ m_writer, "fragSize" } + , sdw::InFloat{ m_writer, "fragDepth" } + , sdw::InCombinedImage2DRgba32{ m_writer, "transmittanceMap" } + , sdw::InCombinedImage2DRgba32{ m_writer, "skyViewMap" } + , sdw::InCombinedImage3DRgba32{ m_writer, "volumeMap" } + , castor3d::shader::InLight{ m_writer, "light" } + , sdw::InVec3{ m_writer, "surfaceWorldNormal" } + , sdw::InMat4{ m_writer, "lightMatrix" } + , sdw::InUInt{ m_writer, "cascadeIndex" } + , sdw::InUInt{ m_writer, "maxCascade" } + , sdw::OutVec4{ m_writer, "transmittance" } + , sdw::OutVec4{ m_writer, "luminance" } ); + } - auto w = m_writer.declLocale( "w" - , sqrt( slice / apSliceCount ) ); // squared distribution + return m_getPixelTransLumShadow( pfragPos + , pfragSize + , pfragDepth + , ptransmittanceMap + , pskyViewMap + , pvolumeMap + , plight + , psurfaceWorldNormal + , plightMatrix + , pcascadeIndex + , pmaxCascade + , ptransmittance + , pluminance ); + } - auto AP = m_writer.declLocale( "AP" - , weight * volumeMap.lod( vec3( fragPos / fragSize, w ), 0.0_f ) ); - L.rgb() += AP.rgb(); - auto opacity = m_writer.declLocale( "opacity" - , AP.a() ); + sdw::Void ScatteringConfig::getPixelTransLum( sdw::Vec2 const & pfragPos + , sdw::Vec2 const & pfragSize + , sdw::Float const & pfragDepth + , sdw::CombinedImage2DRgba32 const & ptransmittanceMap + , sdw::CombinedImage2DRgba32 const & pskyViewMap + , sdw::CombinedImage3DRgba32 const & pvolumeMap + , sdw::Vec4 & ptransmittance + , sdw::Vec4 & pluminance ) + { + if ( !m_getPixelTransLum ) + { + m_getPixelTransLum = m_writer.implementFunction< sdw::Void >( "getPixelTransLum" + , [&]( sdw::Vec2 const & fragPos + , sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::CombinedImage2DRgba32 const & transmittanceMap + , sdw::CombinedImage2DRgba32 const & skyViewMap + , sdw::CombinedImage3DRgba32 const & volumeMap + , sdw::Vec4 transmittance + , sdw::Vec4 luminance ) + { + auto clipSpace = m_writer.declLocale( "clipSpace" + , m_atmosphereConfig.getClipSpace( fragPos, fragSize, 1.0_f ) ); + auto hPos = m_writer.declLocale( "hPos" + , m_cameraData.camProjToWorld( vec4( clipSpace, 1.0_f ) ) ); + auto worldDir = m_writer.declLocale( "worldDir" + , normalize( hPos.xyz() / hPos.w() - m_cameraData.position ) ); + auto worldPos = m_writer.declLocale( "worldPos" + , m_cameraData.position + vec3( 0.0_f, m_atmosphereData.bottomRadius, 0.0_f ) ); + auto L = m_writer.declLocale( "L" + , vec3( 0.0_f ) ); + doRenderSky( fragSize + , fragDepth + , worldPos + , worldDir + , transmittanceMap + , skyViewMap + , L + , luminance ); - luminance = vec4( L, opacity ); - } + if ( m_fastAerialPerspective ) + { + doRenderFastAerial( fragPos + , fragSize + , fragDepth + , worldPos + , volumeMap + , L + , luminance ); } else { @@ -264,29 +292,15 @@ namespace atmosphere_scattering } FI; - SingleScatteringResult ss = m_writer.declLocale( "ss" - , m_atmosphereConfig.integrateScatteredLuminance( fragPos + auto sampleCountIni = 0.0_f; + auto ss = m_writer.declLocale( "ss" + , m_atmosphereConfig.integrateScatteredLuminanceNoShadow( fragPos , worldPos , worldDir , m_atmosphereData.sunDirection , sampleCountIni , fragDepth ) ); - - L += ss.luminance; - auto throughput = m_writer.declLocale( "throughput" - , ss.transmittance ); - - if ( m_colorTransmittance ) - { - luminance = vec4( L, 1.0_f ); - transmittance = vec4( throughput, 1.0_f ); - } - else - { - auto t = m_writer.declLocale( "t" - , dot( throughput, vec3( 1.0_f / 3.0_f ) ) ); - luminance = vec4( L, 1.0_f - t ); - } + doRegisterOutputs( ss, L, luminance, transmittance ); } } , sdw::InVec2{ m_writer, "fragPos" } @@ -304,8 +318,146 @@ namespace atmosphere_scattering , pfragDepth , ptransmittanceMap , pskyViewMap - , pvolumMap + , pvolumeMap , ptransmittance , pluminance ); } + + sdw::Vec4 ScatteringConfig::rescaleLuminance( sdw::Vec4 const & luminance ) + { + luminance.xyz() /= luminance.a(); // Normalise according to sample count when path tracing + + // Similar setup to the Bruneton demo + auto whitePoint = m_writer.declLocale( "whitePoint" + , vec3( 1.08241_f, 0.96756_f, 0.95003_f ) ); + auto exposure = m_writer.declLocale( "exposure" + , 10.0_f ); + auto hdr = vec3( 1.0_f ) - exp( -luminance.rgb() / whitePoint * exposure ); + return vec4( hdr, luminance.a() ); + } + + void ScatteringConfig::doRenderSky( sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::CombinedImage2DRgba32 const & transmittanceMap + , sdw::CombinedImage2DRgba32 const & skyViewMap + , sdw::Vec3 & L + , sdw::Vec4 & luminance ) + { + if ( m_fastSky ) + { + auto viewHeight = m_writer.declLocale( "viewHeight" + , length( worldPos ) ); + + IF( m_writer, viewHeight < m_atmosphereData.topRadius && fragDepth >= 1.0_f ) + { + auto uv = m_writer.declLocale< sdw::Vec2 >( "uv" ); + auto upVector = m_writer.declLocale( "upVector" + , normalize( worldPos ) ); + auto viewZenithCosAngle = m_writer.declLocale( "viewZenithCosAngle" + , dot( worldDir, upVector ) ); + + auto sideVector = m_writer.declLocale( "sideVector" + , normalize( cross( upVector, worldDir ) ) ); // assumes non parallel vectors + auto forwardVector = m_writer.declLocale( "forwardVector" + , normalize( cross( sideVector, upVector ) ) ); // aligns toward the sun light but perpendicular to up vector + auto lightOnPlane = m_writer.declLocale( "lightOnPlane" + , vec2( dot( m_atmosphereData.sunDirection, forwardVector ) + , dot( m_atmosphereData.sunDirection, sideVector ) ) ); + lightOnPlane = normalize( lightOnPlane ); + auto lightViewCosAngle = m_writer.declLocale( "lightViewCosAngle" + , lightOnPlane.x() ); + + auto intersectGround = m_writer.declLocale( "intersectGround" + , m_atmosphereConfig.raySphereIntersectNearest( worldPos + , worldDir + , vec3( 0.0_f ) + , m_atmosphereData.bottomRadius ) >= 0.0_f ); + + m_atmosphereConfig.skyViewLutParamsToUv( intersectGround, viewZenithCosAngle, lightViewCosAngle, viewHeight, uv, fragSize ); + + luminance = vec4( skyViewMap.lod( uv, 0.0_f ).rgb() + getSunLuminance( worldPos, worldDir, transmittanceMap ), 1.0_f ); + m_writer.returnStmt(); + } + FI; + } + else + { + IF( m_writer, fragDepth >= 1.0_f ) + { + L += getSunLuminance( worldPos, worldDir, transmittanceMap ); + } + FI; + } + } + + void ScatteringConfig::doRenderFastAerial( sdw::Vec2 const & fragPos + , sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::Vec3 const & worldPos + , sdw::CombinedImage3DRgba32 const & volumeMap + , sdw::Vec3 & L + , sdw::Vec4 & luminance ) + { + if ( m_colorTransmittance ) + { + castor3d::log::error << "The fastAerialPerspective path does not support colorTransmittance." << std::endl; + } + else + { + auto apSliceCount = 32.0_f; + auto depthBufferWorldPos = m_writer.declLocale( "depthBufferWorldPos" + , m_atmosphereConfig.getWorldPos( fragDepth + , fragPos + , fragSize ) ); + auto tDepth = m_writer.declLocale( "tDepth" + , length( depthBufferWorldPos - ( worldPos + vec3( 0.0_f, -m_atmosphereData.bottomRadius, 0.0_f ) ) ) ); + auto slice = m_writer.declLocale( "slice" + , aerialPerspectiveDepthToSlice( tDepth ) ); + auto weight = m_writer.declLocale( "weight" + , 1.0_f ); + + IF( m_writer, slice < 0.5_f ) + { + // We multiply by weight to fade to 0 at depth 0. That works for luminance and opacity. + weight = clamp( slice * 2.0_f, 0.0_f, 1.0_f ); + slice = 0.5_f; + } + FI; + + auto w = m_writer.declLocale( "w" + , sqrt( slice / apSliceCount ) ); // squared distribution + + auto AP = m_writer.declLocale( "AP" + , weight * volumeMap.lod( vec3( fragPos / fragSize, w ), 0.0_f ) ); + L += AP.rgb(); + auto opacity = m_writer.declLocale( "opacity" + , AP.a() ); + + luminance = vec4( L, opacity ); + } + } + + void ScatteringConfig::doRegisterOutputs( SingleScatteringResult const & ss + , sdw::Vec3 & L + , sdw::Vec4 & luminance + , sdw::Vec4 & transmittance ) + { + L += ss.luminance; + auto throughput = m_writer.declLocale( "throughput" + , ss.transmittance ); + + if ( m_colorTransmittance ) + { + luminance = vec4( L, 1.0_f ); + transmittance = vec4( throughput, 1.0_f ); + } + else + { + auto t = m_writer.declLocale( "t" + , dot( throughput, vec3( 1.0_f / 3.0_f ) ) ); + luminance = vec4( L, 1.0_f - t ); + } + } } diff --git a/source/Plugins/Generic/AtmosphereScattering/Scattering.hpp b/source/Plugins/Generic/AtmosphereScattering/Scattering.hpp index 8fbf4da2ef..2522790d58 100644 --- a/source/Plugins/Generic/AtmosphereScattering/Scattering.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/Scattering.hpp @@ -26,9 +26,44 @@ namespace atmosphere_scattering , sdw::Float const & fragDepth , sdw::CombinedImage2DRgba32 const & transmittanceMap , sdw::CombinedImage2DRgba32 const & skyViewMap - , sdw::CombinedImage3DRgba32 const & volumMap + , sdw::CombinedImage3DRgba32 const & volumeMap , sdw::Vec4 & transmittance , sdw::Vec4 & luminance ); + sdw::Void getPixelTransLum( sdw::Vec2 const & fragPos + , sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::CombinedImage2DRgba32 const & transmittanceMap + , sdw::CombinedImage2DRgba32 const & skyViewMap + , sdw::CombinedImage3DRgba32 const & volumeMap + , castor3d::shader::Light const & light + , sdw::Vec3 const & surfaceWorldNormal + , sdw::Mat4 const & lightMatrix + , sdw::UInt const & cascadeIndex + , sdw::UInt const & maxCascade + , sdw::Vec4 & transmittance + , sdw::Vec4 & luminance ); + sdw::Vec4 rescaleLuminance( sdw::Vec4 const & luminance ); + + private: + void doRenderSky( sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::Vec3 const & worldPos + , sdw::Vec3 const & worldDir + , sdw::CombinedImage2DRgba32 const & transmittanceMap + , sdw::CombinedImage2DRgba32 const & skyViewMap + , sdw::Vec3 & L + , sdw::Vec4 & luminance ); + void doRenderFastAerial( sdw::Vec2 const & fragPos + , sdw::Vec2 const & fragSize + , sdw::Float const & fragDepth + , sdw::Vec3 const & worldPos + , sdw::CombinedImage3DRgba32 const & volumeMap + , sdw::Vec3 & L + , sdw::Vec4 & luminance ); + void doRegisterOutputs( SingleScatteringResult const & ss + , sdw::Vec3 & L + , sdw::Vec4 & luminance + , sdw::Vec4 & transmittance ); private: sdw::ShaderWriter & m_writer; @@ -40,10 +75,6 @@ namespace atmosphere_scattering bool m_fastAerialPerspective; bool m_renderSunDisk; - sdw::Function< sdw::Vec3 - , sdw::InVec3 - , sdw::InVec3 - , sdw::InCombinedImage2DRgba32 > m_getValFromTLUT; sdw::Function< sdw::Vec3 , sdw::InVec3 , sdw::InVec3 @@ -59,6 +90,20 @@ namespace atmosphere_scattering , sdw::InCombinedImage3DRgba32 , sdw::OutVec4 , sdw::OutVec4 > m_getPixelTransLum; + sdw::Function< sdw::Void + , sdw::InVec2 + , sdw::InVec2 + , sdw::InFloat + , sdw::InCombinedImage2DRgba32 + , sdw::InCombinedImage2DRgba32 + , sdw::InCombinedImage3DRgba32 + , castor3d::shader::InLight + , sdw::InVec3 + , sdw::InMat4 + , sdw::InUInt + , sdw::InUInt + , sdw::OutVec4 + , sdw::OutVec4 > m_getPixelTransLumShadow; }; } From 9a766041e5f508bb8f51e0e38f1ee90a085728ab Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 12:21:24 +0200 Subject: [PATCH 10/12] Castor3D: Cached files list in scene file parser. --- .../Core/Castor3D/Scene/SceneFileParser.hpp | 2 ++ .../Core/Castor3D/Scene/SceneFileParser.cpp | 10 ++++++ .../Scene/SceneFileParser_Parsers.cpp | 32 ++++++++----------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/include/Core/Castor3D/Scene/SceneFileParser.hpp b/include/Core/Castor3D/Scene/SceneFileParser.hpp index 701ee907ac..04ecbbc0cf 100644 --- a/include/Core/Castor3D/Scene/SceneFileParser.hpp +++ b/include/Core/Castor3D/Scene/SceneFileParser.hpp @@ -130,6 +130,8 @@ namespace castor3d }; castor::LoggerInstance * logger{}; + castor::PathArray files; + castor::PathArray csnaFiles; SceneRPtr scene{}; SceneUPtr ownScene{}; RenderWindowDesc window{}; diff --git a/source/Core/Castor3D/Scene/SceneFileParser.cpp b/source/Core/Castor3D/Scene/SceneFileParser.cpp index 8c00d62ec2..1d3f157a49 100644 --- a/source/Core/Castor3D/Scene/SceneFileParser.cpp +++ b/source/Core/Castor3D/Scene/SceneFileParser.cpp @@ -460,6 +460,16 @@ namespace castor3d { SceneFileContext * userContext = new SceneFileContext{ *context.logger , static_cast< SceneFileParser * >( context.parser ) }; + castor::File::listDirectoryFiles( context.file.getPath(), userContext->files, true ); + + for ( auto fileName : userContext->files ) + { + if ( fileName.getExtension() == "csna" ) + { + userContext->csnaFiles.push_back( fileName ); + } + } + return userContext; } diff --git a/source/Core/Castor3D/Scene/SceneFileParser_Parsers.cpp b/source/Core/Castor3D/Scene/SceneFileParser_Parsers.cpp index 5dfe6822d7..801a05b978 100644 --- a/source/Core/Castor3D/Scene/SceneFileParser_Parsers.cpp +++ b/source/Core/Castor3D/Scene/SceneFileParser_Parsers.cpp @@ -2653,28 +2653,22 @@ namespace castor3d auto node = parsingContext.scene->addSceneNode( name, parsingContext.sceneNode ).lock(); parsingContext.sceneNode.reset(); - castor::PathArray files; - castor::File::listDirectoryFiles( context.file.getPath(), files, true ); - - for ( auto fileName : files ) + for ( auto fileName : parsingContext.csnaFiles ) { - if ( fileName.getExtension() == "csna" ) + auto fName = fileName.getFileName(); + auto pos = fName.find( name ); + + if ( pos == 0u + && fName[name.size()] == '-' ) { - auto fName = fileName.getFileName(); - auto pos = fName.find( name ); - - if ( pos == 0u - && fName[name.size()] == '-' ) - { - auto animName = fName.substr( name.size() + 1u ); + auto animName = fName.substr( name.size() + 1u ); - if ( !animName.empty() ) - { - auto & animation = node->createAnimation( animName ); - BinaryParser< SceneNodeAnimation > parser; - castor::BinaryFile animFile{ fileName, castor::File::OpenMode::eRead }; - parser.parse( animation, animFile ); - } + if ( !animName.empty() ) + { + auto & animation = node->createAnimation( animName ); + BinaryParser< SceneNodeAnimation > parser; + castor::BinaryFile animFile{ fileName, castor::File::OpenMode::eRead }; + parser.parse( animation, animFile ); } } } From a30ab5d84d355bcbb3bd61c2c9b75ea783fe4fbe Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 12:21:38 +0200 Subject: [PATCH 11/12] Castor3D: Fixed a crash at shutdown. --- .../Core/Castor3D/Scene/Animation/AnimatedTexture.hpp | 7 ++++++- .../Shader/ShaderBuffers/TextureAnimationBuffer.cpp | 11 +++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/Core/Castor3D/Scene/Animation/AnimatedTexture.hpp b/include/Core/Castor3D/Scene/Animation/AnimatedTexture.hpp index 8c9cf1561f..3d902a64ac 100644 --- a/include/Core/Castor3D/Scene/Animation/AnimatedTexture.hpp +++ b/include/Core/Castor3D/Scene/Animation/AnimatedTexture.hpp @@ -60,9 +60,14 @@ namespace castor3d *name Getters. **/ /**@{*/ + bool hasTexture()const + { + return m_texture != nullptr; + } + TextureUnit & getTexture()const { - CU_Require( m_texture ); + CU_Require( hasTexture() ); return *m_texture; } diff --git a/source/Core/Castor3D/Shader/ShaderBuffers/TextureAnimationBuffer.cpp b/source/Core/Castor3D/Shader/ShaderBuffers/TextureAnimationBuffer.cpp index fd78a708fd..eb8dd98e1c 100644 --- a/source/Core/Castor3D/Shader/ShaderBuffers/TextureAnimationBuffer.cpp +++ b/source/Core/Castor3D/Shader/ShaderBuffers/TextureAnimationBuffer.cpp @@ -50,10 +50,13 @@ namespace castor3d void TextureAnimationBuffer::removeTextureAnimation( AnimatedTexture const & texture ) { - auto & unit = texture.getTexture(); - --m_count; - auto lock( castor::makeUniqueLock( m_mutex ) ); - m_animations[unit.getId()] = nullptr; + if ( texture.hasTexture() ) + { + auto & unit = texture.getTexture(); + --m_count; + auto lock( castor::makeUniqueLock( m_mutex ) ); + m_animations[unit.getId()] = nullptr; + } } void TextureAnimationBuffer::update( ashes::CommandBuffer const & commandBuffer ) From 7aba5932eb0661eadf2295a728d746ac7817d789 Mon Sep 17 00:00:00 2001 From: DragonJoker Date: Thu, 23 Jun 2022 14:23:37 +0200 Subject: [PATCH 12/12] Fixed some warnings. --- .../Pass/PBR/Shaders/GlslPbrLighting.cpp | 134 ++++---- .../Pass/Phong/Shaders/GlslPhongLighting.cpp | 178 +++++----- .../AtmosphereScattering/Atmosphere.cpp | 12 +- .../AtmosphereLightingModel.cpp | 57 ++-- .../AtmosphereLightingModel.hpp | 2 + .../AtmosphereScatteringPrerequisites.hpp | 1 + .../ToonMaterial/Shaders/GlslToonLighting.cpp | 312 +++++++++--------- 7 files changed, 350 insertions(+), 346 deletions(-) diff --git a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp index 15bfd8df36..216cd70794 100644 --- a/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/PBR/Shaders/GlslPbrLighting.cpp @@ -142,13 +142,13 @@ namespace castor3d::shader , envMapSet ); } - void PbrLightingModel::compute( DirectionalLight const & light - , LightMaterial const & material - , Surface const & surface - , BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PbrLightingModel::compute( DirectionalLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computeDirectional ) { @@ -289,20 +289,20 @@ namespace castor3d::shader , outputs ); } - m_computeDirectional( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void PbrLightingModel::compute( PointLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PbrLightingModel::compute( PointLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computePoint ) { @@ -367,20 +367,20 @@ namespace castor3d::shader , outputs ); } - m_computePoint( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computePoint( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void PbrLightingModel::compute( SpotLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PbrLightingModel::compute( SpotLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computeSpot ) { @@ -474,12 +474,12 @@ namespace castor3d::shader , outputs ); } - m_computeSpot( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeSpot( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } void PbrLightingModel::computeMapContributions( PassFlags const & passFlags @@ -570,11 +570,11 @@ namespace castor3d::shader , emissive ); } - sdw::Vec3 PbrLightingModel::computeDiffuse( DirectionalLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PbrLightingModel::computeDiffuse( DirectionalLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeDirectionalDiffuse ) { @@ -628,18 +628,18 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeDirectionalDiffuse( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeDirectionalDiffuse( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 PbrLightingModel::computeDiffuse( PointLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PbrLightingModel::computeDiffuse( PointLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computePointDiffuse ) { @@ -693,18 +693,18 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computePointDiffuse( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computePointDiffuse( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 PbrLightingModel::computeDiffuse( SpotLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PbrLightingModel::computeDiffuse( SpotLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeSpotDiffuse ) { @@ -769,11 +769,11 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeSpotDiffuse( light - , static_cast< PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeSpotDiffuse( plight + , static_cast< PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } void PbrLightingModel::computeMapDiffuseContributions( PassFlags const & passFlags diff --git a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp index 2f8465958c..b7748d07ed 100644 --- a/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp +++ b/source/Core/Castor3D/Material/Pass/Phong/Shaders/GlslPhongLighting.cpp @@ -123,13 +123,13 @@ namespace castor3d::shader , envMapSet ); } - void PhongLightingModel::compute( DirectionalLight const & light - , LightMaterial const & material - , Surface const & surface - , BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PhongLightingModel::compute( DirectionalLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computeDirectional ) { @@ -268,20 +268,20 @@ namespace castor3d::shader , outputs ); } - m_computeDirectional( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void PhongLightingModel::compute( PointLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PhongLightingModel::compute( PointLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computePoint ) { @@ -344,20 +344,20 @@ namespace castor3d::shader , outputs ); } - m_computePoint( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computePoint( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void PhongLightingModel::compute( SpotLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , OutputComponents & parentOutput ) + void PhongLightingModel::compute( SpotLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , OutputComponents & pparentOutput ) { if ( !m_computeSpot ) { @@ -449,12 +449,12 @@ namespace castor3d::shader , outputs ); } - m_computeSpot( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeSpot( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } void PhongLightingModel::computeMapContributions( PassFlags const & passFlags @@ -545,11 +545,11 @@ namespace castor3d::shader , emissive ); } - sdw::Vec3 PhongLightingModel::computeDiffuse( DirectionalLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PhongLightingModel::computeDiffuse( DirectionalLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeDirectionalDiffuse ) { @@ -599,18 +599,18 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeDirectionalDiffuse( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeDirectionalDiffuse( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 PhongLightingModel::computeDiffuse( PointLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PhongLightingModel::computeDiffuse( PointLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computePointDiffuse ) { @@ -662,18 +662,18 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computePointDiffuse( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computePointDiffuse( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 PhongLightingModel::computeDiffuse( SpotLight const & light - , LightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 PhongLightingModel::computeDiffuse( SpotLight const & plight + , LightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeSpotDiffuse ) { @@ -737,11 +737,11 @@ namespace castor3d::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeSpotDiffuse( light - , static_cast< PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeSpotDiffuse( plight + , static_cast< PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } void PhongLightingModel::computeMapDiffuseContributions( PassFlags const & passFlags @@ -819,12 +819,12 @@ namespace castor3d::shader , emissive ); } - sdw::RetVec3 PhongLightingModel::doComputeLight( Light const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection - , OutputComponents & parentOutput ) + sdw::RetVec3 PhongLightingModel::doComputeLight( Light const & plight + , PhongLightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Vec3 const & plightDirection + , OutputComponents & pparentOutput ) { if ( !m_computeLight ) { @@ -884,19 +884,19 @@ namespace castor3d::shader , outputs ); } - return m_computeLight( light - , material - , surface - , worldEye - , lightDirection - , parentOutput ); + return m_computeLight( plight + , pmaterial + , psurface + , pworldEye + , plightDirection + , pparentOutput ); } - sdw::Vec3 PhongLightingModel::doComputeLightDiffuse( Light const & light - , PhongLightMaterial const & material - , Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection ) + sdw::Vec3 PhongLightingModel::doComputeLightDiffuse( Light const & plight + , PhongLightMaterial const & pmaterial + , Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Vec3 const & plightDirection ) { if ( !m_computeLightDiffuse ) { @@ -924,11 +924,11 @@ namespace castor3d::shader , sdw::InVec3( m_writer, "lightDirection" ) ); } - return m_computeLightDiffuse( light - , material - , surface - , worldEye - , lightDirection ); + return m_computeLightDiffuse( plight + , pmaterial + , psurface + , pworldEye + , plightDirection ); } //********************************************************************************************* diff --git a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp index fd6d3a7325..ed4d03c852 100644 --- a/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/Atmosphere.cpp @@ -281,7 +281,7 @@ namespace atmosphere_scattering , doInitSampleCount( tMax, sampleCount, sampleCountFloor, tMaxFloor ) ); // Phase functions - auto [miePhaseValue, rayleighPhaseValue] = doInitPhaseFunctions( sunDir, worldDir ); + auto mieRayleighPhaseValues = doInitPhaseFunctions( sunDir, worldDir ); if ( luminanceSettings.illuminanceIsOne ) { @@ -327,8 +327,8 @@ namespace atmosphere_scattering , earthO , upVector , sunZenithCosAngle - , miePhaseValue - , rayleighPhaseValue ); + , mieRayleighPhaseValues.first + , mieRayleighPhaseValues.second ); auto shadow = writer.declLocale( "shadow" , 1.0_f ); @@ -444,7 +444,7 @@ namespace atmosphere_scattering , doInitSampleCount( tMax, sampleCount, sampleCountFloor, tMaxFloor ) ); // Phase functions - auto [miePhaseValue, rayleighPhaseValue] = doInitPhaseFunctions( sunDir, worldDir ); + auto mieRayleighPhaseValues = doInitPhaseFunctions( sunDir, worldDir ); if ( luminanceSettings.illuminanceIsOne ) { @@ -490,8 +490,8 @@ namespace atmosphere_scattering , earthO , upVector , sunZenithCosAngle - , miePhaseValue - , rayleighPhaseValue ); + , mieRayleighPhaseValues.first + , mieRayleighPhaseValues.second ); auto S = writer.declLocale( "S" , globalL * ( earthShadow * transmittanceToSun * phaseTimesScattering + multiScatteredLuminance * medium.scattering ) ); doComputeStep( medium diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp index 51bb44405d..3e10cea3fe 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.cpp @@ -1,5 +1,6 @@ #include "AtmosphereScattering/AtmosphereLightingModel.hpp" +#include "AtmosphereScattering/AtmosphereBackground.hpp" #include "AtmosphereScattering/AtmosphereBackgroundModel.hpp" #include @@ -58,17 +59,17 @@ namespace atmosphere_scattering , false ); } - void AtmospherePhongLightingModel::compute( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , c3d::BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void AtmospherePhongLightingModel::compute( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , c3d::BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_atmosphereBackground ) { - m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( background ); + m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( pbackground ); m_atmosphereBackground->m_atmosphere.shadows = m_shadowModel; } @@ -219,12 +220,12 @@ namespace atmosphere_scattering , outputs ); } - m_computeDirectional( light - , static_cast< c3d::PhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< c3d::PhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } //********************************************************************************************* @@ -295,17 +296,17 @@ namespace atmosphere_scattering , enableVolumetric ); } - void AtmospherePbrLightingModel::compute( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , c3d::BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void AtmospherePbrLightingModel::compute( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , c3d::BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_atmosphereBackground ) { - m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( background ); + m_atmosphereBackground = &static_cast< AtmosphereBackgroundModel & >( pbackground ); m_atmosphereBackground->m_atmosphere.shadows = m_shadowModel; } @@ -432,12 +433,12 @@ namespace atmosphere_scattering , outputs ); } - m_computeDirectional( light - , static_cast< c3d::PbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< c3d::PbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } //********************************************************************************************* diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp index d1fae49d31..359a8fc89c 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereLightingModel.hpp @@ -46,6 +46,7 @@ namespace atmosphere_scattering , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & output )override; + using c3d::PhongLightingModel::compute; //\} public: @@ -105,6 +106,7 @@ namespace atmosphere_scattering , sdw::Vec3 const & worldEye , sdw::Int const & receivesShadows , c3d::OutputComponents & output )override; + using c3d::PbrLightingModel::compute; //\} public: diff --git a/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPrerequisites.hpp b/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPrerequisites.hpp index a28e37cb9d..ae3a08f240 100644 --- a/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPrerequisites.hpp +++ b/source/Plugins/Generic/AtmosphereScattering/AtmosphereScatteringPrerequisites.hpp @@ -11,6 +11,7 @@ namespace atmosphere_scattering class AtmosphereBackground; class AtmosphereScatteringUbo; class CameraUbo; + class AtmosphereBackgroundModel; struct AtmosphereConfig; struct AtmosphereData; diff --git a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp index 8a94deddaf..35e140e2aa 100644 --- a/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp +++ b/source/Plugins/Generic/ToonMaterial/Shaders/GlslToonLighting.cpp @@ -127,13 +127,13 @@ namespace toon::shader , envMapSet ); } - void ToonPhongLightingModel::compute( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , c3d::BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPhongLightingModel::compute( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , c3d::BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computeDirectional ) { @@ -248,20 +248,20 @@ namespace toon::shader , outputs ); } - m_computeDirectional( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void ToonPhongLightingModel::compute( c3d::PointLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPhongLightingModel::compute( c3d::PointLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computePoint ) { @@ -324,20 +324,20 @@ namespace toon::shader , outputs ); } - m_computePoint( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computePoint( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void ToonPhongLightingModel::compute( c3d::SpotLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPhongLightingModel::compute( c3d::SpotLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computeSpot ) { @@ -409,12 +409,12 @@ namespace toon::shader , outputs ); } - m_computeSpot( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeSpot( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } void ToonPhongLightingModel::computeMapContributions( castor3d::PassFlags const & passFlags @@ -505,11 +505,11 @@ namespace toon::shader , emissive ); } - sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeDirectionalDiffuse ) { @@ -559,18 +559,18 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeDirectionalDiffuse( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeDirectionalDiffuse( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::PointLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::PointLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computePointDiffuse ) { @@ -622,18 +622,18 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computePointDiffuse( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computePointDiffuse( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::SpotLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPhongLightingModel::computeDiffuse( c3d::SpotLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeSpotDiffuse ) { @@ -697,11 +697,11 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeSpotDiffuse( light - , static_cast< ToonPhongLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeSpotDiffuse( plight + , static_cast< ToonPhongLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } void ToonPhongLightingModel::computeMapDiffuseContributions( castor3d::PassFlags const & passFlags @@ -779,12 +779,12 @@ namespace toon::shader , emissive ); } - void ToonPhongLightingModel::doComputeLight( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection - , c3d::OutputComponents & parentOutput ) + void ToonPhongLightingModel::doComputeLight( c3d::Light const & plight + , ToonPhongLightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Vec3 const & plightDirection + , c3d::OutputComponents & pparentOutput ) { if ( !m_computeLight ) { @@ -841,19 +841,19 @@ namespace toon::shader , outputs ); } - m_computeLight( light - , material - , surface - , worldEye - , lightDirection - , parentOutput ); + m_computeLight( plight + , pmaterial + , psurface + , pworldEye + , plightDirection + , pparentOutput ); } - sdw::Vec3 ToonPhongLightingModel::doComputeLightDiffuse( c3d::Light const & light - , ToonPhongLightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Vec3 const & lightDirection ) + sdw::Vec3 ToonPhongLightingModel::doComputeLightDiffuse( c3d::Light const & plight + , ToonPhongLightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Vec3 const & plightDirection ) { if ( !m_computeLightDiffuse ) { @@ -881,11 +881,11 @@ namespace toon::shader , sdw::InVec3( m_writer, "lightDirection" ) ); } - return m_computeLightDiffuse( light - , material - , surface - , worldEye - , lightDirection ); + return m_computeLightDiffuse( plight + , pmaterial + , psurface + , pworldEye + , plightDirection ); } //********************************************************************************************* @@ -1059,13 +1059,13 @@ namespace toon::shader , envMapSet ); } - void ToonPbrLightingModel::compute( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , c3d::BackgroundModel & background - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPbrLightingModel::compute( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , c3d::BackgroundModel & pbackground + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computeDirectional ) { @@ -1207,20 +1207,20 @@ namespace toon::shader , outputs ); } - m_computeDirectional( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeDirectional( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void ToonPbrLightingModel::compute( c3d::PointLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPbrLightingModel::compute( c3d::PointLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computePoint ) { @@ -1286,20 +1286,20 @@ namespace toon::shader , outputs ); } - m_computePoint( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computePoint( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } - void ToonPbrLightingModel::compute( c3d::SpotLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows - , c3d::OutputComponents & parentOutput ) + void ToonPbrLightingModel::compute( c3d::SpotLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows + , c3d::OutputComponents & pparentOutput ) { if ( !m_computeSpot ) { @@ -1374,12 +1374,12 @@ namespace toon::shader , outputs ); } - m_computeSpot( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows - , parentOutput ); + m_computeSpot( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows + , pparentOutput ); } void ToonPbrLightingModel::computeMapContributions( castor3d::PassFlags const & passFlags @@ -1474,11 +1474,11 @@ namespace toon::shader , emissive ); } - sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::DirectionalLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::DirectionalLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeDirectionalDiffuse ) { @@ -1532,18 +1532,18 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeDirectionalDiffuse( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeDirectionalDiffuse( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::PointLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::PointLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if (!m_computePointDiffuse ) { @@ -1597,18 +1597,18 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computePointDiffuse( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computePointDiffuse( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } - sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::SpotLight const & light - , c3d::LightMaterial const & material - , c3d::Surface const & surface - , sdw::Vec3 const & worldEye - , sdw::Int const & receivesShadows ) + sdw::Vec3 ToonPbrLightingModel::computeDiffuse( c3d::SpotLight const & plight + , c3d::LightMaterial const & pmaterial + , c3d::Surface const & psurface + , sdw::Vec3 const & pworldEye + , sdw::Int const & preceivesShadows ) { if ( !m_computeSpotDiffuse ) { @@ -1674,11 +1674,11 @@ namespace toon::shader , sdw::InInt( m_writer, "receivesShadows" ) ); } - return m_computeSpotDiffuse( light - , static_cast< ToonPbrLightMaterial const & >( material ) - , surface - , worldEye - , receivesShadows ); + return m_computeSpotDiffuse( plight + , static_cast< ToonPbrLightMaterial const & >( pmaterial ) + , psurface + , pworldEye + , preceivesShadows ); } void ToonPbrLightingModel::computeMapDiffuseContributions( castor3d::PassFlags const & passFlags