diff --git a/src/coders/GLSLExtension.cpp b/src/coders/GLSLExtension.cpp index 76f2394a..f205b9b4 100644 --- a/src/coders/GLSLExtension.cpp +++ b/src/coders/GLSLExtension.cpp @@ -8,11 +8,14 @@ #include "io/engine_paths.hpp" #include "typedefs.hpp" #include "util/stringutil.hpp" +#include "coders/json.hpp" +#include "data/dv_util.hpp" #include "coders/BasicParser.hpp" static debug::Logger logger("glsl-extension"); using Type = PostEffect::Param::Type; +using Value = PostEffect::Param::Value; void GLSLExtension::setPaths(const ResPaths* paths) { this->paths = paths; @@ -92,10 +95,10 @@ inline void source_line(std::stringstream& ss, uint linenum) { ss << "#line " << linenum << "\n"; } -static std::optional param_type_from( +static std::optional param_type_from( const std::string& name ) { - static const std::unordered_map typeNames { + static const std::unordered_map typeNames { {"float", Type::FLOAT}, {"vec2", Type::VEC2}, {"vec3", Type::VEC3}, @@ -108,6 +111,21 @@ static std::optional param_type_from( return found->second; } +static Value default_value_for(Type type) { + switch (type) { + case Type::FLOAT: + return 0.0f; + case Type::VEC2: + return glm::vec2 {0.0f, 0.0f}; + case Type::VEC3: + return glm::vec3 {0.0f, 0.0f, 0.0f}; + case Type::VEC4: + return glm::vec4 {0.0f, 0.0f, 0.0f, 0.0f}; + default: + throw std::runtime_error("unsupported type"); + } +} + class GLSLParser : public BasicParser { public: GLSLParser(GLSLExtension& glsl, std::string_view file, std::string_view source, bool header) @@ -155,22 +173,68 @@ public: return false; } + template + Value parseVectorValue() { + if (peekNoJump() != '[') { + throw error("'[' expected"); + } + // may be more efficient but ok + auto value = json::parse( + filename, + std::string_view(source.data() + pos, source.size() - pos) + ); + glm::vec vec {}; + try { + dv::get_vec(value, vec); + return vec; + } catch (const std::exception& err) { + throw error(err.what()); + } + } + + Value parseDefaultValue(Type type, const std::string& name) { + switch (type) { + case Type::FLOAT: + return static_cast(parseNumber(1).asNumber()); + case Type::VEC2: + return parseVectorValue<2>(); + case Type::VEC3: + return parseVectorValue<3>(); + case Type::VEC4: + return parseVectorValue<4>(); + default: + throw error("unsupported default value for type " + name); + } + } + bool processParamDirective() { skipWhitespace(false); + // Parse type name auto typeName = parseName(); auto type = param_type_from(typeName); if (!type.has_value()) { throw error("unsupported param type " + util::quote(typeName)); } skipWhitespace(false); + // Parse parameter name auto paramName = parseName(); if (params.find(paramName) != params.end()) { throw error("duplicating param " + util::quote(paramName)); } + skipWhitespace(false); + ss << "uniform " << typeName << " " << paramName << ";\n"; + + auto defValue = default_value_for(type.value()); + // Parse default value + if (peekNoJump() == '=') { + skip(1); + skipWhitespace(false); + defValue = parseDefaultValue(type.value(), typeName); + } + skipLine(); - ss << "uniform " << typeName << " " << paramName << ";\n"; - params[paramName] = PostEffect::Param(type.value()); + params[paramName] = PostEffect::Param(type.value(), std::move(defValue)); return false; } diff --git a/src/graphics/core/PostEffect.cpp b/src/graphics/core/PostEffect.cpp index 5f8b41fc..6af987c5 100644 --- a/src/graphics/core/PostEffect.cpp +++ b/src/graphics/core/PostEffect.cpp @@ -4,7 +4,9 @@ PostEffect::Param::Param() : type(Type::FLOAT) {} -PostEffect::Param::Param(Type type) : type(type) {} +PostEffect::Param::Param(Type type, Value defValue) + : type(type), defValue(std::move(defValue)) { +} PostEffect::PostEffect(std::unique_ptr shader) : shader(std::move(shader)) { diff --git a/src/graphics/core/PostEffect.hpp b/src/graphics/core/PostEffect.hpp index 78afda26..f77e121f 100644 --- a/src/graphics/core/PostEffect.hpp +++ b/src/graphics/core/PostEffect.hpp @@ -15,9 +15,10 @@ public: using Value = std::variant; Type type; + Value defValue; Param(); - Param(Type type); + Param(Type type, Value defValue); }; PostEffect(std::unique_ptr shader); diff --git a/test/coders/GLSLExtension.cpp b/test/coders/GLSLExtension.cpp index 8ad71898..87690ad6 100644 --- a/test/coders/GLSLExtension.cpp +++ b/test/coders/GLSLExtension.cpp @@ -18,6 +18,7 @@ TEST(GLSLExtension, processing) { "\n" "#include /* hell\no */ < sum >\n" "#param float p_intensity\n" + "#param vec3 p_pos = [0, 0, 0]\n" "\n" "vec4 effect() {\n" " vec4 color = texture(u_screen, v_uv);\n"