From be03e967afda82e63bbd2fa66572ac420176e12f Mon Sep 17 00:00:00 2001 From: Silverlan Date: Sat, 23 Nov 2024 21:30:47 +0100 Subject: [PATCH] feat(shader_graph): add base scene graph shader and node implementation --- build_scripts/build.py | 2 +- build_scripts/scripts/external_libs.py | 2 +- core/client/include/pragma/c_engine.h | 6 + .../rendering/shader_graph/nodes/camera.hpp | 32 ++++ .../rendering/shader_graph/nodes/fog.hpp | 29 ++++ .../rendering/shader_graph/nodes/lightmap.hpp | 28 ++++ .../rendering/shader_graph/nodes/object.hpp | 27 ++++ .../shader_graph/nodes/scene_output.hpp | 28 ++++ .../shader_graph/nodes/shader_material.hpp | 27 ++++ .../rendering/shader_graph/nodes/time.hpp | 29 ++++ .../pragma/rendering/shader_graph_manager.hpp | 68 ++++++++ .../shaders/world/c_shader_graph.hpp | 37 +++++ core/client/src/c_engine.cpp | 38 ++++- core/client/src/lua/c_luaclass.cpp | 151 ++++++++++++++++- .../rendering/shader_graph/nodes/camera.cpp | 38 +++++ .../src/rendering/shader_graph/nodes/fog.cpp | 31 ++++ .../rendering/shader_graph/nodes/lightmap.cpp | 19 +++ .../rendering/shader_graph/nodes/object.cpp | 27 ++++ .../shader_graph/nodes/scene_output.cpp | 27 ++++ .../shader_graph/nodes/shader_material.cpp | 39 +++++ .../src/rendering/shader_graph/nodes/time.cpp | 31 ++++ .../src/rendering/shader_graph_manager.cpp | 153 ++++++++++++++++++ .../shaders/world/c_shader_graph.cpp | 88 ++++++++++ 23 files changed, 950 insertions(+), 7 deletions(-) create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/camera.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/fog.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/lightmap.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/object.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/scene_output.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/shader_material.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph/nodes/time.hpp create mode 100644 core/client/include/pragma/rendering/shader_graph_manager.hpp create mode 100644 core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp create mode 100644 core/client/src/rendering/shader_graph/nodes/camera.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/fog.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/lightmap.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/object.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/scene_output.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/shader_material.cpp create mode 100644 core/client/src/rendering/shader_graph/nodes/time.cpp create mode 100644 core/client/src/rendering/shader_graph_manager.cpp create mode 100644 core/client/src/rendering/shaders/world/c_shader_graph.cpp diff --git a/build_scripts/build.py b/build_scripts/build.py index 77dea358b..6fa5764f0 100644 --- a/build_scripts/build.py +++ b/build_scripts/build.py @@ -1137,7 +1137,7 @@ def download_addon(name,addonName,url,commitId=None): if not skip_repository_updates: if with_pfm: download_addon("PFM","filmmaker","https://github.com/Silverlan/pfm.git","b0cc0afcdb96aab8a5fe778fb20aef7eb5329115") - download_addon("model editor","tool_model_editor","https://github.com/Silverlan/pragma_model_editor.git","bd4844c06b9a42bacd17bb7e52d3381c3fd119e4") + download_addon("model editor","tool_model_editor","https://github.com/Silverlan/pragma_model_editor.git","a9ea4820f03be250bdf1e6951dad313561b75b17") if with_vr: download_addon("VR","virtual_reality","https://github.com/Silverlan/PragmaVR.git","93fe4f849493651c14133ddf1963b0a8b719f836") diff --git a/build_scripts/scripts/external_libs.py b/build_scripts/scripts/external_libs.py index 5254b4692..4316a54ad 100644 --- a/build_scripts/scripts/external_libs.py +++ b/build_scripts/scripts/external_libs.py @@ -32,7 +32,7 @@ get_submodule("util_versioned_archive","https://github.com/Silverlan/util_versioned_archive.git","e8db74a6ad9ed44d7e8a4492eb8fe44eae3452f6") get_submodule("util_vmf","https://github.com/Silverlan/util_vmf.git","4e477b1425e1a7b9898975effaf527f661e792da") get_submodule("util_zip","https://github.com/Silverlan/util_zip.git","d9bf05a5cbf71bf53f9fbea82c7352f870989ed1") -get_submodule("util_shadergraph","https://github.com/Silverlan/util_shadergraph.git","33b89dfa095b64414703de5bcf9a7f9cd87bcbf6") +get_submodule("util_shadergraph","https://github.com/Silverlan/util_shadergraph.git","610d417e369a7a7408ad29949e72f81aab74456e") get_submodule("vfilesystem","https://github.com/Silverlan/vfilesystem.git","3d6001b2202ac4eecb8d68de1909f72c22060a31") get_submodule("wgui","https://github.com/Silverlan/wgui.git","66d3758336d6e58046813a30298a6a3d9af74318") get_submodule("util_unicode","https://github.com/Silverlan/util_unicode.git","5a0ac6c02f199e42d7d38d99231503cf42e26f8a") diff --git a/core/client/include/pragma/c_engine.h b/core/client/include/pragma/c_engine.h index 0225b43d1..b31c17cfa 100644 --- a/core/client/include/pragma/c_engine.h +++ b/core/client/include/pragma/c_engine.h @@ -37,6 +37,9 @@ namespace pragma::debug { namespace pragma::string { class Utf8String; }; +namespace pragma::rendering { + class ShaderGraphManager; +}; struct InputBindingLayer; struct CoreInputBindingLayer; struct FontSet; @@ -203,6 +206,8 @@ class DLLCLIENT CEngine : public Engine, public pragma::RenderContext { // Shaders ::util::WeakHandle ReloadShader(const std::string &name); void ReloadShaderPipelines(); + pragma::rendering::ShaderGraphManager &GetShaderGraphManager() { return *m_shaderGraphManager; } + const pragma::rendering::ShaderGraphManager &GetShaderGraphManager() const { return const_cast(this)->GetShaderGraphManager(); } // Double GetDeltaFrameTime() const; @@ -272,6 +277,7 @@ class DLLCLIENT CEngine : public Engine, public pragma::RenderContext { float m_nearZ, m_farZ; std::unique_ptr m_clInstance; std::unique_ptr m_clConfig; + std::unique_ptr m_shaderGraphManager; std::optional m_renderResolution = {}; std::shared_ptr m_gpuProfiler; diff --git a/core/client/include/pragma/rendering/shader_graph/nodes/camera.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/camera.hpp new file mode 100644 index 000000000..11244ded4 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/camera.hpp @@ -0,0 +1,32 @@ +/* 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_CAMERA_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_CAMERA_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT CameraNode : public pragma::shadergraph::Node { + public: + static constexpr const char *OUT_POSITION = "position"; + static constexpr const char *OUT_FOV = "fov"; + static constexpr const char *OUT_NEARZ = "nearZ"; + static constexpr const char *OUT_FARZ = "farZ"; + static constexpr const char *OUT_VIEW_MATRIX = "viewMatrix"; + static constexpr const char *OUT_PROJECTION_MATRIX = "projectionMatrix"; + static constexpr const char *OUT_VIEW_PROJECTION_MATRIX = "viewProjectionMatrix"; + + CameraNode(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/shader_graph/nodes/fog.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/fog.hpp new file mode 100644 index 000000000..084b807ce --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/fog.hpp @@ -0,0 +1,29 @@ +/* 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_FOG_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_FOG_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT FogNode : public pragma::shadergraph::Node { + public: + static constexpr const char *OUT_COLOR = "color"; + static constexpr const char *OUT_START_DISTANCE = "startDistance"; + static constexpr const char *OUT_END_DISTANCE = "endDistance"; + static constexpr const char *OUT_DENSITY = "density"; + + FogNode(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/shader_graph/nodes/lightmap.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/lightmap.hpp new file mode 100644 index 000000000..50002118c --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/lightmap.hpp @@ -0,0 +1,28 @@ +/* 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_LIGHTMAP_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_LIGHTMAP_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT LightmapNode : public pragma::shadergraph::Node { + public: + static constexpr const char *OUT_LIGHT_MAP = "lightMap"; + static constexpr const char *OUT_LIGHT_MAP_INDIRECT = "lightMapIndirect"; + static constexpr const char *OUT_LIGHT_MAP_DOMINANT = "lightMapDominant"; + + LightmapNode(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/shader_graph/nodes/object.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/object.hpp new file mode 100644 index 000000000..ec493881f --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/object.hpp @@ -0,0 +1,27 @@ +/* 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_OBJECT_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_OBJECT_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT ObjectNode : public pragma::shadergraph::Node { + public: + static constexpr const char *OUT_MODEL_MATRIX = "modelMatrix"; + static constexpr const char *OUT_COLOR = "color"; + + ObjectNode(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/shader_graph/nodes/scene_output.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/scene_output.hpp new file mode 100644 index 000000000..5fa9684e4 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/scene_output.hpp @@ -0,0 +1,28 @@ +/* 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_SCENE_OUTPUT_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_SCENE_OUTPUT_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT SceneOutputNode : public pragma::shadergraph::Node { + public: + static constexpr const char *IN_COLOR = "color"; + static constexpr const char *IN_ALPHA = "alpha"; + static constexpr const char *IN_BLOOM_COLOR = "bloomColor"; + // TODO: Only allow one of these! + SceneOutputNode(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/shader_graph/nodes/shader_material.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/shader_material.hpp new file mode 100644 index 000000000..6b54f8d5e --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/shader_material.hpp @@ -0,0 +1,27 @@ +/* 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_SHADER_MATERIAL_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_SHADER_MATERIAL_HPP__ + +#include "pragma/clientdefinitions.h" +#include "pragma/rendering/shader_material/shader_material.hpp" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT ShaderMaterialNode : public pragma::shadergraph::Node { + public: + ShaderMaterialNode(const std::string_view &type, const pragma::rendering::shader_material::ShaderMaterial &shaderMaterial); + + virtual std::string DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const override; + private: + const pragma::rendering::shader_material::ShaderMaterial &m_shaderMaterial; + }; +}; + +#endif diff --git a/core/client/include/pragma/rendering/shader_graph/nodes/time.hpp b/core/client/include/pragma/rendering/shader_graph/nodes/time.hpp new file mode 100644 index 000000000..5340eee94 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph/nodes/time.hpp @@ -0,0 +1,29 @@ +/* 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_TIME_HPP__ +#define __PRAGMA_SHADER_GRAPH_NODES_TIME_HPP__ + +#include "pragma/clientdefinitions.h" + +import pragma.shadergraph; + +namespace pragma::rendering::shader_graph { + class DLLCLIENT TimeNode : public pragma::shadergraph::Node { + public: + static constexpr const char *OUT_TIME = "time"; + static constexpr const char *OUT_DELTA_TIME = "deltaTime"; + static constexpr const char *OUT_REAL_TIME = "realTime"; + static constexpr const char *OUT_DELTA_REAL_TIME = "deltaRealTime"; + + TimeNode(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/shader_graph_manager.hpp b/core/client/include/pragma/rendering/shader_graph_manager.hpp new file mode 100644 index 000000000..0581d4c75 --- /dev/null +++ b/core/client/include/pragma/rendering/shader_graph_manager.hpp @@ -0,0 +1,68 @@ +/* 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_MANAGER_HPP__ +#define __SHADER_GRAPH_MANAGER_HPP__ + +#include +#include +#include +#include + +import pragma.shadergraph; + +namespace pragma::rendering { + class DLLCLIENT ShaderGraphData { + 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; } + void GenerateGlsl(); + private: + std::string m_typeName; + std::string m_identifier; + std::shared_ptr m_graph; + }; + + class ShaderGraphManager; + class DLLCLIENT ShaderGraphTypeManager { + public: + ShaderGraphTypeManager(const std::string &typeName, std::shared_ptr nodeRegistry) : m_typeName {typeName}, m_nodeRegistry {nodeRegistry} {} + void ReloadShader(const std::string &identifier); + std::shared_ptr GetGraph(const std::string &identifier) const; + const std::shared_ptr &GetNodeRegistry() const { return m_nodeRegistry; } + private: + friend ShaderGraphManager; + void RegisterGraph(const std::string &identifier, std::shared_ptr graph); + std::shared_ptr RegisterGraph(const std::string &identifier); + std::shared_ptr CreateGraph() const; + std::string m_typeName; + std::unordered_map> m_graphs; + std::shared_ptr m_nodeRegistry; + }; + + 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() {} + 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; + void ReloadShader(const std::string &identifier); + std::shared_ptr GetGraph(const std::string &identifier) const; + std::shared_ptr GetNodeRegistry(const std::string &type) const; + private: + std::unordered_map> m_shaderGraphTypeManagers; + std::unordered_map m_shaderNameToType; + }; +} + +#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 new file mode 100644 index 000000000..46c56f20f --- /dev/null +++ b/core/client/include/pragma/rendering/shaders/world/c_shader_graph.hpp @@ -0,0 +1,37 @@ +/* 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 __C_SHADER_GRAPH_HPP__ +#define __C_SHADER_GRAPH_HPP__ + +#include "pragma/rendering/shaders/world/c_shader_textured.hpp" + +class Texture; +namespace pragma { + class DLLCLIENT ShaderGraph : public ShaderGameWorldLightingPass { + public: + ShaderGraph(prosper::IPrContext &context, const std::string &identifier, const std::string &fsShader); + + 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 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; + }; +}; + +#endif diff --git a/core/client/src/c_engine.cpp b/core/client/src/c_engine.cpp index a592f9aa2..64f3562ab 100644 --- a/core/client/src/c_engine.cpp +++ b/core/client/src/c_engine.cpp @@ -31,6 +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 #include #include @@ -79,7 +80,7 @@ namespace pragma::string { #endif import util_zip; - +import pragma.shadergraph; extern "C" { void DLLCLIENT RunCEngine(int argc, char *argv[]) { @@ -103,6 +104,14 @@ decltype(CEngine::AXIS_PRESS_THRESHOLD) CEngine::AXIS_PRESS_THRESHOLD = 0.5f; // can be bound individually static const auto SEPARATE_JOYSTICK_AXES = true; +#include "pragma/rendering/shader_graph/nodes/scene_output.hpp" +#include "pragma/rendering/shader_graph/nodes/shader_material.hpp" +#include "pragma/rendering/shader_graph/nodes/camera.hpp" +#include "pragma/rendering/shader_graph/nodes/fog.hpp" +#include "pragma/rendering/shader_graph/nodes/lightmap.hpp" +#include "pragma/rendering/shader_graph/nodes/object.hpp" +#include "pragma/rendering/shader_graph/nodes/time.hpp" + CEngine::CEngine(int argc, char *argv[]) : Engine(argc, argv), pragma::RenderContext(), m_nearZ(pragma::BaseEnvCameraComponent::DEFAULT_NEAR_Z), //10.0f), //0.1f m_farZ(pragma::BaseEnvCameraComponent::DEFAULT_FAR_Z), m_fps(0), m_tFPSTime(0.f), m_tLastFrame(util::Clock::now()), m_tDeltaFrameTime(0), m_audioAPI {"fmod"} @@ -182,6 +191,33 @@ CEngine::CEngine(int argc, char *argv[]) return wrapper; }); } + + { + auto regBase = std::make_shared(); + regBase->RegisterNode("math"); + + auto regScene = std::make_shared(); + regScene->RegisterNode("output"); + regScene->RegisterNode("combine_xyz"); + regScene->RegisterNode("camera"); + regScene->RegisterNode("fog"); + regScene->RegisterNode("lightmap"); + regScene->RegisterNode("object"); + regScene->RegisterNode("time"); + + auto shaderMat = pragma::rendering::shader_material::get_cache().Load("pbr"); + auto node = std::make_shared("test", *shaderMat); + regScene->RegisterNode(node); + + regScene->AddChildRegistry(regBase); + + auto regPp = std::make_shared(); + regPp->AddChildRegistry(regBase); + + m_shaderGraphManager = std::make_unique(); + m_shaderGraphManager->RegisterGraphTypeManager("post_processing", regPp); + m_shaderGraphManager->RegisterGraphTypeManager("object", regScene); + } } void CEngine::Release() diff --git a/core/client/src/lua/c_luaclass.cpp b/core/client/src/lua/c_luaclass.cpp index ded4ddc30..f6b11da38 100644 --- a/core/client/src/lua/c_luaclass.cpp +++ b/core/client/src/lua/c_luaclass.cpp @@ -57,6 +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/lua/libraries/ludm.hpp" #include #include @@ -78,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +92,9 @@ import pragma.shadergraph; extern DLLCLIENT CEngine *c_engine; extern DLLCLIENT ClientState *client; extern DLLCLIENT CGame *c_game; + +static spdlog::logger &LOGGER_SG = pragma::register_logger("shadergraph"); + static void reload_textures(CMaterial &mat) { auto &data = mat.GetDataBlock(); @@ -128,6 +133,21 @@ static luabind::object shader_mat_value_to_lua_object(lua_State *l, const pragma static void register_shader_graph(lua_State *l, luabind::module_ &modShader) { auto defGraph = luabind::class_("ShaderGraph"); + defGraph.scope[luabind::def( + "load", +[](const std::string &type, const std::string &name) -> std::pair, std::optional> { + auto filePath = pragma::rendering::ShaderGraphManager::GetShaderGraphFilePath(type, name); + auto reg = c_engine->GetShaderGraphManager().GetNodeRegistry(type); + if(!reg) { + LOGGER_SG.error("Failed to load shader graph of type '{}' with name '{}' - no registry found!", type, name); + return {std::shared_ptr {}, std::optional {}}; + } + auto graph = std::make_shared(reg); + std::string err; + auto result = graph->Load(filePath, err); + if(!result) + return {std::shared_ptr {}, std::optional {err}}; + return {graph, {}}; + })]; defGraph.scope[luabind::def( "load", +[](udm::AssetData &assetData, const std::shared_ptr &nodeReg) -> std::pair, std::optional> { auto graph = std::make_shared(nodeReg); @@ -143,10 +163,27 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) "Save", +[](const pragma::shadergraph::Graph &graph, udm::AssetData &assetData) -> std::pair> { std::string err; if(!graph.Save(assetData, err)) - return {false, std::optional {}}; - return {true, err}; + return {false, err}; + return {true, std::optional {}}; + }); + defGraph.def( + "Save", +[](const pragma::shadergraph::Graph &graph, const std::string &type, const std::string &name) -> std::pair> { + auto filePath = pragma::rendering::ShaderGraphManager::GetShaderGraphFilePath(type, name); + std::string err; + filemanager::create_path(ufile::get_path_from_filename(filePath)); + if(!graph.Save(filePath, err)) + return {false, err}; + return {true, std::optional {}}; + }); + defGraph.def( + "AddNode", +[](pragma::shadergraph::Graph &graph, const std::string &type) -> std::shared_ptr { + auto node = graph.AddNode(type); + if(!node) { + LOGGER_SG.error("Failed to add node of type '{}'!", type); + return nullptr; + } + return node; }); - defGraph.def("AddNode", &pragma::shadergraph::Graph::AddNode); defGraph.def("RemoveNode", &pragma::shadergraph::Graph::RemoveNode); defGraph.def("GetNode", &pragma::shadergraph::Graph::GetNode); defGraph.def( @@ -157,6 +194,8 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) t[idx++] = node.get(); return t; }); + defGraph.def("GenerateGlsl", &pragma::shadergraph::Graph::GenerateGlsl); + defGraph.def("DebugPrint", &pragma::shadergraph::Graph::DebugPrint); auto defNode = luabind::class_("Node"); defNode.def("GetType", &pragma::shadergraph::Node::GetType); @@ -179,12 +218,35 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) modShader[defNode]; auto defSocket = luabind::class_("Socket"); + defSocket.add_static_constant("TYPE_BOOLEAN", umath::to_integral(pragma::shadergraph::SocketType::Boolean)); + defSocket.add_static_constant("TYPE_INT", umath::to_integral(pragma::shadergraph::SocketType::Int)); + defSocket.add_static_constant("TYPE_UINT", umath::to_integral(pragma::shadergraph::SocketType::UInt)); + defSocket.add_static_constant("TYPE_FLOAT", umath::to_integral(pragma::shadergraph::SocketType::Float)); + defSocket.add_static_constant("TYPE_COLOR", umath::to_integral(pragma::shadergraph::SocketType::Color)); + defSocket.add_static_constant("TYPE_VECTOR", umath::to_integral(pragma::shadergraph::SocketType::Vector)); + defSocket.add_static_constant("TYPE_POINT", umath::to_integral(pragma::shadergraph::SocketType::Point)); + defSocket.add_static_constant("TYPE_NORMAL", umath::to_integral(pragma::shadergraph::SocketType::Normal)); + defSocket.add_static_constant("TYPE_POINT2", umath::to_integral(pragma::shadergraph::SocketType::Point2)); + defSocket.add_static_constant("TYPE_STRING", umath::to_integral(pragma::shadergraph::SocketType::String)); + defSocket.add_static_constant("TYPE_TRANSFORM", umath::to_integral(pragma::shadergraph::SocketType::Transform)); + defSocket.add_static_constant("TYPE_ENUM", umath::to_integral(pragma::shadergraph::SocketType::Enum)); + defSocket.add_static_constant("TYPE_INVALID", umath::to_integral(pragma::shadergraph::SocketType::Invalid)); + defSocket.scope[luabind::def("udm_to_socket_type", &pragma::shadergraph::to_socket_type)]; + defSocket.scope[luabind::def("to_udm_type", &pragma::shadergraph::to_udm_type)]; + defSocket.scope[luabind::def("to_glsl_type", &pragma::shadergraph::to_glsl_type)]; + defSocket.def_readonly("name", &pragma::shadergraph::Socket::name); defSocket.def_readonly("type", &pragma::shadergraph::Socket::type); modShader[defSocket]; auto defNodeRegistry = luabind::class_("NodeRegistry"); defNodeRegistry.def("GetNode", &pragma::shadergraph::NodeRegistry::GetNode); + defNodeRegistry.def( + "GetNodeTypes", +[](const pragma::shadergraph::NodeRegistry ®) -> std::vector { + std::vector names; + reg.GetNodeTypes(names); + return names; + }); modShader[defNodeRegistry]; auto defGraphNode = luabind::class_("GraphNode"); @@ -193,8 +255,46 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) defGraphNode.def("SetDisplayName", &pragma::shadergraph::GraphNode::SetDisplayName); 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) { + auto type = Lua::udm::determine_udm_type(value); + ::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); + } + }); + }); + defGraphNode.def( + "GetInputValue", +[](lua_State *l, const pragma::shadergraph::GraphNode &graphNode, const std::string_view &inputName) -> Lua::udm_type { + auto *input = graphNode.FindInput(inputName); + if(!input) + return Lua::nil; + auto type = pragma::shadergraph::to_udm_type(input->GetSocket().type); + if(type == udm::Type::Invalid) + return Lua::nil; + return ::udm::visit(type, [l, &graphNode, &inputName](auto tag) { + using T = typename decltype(tag)::type; + if constexpr(pragma::shadergraph::is_socket_type()) { + T val; + auto res = graphNode.GetInputValue(inputName, val); + if(!res) + return Lua::nil; + return luabind::object {l, val}; + } + return Lua::nil; + }); + }); defGraphNode.def("CanLink", &pragma::shadergraph::GraphNode::CanLink); - defGraphNode.def("Link", &pragma::shadergraph::GraphNode::Link); + defGraphNode.def( + "Link", +[](pragma::shadergraph::GraphNode &graphNode, const std::string_view &outputName, pragma::shadergraph::GraphNode &linkTarget, const std::string_view &inputName) -> std::pair> { + std::string err; + auto res = graphNode.Link(outputName, linkTarget, inputName, &err); + if(!res) + LOGGER_SG.debug("Failed to link output '{}' of node '{}' ({}) to input '{}' of node '{}' ({}): {}", outputName, graphNode.GetName(), graphNode->GetType(), inputName, linkTarget.GetName(), linkTarget->GetType(), err); + return {res, err.empty() ? std::optional {} : std::optional {err}}; + }); defGraphNode.def("Disconnect", static_cast(&pragma::shadergraph::GraphNode::Disconnect)); defGraphNode.def("IsOutputLinked", &pragma::shadergraph::GraphNode::IsOutputLinked); defGraphNode.def("FindOutputIndex", &pragma::shadergraph::GraphNode::FindOutputIndex); @@ -241,6 +341,7 @@ static void register_shader_graph(lua_State *l, luabind::module_ &modShader) oGraph["EXTENSION_ASCII"] = pragma::shadergraph::Graph::EXTENSION_ASCII; oGraph["PSG_IDENTIFIER"] = pragma::shadergraph::Graph::PSG_IDENTIFIER; oGraph["PSG_VERSION"] = pragma::shadergraph::Graph::PSG_VERSION; + oGraph["ROOT_PATH"] = pragma::rendering::ShaderGraphManager::ROOT_GRAPH_PATH; } void ClientState::RegisterSharedLuaClasses(Lua::Interface &lua, bool bGUI) @@ -386,6 +487,48 @@ 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); diff --git a/core/client/src/rendering/shader_graph/nodes/camera.cpp b/core/client/src/rendering/shader_graph/nodes/camera.cpp new file mode 100644 index 000000000..dd67beafc --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/camera.cpp @@ -0,0 +1,38 @@ +/* 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/camera.hpp" + +using namespace pragma::rendering::shader_graph; + +CameraNode::CameraNode(const std::string_view &type) : Node {type} +{ + AddOutput(OUT_POSITION, pragma::shadergraph::SocketType::Vector); + AddOutput(OUT_FOV, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_NEARZ, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_FARZ, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_VIEW_MATRIX, pragma::shadergraph::SocketType::Transform); + AddOutput(OUT_PROJECTION_MATRIX, pragma::shadergraph::SocketType::Transform); + AddOutput(OUT_VIEW_PROJECTION_MATRIX, pragma::shadergraph::SocketType::Transform); + + AddModuleDependency("camera"); + AddModuleDependency("render_settings"); +} + +std::string CameraNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + code << instance.GetOutputVarName(OUT_POSITION) << " = u_renderSettings.posCam.xyz;\n"; + code << instance.GetOutputVarName(OUT_FOV) << " = u_renderSettings.posCam.w;\n"; + code << instance.GetOutputVarName(OUT_NEARZ) << " = u_renderSettings.nearZ;\n"; + code << instance.GetOutputVarName(OUT_FARZ) << " = u_renderSettings.farZ;\n"; + code << instance.GetOutputVarName(OUT_VIEW_MATRIX) << " = u_camera.V;\n"; + code << instance.GetOutputVarName(OUT_PROJECTION_MATRIX) << " = u_camera.P;\n"; + code << instance.GetOutputVarName(OUT_VIEW_PROJECTION_MATRIX) << " = u_camera.VP;\n"; + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph/nodes/fog.cpp b/core/client/src/rendering/shader_graph/nodes/fog.cpp new file mode 100644 index 000000000..868d0f789 --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/fog.cpp @@ -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 + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/nodes/fog.hpp" + +using namespace pragma::rendering::shader_graph; + +FogNode::FogNode(const std::string_view &type) : Node {type} +{ + AddOutput(OUT_COLOR, pragma::shadergraph::SocketType::Color); + AddOutput(OUT_START_DISTANCE, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_END_DISTANCE, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_DENSITY, pragma::shadergraph::SocketType::Float); + + AddModuleDependency("fog"); +} + +std::string FogNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + code << instance.GetOutputVarName(OUT_COLOR) << " = u_fog.color.rgb;\n"; + code << instance.GetOutputVarName(OUT_START_DISTANCE) << " = u_fog.start;\n"; + code << instance.GetOutputVarName(OUT_END_DISTANCE) << " = u_fog.end;\n"; + code << instance.GetOutputVarName(OUT_DENSITY) << " = u_fog.density;\n"; + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph/nodes/lightmap.cpp b/core/client/src/rendering/shader_graph/nodes/lightmap.cpp new file mode 100644 index 000000000..815b8742b --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/lightmap.cpp @@ -0,0 +1,19 @@ +/* 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/lightmap.hpp" + +using namespace pragma::rendering::shader_graph; + +LightmapNode::LightmapNode(const std::string_view &type) : Node {type} { AddModuleDependency("lightmap"); } + +std::string LightmapNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph/nodes/object.cpp b/core/client/src/rendering/shader_graph/nodes/object.cpp new file mode 100644 index 000000000..dc29994c6 --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/object.cpp @@ -0,0 +1,27 @@ +/* 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/object.hpp" + +using namespace pragma::rendering::shader_graph; + +ObjectNode::ObjectNode(const std::string_view &type) : Node {type} +{ + AddOutput(OUT_MODEL_MATRIX, pragma::shadergraph::SocketType::Transform); + AddOutput(OUT_COLOR, pragma::shadergraph::SocketType::Color); + + AddModuleDependency("object"); +} + +std::string ObjectNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + code << instance.GetOutputVarName(OUT_MODEL_MATRIX) << " = u_instance.M;\n"; + code << instance.GetOutputVarName(OUT_COLOR) << " = u_instance.color;\n"; + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph/nodes/scene_output.cpp b/core/client/src/rendering/shader_graph/nodes/scene_output.cpp new file mode 100644 index 000000000..7f8f0ab1e --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/scene_output.cpp @@ -0,0 +1,27 @@ +/* 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 + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/nodes/scene_output.hpp" + +using namespace pragma::rendering::shader_graph; + +SceneOutputNode::SceneOutputNode(const std::string_view &type) : Node {type} +{ + AddInput(IN_COLOR, pragma::shadergraph::SocketType::Color, Vector3 {1.f, 1.f, 1.f}); + AddInput(IN_ALPHA, pragma::shadergraph::SocketType::Float, 1.f); + AddInput(IN_BLOOM_COLOR, pragma::shadergraph::SocketType::Color, Vector3 {0.f, 0.f, 0.f}); +} + +std::string SceneOutputNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + code << "fs_color = vec4(" << GetInputNameOrValue(instance, IN_COLOR) << ", " << GetInputNameOrValue(instance, IN_ALPHA) << ");\n"; + code << "fs_brightColor = vec4(" << GetInputNameOrValue(instance, IN_BLOOM_COLOR) << ", 1.0);\n"; + return code.str(); + // +} diff --git a/core/client/src/rendering/shader_graph/nodes/shader_material.cpp b/core/client/src/rendering/shader_graph/nodes/shader_material.cpp new file mode 100644 index 000000000..e268aaff4 --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/shader_material.cpp @@ -0,0 +1,39 @@ +/* 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 + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/nodes/shader_material.hpp" + +using namespace pragma::rendering::shader_graph; + +ShaderMaterialNode::ShaderMaterialNode(const std::string_view &type, const pragma::rendering::shader_material::ShaderMaterial &shaderMaterial) : pragma::shadergraph::Node {type}, m_shaderMaterial {shaderMaterial} +{ + for(auto &prop : m_shaderMaterial.properties) { + auto socketType = pragma::shadergraph::to_socket_type(prop.type); + if(socketType == pragma::shadergraph::SocketType::Invalid) + continue; + AddOutput(prop.name.c_str(), socketType); + } +} +std::string ShaderMaterialNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + // TODO: Only write output var is output is set? + // get_mat_x(); + std::ostringstream code; + for(auto &prop : m_shaderMaterial.properties) { + auto socketType = pragma::shadergraph::to_socket_type(prop.type); + if(socketType == pragma::shadergraph::SocketType::Invalid) + continue; + if(!instance.IsOutputLinked(prop.name)) + continue; + auto *glslType = pragma::shadergraph::to_glsl_type(socketType); + code << glslType << " "; + code << instance.GetOutputVarName(prop.name.c_str()) << " = "; + code << "get_mat_" << prop.name.c_str() << "();\n"; + } + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph/nodes/time.cpp b/core/client/src/rendering/shader_graph/nodes/time.cpp new file mode 100644 index 000000000..abb08998e --- /dev/null +++ b/core/client/src/rendering/shader_graph/nodes/time.cpp @@ -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 + */ + +#include "stdafx_client.h" +#include "pragma/rendering/shader_graph/nodes/time.hpp" + +using namespace pragma::rendering::shader_graph; + +TimeNode::TimeNode(const std::string_view &type) : Node {type} +{ + AddOutput(OUT_TIME, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_DELTA_TIME, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_REAL_TIME, pragma::shadergraph::SocketType::Float); + AddOutput(OUT_DELTA_REAL_TIME, pragma::shadergraph::SocketType::Float); + + AddModuleDependency("time"); +} + +std::string TimeNode::DoEvaluate(const pragma::shadergraph::Graph &graph, const pragma::shadergraph::GraphNode &instance) const +{ + std::ostringstream code; + code << instance.GetOutputVarName(OUT_TIME) << " = u_time.time;\n"; + code << instance.GetOutputVarName(OUT_DELTA_TIME) << " = u_time.deltaTime;\n"; + code << instance.GetOutputVarName(OUT_REAL_TIME) << " = u_time.realTime;\n"; + code << instance.GetOutputVarName(OUT_DELTA_REAL_TIME) << " = u_time.deltaRealTime;\n"; + return code.str(); +} diff --git a/core/client/src/rendering/shader_graph_manager.cpp b/core/client/src/rendering/shader_graph_manager.cpp new file mode 100644 index 000000000..298e6876e --- /dev/null +++ b/core/client/src/rendering/shader_graph_manager.cpp @@ -0,0 +1,153 @@ +/* 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_manager.hpp" +#include "pragma/rendering/shaders/world/c_shader_graph.hpp" + +extern DLLCLIENT CEngine *c_engine; + +using namespace pragma::rendering; +void ShaderGraphTypeManager::RegisterGraph(const std::string &identifier, std::shared_ptr graph) +{ + auto fragFilePath = util::FilePath(ShaderGraphManager::GetShaderFilePath(m_typeName, identifier)); + fragFilePath.PopFront(); + auto strFragFilePath = fragFilePath.GetString(); + auto &shaderManager = c_engine->GetShaderManager(); + auto shader = shaderManager.GetShader(identifier); + 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 + 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; +} + +std::shared_ptr ShaderGraphTypeManager::RegisterGraph(const std::string &identifier) +{ + auto graph = CreateGraph(); + RegisterGraph(identifier, graph); + return graph; +} + +std::shared_ptr ShaderGraphTypeManager::CreateGraph() const { return std::make_shared(m_nodeRegistry); } + +void ShaderGraphTypeManager::ReloadShader(const std::string &identifier) +{ + auto graphData = GetGraph(identifier); + if(!graphData) + return; + graphData->GenerateGlsl(); +} + +std::shared_ptr ShaderGraphTypeManager::GetGraph(const std::string &identifier) const +{ + auto it = m_graphs.find(identifier); + if(it != m_graphs.end()) + return it->second; + return nullptr; +} + +std::string ShaderGraphManager::GetShaderFilePath(const std::string &type, const std::string &identifier) +{ + std::string shaderName = identifier; + auto path = util::FilePath("shaders/programs/graph_shaders/", type, shaderName + ".frag"); + return path.GetString(); +} +std::string ShaderGraphManager::GetShaderGraphFilePath(const std::string &type, const std::string &identifier) +{ + auto path = util::FilePath("scripts/shader_data/graphs/", type, identifier); + auto strPath = path.GetString(); + if(!ufile::compare_extension(strPath, {pragma::shadergraph::Graph::EXTENSION_BINARY, pragma::shadergraph::Graph::EXTENSION_ASCII})) + strPath += "." + std::string {pragma::shadergraph::Graph::EXTENSION_ASCII}; + return strPath; +} +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) +{ + auto itType = m_shaderNameToType.find(identifier); + if(itType != m_shaderNameToType.end() && itType->second != type) + throw std::runtime_error {"Shader '" + identifier + "' already registered with type '" + itType->second + "'!"}; + auto it = m_shaderGraphTypeManagers.find(type); + if(it == m_shaderGraphTypeManagers.end()) + return nullptr; + auto graph = it->second->RegisterGraph(identifier); + if(!graph) + return nullptr; + m_shaderNameToType[identifier] = type; + return graph; +} +std::shared_ptr ShaderGraphManager::CreateGraph(const std::string &type) const +{ + auto it = m_shaderGraphTypeManagers.find(type); + if(it == m_shaderGraphTypeManagers.end()) + return nullptr; + return it->second->CreateGraph(); +} +void ShaderGraphManager::ReloadShader(const std::string &identifier) +{ + auto itType = m_shaderNameToType.find(identifier); + if(itType == m_shaderNameToType.end()) + return; + auto &type = itType->second; + auto it = m_shaderGraphTypeManagers.find(type); + if(it == m_shaderGraphTypeManagers.end()) + return; + it->second->ReloadShader(identifier); +} +std::shared_ptr ShaderGraphManager::GetGraph(const std::string &identifier) const +{ + auto itType = m_shaderNameToType.find(identifier); + if(itType == m_shaderNameToType.end()) + return nullptr; + auto &type = itType->second; + auto it = m_shaderGraphTypeManagers.find(type); + if(it == m_shaderGraphTypeManagers.end()) + return nullptr; + return it->second->GetGraph(identifier); +} + +std::shared_ptr ShaderGraphManager::GetNodeRegistry(const std::string &type) const +{ + auto it = m_shaderGraphTypeManagers.find(type); + if(it == m_shaderGraphTypeManagers.end()) + return nullptr; + return it->second->GetNodeRegistry(); +} + +void ShaderGraphData::GenerateGlsl() +{ + auto placeholder = filemanager::read_file("shaders/graph_placeholder.frag"); + if(!placeholder) + return; + + std::string shaderName = m_identifier; + std::ostringstream header; + std::ostringstream body; + m_graph->GenerateGlsl(header, body); + + auto strHeader = header.str(); + auto strBody = body.str(); + + ustring::replace(strBody, "\n", "\n\t"); + + auto code = *placeholder; + ustring::replace(code, "{{header}}", strHeader); + ustring::replace(code, "{{body}}", strBody); + + auto path = ShaderGraphManager::GetShaderFilePath(m_typeName, m_identifier); + filemanager::create_path(ufile::get_path_from_filename(path)); + std::string err; + auto f = filemanager::open_file(path, filemanager::FileMode::Write, &err); + if(!f) + return; + f->WriteString(code); + f = {}; +} diff --git a/core/client/src/rendering/shaders/world/c_shader_graph.cpp b/core/client/src/rendering/shaders/world/c_shader_graph.cpp new file mode 100644 index 000000000..236fc88f4 --- /dev/null +++ b/core/client/src/rendering/shaders/world/c_shader_graph.cpp @@ -0,0 +1,88 @@ +/* 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/shaders/world/c_shader_graph.hpp" +#include "cmaterialmanager.h" +#include "pragma/entities/environment/c_env_reflection_probe.hpp" +#include "pragma/entities/environment/c_env_camera.h" +#include "pragma/rendering/renderers/rasterization_renderer.hpp" +#include "pragma/rendering/render_processor.hpp" +#include "pragma/rendering/shader_material/shader_material.hpp" +#include "pragma/model/vk_mesh.h" +#include "pragma/model/c_modelmesh.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern DLLCLIENT CGame *c_game; +extern DLLCLIENT ClientState *client; +extern DLLCLIENT CEngine *c_engine; + +import pragma.shadergraph; + +using namespace pragma; + +ShaderGraph::ShaderGraph(prosper::IPrContext &context, const std::string &identifier, const std::string &fsShader) : ShaderGameWorldLightingPass {context, identifier, "programs/scene/textured", fsShader} {} + +void ShaderGraph::UpdateRenderFlags(CModelSubMesh &mesh, SceneFlags &inOutFlags) +{ + ShaderGameWorldLightingPass::UpdateRenderFlags(mesh, inOutFlags); + inOutFlags |= m_extRenderFlags; +} +void ShaderGraph::InitializeGfxPipelineDescriptorSets() { ShaderGameWorldLightingPass::InitializeGfxPipelineDescriptorSets(); } + +void ShaderGraph::InitializeMaterialData(const CMaterial &mat, const rendering::shader_material::ShaderMaterial &shaderMat, pragma::rendering::shader_material::ShaderMaterialData &inOutMatData) +{ + ShaderGameWorldLightingPass::InitializeMaterialData(mat, shaderMat, inOutMatData); + auto &data = mat.GetDataBlock(); + float specularFactor; + if(data->GetFloat("specular_factor", &specularFactor)) { + auto roughnessFactor = inOutMatData.GetValue("roughness_factor"); + if(!roughnessFactor) + roughnessFactor = 1.f; + *roughnessFactor *= (1.f - specularFactor); + inOutMatData.SetValue("roughness_factor", *roughnessFactor); + } +} + +std::shared_ptr ShaderGraph::InitializeMaterialDescriptorSet(CMaterial &mat, const prosper::DescriptorSetInfo &descSetInfo) { return ShaderGameWorldLightingPass::InitializeMaterialDescriptorSet(mat, descSetInfo); } +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.flags = inOutSceneFlags; + pushConstants.drawOrigin = drawOrigin; + shaderProcessor.GetCommandBuffer().RecordPushConstants(shaderProcessor.GetCurrentPipelineLayout(), prosper::ShaderStageFlags::VertexBit | prosper::ShaderStageFlags::FragmentBit, 0u, sizeof(pushConstants), &pushConstants); +}