diff --git a/engine/asset/CMakeLists.txt b/engine/asset/CMakeLists.txt index 4828810..e8cf62a 100644 --- a/engine/asset/CMakeLists.txt +++ b/engine/asset/CMakeLists.txt @@ -2,9 +2,8 @@ set(SRC include/asset_types.hpp include/asset.hpp include/assetptr.hpp - include/material_nodes.hpp - - src/asset.cpp) + + src/asset.cpp) add_library(Asset STATIC ${SRC}) target_include_directories(Asset PUBLIC include) diff --git a/engine/asset/include/asset_types.hpp b/engine/asset/include/asset_types.hpp index 9a0f24d..8272730 100644 --- a/engine/asset/include/asset_types.hpp +++ b/engine/asset/include/asset_types.hpp @@ -4,7 +4,6 @@ #include "assetptr.hpp" #include "math.hpp" -#include "material_nodes.hpp" #include "aabb.hpp" #include "utility.hpp" @@ -19,28 +18,31 @@ public: class GFXPipeline; +enum class DataType { + Vector3, + Float, + AssetTexture +}; + +struct MaterialProperty { + std::string name; + DataType type; + + MaterialProperty() { + name = ""; + type = DataType::Vector3; + } + MaterialProperty(std::string n, DataType t) : name(n), type(t) {} + + prism::float3 value; + AssetPtr value_tex; + float float_value = 0.0f; +}; + class Material : public Asset { public: - std::vector> nodes; - - void delete_node(MaterialNode* node) { - // disconnect all inputs from their node outputs - for(auto& input : node->inputs) { - if(input.is_connected()) - input.disconnect(); - } - - // disconnect all our outputs from other node's inputs - for(auto& output : node->outputs) { - if(output.is_connected()) - output.connected_connector->disconnect(); - } - - utility::erase_if(nodes, [node](std::unique_ptr& other_node) { - return node == other_node.get(); - }); - } - + MaterialProperty colorProperty; + GFXPipeline* static_pipeline = nullptr; GFXPipeline* skinned_pipeline = nullptr; GFXPipeline* capture_pipeline = nullptr; diff --git a/engine/asset/include/material_nodes.hpp b/engine/asset/include/material_nodes.hpp deleted file mode 100644 index a22ea0c..0000000 --- a/engine/asset/include/material_nodes.hpp +++ /dev/null @@ -1,243 +0,0 @@ -#pragma once - -#include "assetptr.hpp" -#include "render_options.hpp" - -class MaterialNode; - -enum class DataType { - Vector3, - Float, - AssetTexture -}; - -struct MaterialConnector { - MaterialConnector(std::string n, DataType t) : name(n), type(t) {} - MaterialConnector(std::string n, DataType t, bool isn) : name(n), type(t), is_normal_map(isn) {} - - bool is_connected() const { - return connected_connector != nullptr && connected_node != nullptr && connected_index != -1; - } - - void disconnect() { - connected_connector = nullptr; - connected_node = nullptr; - connected_index = -1; - } - - std::string name; - DataType type; - - bool is_normal_map = false; - - MaterialConnector* connected_connector = nullptr; - MaterialNode* connected_node = nullptr; - int connected_index = -1; -}; - -inline bool operator==(const MaterialConnector& a, const MaterialConnector& b) { - return a.name == b.name; -} - -class Texture; - -struct MaterialProperty { - std::string name; - DataType type; - - MaterialProperty(std::string n, DataType t) : name(n), type(t) {} - - prism::float3 value; - AssetPtr value_tex; - float float_value = 0.0f; -}; - -static int last_id = 0; - -class MaterialNode { -public: - virtual ~MaterialNode() {} - - int id = last_id++; - - std::vector inputs, outputs; - std::vector properties; - - virtual const char* get_prefix() = 0; - virtual const char* get_name() = 0; - - virtual std::string get_glsl() = 0; - - std::string get_connector_variable_name(MaterialConnector& connector) { - return std::string(get_prefix()) + std::to_string(id) + "_" + connector.name; - } - - std::string get_property_variable_name(MaterialProperty& property) { - return std::string(get_prefix()) + std::to_string(id) + "_" + property.name; - } - - std::string get_connector_value(MaterialConnector& connector) { - if(connector.connected_node != nullptr) { - if(connector.type != connector.connected_connector->type) { - return connector.connected_node->get_connector_variable_name(*connector.connected_connector) + ".r"; - } else { - if(connector.is_normal_map) { - if(render_options.enable_normal_mapping) { - return "in_tbn * (2.0 * " + connector.connected_node->get_connector_variable_name(*connector.connected_connector) + " - 1.0)"; - } else { - return "in_normal"; - } - } else { - return connector.connected_node->get_connector_variable_name(*connector.connected_connector); - } - } - } else { - switch(connector.type) { - case DataType::Float: - return "0.0"; - default: - return "vec3(1, 1, 1)"; - } - } - } - - std::string get_property_value(MaterialProperty& property) { - switch(property.type) { - case DataType::Vector3: - return "vec3(" + std::to_string(property.value.x) + ", " + std::to_string(property.value.y) + ", " + std::to_string(property.value.z) + ")"; - case DataType::Float: - return std::to_string(property.float_value); - case DataType::AssetTexture: - return "texture(" + get_property_variable_name(property) + ", in_uv).rgb"; - } - } - - MaterialConnector* find_connector(std::string name) { - for(auto& input : inputs) { - if(input.name == name) - return &input; - } - - for(auto& output : outputs) { - if(output.name == name) - return &output; - } - - return nullptr; - } - - float x = 0.0f, y = 0.0f; -}; - -class MaterialOutput : public MaterialNode { -public: - MaterialOutput() { - inputs = { - MaterialConnector("Color", DataType::Vector3), - MaterialConnector("Roughness", DataType::Float), - MaterialConnector("Metallic", DataType::Float), - MaterialConnector("Normals", DataType::Vector3, true), - }; - } - - const char* get_prefix() override { - return "material_output_"; - } - - const char* get_name() override { - return "Material Output"; - } - - std::string get_glsl() override { - std::string glsl = "vec3 final_diffuse_color = from_srgb_to_linear(Color);\n \ - float final_roughness = Roughness;\n \ - float final_metallic = Metallic;\n"; - - if(find_connector("Normals")->connected_node != nullptr) { - glsl += "vec3 final_normal = Normals;\n"; - } else { - glsl += "vec3 final_normal = in_normal;\n"; - } - - return glsl; - } -}; - -class Vector3Constant : public MaterialNode { -public: - Vector3Constant() { - outputs = {MaterialConnector("Value", DataType::Vector3)}; - properties = {MaterialProperty("Color", DataType::Vector3)}; - } - - const char* get_prefix() override { - return "vec3const_"; - } - - const char* get_name() override { - return "Vector3 Constant"; - } - - std::string get_glsl() override { - return "vec3 Value = Color;\n"; - } -}; - -class FloatConstant : public MaterialNode { -public: - FloatConstant() { - outputs = {MaterialConnector("Value", DataType::Float)}; - properties = {MaterialProperty("Data", DataType::Float)}; - } - - const char* get_prefix() override { - return "floatconst_"; - } - - const char* get_name() override { - return "Float Constant"; - } - - std::string get_glsl() override { - return "float Value = Data;\n"; - } -}; - -class TextureNode : public MaterialNode { -public: - TextureNode() { - outputs = {MaterialConnector("Value", DataType::Vector3)}; - properties = {MaterialProperty("Texture", DataType::AssetTexture)}; - } - - const char* get_prefix() override { - return "texture_"; - } - - const char* get_name() override { - return "Texture"; - } - - std::string get_glsl() override { - return "vec3 Value = Texture;\n"; - } -}; - -class Geometry : public MaterialNode { -public: - Geometry() { - outputs = {MaterialConnector("Normal", DataType::Vector3)}; - } - - const char* get_prefix() override { - return "geometry_"; - } - - const char* get_name() override { - return "Geometry"; - } - - std::string get_glsl() override { - return "vec3 Normal = normalize(in_normal);\n"; - } -}; diff --git a/engine/asset/src/asset.cpp b/engine/asset/src/asset.cpp index 56f4950..780e91f 100644 --- a/engine/asset/src/asset.cpp +++ b/engine/asset/src/asset.cpp @@ -257,75 +257,17 @@ std::unique_ptr load_material(const prism::path path) { auto mat = std::make_unique(); mat->path = path.string(); - if(!j.count("version") || j["version"] != 2) { + if(!j.count("version") || j["version"] != 3) { prism::log("Material {} failed the version check!", path.string()); return mat; } - - for(auto node : j["nodes"]) { - std::unique_ptr n; - - auto name = node["name"]; - if(name == "Material Output") { - n = std::make_unique(); - } else if(name == "Texture") { - n = std::make_unique(); - } else if(name == "Float Constant") { - n = std::make_unique(); - } else if(name == "Vector3 Constant") { - n = std::make_unique(); - } - - n->id = node["id"]; - n->x = node["x"]; - n->y = node["y"]; - - for(auto& property : node["properties"]) { - for(auto& p : n->properties) { - if(property["name"] == p.name) { - p.value = property["value"]; - p.float_value = property["float_value"]; - - if(!property["asset_value"].get().empty()) { - p.value_tex = assetm->get(prism::app_domain / property["asset_value"].get()); - } - } - } - } - - mat->nodes.emplace_back(std::move(n)); - } - for(auto node : j["nodes"]) { - MaterialNode* n = nullptr; - for(auto& nn : mat->nodes) { - if(nn->id == node["id"]) - n = nn.get(); - } - - if(n == nullptr) - continue; - - for(auto connection : node["connections"]) { - for(auto [i, output] : utility::enumerate(n->outputs)) { - if(connection["name"] == output.name) { - for(auto& nn : mat->nodes) { - if(nn->id == connection["connected_node"]) { - output.connected_node = nn.get(); - - auto connector = nn->find_connector(connection["connected_connector"]); - output.connected_connector = connector; - - connector->connected_index = i; - connector->connected_node = n; - connector->connected_connector = &output; - } - } - - output.connected_index = connection["connected_index"]; - } - } - } + auto property = j["color"]; + mat->colorProperty.value = property["value"]; + mat->colorProperty.float_value = property["float_value"]; + + if(!property["asset_value"].get().empty()) { + mat->colorProperty.value_tex = assetm->get(prism::app_domain / property["asset_value"].get()); } return mat; @@ -336,40 +278,15 @@ void save_material(Material* material, const prism::path path) { Expects(!path.empty()); nlohmann::json j; + j["version"] = 3; - j["version"] = 2; + nlohmann::json p; + p["name"] = material->colorProperty.name; + p["value"] = material->colorProperty.value; + p["asset_value"] = material->colorProperty.value_tex ? material->colorProperty.value_tex->path : ""; + p["float_value"] = material->colorProperty.float_value; - for(auto& node : material->nodes) { - nlohmann::json n; - n["name"] = node->get_name(); - n["id"] = node->id; - n["x"] = node->x; - n["y"] = node->y; - - for(auto property : node->properties) { - nlohmann::json p; - p["name"] = property.name; - p["value"] = property.value; - p["asset_value"] = property.value_tex ? property.value_tex->path : ""; - p["float_value"] = property.float_value; - - n["properties"].push_back(p); - } - - for(const auto& output : node->outputs) { - if(output.connected_connector != nullptr) { - nlohmann::json c; - c["name"] = output.name; - c["connected_connector"] = output.connected_connector->name; - c["connected_node"] = output.connected_node->id; - c["connected_index"] = output.connected_index; - - n["connections"].push_back(c); - } - } - - j["nodes"].push_back(n); - } + j["color"] = p; std::ofstream out(path); out << j; diff --git a/engine/renderer/src/materialcompiler.cpp b/engine/renderer/src/materialcompiler.cpp index 8ad46de..9b6c012 100755 --- a/engine/renderer/src/materialcompiler.cpp +++ b/engine/renderer/src/materialcompiler.cpp @@ -7,7 +7,6 @@ #include "engine.hpp" #include "string_utils.hpp" #include "shadercompiler.hpp" -#include "material_nodes.hpp" #include "renderer.hpp" ShaderSource get_shader(const std::string& filename, bool skinned, bool cubemap) { @@ -129,35 +128,6 @@ std::tuple MaterialCompiler::create_pipeline_permuta return {st, ss}; } -std::vector walked_nodes; - -void walk_node(std::string& src, MaterialNode* node) { - if(utility::contains(walked_nodes, node)) - return; - - walked_nodes.push_back(node); - - for(auto& input : node->inputs) { - if(input.connected_node != nullptr) - walk_node(src, input.connected_node); - } - - std::string intermediate = node->get_glsl(); - for(auto& property : node->properties) { - intermediate = replace_substring(intermediate, property.name, node->get_property_value(property)); - } - - for(auto& input : node->inputs) { - intermediate = replace_substring(intermediate, input.name, node->get_connector_value(input)); - } - - for(auto& output : node->outputs) { - intermediate = replace_substring(intermediate, output.name, node->get_connector_variable_name(output)); - } - - src += intermediate; -} - constexpr std::string_view struct_info = "layout (constant_id = 0) const int max_materials = 25;\n \ layout (constant_id = 1) const int max_lights = 25;\n \ @@ -192,8 +162,6 @@ layout(push_constant, binding = 0) uniform PushConstant {\n \ };\n"; ShaderSource MaterialCompiler::compile_material_fragment(Material& material, bool use_ibl) { - walked_nodes.clear(); - if(!render_options.enable_ibl) use_ibl = false; @@ -241,14 +209,10 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo // insert samplers as needed int sampler_index = 10; - for(auto& node : material.nodes) { - for(auto& property : node->properties) { - if(property.type == DataType::AssetTexture) { - material.bound_textures[sampler_index] = property.value_tex; - - src += "layout(binding = " + std::to_string(sampler_index++) + ") uniform sampler2D " + node->get_property_variable_name(property) + ";\n"; - } - } + if(material.colorProperty.type == DataType::AssetTexture) { + material.bound_textures[sampler_index] = material.colorProperty.value_tex; + + src += "layout(binding = " + std::to_string(sampler_index++) + ") uniform sampler2D colorTexture;\n"; } if(use_ibl) { @@ -313,30 +277,21 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo } src += "void main() {\n"; - - bool has_output = false; - bool has_normal_mapping = false; - std::string normal_map_property_name; - for(auto& node : material.nodes) { - if(!strcmp(node->get_name(), "Material Output")) { - for(auto& input : node->inputs) { - if(input.is_normal_map && input.connected_node != nullptr) { - has_normal_mapping = true; - normal_map_property_name = input.connected_node->get_property_variable_name(input.connected_node->properties[0]); // quick and dirty workaround to get the normal map texture name - } - } - - walk_node(src, node.get()); - has_output = true; - } - } - - if(!has_output) { - src += "vec3 final_diffuse_color = vec3(1);\n"; - src += "float final_roughness = 0.5;\n"; - src += "float final_metallic = 0.0;\n"; - src += "vec3 final_normal = in_normal;\n"; + + if(material.colorProperty.type == DataType::Vector3) { + src += "vec3 Color = vec3(" + std::to_string(material.colorProperty.value.x) + "," + + std::to_string(material.colorProperty.value.y) + "," + + std::to_string(material.colorProperty.value.z) + ");\n"; + } else if(material.colorProperty.type == DataType::AssetTexture) { + src += "vec3 Color = texture(colorTexture, in_uv).rgb;\n"; + } else if(material.colorProperty.type == DataType::Float) { + src += "vec3 Color = vec3(" + std::to_string(material.colorProperty.float_value) + ");\n"; } + + src += "vec3 final_diffuse_color = from_srgb_to_linear(Color);\n"; + src += "float final_roughness = 0.5;\n"; + src += "float final_metallic = 0.0;\n"; + src += "vec3 final_normal = in_normal;\n"; src += "ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness);\n \ @@ -356,10 +311,6 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo break;\n \ }\n \ SurfaceBRDF surface_brdf = brdf(light_info.direction, surface_info);\n"; - - if(render_options.enable_normal_mapping && has_normal_mapping && render_options.enable_normal_shadowing) { - src += std::string("light_info.radiance *= calculate_normal_lighting(") + normal_map_property_name + ", final_normal, light_info.direction);\n"; - } src += "Lo += ((surface_brdf.specular + surface_brdf.diffuse) * light_info.radiance * surface_brdf.NdotL) * scene.lights[i].colorSize.rgb;\n \ }\n";