diff options
Diffstat (limited to 'servers/visual')
-rw-r--r-- | servers/visual/rasterizer.h | 22 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 128 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 144 | ||||
-rw-r--r-- | servers/visual/shader_types.cpp | 4 | ||||
-rw-r--r-- | servers/visual/visual_server_canvas.cpp | 108 | ||||
-rw-r--r-- | servers/visual/visual_server_canvas.h | 17 | ||||
-rw-r--r-- | servers/visual/visual_server_globals.cpp (renamed from servers/visual/visual_server_global.cpp) | 4 | ||||
-rw-r--r-- | servers/visual/visual_server_globals.h (renamed from servers/visual/visual_server_global.h) | 8 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 9 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 11 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.cpp | 89 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.h | 14 | ||||
-rw-r--r-- | servers/visual/visual_server_viewport.cpp | 134 | ||||
-rw-r--r-- | servers/visual/visual_server_viewport.h | 6 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 8 |
15 files changed, 465 insertions, 241 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 33081dcd0c..31888261ec 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -355,6 +355,7 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) = 0; /* Light API */ @@ -372,6 +373,7 @@ public: virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0; virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0; @@ -391,6 +393,7 @@ public: virtual AABB light_get_aabb(RID p_light) const = 0; virtual float light_get_param(RID p_light, VS::LightParam p_param) = 0; virtual Color light_get_color(RID p_light) = 0; + virtual bool light_get_use_gi(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; /* PROBE API */ @@ -547,12 +550,15 @@ public: RENDER_TARGET_NO_SAMPLING, RENDER_TARGET_HDR, RENDER_TARGET_KEEP_3D_LINEAR, + RENDER_TARGET_DIRECT_TO_SCREEN, RENDER_TARGET_FLAG_MAX }; virtual RID render_target_create() = 0; + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0; virtual RID render_target_get_texture(RID p_render_target) const = 0; + virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; virtual bool render_target_was_used(RID p_render_target) = 0; virtual void render_target_clear_used(RID p_render_target) = 0; @@ -787,6 +793,8 @@ public: RID mesh; RID texture; RID normal_map; + Transform2D transform; + Color modulate; CommandMesh() { type = TYPE_MESH; } }; @@ -870,7 +878,7 @@ public: Rect2 global_rect_cache; const Rect2 &get_rect() const { - if (custom_rect || !rect_dirty) + if (custom_rect || (!rect_dirty && !update_when_visible)) return rect; //must update rect @@ -940,9 +948,8 @@ public: const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); r.position = primitive->points[0]; - for (int i = 1; i < primitive->points.size(); i++) { - - r.expand_to(primitive->points[i]); + for (int j = 1; j < primitive->points.size(); j++) { + r.expand_to(primitive->points[j]); } } break; case Item::Command::TYPE_POLYGON: { @@ -951,9 +958,8 @@ public: int l = polygon->points.size(); const Point2 *pp = &polygon->points[0]; r.position = pp[0]; - for (int i = 1; i < l; i++) { - - r.expand_to(pp[i]); + for (int j = 1; j < l; j++) { + r.expand_to(pp[j]); } } break; case Item::Command::TYPE_MESH: { @@ -1102,7 +1108,7 @@ public: virtual void initialize() = 0; virtual void begin_frame(double frame_step) = 0; virtual void set_current_render_target(RID p_render_target) = 0; - virtual void restore_render_target() = 0; + virtual void restore_render_target(bool p_3d) = 0; virtual void clear_render_target(const Color &p_color) = 0; virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0) = 0; virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index c2dae7c2d5..6efd05593e 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -616,7 +616,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { else tk.type = TK_INT_CONSTANT; - tk.constant = str.to_double(); //wont work with hex + tk.constant = str.to_double(); //won't work with hex tk.line = tk_line; return tk; @@ -2075,7 +2075,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p for (int i = 0; i < argcount; i++) { if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) { - //all good + //all good, but needs implicit conversion later } else if (args[i] != builtin_func_defs[idx].args[i]) { fail = true; break; @@ -2121,6 +2121,24 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p outarg_idx++; } + //implicitly convert values if possible + for (int i = 0; i < argcount; i++) { + + if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) { + //can't do implicit conversion here + continue; + } + + //this is an implicit conversion + ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[i + 1]); + ConstantNode *conversion = alloc_node<ConstantNode>(); + + conversion->datatype = builtin_func_defs[idx].args[i]; + conversion->values.resize(1); + + convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw()); + p_func->arguments.write[i + 1] = conversion; + } if (r_ret_type) *r_ret_type = builtin_func_defs[idx].rettype; @@ -2184,17 +2202,37 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p bool fail = false; - for (int i = 0; i < args.size(); i++) { + for (int j = 0; j < args.size(); j++) { - if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), pfunc->arguments[i].type)) { - //all good - } else if (args[i] != pfunc->arguments[i].type) { + if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { + //all good, but it needs implicit conversion later + } else if (args[j] != pfunc->arguments[j].type) { fail = true; break; } } if (!fail) { + + //implicitly convert values if possible + for (int k = 0; k < args.size(); k++) { + + if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) { + //can't do implicit conversion here + continue; + } + + //this is an implicit conversion + ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[k + 1]); + ConstantNode *conversion = alloc_node<ConstantNode>(); + + conversion->datatype = pfunc->arguments[k].type; + conversion->values.resize(1); + + convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw()); + p_func->arguments.write[k + 1] = conversion; + } + if (r_ret_type) *r_ret_type = pfunc->return_type; return true; @@ -2897,7 +2935,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons /* OK now see what's NEXT to the operator.. */ while (true) { - TkPos pos = _get_tkpos(); + TkPos pos2 = _get_tkpos(); tk = _get_token(); if (tk.type == TK_CURSOR) { @@ -2930,6 +2968,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons member_type = DataType(dt - 1); } else if (l == 2) { member_type = dt; + } else if (l == 3) { + member_type = DataType(dt + 1); + } else if (l == 4) { + member_type = DataType(dt + 2); } else { ok = false; break; @@ -2963,6 +3005,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons member_type = DataType(dt - 1); } else if (l == 3) { member_type = dt; + } else if (l == 4) { + member_type = DataType(dt + 1); } else { ok = false; break; @@ -3181,7 +3225,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = op; } else { - _set_tkpos(pos); + _set_tkpos(pos2); break; } } @@ -3374,10 +3418,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!_validate_operator(op, &op->return_cache)) { String at; - for (int i = 0; i < op->arguments.size(); i++) { - if (i > 0) + for (int j = 0; j < op->arguments.size(); j++) { + if (j > 0) at += " and "; - at += get_datatype_name(op->arguments[i]->get_datatype()); + at += get_datatype_name(op->arguments[j]->get_datatype()); } _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); return NULL; @@ -3582,7 +3626,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha case TYPE_FLOAT: { nv.real = -cn->values[i].real; } break; - default: {} + default: { + } } values.push_back(nv); @@ -4103,17 +4148,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (uniform) { - ShaderNode::Uniform uniform; + ShaderNode::Uniform uniform2; if (is_sampler_type(type)) { - uniform.texture_order = texture_uniforms++; - uniform.order = -1; + uniform2.texture_order = texture_uniforms++; + uniform2.order = -1; } else { - uniform.texture_order = -1; - uniform.order = uniforms++; + uniform2.texture_order = -1; + uniform2.order = uniforms++; } - uniform.type = type; - uniform.precission = precision; + uniform2.type = type; + uniform2.precision = precision; //todo parse default value @@ -4124,26 +4169,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_HINT_WHITE_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_WHITE; + uniform2.hint = ShaderNode::Uniform::HINT_WHITE; } else if (tk.type == TK_HINT_BLACK_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_BLACK; + uniform2.hint = ShaderNode::Uniform::HINT_BLACK; } else if (tk.type == TK_HINT_NORMAL_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_NORMAL; + uniform2.hint = ShaderNode::Uniform::HINT_NORMAL; } else if (tk.type == TK_HINT_ANISO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_ANISO; + uniform2.hint = ShaderNode::Uniform::HINT_ANISO; } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_ALBEDO; + uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO; } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) { - uniform.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; + uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; } else if (tk.type == TK_HINT_COLOR) { if (type != TYPE_VEC4) { _set_error("Color hint is for vec4 only"); return ERR_PARSE_ERROR; } - uniform.hint = ShaderNode::Uniform::HINT_COLOR; + uniform2.hint = ShaderNode::Uniform::HINT_COLOR; } else if (tk.type == TK_HINT_RANGE) { - uniform.hint = ShaderNode::Uniform::HINT_RANGE; + uniform2.hint = ShaderNode::Uniform::HINT_RANGE; if (type != TYPE_FLOAT && type != TYPE_INT) { _set_error("Range hint is for float and int only"); return ERR_PARSE_ERROR; @@ -4169,8 +4214,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[0] = tk.constant; - uniform.hint_range[0] *= sign; + uniform2.hint_range[0] = tk.constant; + uniform2.hint_range[0] *= sign; tk = _get_token(); @@ -4193,8 +4238,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[1] = tk.constant; - uniform.hint_range[1] *= sign; + uniform2.hint_range[1] = tk.constant; + uniform2.hint_range[1] *= sign; tk = _get_token(); @@ -4206,13 +4251,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - uniform.hint_range[2] = tk.constant; + uniform2.hint_range[2] = tk.constant; tk = _get_token(); } else { if (type == TYPE_INT) { - uniform.hint_range[2] = 1; + uniform2.hint_range[2] = 1; } else { - uniform.hint_range[2] = 0.001; + uniform2.hint_range[2] = 0.001; } } @@ -4225,7 +4270,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _set_error("Expected valid type hint after ':'."); } - if (uniform.hint != ShaderNode::Uniform::HINT_RANGE && uniform.hint != ShaderNode::Uniform::HINT_NONE && uniform.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { + if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { _set_error("This hint is only for sampler types"); return ERR_PARSE_ERROR; } @@ -4245,16 +4290,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ConstantNode *cn = static_cast<ConstantNode *>(expr); - uniform.default_value.resize(cn->values.size()); + uniform2.default_value.resize(cn->values.size()); - if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) { - _set_error("Can't convert constant to " + get_datatype_name(uniform.type)); + if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) { + _set_error("Can't convert constant to " + get_datatype_name(uniform2.type)); return ERR_PARSE_ERROR; } tk = _get_token(); } - shader->uniforms[name] = uniform; + shader->uniforms[name] = uniform2; if (tk.type != TK_SEMICOLON) { _set_error("Expected ';'"); @@ -4264,7 +4309,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ShaderNode::Varying varying; varying.type = type; - varying.precission = precision; + varying.precision = precision; varying.interpolation = interpolation; shader->varyings[name] = varying; @@ -4784,7 +4829,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct case TYPE_MAT2: limit = 2; break; case TYPE_MAT3: limit = 3; break; case TYPE_MAT4: limit = 4; break; - default: {} + default: { + } } for (int i = 0; i < limit; i++) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index b908f9539b..67c273d267 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -33,7 +33,7 @@ #include "core/list.h" #include "core/map.h" -#include "core/string_db.h" +#include "core/string_name.h" #include "core/typedefs.h" #include "core/ustring.h" #include "core/variant.h" @@ -42,7 +42,6 @@ class ShaderLanguage { public: enum TokenType { - TK_EMPTY, TK_IDENTIFIER, TK_TRUE, @@ -267,18 +266,15 @@ public: FLOW_OP_SWITCH, FLOW_OP_CONTINUE, FLOW_OP_DISCARD - }; enum ArgumentQualifier { ARGUMENT_QUALIFIER_IN, ARGUMENT_QUALIFIER_OUT, ARGUMENT_QUALIFIER_INOUT, - }; struct Node { - Node *next; enum Type { @@ -296,7 +292,9 @@ public: Type type; virtual DataType get_datatype() const { return TYPE_VOID; } - + Node(Type t) : + next(NULL), + type(t) {} virtual ~Node() {} }; @@ -311,18 +309,17 @@ public: Node *nodes; struct OperatorNode : public Node { - DataType return_cache; DataPrecision return_precision_cache; Operator op; Vector<Node *> arguments; virtual DataType get_datatype() const { return return_cache; } - OperatorNode() { - type = TYPE_OPERATOR; - return_cache = TYPE_VOID; - return_precision_cache = PRECISION_DEFAULT; - } + OperatorNode() : + Node(TYPE_OPERATOR), + return_cache(TYPE_VOID), + return_precision_cache(PRECISION_DEFAULT), + op(OP_EQUAL) {} }; struct VariableNode : public Node { @@ -330,20 +327,16 @@ public: StringName name; virtual DataType get_datatype() const { return datatype_cache; } - VariableNode() { - - type = TYPE_VARIABLE; - datatype_cache = TYPE_VOID; - } + VariableNode() : + Node(TYPE_VARIABLE), + datatype_cache(TYPE_VOID) {} }; struct VariableDeclarationNode : public Node { - DataPrecision precision; DataType datatype; struct Declaration { - StringName name; Node *initializer; }; @@ -351,13 +344,13 @@ public: Vector<Declaration> declarations; virtual DataType get_datatype() const { return datatype; } - VariableDeclarationNode() { - type = TYPE_VARIABLE_DECLARATION; - } + VariableDeclarationNode() : + Node(TYPE_VARIABLE_DECLARATION), + precision(PRECISION_DEFAULT), + datatype(TYPE_VOID) {} }; struct ConstantNode : public Node { - DataType datatype; union Value { @@ -370,7 +363,9 @@ public: Vector<Value> values; virtual DataType get_datatype() const { return datatype; } - ConstantNode() { type = TYPE_CONSTANT; } + ConstantNode() : + Node(TYPE_CONSTANT), + datatype(TYPE_VOID) {} }; struct FunctionNode; @@ -388,39 +383,41 @@ public: Map<StringName, Variable> variables; List<Node *> statements; bool single_statement; - BlockNode() { - type = TYPE_BLOCK; - parent_block = NULL; - parent_function = NULL; - single_statement = false; - } + + BlockNode() : + Node(TYPE_BLOCK), + parent_function(NULL), + parent_block(NULL), + single_statement(false) {} }; struct ControlFlowNode : public Node { - FlowOperation flow_op; Vector<Node *> expressions; Vector<BlockNode *> blocks; - ControlFlowNode() { - type = TYPE_CONTROL_FLOW; - flow_op = FLOW_OP_IF; - } + + ControlFlowNode() : + Node(TYPE_CONTROL_FLOW), + flow_op(FLOW_OP_IF) {} }; struct MemberNode : public Node { - DataType basetype; DataType datatype; StringName name; Node *owner; + virtual DataType get_datatype() const { return datatype; } - MemberNode() { type = TYPE_MEMBER; } + + MemberNode() : + Node(TYPE_MEMBER), + basetype(TYPE_VOID), + datatype(TYPE_VOID), + owner(NULL) {} }; struct FunctionNode : public Node { - struct Argument { - ArgumentQualifier qualifier; StringName name; DataType type; @@ -434,16 +431,15 @@ public: BlockNode *body; bool can_discard; - FunctionNode() { - type = TYPE_FUNCTION; - return_type = TYPE_VOID; - return_precision = PRECISION_DEFAULT; - can_discard = false; - } + FunctionNode() : + Node(TYPE_FUNCTION), + return_type(TYPE_VOID), + return_precision(PRECISION_DEFAULT), + body(NULL), + can_discard(false) {} }; struct ShaderNode : public Node { - struct Function { StringName name; FunctionNode *function; @@ -454,7 +450,12 @@ public: struct Varying { DataType type; DataInterpolation interpolation; - DataPrecision precission; + DataPrecision precision; + + Varying() : + type(TYPE_VOID), + interpolation(INTERPOLATION_FLAT), + precision(PRECISION_DEFAULT) {} }; struct Uniform { @@ -474,16 +475,20 @@ public: int order; int texture_order; DataType type; - DataPrecision precission; + DataPrecision precision; Vector<ConstantNode::Value> default_value; Hint hint; float hint_range[3]; - Uniform() { - hint = HINT_NONE; - hint_range[0] = 0; - hint_range[1] = 1; - hint_range[2] = 0.001; + Uniform() : + order(0), + texture_order(0), + type(TYPE_VOID), + precision(PRECISION_DEFAULT), + hint(HINT_NONE) { + hint_range[0] = 0.0f; + hint_range[1] = 1.0f; + hint_range[2] = 0.001f; } }; @@ -493,11 +498,11 @@ public: Vector<Function> functions; - ShaderNode() { type = TYPE_SHADER; } + ShaderNode() : + Node(TYPE_SHADER) {} }; struct Expression { - bool is_op; union { Operator op; @@ -506,7 +511,6 @@ public: }; struct VarInfo { - StringName name; DataType type; }; @@ -522,7 +526,6 @@ public: }; struct Token { - TokenType type; StringName text; double constant; @@ -556,11 +559,14 @@ public: struct BuiltInInfo { DataType type; bool constant; - BuiltInInfo() {} - BuiltInInfo(DataType p_type, bool p_constant = false) { - type = p_type; - constant = p_constant; - } + + BuiltInInfo() : + type(TYPE_VOID), + constant(false) {} + + BuiltInInfo(DataType p_type, bool p_constant = false) : + type(p_type), + constant(p_constant) {} }; struct FunctionInfo { @@ -573,6 +579,7 @@ private: TokenType token; const char *text; }; + static const KeyWord keyword_list[]; bool error_set; @@ -628,22 +635,18 @@ private: }; bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL); - bool _is_operator_assign(Operator p_op) const; bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL); - bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); struct BuiltinFuncDef { - enum { MAX_ARGS = 5 }; const char *name; DataType rettype; const DataType args[MAX_ARGS]; }; - struct BuiltinFuncOutArgs { //arguments used as out in built in funcions - + struct BuiltinFuncOutArgs { //arguments used as out in built in functions const char *name; int argument; }; @@ -656,20 +659,17 @@ private: int completion_argument; bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); - static const BuiltinFuncDef builtin_func_defs[]; static const BuiltinFuncOutArgs builtin_func_out_args[]; - bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type); + bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type); bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL); Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); - ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); - Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); + Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); public: diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 7a42bc475e..bc6010117c 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -76,7 +76,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); @@ -147,6 +147,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true; @@ -187,6 +188,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); shader_modes[VS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity"); shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index bb02027479..d5e154a7fc 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -29,15 +29,13 @@ /*************************************************************************/ #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_raster.h" #include "visual_server_viewport.h" -void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) { +static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1; - static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1; - RasterizerCanvas::Item *z_list[z_range]; - RasterizerCanvas::Item *z_last_list[z_range]; +void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) { memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); @@ -51,20 +49,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra } } -void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) { +void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, VisualServerCanvas::Item **r_items, int &r_index) { int child_item_count = p_canvas_item->child_items.size(); VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { - if (r_items) { - r_items[r_index] = child_items[i]; - child_items[i]->ysort_xform = p_transform; - child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); - } + if (child_items[i]->visible) { + if (r_items) { + r_items[r_index] = child_items[i]; + child_items[i]->ysort_xform = p_transform; + child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); + child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL; + } - r_index++; + r_index++; - if (child_items[i]->sort_y) - _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index); + if (child_items[i]->sort_y) + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); + } } } @@ -124,14 +125,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (ci->ysort_children_count == -1) { ci->ysort_children_count = 0; - _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count); + _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count); } child_item_count = ci->ysort_children_count; child_items = (Item **)alloca(child_item_count * sizeof(Item *)); int i = 0; - _collect_ysort_children(ci, Transform2D(), child_items, i); + _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); @@ -147,7 +148,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -189,7 +190,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -267,24 +268,24 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr for (int i = 0; i < l; i++) { - const Canvas::ChildItem &ci = p_canvas->child_items[i]; - _render_canvas_item_tree(ci.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); + const Canvas::ChildItem &ci2 = p_canvas->child_items[i]; + _render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x != 0) { + if (ci2.mirror.x != 0) { - Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci.mirror.x, 0)); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0)); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } - if (ci.mirror.y != 0) { + if (ci2.mirror.y != 0) { - Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci.mirror.y)); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y)); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } - if (ci.mirror.y != 0 && ci.mirror.x != 0) { + if (ci2.mirror.y != 0 && ci2.mirror.x != 0) { - Transform2D xform2 = p_transform * Transform2D(0, ci.mirror); - _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror); + _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); } } } @@ -319,6 +320,19 @@ void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) canvas->modulate = p_color; } +void VisualServerCanvas::canvas_set_disable_scale(bool p_disable) { + disable_scale = p_disable; +} + +void VisualServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) { + + Canvas *canvas = canvas_owner.get(p_canvas); + ERR_FAIL_COND(!canvas); + + canvas->parent = p_parent; + canvas->parent_scale = p_scale; +} + RID VisualServerCanvas::canvas_item_create() { Item *canvas_item = memnew(Item); @@ -380,6 +394,10 @@ void VisualServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) { ERR_FAIL_COND(!canvas_item); canvas_item->visible = p_visible; + + if (canvas_item->parent.is_valid() && canvas_item_owner.owns(canvas_item->parent)) { + _mark_ysort_dirty(canvas_item_owner.get(canvas_item->parent), canvas_item_owner); + } } void VisualServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) { @@ -616,7 +634,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p if (p_tile) { rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE; rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION; - rect->source = Rect2(0, 0, p_rect.size.width, p_rect.size.height); + rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height)); } if (p_rect.size.x < 0) { @@ -758,11 +776,12 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); - int ps = p_points.size(); - ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != ps && p_colors.size() != 1); - ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != ps); - ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != ps * 4); - ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != ps * 4); + int vertex_count = p_points.size(); + ERR_FAIL_COND(vertex_count == 0); + ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1); + ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count); + ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4); + ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4); Vector<int> indices = p_indices; @@ -770,9 +789,9 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector if (indices.empty()) { - ERR_FAIL_COND(ps % 3 != 0); + ERR_FAIL_COND(vertex_count % 3 != 0); if (p_count == -1) - count = ps; + count = vertex_count; } else { ERR_FAIL_COND(indices.size() % 3 != 0); @@ -809,7 +828,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo canvas_item->commands.push_back(tr); } -void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) { +void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -819,6 +838,8 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID m->mesh = p_mesh; m->texture = p_texture; m->normal_map = p_normal_map; + m->transform = p_transform; + m->modulate = p_modulate; canvas_item->commands.push_back(m); } @@ -1433,4 +1454,15 @@ bool VisualServerCanvas::free(RID p_rid) { } VisualServerCanvas::VisualServerCanvas() { + + z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + + disable_scale = false; +} + +VisualServerCanvas::~VisualServerCanvas() { + + memfree(z_list); + memfree(z_last_list); } diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 7d788cbe14..26424f927e 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -82,7 +82,7 @@ public: _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { - if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON) + if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) return p_left->ysort_pos.x < p_right->ysort_pos.x; else return p_left->ysort_pos.y < p_right->ysort_pos.y; @@ -126,6 +126,8 @@ public: bool children_order_dirty; Vector<ChildItem> child_items; Color modulate; + RID parent; + float parent_scale; int find_item(Item *p_item) { for (int i = 0; i < child_items.size(); i++) { @@ -143,24 +145,32 @@ public: Canvas() { modulate = Color(1, 1, 1, 1); children_order_dirty = true; + parent_scale = 1.0; } }; - RID_Owner<Canvas> canvas_owner; + mutable RID_Owner<Canvas> canvas_owner; RID_Owner<Item> canvas_item_owner; RID_Owner<RasterizerCanvas::Light> canvas_light_owner; + bool disable_scale; + private: void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights); void _render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights); + RasterizerCanvas::Item **z_list; + RasterizerCanvas::Item **z_last_list; + public: void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect); RID canvas_create(); void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); void canvas_set_modulate(RID p_canvas, const Color &p_color); + void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale); + void canvas_set_disable_scale(bool p_disable); RID canvas_item_create(); void canvas_item_set_parent(RID p_item, RID p_parent); @@ -190,7 +200,7 @@ public: void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false); void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()); - void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); + void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal); void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); @@ -247,6 +257,7 @@ public: bool free(RID p_rid); VisualServerCanvas(); + ~VisualServerCanvas(); }; #endif // VISUALSERVERCANVAS_H diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_globals.cpp index 2d6d489759..5c247c7f0f 100644 --- a/servers/visual/visual_server_global.cpp +++ b/servers/visual/visual_server_globals.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* visual_server_global.cpp */ +/* visual_server_globals.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "visual_server_global.h" +#include "visual_server_globals.h" RasterizerStorage *VisualServerGlobals::storage = NULL; RasterizerCanvas *VisualServerGlobals::canvas_render = NULL; diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_globals.h index b510307e81..04d52aa1eb 100644 --- a/servers/visual/visual_server_global.h +++ b/servers/visual/visual_server_globals.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* visual_server_global.h */ +/* visual_server_globals.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSERVERGLOBAL_H -#define VISUALSERVERGLOBAL_H +#ifndef VISUAL_SERVER_GLOBALS_H +#define VISUAL_SERVER_GLOBALS_H #include "rasterizer.h" @@ -51,4 +51,4 @@ public: #define VSG VisualServerGlobals -#endif // VISUALSERVERGLOBAL_H +#endif // VISUAL_SERVER_GLOBALS_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 7be3bc562d..310aa16130 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -33,9 +33,9 @@ #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "core/sort.h" +#include "core/sort_array.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" // careful, these may run in different threads than the visual server @@ -123,7 +123,6 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) { frame_drawn_callbacks.pop_front(); } - VS::get_singleton()->emit_signal("frame_post_draw"); } void VisualServerRaster::sync() { @@ -202,8 +201,10 @@ VisualServerRaster::VisualServerRaster() { VSG::canvas_render = VSG::rasterizer->get_canvas(); VSG::scene_render = VSG::rasterizer->get_scene(); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { black_margin[i] = 0; + black_image[i] = RID(); + } } VisualServerRaster::~VisualServerRaster() { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e6434189f9..921d55556d 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -31,12 +31,11 @@ #ifndef VISUAL_SERVER_RASTER_H #define VISUAL_SERVER_RASTER_H -#include "core/allocators.h" #include "core/math/octree.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" #include "visual_server_viewport.h" /** @@ -297,6 +296,7 @@ public: BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &) + BIND3(skeleton_set_world_transform, RID, bool, const Transform &) /* Light API */ @@ -312,6 +312,7 @@ public: BIND2(light_set_negative, RID, bool) BIND2(light_set_cull_mask, RID, uint32_t) BIND2(light_set_reverse_cull_face_mode, RID, bool) + BIND2(light_set_use_gi, RID, bool) BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail) @@ -430,6 +431,7 @@ public: BIND0R(RID, camera_create) BIND4(camera_set_perspective, RID, float, float, float) BIND4(camera_set_orthogonal, RID, float, float, float) + BIND5(camera_set_frustum, RID, float, Vector2, float, float) BIND2(camera_set_transform, RID, const Transform &) BIND2(camera_set_cull_mask, RID, uint32_t) BIND2(camera_set_environment, RID, RID) @@ -452,6 +454,7 @@ public: BIND2(viewport_set_clear_mode, RID, ViewportClearMode) BIND3(viewport_attach_to_screen, RID, const Rect2 &, int) + BIND2(viewport_set_render_direct_to_screen, RID, bool) BIND1(viewport_detach, RID) BIND2(viewport_set_update_mode, RID, ViewportUpdateMode) @@ -569,6 +572,8 @@ public: BIND0R(RID, canvas_create) BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &) BIND2(canvas_set_modulate, RID, const Color &) + BIND3(canvas_set_parent, RID, RID, float) + BIND1(canvas_set_disable_scale, bool) BIND0R(RID, canvas_item_create) BIND2(canvas_item_set_parent, RID, RID) @@ -598,7 +603,7 @@ public: BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) - BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID) + BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) BIND4(canvas_item_add_multimesh, RID, RID, RID, RID) BIND4(canvas_item_add_particles, RID, RID, RID, RID) BIND2(canvas_item_add_set_transform, RID, const Transform2D &) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index c8d64fca45..3ee23e9290 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -30,7 +30,7 @@ #include "visual_server_scene.h" #include "core/os/os.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_raster.h" #include <new> /* CAMERA API */ @@ -61,6 +61,16 @@ void VisualServerScene::camera_set_orthogonal(RID p_camera, float p_size, float camera->zfar = p_z_far; } +void VisualServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.get(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::FRUSTUM; + camera->size = p_size; + camera->offset = p_offset; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) { Camera *camera = camera_owner.get(p_camera); @@ -399,7 +409,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { VSG::scene_render->free(gi_probe->probe_instance); } break; - default: {} + default: { + } } if (instance->base_data) { @@ -445,6 +456,9 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { InstanceGeometryData *geom = memnew(InstanceGeometryData); instance->base_data = geom; + if (instance->base_type == VS::INSTANCE_MESH) { + instance->blend_values.resize(VSG::storage->mesh_get_blend_shape_count(p_base)); + } } break; case VS::INSTANCE_REFLECTION_PROBE: { @@ -473,7 +487,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create(); } break; - default: {} + default: { + } } VSG::storage->instance_add_dependency(p_base, instance); @@ -521,7 +536,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { gi_probe_update_list.remove(&gi_probe->update_element); } } break; - default: {} + default: { + } } instance->scenario = NULL; @@ -553,7 +569,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { gi_probe_update_list.add(&gi_probe->update_element); } } break; - default: {} + default: { + } } _instance_queue_update(instance, true, true); @@ -590,12 +607,12 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform & instance->transform = p_transform; _instance_queue_update(instance, true); } -void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_ID) { +void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { Instance *instance = instance_owner.get(p_instance); ERR_FAIL_COND(!instance); - instance->object_ID = p_ID; + instance->object_id = p_id; } void VisualServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { @@ -668,7 +685,8 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { } } break; - default: {} + default: { + } } } inline bool is_geometry_instance(VisualServer::InstanceType p_type) { @@ -773,10 +791,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -795,10 +813,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3 &p_from, co for (int i = 0; i < culled; i++) { Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -819,10 +837,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane> &p Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -845,7 +863,8 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF instance->redraw_if_visible = p_enabled; } break; - default: {} + default: { + } } } void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { @@ -1037,7 +1056,8 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base); } break; - default: {} + default: { + } } // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs @@ -1720,6 +1740,17 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view ortho = false; } break; + case Camera::FRUSTUM: { + + camera_matrix.set_frustum( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->offset, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + } break; } _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); @@ -1861,7 +1892,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca //failure } else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) { - if (ins->visible && light_cull_count < MAX_LIGHTS_CULLED) { + if (light_cull_count < MAX_LIGHTS_CULLED) { InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); @@ -1878,7 +1909,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca } } else if (ins->base_type == VS::INSTANCE_REFLECTION_PROBE && ins->visible) { - if (ins->visible && reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { + if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data); @@ -2480,7 +2511,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { uint32_t a = uint32_t(alpha_block[x][y]) - min_alpha; //convert range to 3 bits a = int((a * 7.0 / (max_alpha - min_alpha)) + 0.5); - a = CLAMP(a, 0, 7); //just to be sure + a = MIN(a, 7); //just to be sure a = 7 - a; //because range is inverted in this mode if (a == 0) { //do none, remain @@ -2623,7 +2654,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co for (int i = 0; i < 3; i++) { - if (ABS(light_axis[i]) < CMP_EPSILON) + if (Math::is_zero_approx(light_axis[i])) continue; clip[clip_planes].normal[i] = 1.0; @@ -2758,7 +2789,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co for (int c = 0; c < 3; c++) { - if (ABS(light_axis[c]) < CMP_EPSILON) + if (Math::is_zero_approx(light_axis[c])) continue; clip[clip_planes].normal[c] = 1.0; @@ -2916,7 +2947,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t idx = level_cells[j]; - uint32_t r = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2; + uint32_t r2 = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t g = (uint32_t(local_data[idx].energy[1]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t b = (uint32_t(local_data[idx].energy[2]) / probe_data->dynamic.bake_dynamic_range) >> 2; uint32_t a = (cells[idx].level_alpha >> 8) & 0xFF; @@ -2924,10 +2955,10 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t mm_ofs = sizes[0] * sizes[1] * (local_data[idx].pos[2]) + sizes[0] * (local_data[idx].pos[1]) + (local_data[idx].pos[0]); mm_ofs *= 4; //for RGBA (4 bytes) - mipmapw[mm_ofs + 0] = uint8_t(CLAMP(r, 0, 255)); - mipmapw[mm_ofs + 1] = uint8_t(CLAMP(g, 0, 255)); - mipmapw[mm_ofs + 2] = uint8_t(CLAMP(b, 0, 255)); - mipmapw[mm_ofs + 3] = uint8_t(CLAMP(a, 0, 255)); + mipmapw[mm_ofs + 0] = uint8_t(MIN(r2, 255)); + mipmapw[mm_ofs + 1] = uint8_t(MIN(g, 255)); + mipmapw[mm_ofs + 2] = uint8_t(MIN(b, 255)); + mipmapw[mm_ofs + 3] = uint8_t(MIN(a, 255)); } } } else if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) { @@ -3086,6 +3117,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { for (List<Instance *>::Element *E = p_gi_probe->scenario->directional_lights.front(); E; E = E->next()) { + if (!VSG::storage->light_get_use_gi(E->get()->base)) + continue; + InstanceGIProbeData::LightCache lc; lc.type = VSG::storage->light_get_type(E->get()->base); lc.color = VSG::storage->light_get_color(E->get()->base); @@ -3106,6 +3140,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { for (Set<Instance *>::Element *E = probe_data->lights.front(); E; E = E->next()) { + if (!VSG::storage->light_get_use_gi(E->get()->base)) + continue; + InstanceGIProbeData::LightCache lc; lc.type = VSG::storage->light_get_type(E->get()->base); lc.color = VSG::storage->light_get_color(E->get()->base); diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 539855bdc4..629d66c6cb 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -33,7 +33,6 @@ #include "servers/visual/rasterizer.h" -#include "core/allocators.h" #include "core/math/geometry.h" #include "core/math/octree.h" #include "core/os/semaphore.h" @@ -78,12 +77,14 @@ public: enum Type { PERSPECTIVE, - ORTHOGONAL + ORTHOGONAL, + FRUSTUM }; Type type; float fov; float znear, zfar; float size; + Vector2 offset; uint32_t visible_layers; bool vaspect; RID env; @@ -98,6 +99,7 @@ public: znear = 0.05; zfar = 100; size = 1.0; + offset = Vector2(); vaspect = false; } }; @@ -107,6 +109,7 @@ public: virtual RID camera_create(); virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); virtual void camera_set_transform(RID p_camera, const Transform &p_transform); virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); virtual void camera_set_environment(RID p_camera, RID p_env); @@ -120,7 +123,6 @@ public: VS::ScenarioDebugMode debug; RID self; - // well wtf, balloon allocator is slower? Octree<Instance, true> octree; @@ -172,7 +174,7 @@ public: AABB transformed_aabb; AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? float extra_margin; - uint32_t object_ID; + uint32_t object_id; float lod_begin; float lod_end; @@ -209,7 +211,7 @@ public: extra_margin = 0; - object_ID = 0; + object_id = 0; visible = true; lod_begin = 0; @@ -455,7 +457,7 @@ public: virtual void instance_set_scenario(RID p_instance, RID p_scenario); // from can be mesh, light, poly, area and portal so far. virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); virtual void instance_set_transform(RID p_instance, const Transform &p_transform); - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_ID); + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); virtual void instance_set_visible(RID p_instance, bool p_visible); diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 7a7ae3a823..b7c54caffd 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -32,9 +32,46 @@ #include "core/project_settings.h" #include "visual_server_canvas.h" -#include "visual_server_global.h" +#include "visual_server_globals.h" #include "visual_server_scene.h" +static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewport, VisualServerCanvas::Canvas *p_canvas, VisualServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) { + + Transform2D xf = p_viewport->global_transform; + + float scale = 1.0; + if (p_viewport->canvas_map.has(p_canvas->parent)) { + xf = xf * p_viewport->canvas_map[p_canvas->parent].transform; + scale = p_canvas->parent_scale; + } + + xf = xf * p_canvas_data->transform; + + if (scale != 1.0 && !VSG::canvas->disable_scale) { + Vector2 pivot = p_vp_size * 0.5; + Transform2D xfpivot; + xfpivot.set_origin(pivot); + Transform2D xfscale; + xfscale.scale(Vector2(scale, scale)); + + xf = xfpivot.affine_inverse() * xf; + xf = xfscale * xf; + xf = xfpivot * xf; + } + + return xf; +} + +void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { + Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); + + if (p_viewport->use_arvr && arvr_interface.is_valid()) { + VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } else { + VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } +} + void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { /* Camera should always be BEFORE any other 3D */ @@ -62,13 +99,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E } if (!scenario_draw_canvas_bg && can_draw_3d) { - Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - - if (p_viewport->use_arvr && arvr_interface.is_valid()) { - VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); - } else { - VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); - } + _draw_3d(p_viewport, p_eye); } if (!p_viewport->hide_canvas) { @@ -86,10 +117,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - Transform2D xf = p_viewport->global_transform * E->get().transform; - VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas); + Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); + //find lights in canvas for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { @@ -167,24 +198,20 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E RasterizerCanvas::Light *light = lights_with_shadow; while (light) { - VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache); + VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache); light = light->shadows_next_ptr; } //VSG::canvas_render->reset_canvas(); } - VSG::rasterizer->restore_render_target(); + VSG::rasterizer->restore_render_target(!scenario_draw_canvas_bg && can_draw_3d); if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { - Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - if (!can_draw_3d) { VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); - } else if (p_viewport->use_arvr && arvr_interface.is_valid()) { - VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } else { - VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + _draw_3d(p_viewport, p_eye); } scenario_draw_canvas_bg = false; } @@ -193,7 +220,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas); - Transform2D xform = p_viewport->global_transform * E->get()->transform; + Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size); RasterizerCanvas::Light *canvas_lights = NULL; @@ -210,14 +237,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E i++; if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { - Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - if (!can_draw_3d) { VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); - } else if (p_viewport->use_arvr && arvr_interface.is_valid()) { - VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } else { - VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + _draw_3d(p_viewport, p_eye); } scenario_draw_canvas_bg = false; @@ -225,14 +248,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E } if (scenario_draw_canvas_bg) { - Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - if (!can_draw_3d) { VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); - } else if (p_viewport->use_arvr && arvr_interface.is_valid()) { - VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } else { - VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + _draw_3d(p_viewport, p_eye); } scenario_draw_canvas_bg = false; @@ -276,17 +295,27 @@ void VisualServerViewport::draw_viewports() { if (vp->use_arvr && arvr_interface.is_valid()) { // override our size, make sure it matches our required size - Size2 size = arvr_interface->get_render_targetsize(); - VSG::storage->render_target_set_size(vp->render_target, size.x, size.y); + vp->size = arvr_interface->get_render_targetsize(); + VSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y); // render mono or left eye first ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO; + + // check for an external texture destination for our left eye/mono + VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono)); + + // set our render target as current VSG::rasterizer->set_current_render_target(vp->render_target); + + // and draw left eye/mono _draw_viewport(vp, leftOrMono); arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect); // render right eye if (leftOrMono == ARVRInterface::EYE_LEFT) { + // check for an external texture destination for our right eye + VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT)); + // commit for eye may have changed the render target VSG::rasterizer->set_current_render_target(vp->render_target); @@ -297,6 +326,7 @@ void VisualServerViewport::draw_viewports() { // and for our frame timing, mark when we've finished committing our eyes ARVRServer::get_singleton()->_mark_commit(); } else { + VSG::storage->render_target_set_external_texture(vp->render_target, 0); VSG::rasterizer->set_current_render_target(vp->render_target); VSG::scene_render->set_debug_draw_mode(vp->debug_draw); @@ -313,7 +343,7 @@ void VisualServerViewport::draw_viewports() { vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); - if (vp->viewport_to_screen_rect != Rect2()) { + if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { //copy to screen if set as such VSG::rasterizer->set_current_render_target(RID()); VSG::rasterizer->blit_render_target_to_screen(vp->render_target, vp->viewport_to_screen_rect, vp->viewport_to_screen); @@ -338,6 +368,7 @@ RID VisualServerViewport::viewport_create() { viewport->hide_canvas = false; viewport->render_target = VSG::storage->render_target_create(); viewport->shadow_atlas = VSG::scene_render->shadow_atlas_create(); + viewport->viewport_render_direct_to_screen = false; return rid; } @@ -394,14 +425,55 @@ void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); + // If using GLES2 we can optimize this operation by rendering directly to system_fbo + // instead of rendering to fbo and copying to system_fbo after + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); + VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); + } + viewport->viewport_to_screen_rect = p_rect; viewport->viewport_to_screen = p_screen; } + +void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_enable == viewport->viewport_render_direct_to_screen) + return; + + // if disabled, reset render_target size and position + if (!p_enable) { + + VSG::storage->render_target_set_position(viewport->render_target, 0, 0); + VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + + VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); + viewport->viewport_render_direct_to_screen = p_enable; + + // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unneccesary buffer allocation + if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) { + + VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y); + VSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y); + } +} + void VisualServerViewport::viewport_detach(RID p_viewport) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); + // if render_direct_to_screen was used, reset size and position + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + VSG::storage->render_target_set_position(viewport->render_target, 0, 0); + VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + viewport->viewport_to_screen_rect = Rect2(); viewport->viewport_to_screen = 0; } diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index 4e3015c020..43bbcb66c3 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -58,6 +58,7 @@ public: int viewport_to_screen; Rect2 viewport_to_screen_rect; + bool viewport_render_direct_to_screen; bool hide_scenario; bool hide_canvas; @@ -90,7 +91,8 @@ public: } CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) { canvas = p_canvas; - stacking = ((int64_t)p_layer << 32) + p_sublayer; + int64_t sign = p_layer < 0 ? -1 : 1; + stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer; } int get_layer() const { return stacking >> 32; } }; @@ -146,6 +148,7 @@ public: private: Color clear_color; + void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye); void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO); public: @@ -156,6 +159,7 @@ public: void viewport_set_size(RID p_viewport, int p_width, int p_height); void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0); + void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable); void viewport_detach(RID p_viewport); void viewport_set_active(RID p_viewport, bool p_active); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index a6f0bd9d16..cd24deb60c 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -232,6 +232,7 @@ public: FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) + FUNC3(skeleton_set_world_transform, RID, bool, const Transform &) /* Light API */ @@ -247,6 +248,7 @@ public: FUNC2(light_set_negative, RID, bool) FUNC2(light_set_cull_mask, RID, uint32_t) FUNC2(light_set_reverse_cull_face_mode, RID, bool) + FUNC2(light_set_use_gi, RID, bool) FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail) @@ -359,6 +361,7 @@ public: FUNCRID(camera) FUNC4(camera_set_perspective, RID, float, float, float) FUNC4(camera_set_orthogonal, RID, float, float, float) + FUNC5(camera_set_frustum, RID, float, Vector2, float, float) FUNC2(camera_set_transform, RID, const Transform &) FUNC2(camera_set_cull_mask, RID, uint32_t) FUNC2(camera_set_environment, RID, RID) @@ -378,6 +381,7 @@ public: FUNC2(viewport_set_clear_mode, RID, ViewportClearMode) FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int) + FUNC2(viewport_set_render_direct_to_screen, RID, bool) FUNC1(viewport_detach, RID) FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) @@ -486,6 +490,8 @@ public: FUNCRID(canvas) FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &) FUNC2(canvas_set_modulate, RID, const Color &) + FUNC3(canvas_set_parent, RID, RID, float) + FUNC1(canvas_set_disable_scale, bool) FUNCRID(canvas_item) FUNC2(canvas_item_set_parent, RID, RID) @@ -515,7 +521,7 @@ public: FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) - FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID) + FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID) FUNC4(canvas_item_add_particles, RID, RID, RID, RID) FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) |