diff options
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r-- | servers/rendering/shader_language.cpp | 191 |
1 files changed, 114 insertions, 77 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 816a02761d..1fd7062d6e 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -3467,7 +3467,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C } value = Variant(array); } else { - value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint)); + value = Variant(Quaternion(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint)); } break; case ShaderLanguage::TYPE_UINT: @@ -3517,7 +3517,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C } value = Variant(array); } else { - value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint)); + value = Variant(Quaternion(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint)); } break; case ShaderLanguage::TYPE_FLOAT: @@ -3548,13 +3548,25 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 3; - PackedVector3Array array = PackedVector3Array(); - for (int i = 0; i < array_size; i += 3) { - array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); + if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + PackedColorArray array = PackedColorArray(); + for (int i = 0; i < array_size; i += 3) { + array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); + } + value = Variant(array); + } else { + PackedVector3Array array = PackedVector3Array(); + for (int i = 0; i < array_size; i += 3) { + array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); + } + value = Variant(array); } - value = Variant(array); } else { - value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real)); + if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real)); + } else { + value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real)); + } } break; case ShaderLanguage::TYPE_VEC4: @@ -3581,7 +3593,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); } else { - value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + value = Variant(Quaternion(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); } } break; @@ -3760,9 +3772,19 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform break; case ShaderLanguage::TYPE_VEC3: if (p_uniform.array_size > 0) { - pi.type = Variant::PACKED_VECTOR3_ARRAY; + if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.hint = PROPERTY_HINT_COLOR_NO_ALPHA; + pi.type = Variant::PACKED_COLOR_ARRAY; + } else { + pi.type = Variant::PACKED_VECTOR3_ARRAY; + } } else { - pi.type = Variant::VECTOR3; + if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.hint = PROPERTY_HINT_COLOR_NO_ALPHA; + pi.type = Variant::COLOR; + } else { + pi.type = Variant::VECTOR3; + } } break; case ShaderLanguage::TYPE_VEC4: { @@ -3776,7 +3798,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { pi.type = Variant::COLOR; } else { - pi.type = Variant::PLANE; + pi.type = Variant::QUATERNION; } } } break; @@ -4670,16 +4692,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = _parse_array_constructor(p_block, p_function_info); } else { DataType datatype; - DataPrecision precision; - bool precision_defined = false; + DataPrecision precision = PRECISION_DEFAULT; if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } datatype = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(datatype, precision) != OK) { + return nullptr; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -4697,7 +4721,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *func = alloc_node<OperatorNode>(); func->op = OP_CONSTRUCT; - if (precision_defined) { + if (precision != PRECISION_DEFAULT) { func->return_precision_cache = precision; } @@ -6426,10 +6450,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!is_struct) { is_struct = shader->structs.has(tk.text); // check again. } - if (is_struct && precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected variable type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6449,6 +6469,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + int array_size = 0; bool fixed_array_size = false; bool first = true; @@ -6600,10 +6624,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (is_token_precision(tk.type)) { precision2 = get_token_precision(tk.type); tk = _get_token(); - if (shader->structs.has(tk.text)) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } if (!is_token_nonvoid_datatype(tk.type)) { _set_error(RTR("Expected data type after precision modifier.")); return ERR_PARSE_ERROR; @@ -6624,6 +6644,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun type2 = get_token_datatype(tk.type); } + if (precision2 != PRECISION_DEFAULT && _validate_precision(type2, precision2) != OK) { + return ERR_PARSE_ERROR; + } + int array_size2 = 0; tk = _get_token(); @@ -7427,6 +7451,25 @@ String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { return ""; } +Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_precision) { + switch (p_type) { + case TYPE_STRUCT: { + _set_error(RTR("The precision modifier cannot be used on structs.")); + return FAILED; + } break; + case TYPE_BOOL: + case TYPE_BVEC2: + case TYPE_BVEC3: + case TYPE_BVEC4: { + _set_error(RTR("The precision modifier cannot be used on boolean types.")); + return FAILED; + } break; + default: + break; + } + return OK; +} + Error ShaderLanguage::_validate_datatype(DataType p_type) { if (RenderingServer::get_singleton()->is_low_end()) { bool invalid_type = false; @@ -7608,8 +7651,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } StringName struct_name = ""; bool struct_dt = false; - bool use_precision = false; - DataPrecision precision = DataPrecision::PRECISION_DEFAULT; + DataPrecision precision = PRECISION_DEFAULT; if (tk.type == TK_STRUCT) { _set_error(RTR("Nested structs are not allowed.")); @@ -7618,7 +7660,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - use_precision = true; tk = _get_token(); } @@ -7630,10 +7671,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } #endif // DEBUG_ENABLED struct_dt = true; - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_token_datatype(tk.type) && !struct_dt) { @@ -7642,6 +7679,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID || is_sampler_type(type)) { _set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type))); return ERR_PARSE_ERROR; @@ -7762,7 +7803,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } - bool precision_defined = false; DataPrecision precision = PRECISION_DEFAULT; DataInterpolation interpolation = INTERPOLATION_SMOOTH; DataType type; @@ -7781,16 +7821,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (is_token_precision(tk.type)) { precision = get_token_precision(tk.type); - precision_defined = true; tk = _get_token(); } if (shader->structs.has(tk.text)) { if (uniform) { - if (precision_defined) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { @@ -7806,6 +7841,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct type = get_token_datatype(tk.type); + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + if (type == TYPE_VOID) { _set_error(vformat(RTR("The '%s' data type is not allowed here."), "void")); return ERR_PARSE_ERROR; @@ -7984,8 +8023,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) { uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; } else if (tk.type == TK_HINT_COLOR) { - if (type != TYPE_VEC4) { - _set_error(vformat(RTR("Color hint is for '%s' only."), "vec4")); + if (type != TYPE_VEC3 && type != TYPE_VEC4) { + _set_error(vformat(RTR("Color hint is for '%s' or '%s' only."), "vec3", "vec4")); return ERR_PARSE_ERROR; } uniform2.hint = ShaderNode::Uniform::HINT_COLOR; @@ -8249,10 +8288,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (shader->structs.has(tk.text)) { - if (precision != PRECISION_DEFAULT) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } is_struct = true; struct_name = tk.text; } else { @@ -8276,6 +8311,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { type = get_token_datatype(tk.type); } + + if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) { + return ERR_PARSE_ERROR; + } + prev_pos = _get_tkpos(); tk = _get_token(); @@ -8652,44 +8692,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } - bool is_const = false; + bool param_is_const = false; if (tk.type == TK_CONST) { - is_const = true; + param_is_const = true; tk = _get_token(); } - ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; - + ArgumentQualifier param_qualifier = ARGUMENT_QUALIFIER_IN; if (tk.type == TK_ARG_IN) { - qualifier = ARGUMENT_QUALIFIER_IN; + param_qualifier = ARGUMENT_QUALIFIER_IN; tk = _get_token(); } else if (tk.type == TK_ARG_OUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_OUT; + param_qualifier = ARGUMENT_QUALIFIER_OUT; tk = _get_token(); } else if (tk.type == TK_ARG_INOUT) { - if (is_const) { + if (param_is_const) { _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const")); return ERR_PARSE_ERROR; } - qualifier = ARGUMENT_QUALIFIER_INOUT; + param_qualifier = ARGUMENT_QUALIFIER_INOUT; tk = _get_token(); } - DataType ptype; - StringName pname; + DataType param_type; + StringName param_name; StringName param_struct_name; - DataPrecision pprecision = PRECISION_DEFAULT; - bool use_precision = false; + DataPrecision param_precision = PRECISION_DEFAULT; int arg_array_size = 0; if (is_token_precision(tk.type)) { - pprecision = get_token_precision(tk.type); + param_precision = get_token_precision(tk.type); tk = _get_token(); - use_precision = true; } is_struct = false; @@ -8702,10 +8739,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct used_structs[param_struct_name].used = true; } #endif // DEBUG_ENABLED - if (use_precision) { - _set_error(RTR("The precision modifier cannot be used on structs.")); - return ERR_PARSE_ERROR; - } } if (!is_struct && !is_token_datatype(tk.type)) { @@ -8713,7 +8746,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { + if (param_qualifier == ARGUMENT_QUALIFIER_OUT || param_qualifier == ARGUMENT_QUALIFIER_INOUT) { if (is_sampler_type(get_token_datatype(tk.type))) { _set_error(RTR("Opaque types cannot be output parameters.")); return ERR_PARSE_ERROR; @@ -8721,18 +8754,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (is_struct) { - ptype = TYPE_STRUCT; + param_type = TYPE_STRUCT; } else { - ptype = get_token_datatype(tk.type); - if (_validate_datatype(ptype) != OK) { + param_type = get_token_datatype(tk.type); + if (_validate_datatype(param_type) != OK) { return ERR_PARSE_ERROR; } - if (ptype == TYPE_VOID) { + if (param_type == TYPE_VOID) { _set_error(RTR("Void type not allowed as argument.")); return ERR_PARSE_ERROR; } } + if (param_precision != PRECISION_DEFAULT && _validate_precision(param_type, param_precision) != OK) { + return ERR_PARSE_ERROR; + } + tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -8747,32 +8784,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - pname = tk.text; + param_name = tk.text; ShaderLanguage::IdentifierType itype; - if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { + if (_find_identifier(func_node->body, false, builtins, param_name, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { - _set_redefinition_error(String(pname)); + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } } - if (has_builtin(p_functions, pname)) { - _set_redefinition_error(String(pname)); + if (has_builtin(p_functions, param_name)) { + _set_redefinition_error(String(param_name)); return ERR_PARSE_ERROR; } FunctionNode::Argument arg; - arg.type = ptype; - arg.name = pname; + arg.type = param_type; + arg.name = param_name; arg.type_str = param_struct_name; - arg.precision = pprecision; - arg.qualifier = qualifier; + arg.precision = param_precision; + arg.qualifier = param_qualifier; arg.tex_argument_check = false; arg.tex_builtin_check = false; arg.tex_argument_filter = FILTER_DEFAULT; arg.tex_argument_repeat = REPEAT_DEFAULT; - arg.is_const = is_const; + arg.is_const = param_is_const; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -9499,7 +9536,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_HINT: { - if (completion_base == DataType::TYPE_VEC4) { + if (completion_base == DataType::TYPE_VEC3 || completion_base == DataType::TYPE_VEC4) { ScriptLanguage::CodeCompletionOption option("hint_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); r_options->push_back(option); } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) { |