diff --git a/assets/shaders/modules/pbr.glsl b/assets/shaders/modules/pbr.glsl new file mode 100644 index 000000000..168c2b389 --- /dev/null +++ b/assets/shaders/modules/pbr.glsl @@ -0,0 +1 @@ +#include "/common/pbr/fs_pbr.glsl" diff --git a/core/client/include/pragma/rendering/shader_graph_manager.hpp b/core/client/include/pragma/rendering/shader_graph/manager.hpp similarity index 86% rename from core/client/include/pragma/rendering/shader_graph_manager.hpp rename to core/client/include/pragma/rendering/shader_graph/manager.hpp index 0581d4c75..f846dcfb2 100644 --- a/core/client/include/pragma/rendering/shader_graph_manager.hpp +++ b/core/client/include/pragma/rendering/shader_graph/manager.hpp @@ -20,6 +20,8 @@ namespace pragma::rendering { public: ShaderGraphData(const std::string &typeName, const std::string &identifier, const std::shared_ptr &graph) : m_typeName {typeName}, m_identifier {identifier}, m_graph {graph} {} const std::string &GetIdentifier() const { return m_identifier; } + const std::string &GetTypeName() const { return m_typeName; } + const std::shared_ptr &GetGraph() const { return m_graph; } void GenerateGlsl(); private: std::string m_typeName; @@ -44,24 +46,30 @@ namespace pragma::rendering { std::shared_ptr m_nodeRegistry; }; + class ShaderGraphModuleManager; class DLLCLIENT ShaderGraphManager { public: static constexpr const char *ROOT_GRAPH_PATH = "scripts/shader_data/graphs/"; static std::string GetShaderFilePath(const std::string &type, const std::string &identifier); static std::string GetShaderGraphFilePath(const std::string &type, const std::string &identifier); - ShaderGraphManager() {} - ~ShaderGraphManager() {} + ShaderGraphManager(); + ~ShaderGraphManager(); const std::unordered_map> &GetShaderGraphTypeManagers() const { return m_shaderGraphTypeManagers; } void RegisterGraphTypeManager(const std::string &type, std::shared_ptr nodeRegistry); std::shared_ptr RegisterGraph(const std::string &type, const std::string &identifier); std::shared_ptr CreateGraph(const std::string &type) const; + std::shared_ptr LoadShader(const std::string &identifier, std::string &outErr); void ReloadShader(const std::string &identifier); std::shared_ptr GetGraph(const std::string &identifier) const; std::shared_ptr GetNodeRegistry(const std::string &type) const; + + ShaderGraphModuleManager &GetModuleManager(); + const ShaderGraphModuleManager &GetModuleManager() const; private: std::unordered_map> m_shaderGraphTypeManagers; std::unordered_map m_shaderNameToType; + std::unique_ptr m_moduleManager; }; } diff --git a/core/client/include/pragma/rendering/shader_graph/module.hpp b/core/client/include/pragma/rendering/shader_graph/module.hpp new file mode 100644 index 000000000..1c5b5e059 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/module.hpp @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2021 Silverlan + */ + +#ifndef __SHADER_GRAPH_MODULE_HPP__ +#define __SHADER_GRAPH_MODULE_HPP__ + +#include +#include "pragma/rendering/shaders/world/c_shader_scene.hpp" + +namespace prosper { + class Shader; +} + +namespace pragma { + class CSceneComponent; + class CRasterizationRendererComponent; +}; + +class CModelSubMesh; +namespace pragma::rendering { + class ShaderProcessor; + class DLLCLIENT ShaderGraphModule { + public: + ShaderGraphModule(prosper::Shader &shader) : m_shader(shader) {} + virtual ~ShaderGraphModule() {} + virtual void InitializeGfxPipelineDescriptorSets() = 0; + virtual void UpdateRenderFlags(CModelSubMesh &mesh, ShaderGameWorld::SceneFlags &inOutFlags) {} + virtual void RecordBindScene(ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, ShaderGameWorld::SceneFlags &inOutSceneFlags) const = 0; + protected: + prosper::Shader &m_shader; + }; + + class DLLCLIENT ShaderGraphModuleManager { + public: + using Factory = std::function(prosper::Shader &shader)>; + ShaderGraphModuleManager() {} + void RegisterFactory(const std::string &name, const Factory &factory); + std::unique_ptr CreateModule(const std::string &name, prosper::Shader &shader) const; + const std::unordered_map &GetFactories() const { return m_factories; } + private: + std::unordered_map m_factories; + }; +} + +#endif diff --git a/core/client/include/pragma/rendering/shader_graph/modules/pbr.hpp b/core/client/include/pragma/rendering/shader_graph/modules/pbr.hpp new file mode 100644 index 000000000..56b5694a5 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/modules/pbr.hpp @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2024 Silverlan + */ + +#ifndef __PRAGMA_SHADER_GRAPH_MODULES_PBR_HPP__ +#define __PRAGMA_SHADER_GRAPH_MODULES_PBR_HPP__ + +#include "pragma/clientdefinitions.h" +#include "pragma/rendering/shader_graph/module.hpp" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT PbrModule : public pragma::rendering::ShaderGraphModule { + public: + public: + enum class PBRBinding : uint32_t { + IrradianceMap = 0u, + PrefilterMap, + BRDFMap, + + Count + }; + PbrModule(prosper::Shader &shader); + virtual ~PbrModule() override; + virtual void InitializeGfxPipelineDescriptorSets() override; + virtual void RecordBindScene(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, ShaderGameWorld::SceneFlags &inOutSceneFlags) const override; + prosper::IDescriptorSet *GetReflectionProbeDescriptorSet(const pragma::CSceneComponent &scene, float &outIblStrength, ShaderGameWorld::SceneFlags &inOutSceneFlags) const; + prosper::IDescriptorSet &GetDefaultPbrDescriptorSet() const; + private: + prosper::DescriptorSetInfo m_pbrDescSetInfo; + static std::shared_ptr g_defaultPbrDsg; + static size_t g_instanceCount; + }; +}; + +#endif diff --git a/core/client/include/pragma/rendering/shader_graph/nodes/pbr.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/pbr.hpp new file mode 100644 index 000000000..56d04375a --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/pbr.hpp @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2024 Silverlan + */ + +#ifndef __PRAGMA_SHADER_GRAPH_NODES_PBR_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_PBR_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT PbrNode : public pragma::shadergraph::Node { + public: + static constexpr const char *IN_ALBEDO_COLOR = "albedoColor"; + static constexpr const char *IN_METALNESS = "metalness"; + static constexpr const char *IN_ROUGHNESS = "roughness"; + static constexpr const char *IN_AMBIENT_OCCLUSION = "ambientOcclusion"; + + static constexpr const char *OUT_COLOR = "color"; + + PbrNode(const std::string_view &type); + + virtual std::string DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const override; + }; +}; + +#endif diff --git a/core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp b/core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp index 46c56f20f..f175d0940 100644 --- a/core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp +++ b/core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp @@ -12,25 +12,29 @@ class Texture; namespace pragma { + namespace rendering { + class ShaderGraphModule; + }; class DLLCLIENT ShaderGraph : public ShaderGameWorldLightingPass { public: ShaderGraph(prosper::IPrContext &context, const std::string &identifier, const std::string &fsShader); + virtual ~ShaderGraph() override; virtual void RecordBindScene(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, prosper::IDescriptorSet &dsScene, prosper::IDescriptorSet &dsRenderer, prosper::IDescriptorSet &dsRenderSettings, prosper::IDescriptorSet &dsLights, prosper::IDescriptorSet &dsShadows, const Vector4 &drawOrigin, ShaderGameWorld::SceneFlags &inOutSceneFlags) const override; protected: using ShaderGameWorldLightingPass::RecordDraw; - void RecordBindSceneDescriptorSets(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, prosper::IDescriptorSet &dsScene, prosper::IDescriptorSet &dsRenderer, - prosper::IDescriptorSet &dsRenderSettings, prosper::IDescriptorSet &dsLights, prosper::IDescriptorSet &dsShadows, ShaderGameWorld::SceneFlags &inOutSceneFlags, float &outIblStrength) const; virtual void OnPipelinesInitialized() override; + virtual void ClearShaderResources() override; + virtual void InitializeShaderResources() override; virtual void InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx) override; virtual void InitializeMaterialData(const CMaterial &mat, const rendering::shader_material::ShaderMaterial &shaderMat, pragma::rendering::shader_material::ShaderMaterialData &inOutMatData) override; virtual void UpdateRenderFlags(CModelSubMesh &mesh, SceneFlags &inOutFlags) override; virtual void InitializeGfxPipelineDescriptorSets() override; std::shared_ptr InitializeMaterialDescriptorSet(CMaterial &mat, const prosper::DescriptorSetInfo &descSetInfo); - SceneFlags m_extRenderFlags = SceneFlags::None; std::shared_ptr m_defaultPbrDsg = nullptr; + std::vector> m_modules; }; }; diff --git a/core/client/src/c_engine.cpp b/core/client/src/c_engine.cpp index 64f3562ab..90b05f34b 100644 --- a/core/client/src/c_engine.cpp +++ b/core/client/src/c_engine.cpp @@ -31,7 +31,7 @@ namespace pragma::string { #include "pragma/rendering/c_sci_gpu_timer_manager.hpp" #include #include "pragma/rendering/shaders/world/c_shader_textured.hpp" -#include "pragma/rendering/shader_graph_manager.hpp" +#include "pragma/rendering/shader_graph/manager.hpp" #include #include #include @@ -111,6 +111,8 @@ static const auto SEPARATE_JOYSTICK_AXES = true; #include "pragma/rendering/shader_graph/nodes/lightmap.hpp" #include "pragma/rendering/shader_graph/nodes/object.hpp" #include "pragma/rendering/shader_graph/nodes/time.hpp" +#include "pragma/rendering/shader_graph/nodes/pbr.hpp" +#include "pragma/rendering/shader_graph/modules/pbr.hpp" CEngine::CEngine(int argc, char *argv[]) : Engine(argc, argv), pragma::RenderContext(), m_nearZ(pragma::BaseEnvCameraComponent::DEFAULT_NEAR_Z), //10.0f), //0.1f @@ -204,6 +206,7 @@ CEngine::CEngine(int argc, char *argv[]) regScene->RegisterNode("lightmap"); regScene->RegisterNode("object"); regScene->RegisterNode("time"); + regScene->RegisterNode("pbr"); auto shaderMat = pragma::rendering::shader_material::get_cache().Load("pbr"); auto node = std::make_shared("test", *shaderMat); @@ -217,6 +220,8 @@ CEngine::CEngine(int argc, char *argv[]) m_shaderGraphManager = std::make_unique(); m_shaderGraphManager->RegisterGraphTypeManager("post_processing", regPp); m_shaderGraphManager->RegisterGraphTypeManager("object", regScene); + + m_shaderGraphManager->GetModuleManager().RegisterFactory("pbr", [](prosper::Shader &shader) -> std::unique_ptr { return std::make_unique(shader); }); } } diff --git a/core/client/src/lua/c_luaclass.cpp b/core/client/src/lua/c_luaclass.cpp index f6b11da38..3cdd06a6a 100644 --- a/core/client/src/lua/c_luaclass.cpp +++ b/core/client/src/lua/c_luaclass.cpp @@ -57,7 +57,7 @@ #include "pragma/rendering/shaders/util/c_shader_compose_rma.hpp" #include "pragma/rendering/shaders/post_processing/c_shader_pp_glow.hpp" #include "pragma/rendering/shader_material/shader_material.hpp" -#include "pragma/rendering/shader_graph_manager.hpp" +#include "pragma/rendering/shader_graph/manager.hpp" #include "pragma/lua/libraries/ludm.hpp" #include #include @@ -256,14 +256,15 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) defGraphNode.def("GetDisplayName", &pragma::shadergraph::GraphNode::GetDisplayName); defGraphNode.def("ClearInputValue", &pragma::shadergraph::GraphNode::ClearInputValue); defGraphNode.def( - "SetInputValue", +[](pragma::shadergraph::GraphNode &graphNode, const std::string_view &inputName, luabind::object value) { + "SetInputValue", +[](pragma::shadergraph::GraphNode &graphNode, const std::string_view &inputName, luabind::object value) -> bool { auto type = Lua::udm::determine_udm_type(value); - ::udm::visit(type, [&graphNode, &inputName, &value](auto tag) { + return ::udm::visit(type, [&graphNode, &inputName, &value](auto tag) { using T = typename decltype(tag)::type; if constexpr(pragma::shadergraph::is_socket_type()) { auto val = luabind::object_cast(value); - graphNode.SetInputValue(inputName, val); + return graphNode.SetInputValue(inputName, val); } + return false; }); }); defGraphNode.def( @@ -487,48 +488,6 @@ void ClientState::RegisterSharedLuaClasses(Lua::Interface &lua, bool bGUI) } return 0; }}, - {"register_graph", - [](lua_State *l) { - std::string type = Lua::CheckString(l, 1); - std::string identifier = Lua::CheckString(l, 2); - auto &manager = c_engine->GetShaderGraphManager(); - auto graph = manager.RegisterGraph(type, identifier); - Lua::Push(l, graph); - return 1; - }}, - {"create_graph", - [](lua_State *l) { - std::string type = Lua::CheckString(l, 1); - auto &manager = c_engine->GetShaderGraphManager(); - auto graph = manager.CreateGraph(type); - Lua::Push(l, graph); - return 1; - }}, - {"get_graph", - [](lua_State *l) { - std::string identifier = Lua::CheckString(l, 1); - auto &manager = c_engine->GetShaderGraphManager(); - auto graph = manager.GetGraph(identifier); - Lua::Push(l, graph); - return 1; - }}, - {"reload_graph_shader", - [](lua_State *l) { - std::string identifier = Lua::CheckString(l, 1); - auto &manager = c_engine->GetShaderGraphManager(); - manager.ReloadShader(identifier); - return 0; - }}, - {"get_graph_node_registry", - [](lua_State *l) { - std::string type = Lua::CheckString(l, 1); - auto &manager = c_engine->GetShaderGraphManager(); - auto reg = manager.GetNodeRegistry(type); - if(!reg) - return 0; - Lua::Push(l, reg); - return 1; - }}, {"get", [](lua_State *l) { auto *className = Lua::CheckString(l, 1); @@ -572,6 +531,44 @@ void ClientState::RegisterSharedLuaClasses(Lua::Interface &lua, bool bGUI) return 1; }}}); + modShader[luabind::def( + "register_graph", +[](const std::string &type, const std::string &identifier) -> std::shared_ptr { + auto &manager = c_engine->GetShaderGraphManager(); + return manager.RegisterGraph(type, identifier); + })]; + modShader[luabind::def( + "create_graph", +[](const std::string &type) -> std::shared_ptr { + auto &manager = c_engine->GetShaderGraphManager(); + return manager.CreateGraph(type); + })]; + modShader[luabind::def( + "get_graph", +[](const std::string &identifier) -> std::shared_ptr { + auto &manager = c_engine->GetShaderGraphManager(); + auto graphData = manager.GetGraph(identifier); + if(!graphData) + return nullptr; + return graphData->GetGraph(); + })]; + modShader[luabind::def( + "reload_graph_shader", +[](const std::string &identifier) { + auto &manager = c_engine->GetShaderGraphManager(); + manager.ReloadShader(identifier); + })]; + modShader[luabind::def( + "get_graph_node_registry", +[](const std::string &type) -> std::shared_ptr { + auto &manager = c_engine->GetShaderGraphManager(); + return manager.GetNodeRegistry(type); + })]; + modShader[luabind::def( + "load_shader_graph", +[](const std::string &identifier) -> std::pair, std::optional> { + auto &manager = c_engine->GetShaderGraphManager(); + std::string err; + auto graph = manager.LoadShader(identifier, err); + if(!graph) + return {nullptr, std::optional {err}}; + return {graph, std::optional {}}; + })]; + // These have to match shaders/modules/fs_tonemapping.gls! enum class ToneMapping : uint8_t { None = 0, diff --git a/core/client/src/rendering/shader_graph_manager.cpp b/core/client/src/rendering/shader_graph/manager.cpp similarity index 80% rename from core/client/src/rendering/shader_graph_manager.cpp rename to core/client/src/rendering/shader_graph/manager.cpp index 429aae7bc..c0ad17cd3 100644 --- a/core/client/src/rendering/shader_graph_manager.cpp +++ b/core/client/src/rendering/shader_graph/manager.cpp @@ -6,13 +6,13 @@ */ #include "stdafx_client.h" -#include "pragma/rendering/shader_graph_manager.hpp" +#include "pragma/rendering/shader_graph/manager.hpp" +#include "pragma/rendering/shader_graph/module.hpp" #include "pragma/rendering/shaders/world/c_shader_graph.hpp" extern DLLCLIENT CEngine *c_engine; using namespace pragma::rendering; -#pragma optimize("", off) void ShaderGraphTypeManager::RegisterGraph(const std::string &identifier, std::shared_ptr graph) { auto fragFilePath = util::FilePath(ShaderGraphManager::GetShaderFilePath(m_typeName, identifier)); @@ -20,14 +20,18 @@ void ShaderGraphTypeManager::RegisterGraph(const std::string &identifier, std::s auto strFragFilePath = fragFilePath.GetString(); auto &shaderManager = c_engine->GetShaderManager(); auto shader = shaderManager.GetShader(identifier); + auto graphData = std::make_shared(m_typeName, identifier, graph); if(shader.valid()) { auto *sgShader = dynamic_cast(shader.get()); if(!sgShader) throw std::runtime_error {"Shader '" + identifier + "' already exists and is not a ShaderGraph!"}; } - else + else { + auto path = ShaderGraphManager::GetShaderFilePath(m_typeName, identifier); + if(!filemanager::exists(path)) + graphData->GenerateGlsl(); shaderManager.RegisterShader(identifier, [strFragFilePath](prosper::IPrContext &context, const std::string &identifier) { return new pragma::ShaderGraph {context, identifier, strFragFilePath}; }); - auto graphData = std::make_shared(m_typeName, identifier, graph); + } m_graphs[identifier] = graphData; } @@ -70,6 +74,10 @@ std::string ShaderGraphManager::GetShaderGraphFilePath(const std::string &type, strPath += "." + std::string {pragma::shadergraph::Graph::EXTENSION_ASCII}; return strPath; } +ShaderGraphManager::ShaderGraphManager() : m_moduleManager {std::make_unique()} {} +ShaderGraphManager::~ShaderGraphManager() {} +ShaderGraphModuleManager &ShaderGraphManager::GetModuleManager() { return *m_moduleManager; } +const ShaderGraphModuleManager &ShaderGraphManager::GetModuleManager() const { return *m_moduleManager; } void ShaderGraphManager::RegisterGraphTypeManager(const std::string &type, std::shared_ptr nodeRegistry) { m_shaderGraphTypeManagers[type] = std::make_shared(type, nodeRegistry); } std::shared_ptr ShaderGraphManager::RegisterGraph(const std::string &type, const std::string &identifier) { @@ -92,6 +100,26 @@ std::shared_ptr ShaderGraphManager::CreateGraph(cons return nullptr; return it->second->CreateGraph(); } +std::shared_ptr ShaderGraphManager::LoadShader(const std::string &identifier, std::string &outErr) +{ + auto graph = GetGraph(identifier); + if(graph) + return graph->GetGraph(); + for(auto &[typeName, typeManager] : m_shaderGraphTypeManagers) { + auto path = GetShaderGraphFilePath(typeName, identifier); + if(!filemanager::exists(path)) + continue; + auto graph = std::make_shared(typeManager->GetNodeRegistry()); + auto result = graph->Load(path, outErr); + if(!result) + return nullptr; + typeManager->RegisterGraph(identifier, graph); + m_shaderNameToType[identifier] = typeName; + return graph; + } + outErr = "Failed to load shader graph '" + identifier + "': No shader graph file found!"; + return nullptr; +} void ShaderGraphManager::ReloadShader(const std::string &identifier) { auto itType = m_shaderNameToType.find(identifier); diff --git a/core/client/src/rendering/shader_graph/module.cpp b/core/client/src/rendering/shader_graph/module.cpp new file mode 100644 index 000000000..3d6c36e47 --- /dev/null +++ b/core/client/src/rendering/shader_graph/module.cpp @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2024 Silverlan + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/module.hpp" + +using namespace pragma::rendering; + +void ShaderGraphModuleManager::RegisterFactory(const std::string &name, const Factory &factory) { m_factories[name] = factory; } +std::unique_ptr ShaderGraphModuleManager::CreateModule(const std::string &name, prosper::Shader &shader) const +{ + auto it = m_factories.find(name); + if(it == m_factories.end()) + return nullptr; + auto &factory = it->second; + return factory(shader); +} diff --git a/core/client/src/rendering/shader_graph/modules/pbr.cpp b/core/client/src/rendering/shader_graph/modules/pbr.cpp new file mode 100644 index 000000000..07e5db830 --- /dev/null +++ b/core/client/src/rendering/shader_graph/modules/pbr.cpp @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2024 Silverlan + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/modules/pbr.hpp" +#include "pragma/rendering/render_processor.hpp" +#include "pragma/entities/environment/c_env_reflection_probe.hpp" +#include "pragma/entities/environment/c_env_camera.h" +#include + +using namespace pragma::rendering::shader_graph; + +extern DLLCLIENT CEngine *c_engine; +std::shared_ptr PbrModule::g_defaultPbrDsg = {}; +size_t PbrModule::g_instanceCount = 0; +PbrModule::PbrModule(prosper::Shader &shader) : pragma::rendering::ShaderGraphModule {shader} +{ + m_pbrDescSetInfo = { + "PBR", + {prosper::DescriptorSetInfo::Binding {"IRRADIANCE_MAP", prosper::DescriptorType::CombinedImageSampler, prosper::ShaderStageFlags::FragmentBit, prosper::PrDescriptorSetBindingFlags::Cubemap}, + prosper::DescriptorSetInfo::Binding {"PREFILTER_MAP", prosper::DescriptorType::CombinedImageSampler, prosper::ShaderStageFlags::FragmentBit, prosper::PrDescriptorSetBindingFlags::Cubemap}, + prosper::DescriptorSetInfo::Binding {"BRDF_MAP", prosper::DescriptorType::CombinedImageSampler, prosper::ShaderStageFlags::FragmentBit}}, + }; +} +PbrModule::~PbrModule() +{ + if(--g_instanceCount == 0) + g_defaultPbrDsg = nullptr; +} +void PbrModule::InitializeGfxPipelineDescriptorSets() +{ + m_shader.AddDescriptorSetGroup(m_pbrDescSetInfo); + if(!g_defaultPbrDsg) { + auto &context = c_engine->GetRenderContext(); + g_defaultPbrDsg = context.CreateDescriptorSetGroup(m_pbrDescSetInfo); + auto &dummyTex = context.GetDummyTexture(); + auto &dummyCubemapTex = context.GetDummyCubemapTexture(); + auto &ds = *g_defaultPbrDsg->GetDescriptorSet(0); + ds.SetBindingTexture(*dummyCubemapTex, umath::to_integral(PBRBinding::IrradianceMap)); + ds.SetBindingTexture(*dummyCubemapTex, umath::to_integral(PBRBinding::PrefilterMap)); + ds.SetBindingTexture(*dummyTex, umath::to_integral(PBRBinding::BRDFMap)); + } +} +void PbrModule::RecordBindScene(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, ShaderGameWorld::SceneFlags &inOutSceneFlags) const +{ + float iblStrength = 1.f; + auto *ds = GetReflectionProbeDescriptorSet(scene, iblStrength, inOutSceneFlags); + + shaderProcessor.GetCommandBuffer().RecordBindDescriptorSets(prosper::PipelineBindPoint::Graphics, shaderProcessor.GetCurrentPipelineLayout(), m_pbrDescSetInfo.setIndex, *ds); +} +prosper::IDescriptorSet *PbrModule::GetReflectionProbeDescriptorSet(const pragma::CSceneComponent &scene, float &outIblStrength, ShaderGameWorld::SceneFlags &inOutSceneFlags) const +{ + auto &hCam = scene.GetActiveCamera(); + assert(hCam.valid()); + auto *dsPbr = CReflectionProbeComponent::FindDescriptorSetForClosestProbe(scene, hCam->GetEntity().GetPosition(), outIblStrength); + if(dsPbr == nullptr) // No reflection probe and therefore no IBL available. Fallback to non-IBL rendering. + { + dsPbr = &GetDefaultPbrDescriptorSet(); + inOutSceneFlags |= ShaderGameWorld::SceneFlags::NoIBL; + } + return dsPbr; +} +prosper::IDescriptorSet &PbrModule::GetDefaultPbrDescriptorSet() const { return *g_defaultPbrDsg->GetDescriptorSet(); } diff --git a/core/client/src/rendering/shader_graph/nodes/pbr.cpp b/core/client/src/rendering/shader_graph/nodes/pbr.cpp new file mode 100644 index 000000000..ea5198c64 --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/pbr.cpp @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2024 Silverlan + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/nodes/pbr.hpp" + +using namespace pragma::rendering::shader_graph; + +PbrNode::PbrNode(const std::string_view &type) : Node {type} +{ + AddInput(IN_ALBEDO_COLOR, pragma::shadergraph::SocketType::Color, Vector3 {1.f, 1.f, 1.f}); + AddInput(IN_METALNESS, pragma::shadergraph::SocketType::Float, 0.f); + AddInput(IN_ROUGHNESS, pragma::shadergraph::SocketType::Float, 0.5f); + AddInput(IN_AMBIENT_OCCLUSION, pragma::shadergraph::SocketType::Float, 0.f); + + AddOutput(OUT_COLOR, pragma::shadergraph::SocketType::Color); + + AddModuleDependency("pbr"); +} + +std::string PbrNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &gn) const +{ + std::ostringstream code; + + auto inAc = gn.GetInputNameOrValue(IN_ALBEDO_COLOR); + auto inMetalness = gn.GetInputNameOrValue(IN_METALNESS); + auto inRoughness = gn.GetInputNameOrValue(IN_ROUGHNESS); + auto inAo = gn.GetInputNameOrValue(IN_AMBIENT_OCCLUSION); + + auto prefix = gn.GetBaseVarName() + "_"; + auto vA = prefix + "albedo"; + auto vUv = prefix + "uv"; + auto vDbg = prefix + "debugMode"; + auto vMat = prefix + "material"; + auto vEmission = prefix + "emissionFactor"; + auto vMatFlags = prefix + "matFlags"; + code << "vec4 " << vA << " = vec4(" << inAc << ",1);\n"; + code << "vec2 " << vUv << " = get_uv_coordinates();\n"; + code << "uint " << vDbg << " = 0;\n"; + code << "PbrMaterial " << vMat << ";\n"; + code << vMat << ".color = vec4(1,1,1,1);\n"; + code << vMat << ".metalnessFactor = " << inMetalness << ";\n"; + code << vMat << ".roughnessFactor = " << inRoughness << ";\n"; + code << vMat << ".aoFactor = " << inAo << ";\n"; + code << vMat << ".alphaMode = ALPHA_MODE_OPAQUE;\n"; + code << vMat << ".alphaCutoff = 0.5;\n"; + code << "vec3 " << vEmission << " = vec3(0,0,0);\n"; + code << "uint " << vMatFlags << " = 0;\n"; + code << gn.GetGlslOutputDeclaration(OUT_COLOR) << " = "; + code << "calc_pbr(" << vA << ", " << vUv << ", " << vDbg << ", " << vMat << ", " << vEmission << ", " << vMatFlags << ").rgb;\n"; + return code.str(); +} diff --git a/core/client/src/rendering/shaders/world/c_shader_graph.cpp b/core/client/src/rendering/shaders/world/c_shader_graph.cpp index 236fc88f4..2e739f575 100644 --- a/core/client/src/rendering/shaders/world/c_shader_graph.cpp +++ b/core/client/src/rendering/shaders/world/c_shader_graph.cpp @@ -13,6 +13,8 @@ #include "pragma/rendering/renderers/rasterization_renderer.hpp" #include "pragma/rendering/render_processor.hpp" #include "pragma/rendering/shader_material/shader_material.hpp" +#include "pragma/rendering/shader_graph/manager.hpp" +#include "pragma/rendering/shader_graph/module.hpp" #include "pragma/model/vk_mesh.h" #include "pragma/model/c_modelmesh.h" #include @@ -35,15 +37,55 @@ using namespace pragma; ShaderGraph::ShaderGraph(prosper::IPrContext &context, const std::string &identifier, const std::string &fsShader) : ShaderGameWorldLightingPass {context, identifier, "programs/scene/textured", fsShader} {} +ShaderGraph::~ShaderGraph() {} + void ShaderGraph::UpdateRenderFlags(CModelSubMesh &mesh, SceneFlags &inOutFlags) { ShaderGameWorldLightingPass::UpdateRenderFlags(mesh, inOutFlags); - inOutFlags |= m_extRenderFlags; + for(auto &mod : m_modules) + mod->UpdateRenderFlags(mesh, inOutFlags); +} +void ShaderGraph::InitializeGfxPipelineDescriptorSets() +{ + ShaderGameWorldLightingPass::InitializeGfxPipelineDescriptorSets(); + for(auto &mod : m_modules) + mod->InitializeGfxPipelineDescriptorSets(); +} + +void ShaderGraph::ClearShaderResources() +{ + m_modules.clear(); + ShaderGameWorldLightingPass::ClearShaderResources(); +} + +void ShaderGraph::InitializeShaderResources() +{ + auto &graphManager = c_engine->GetShaderGraphManager(); + auto graphData = graphManager.GetGraph(GetIdentifier()); + if(graphData) { + auto &graph = graphData->GetGraph(); + std::unordered_set moduleNames; + for(auto &node : graph->GetNodes()) { + auto &deps = (*node)->GetModuleDependencies(); + moduleNames.reserve(moduleNames.size() + deps.size()); + moduleNames.insert(deps.begin(), deps.end()); + } + for(auto &modName : moduleNames) { + auto mod = graphManager.GetModuleManager().CreateModule(modName, *this); + if(mod) + m_modules.emplace_back(std::move(mod)); + } + } + + ShaderGameWorldLightingPass::InitializeShaderResources(); } -void ShaderGraph::InitializeGfxPipelineDescriptorSets() { ShaderGameWorldLightingPass::InitializeGfxPipelineDescriptorSets(); } void ShaderGraph::InitializeMaterialData(const CMaterial &mat, const rendering::shader_material::ShaderMaterial &shaderMat, pragma::rendering::shader_material::ShaderMaterialData &inOutMatData) { + + // If graph has "pbr" module, pbr descriptor set should be added + //prosper::DescriptorSetInfo + ShaderGameWorldLightingPass::InitializeMaterialData(mat, shaderMat, inOutMatData); auto &data = mat.GetDataBlock(); float specularFactor; @@ -60,29 +102,17 @@ std::shared_ptr ShaderGraph::InitializeMaterialDes void ShaderGraph::OnPipelinesInitialized() { ShaderGameWorldLightingPass::OnPipelinesInitialized(); } void ShaderGraph::InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx) { ShaderGameWorldLightingPass::InitializeGfxPipeline(pipelineInfo, pipelineIdx); } -// - -void ShaderGraph::RecordBindSceneDescriptorSets(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, prosper::IDescriptorSet &dsScene, prosper::IDescriptorSet &dsRenderer, - prosper::IDescriptorSet &dsRenderSettings, prosper::IDescriptorSet &dsLights, prosper::IDescriptorSet &dsShadows, ShaderGameWorld::SceneFlags &inOutSceneFlags, float &outIblStrength) const -{ - outIblStrength = 1.f; - std::array descSets {&dsScene, &dsRenderer, &dsRenderSettings, &dsLights, &dsShadows}; - - static const std::vector dynamicOffsets {}; - shaderProcessor.GetCommandBuffer().RecordBindDescriptorSets(prosper::PipelineBindPoint::Graphics, shaderProcessor.GetCurrentPipelineLayout(), GetSceneDescriptorSetIndex(), descSets, dynamicOffsets); -} - void ShaderGraph::RecordBindScene(rendering::ShaderProcessor &shaderProcessor, const pragma::CSceneComponent &scene, const pragma::CRasterizationRendererComponent &renderer, prosper::IDescriptorSet &dsScene, prosper::IDescriptorSet &dsRenderer, prosper::IDescriptorSet &dsRenderSettings, prosper::IDescriptorSet &dsLights, prosper::IDescriptorSet &dsShadows, const Vector4 &drawOrigin, ShaderGameWorld::SceneFlags &inOutSceneFlags) const { - auto iblStrength = 1.f; - RecordBindSceneDescriptorSets(shaderProcessor, scene, renderer, dsScene, dsRenderer, dsRenderSettings, dsLights, dsShadows, inOutSceneFlags, iblStrength); - ShaderGameWorldLightingPass::PushConstants pushConstants {}; pushConstants.Initialize(); pushConstants.debugMode = scene.GetDebugMode(); - pushConstants.reflectionProbeIntensity = iblStrength; + pushConstants.reflectionProbeIntensity = 1.f; pushConstants.flags = inOutSceneFlags; pushConstants.drawOrigin = drawOrigin; shaderProcessor.GetCommandBuffer().RecordPushConstants(shaderProcessor.GetCurrentPipelineLayout(), prosper::ShaderStageFlags::VertexBit | prosper::ShaderStageFlags::FragmentBit, 0u, sizeof(pushConstants), &pushConstants); + + for(auto &mod : m_modules) + mod->RecordBindScene(shaderProcessor, scene, renderer, inOutSceneFlags); }