diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/arvr/arvr_positional_tracker.cpp | 14 | ||||
-rw-r--r-- | servers/arvr/arvr_positional_tracker.h | 12 | ||||
-rw-r--r-- | servers/arvr_server.cpp | 9 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_limiter.cpp | 5 | ||||
-rw-r--r-- | servers/audio_server.cpp | 3 | ||||
-rw-r--r-- | servers/physics/broad_phase_basic.cpp | 3 | ||||
-rw-r--r-- | servers/physics/collision_object_sw.cpp | 32 | ||||
-rw-r--r-- | servers/physics/collision_object_sw.h | 2 | ||||
-rw-r--r-- | servers/physics/physics_server_sw.cpp | 21 | ||||
-rw-r--r-- | servers/physics/physics_server_sw.h | 4 | ||||
-rw-r--r-- | servers/physics/shape_sw.cpp | 3 | ||||
-rw-r--r-- | servers/physics/step_sw.cpp | 2 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 2 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 135 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 22 | ||||
-rw-r--r-- | servers/visual/shader_types.cpp | 3 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 1 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.cpp | 104 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 1 | ||||
-rw-r--r-- | servers/visual_server.cpp | 23 | ||||
-rw-r--r-- | servers/visual_server.h | 10 |
21 files changed, 341 insertions, 70 deletions
diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp index 539bac6703..4ecd7a3898 100644 --- a/servers/arvr/arvr_positional_tracker.cpp +++ b/servers/arvr/arvr_positional_tracker.cpp @@ -31,6 +31,10 @@ #include "core/os/input.h" void ARVRPositionalTracker::_bind_methods() { + BIND_ENUM_CONSTANT(TRACKER_HAND_UNKNOWN); + BIND_ENUM_CONSTANT(TRACKER_LEFT_HAND); + BIND_ENUM_CONSTANT(TRACKER_RIGHT_HAND); + // this class is read only from GDScript, so we only have access to getters.. ClassDB::bind_method(D_METHOD("get_type"), &ARVRPositionalTracker::get_type); ClassDB::bind_method(D_METHOD("get_name"), &ARVRPositionalTracker::get_name); @@ -39,6 +43,7 @@ void ARVRPositionalTracker::_bind_methods() { ClassDB::bind_method(D_METHOD("get_orientation"), &ARVRPositionalTracker::get_orientation); ClassDB::bind_method(D_METHOD("get_tracks_position"), &ARVRPositionalTracker::get_tracks_position); ClassDB::bind_method(D_METHOD("get_position"), &ARVRPositionalTracker::get_position); + ClassDB::bind_method(D_METHOD("get_hand"), &ARVRPositionalTracker::get_hand); ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &ARVRPositionalTracker::get_transform); // these functions we don't want to expose to normal users but do need to be callable from GDNative @@ -141,6 +146,14 @@ Vector3 ARVRPositionalTracker::get_rw_position() const { return rw_position; }; +ARVRPositionalTracker::TrackerHand ARVRPositionalTracker::get_hand() const { + return hand; +}; + +void ARVRPositionalTracker::set_hand(const ARVRPositionalTracker::TrackerHand p_hand) { + hand = p_hand; +}; + Transform ARVRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const { Transform new_transform; @@ -164,6 +177,7 @@ ARVRPositionalTracker::ARVRPositionalTracker() { tracker_id = 0; tracks_orientation = false; tracks_position = false; + hand = TRACKER_HAND_UNKNOWN; }; ARVRPositionalTracker::~ARVRPositionalTracker(){ diff --git a/servers/arvr/arvr_positional_tracker.h b/servers/arvr/arvr_positional_tracker.h index f91f862ba3..ff0c150f89 100644 --- a/servers/arvr/arvr_positional_tracker.h +++ b/servers/arvr/arvr_positional_tracker.h @@ -48,6 +48,13 @@ class ARVRPositionalTracker : public Object { GDCLASS(ARVRPositionalTracker, Object); _THREAD_SAFE_CLASS_ +public: + enum TrackerHand { + TRACKER_HAND_UNKNOWN, /* unknown or not applicable */ + TRACKER_LEFT_HAND, /* controller is the left hand controller */ + TRACKER_RIGHT_HAND /* controller is the right hand controller */ + }; + private: ARVRServer::TrackerType type; // type of tracker StringName name; // (unique) name of the tracker @@ -57,6 +64,7 @@ private: Basis orientation; // our orientation bool tracks_position; // do we track position? Vector3 rw_position; // our position "in the real world, so without world_scale applied" + TrackerHand hand; // if known, the hand this tracker is held in protected: static void _bind_methods(); @@ -77,6 +85,8 @@ public: Vector3 get_position() const; // get position with world_scale applied void set_rw_position(const Vector3 &p_rw_position); Vector3 get_rw_position() const; + ARVRPositionalTracker::TrackerHand get_hand() const; + void set_hand(const ARVRPositionalTracker::TrackerHand p_hand); Transform get_transform(bool p_adjust_by_reference_frame) const; @@ -84,4 +94,6 @@ public: ~ARVRPositionalTracker(); }; +VARIANT_ENUM_CAST(ARVRPositionalTracker::TrackerHand); + #endif diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index bac24f6438..5d8cf20c92 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -68,8 +68,8 @@ void ARVRServer::_bind_methods() { ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING, "name"))); ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING, "name"))); - ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"))); - ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); }; real_t ARVRServer::get_world_scale() const { @@ -130,7 +130,6 @@ void ARVRServer::request_reference_frame(bool p_ignore_tilt, bool p_keep_height) void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) { ERR_FAIL_COND(p_interface.is_null()); - int idx = -1; for (int i = 0; i < interfaces.size(); i++) { if (interfaces[i] == p_interface) { @@ -232,7 +231,7 @@ void ARVRServer::add_tracker(ARVRPositionalTracker *p_tracker) { ERR_FAIL_NULL(p_tracker); trackers.push_back(p_tracker); - emit_signal("tracker_added", p_tracker->get_name(), p_tracker->get_type()); + emit_signal("tracker_added", p_tracker->get_name(), p_tracker->get_type(), p_tracker->get_tracker_id()); }; void ARVRServer::remove_tracker(ARVRPositionalTracker *p_tracker) { @@ -250,7 +249,7 @@ void ARVRServer::remove_tracker(ARVRPositionalTracker *p_tracker) { ERR_FAIL_COND(idx == -1); - emit_signal("tracker_removed", p_tracker->get_name()); + emit_signal("tracker_removed", p_tracker->get_name(), p_tracker->get_type(), p_tracker->get_tracker_id()); trackers.remove(idx); }; diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp index 391e5db639..9787ba8109 100644 --- a/servers/audio/effects/audio_effect_limiter.cpp +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -31,18 +31,13 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { - float thresh = Math::db2linear(base->threshold); float threshdb = base->threshold; float ceiling = Math::db2linear(base->ceiling); float ceildb = base->ceiling; float makeup = Math::db2linear(ceildb - threshdb); - float makeupdb = ceildb - threshdb; float sc = -base->soft_clip; float scv = Math::db2linear(sc); - float sccomp = Math::db2linear(-sc); float peakdb = ceildb + 25; - float peaklvl = Math::db2linear(peakdb); - float scratio = base->soft_clip_ratio; float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); for (int i = 0; i < p_frame_count; i++) { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 3139c6bb7a..29014a7ced 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -203,8 +203,9 @@ void AudioServer::_mix_step() { if (!bus_map.has(bus->send)) { bus = buses[0]; //send to master } else { + int prev_index_cache = bus->index_cache; bus = bus_map[bus->send]; - if (bus->index_cache >= bus->index_cache) { //invalid, send to master + if (prev_index_cache >= bus->index_cache) { //invalid, send to master bus = buses[0]; } } diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp index 959718a252..c6565ac2e9 100644 --- a/servers/physics/broad_phase_basic.cpp +++ b/servers/physics/broad_phase_basic.cpp @@ -30,9 +30,10 @@ #include "broad_phase_basic.h" #include "list.h" #include "print_string.h" + BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object, int p_subindex) { - ERR_FAIL_COND_V(p_object == NULL, NULL); + ERR_FAIL_COND_V(p_object == NULL, 0); current++; diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index ab716a8f6e..3af8b542fa 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "collision_object_sw.h" +#include "servers/physics/physics_server_sw.h" #include "space_sw.h" void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform) { @@ -39,8 +40,12 @@ void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform s.bpid = 0; //needs update shapes.push_back(s); p_shape->add_owner(this); - _update_shapes(); - _shapes_changed(); + + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) { @@ -50,8 +55,11 @@ void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) { shapes[p_index].shape = p_shape; p_shape->add_owner(this); - _update_shapes(); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_transform) { @@ -59,8 +67,11 @@ void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_tran shapes[p_index].xform = p_transform; shapes[p_index].xform_inv = p_transform.affine_inverse(); - _update_shapes(); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::remove_shape(ShapeSW *p_shape) { @@ -90,7 +101,11 @@ void CollisionObjectSW::remove_shape(int p_index) { shapes[p_index].shape->remove_owner(this); shapes.remove(p_index); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::_set_static(bool p_static) { @@ -202,7 +217,8 @@ void CollisionObjectSW::_shape_changed() { _shapes_changed(); } -CollisionObjectSW::CollisionObjectSW(Type p_type) { +CollisionObjectSW::CollisionObjectSW(Type p_type) + : pending_shape_update_list(this) { _static = true; type = p_type; diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index dc988aae86..67a8a44944 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -75,6 +75,8 @@ private: Transform inv_transform; bool _static; + SelfList<CollisionObjectSW> pending_shape_update_list; + void _update_shapes(); protected: diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 8d6f7b3fd8..2d46770924 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -763,6 +763,8 @@ void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + body->apply_impulse(p_pos, p_impulse); body->wakeup(); }; @@ -772,6 +774,8 @@ void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_imp BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + body->apply_torque_impulse(p_impulse); body->wakeup(); }; @@ -781,6 +785,8 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_v BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + Vector3 v = body->get_linear_velocity(); Vector3 axis = p_axis_velocity.normalized(); v -= axis * axis.dot(v); @@ -793,6 +799,7 @@ void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxisLock p_lock) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + body->set_axis_lock(p_lock); body->wakeup(); } @@ -902,6 +909,8 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons ERR_FAIL_COND_V(!body->get_space(), false); ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + _update_shapes(); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result); } @@ -1209,6 +1218,8 @@ bool PhysicsServerSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_a void PhysicsServerSW::free(RID p_rid) { + _update_shapes(); //just in case + if (shape_owner.owns(p_rid)) { ShapeSW *shape = shape_owner.get(p_rid); @@ -1312,6 +1323,8 @@ void PhysicsServerSW::step(real_t p_step) { if (!active) return; + _update_shapes(); + doing_sync = false; last_step = p_step; @@ -1409,6 +1422,14 @@ int PhysicsServerSW::get_process_info(ProcessInfo p_info) { return 0; } +void PhysicsServerSW::_update_shapes() { + + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + void PhysicsServerSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { CollCbkData *cbk = (CollCbkData *)p_userdata; diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 2e1fa7065a..99ba302acd 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -62,6 +62,10 @@ class PhysicsServerSW : public PhysicsServer { mutable RID_Owner<JointSW> joint_owner; //void _clear_query(QuerySW *p_query); + friend class CollisionObjectSW; + SelfList<CollisionObjectSW>::List pending_shape_update_list; + void _update_shapes(); + public: static PhysicsServerSW *singleton; diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index 1845188089..80eeff93d0 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -954,6 +954,9 @@ Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { void ConvexPolygonShapeSW::_setup(const Vector<Vector3> &p_vertices) { Error err = QuickHull::build(p_vertices, mesh); + if (err != OK) + ERR_PRINT("Failed to build QuickHull"); + Rect3 _aabb; for (int i = 0; i < mesh.vertices.size(); i++) { diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp index 79a55e0af1..76b097dda6 100644 --- a/servers/physics/step_sw.cpp +++ b/servers/physics/step_sw.cpp @@ -62,7 +62,7 @@ void StepSW::_setup_island(ConstraintSW *p_island, real_t p_delta) { ConstraintSW *ci = p_island; while (ci) { - bool process = ci->setup(p_delta); + ci->setup(p_delta); //todo remove from island if process fails ci = ci->get_island_next(); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 187a0b180b..344c10089a 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -335,6 +335,8 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; virtual bool light_directional_get_blend_splits(RID p_light) const = 0; + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 0684cb1701..6ad433268f 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -79,7 +79,11 @@ String ShaderLanguage::get_operator_text(Operator p_op) { "|", "^", "~", - "++" + "++", + "--", + "?", + ":", + "++", "--", "()", "construct", @@ -2996,8 +3000,6 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha if (op->op == OP_CONSTRUCT) { ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node); - VariableNode *vn = static_cast<VariableNode *>(op->arguments[0]); - //StringName name=vn->name; DataType base = get_scalar_type(op->get_datatype()); @@ -3116,6 +3118,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat tk = _get_token(); + VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>(); + vardecl->datatype = type; + vardecl->precision = precision; + + p_block->statements.push_back(vardecl); + while (true) { if (tk.type != TK_IDENTIFIER) { @@ -3133,8 +3141,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat var.type = type; var.precision = precision; var.line = tk_line; + p_block->variables[name] = var; + VariableDeclarationNode::Declaration decl; + + decl.name = name; + decl.initializer = NULL; + tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { @@ -3143,22 +3157,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat if (!n) return ERR_PARSE_ERROR; - OperatorNode *assign = alloc_node<OperatorNode>(); - VariableNode *vnode = alloc_node<VariableNode>(); - vnode->name = name; - vnode->datatype_cache = type; - assign->arguments.push_back(vnode); - assign->arguments.push_back(n); - assign->op = OP_ASSIGN; - p_block->statements.push_back(assign); - tk = _get_token(); + decl.initializer = n; - if (!_validate_operator(assign)) { - _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'"); + if (var.type != n->get_datatype()) { + _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'"); return ERR_PARSE_ERROR; } + tk = _get_token(); } + vardecl->declarations.push_back(decl); + if (tk.type == TK_COMMA) { tk = _get_token(); //another variable @@ -3221,7 +3230,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat //if () {} tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after if"); + _set_error("Expected '(' after while"); return ERR_PARSE_ERROR; } @@ -3243,7 +3252,63 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + Error err = _parse_block(block, p_builtin_types, true, true, true); + if (err) + return err; + } else if (tk.type == TK_CF_FOR) { + //if () {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after for"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_FOR; + + BlockNode *init_block = alloc_node<BlockNode>(); + init_block->parent_block = p_block; + init_block->single_statement = true; + cf->blocks.push_back(init_block); + if (_parse_block(init_block, p_builtin_types, true, false, false) != OK) { + return ERR_PARSE_ERROR; + } + + Node *n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + if (n->get_datatype() != TYPE_BOOL) { + _set_error("Middle expression is expected to be boolean."); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after middle expression"); + return ERR_PARSE_ERROR; + } + + cf->expressions.push_back(n); + + n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + cf->expressions.push_back(n); + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after third expression"); + return ERR_PARSE_ERROR; + } + + BlockNode *block = alloc_node<BlockNode>(); + block->parent_block = p_block; + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + Error err = _parse_block(block, p_builtin_types, true, true, true); if (err) return err; @@ -3320,6 +3385,42 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat } p_block->statements.push_back(flow); + } else if (tk.type == TK_CF_BREAK) { + + if (!p_can_break) { + //all is good + _set_error("Breaking is not allowed here"); + } + + ControlFlowNode *flow = alloc_node<ControlFlowNode>(); + flow->flow_op = FLOW_OP_BREAK; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after break"); + } + + p_block->statements.push_back(flow); + } else if (tk.type == TK_CF_CONTINUE) { + + if (!p_can_break) { + //all is good + _set_error("Contiuning is not allowed here"); + } + + ControlFlowNode *flow = alloc_node<ControlFlowNode>(); + flow->flow_op = FLOW_OP_CONTINUE; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after continue"); + } + + p_block->statements.push_back(flow); } else { @@ -3872,6 +3973,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct shader = alloc_node<ShaderNode>(); Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); + if (err != OK) + ERR_PRINT("Failed to parse shader"); switch (completion_type) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index f00b4c5a97..50f5cebeaa 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -266,6 +266,7 @@ public: TYPE_FUNCTION, TYPE_BLOCK, TYPE_VARIABLE, + TYPE_VARIABLE_DECLARATION, TYPE_CONSTANT, TYPE_OPERATOR, TYPE_CONTROL_FLOW, @@ -315,6 +316,25 @@ public: } }; + struct VariableDeclarationNode : public Node { + + DataPrecision precision; + DataType datatype; + + struct Declaration { + + StringName name; + Node *initializer; + }; + + Vector<Declaration> declarations; + virtual DataType get_datatype() const { return datatype; } + + VariableDeclarationNode() { + type = TYPE_VARIABLE_DECLARATION; + } + }; + struct ConstantNode : public Node { DataType datatype; @@ -346,10 +366,12 @@ public: Map<StringName, Variable> variables; List<Node *> statements; + bool single_statement; BlockNode() { type = TYPE_BLOCK; parent_block = NULL; parent_function = NULL; + single_statement=false; } }; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index ef0d063f83..91c5d430f5 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -102,6 +102,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; @@ -137,7 +138,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_half_lambert"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert_wrap"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_oren_nayar"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_burley"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_toon"); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 3953bc5f48..7c7ce46268 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -795,6 +795,7 @@ public: BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) BIND2(light_directional_set_blend_splits, RID, bool) + BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 0d70b7fc0e..9fb4dc524d 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -101,7 +101,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance SWAP(A, B); //lesser always first } - if (B->base_type == VS::INSTANCE_LIGHT && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -119,7 +119,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance geom->lighting_dirty = true; return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -133,7 +133,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance geom->reflection_dirty = true; return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_GI_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -151,8 +151,6 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceLightData *light = static_cast<InstanceLightData *>(A->base_data); - return gi_probe->lights.insert(A); } @@ -169,7 +167,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance SWAP(A, B); //lesser always first } - if (B->base_type == VS::INSTANCE_LIGHT && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -184,7 +182,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance } geom->lighting_dirty = true; - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -196,7 +194,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance geom->reflection_dirty = true; - } else if (B->base_type == VS::INSTANCE_GI_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -211,8 +209,6 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceLightData *light = static_cast<InstanceLightData *>(A->base_data); - Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata); gi_probe->lights.erase(E); @@ -886,12 +882,53 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons float max_distance = p_cam_projection.get_z_far(); float shadow_max = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); - if (shadow_max > 0) { + if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera max_distance = MIN(shadow_max, max_distance); } max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); + float min_distance = MIN(p_cam_projection.get_z_near(), max_distance); + + VS::LightDirectionalShadowDepthRangeMode depth_range_mode = VSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); + + if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) { + //optimize min/max + Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); + Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2)); + //check distance max and min + + bool found_items = false; + float z_max = -1e20; + float z_min = 1e20; + + for (int i = 0; i < cull_count; i++) { + + Instance *instance = instance_shadow_cull_result[i]; + if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + continue; + } + + float max, min; + instance->transformed_aabb.project_range_in_plane(base, min, max); + + if (max > z_max) { + z_max = max; + } + + if (min < z_min) { + z_min = min; + } - float range = max_distance - p_cam_projection.get_z_near(); + found_items = true; + } + + if (found_items) { + min_distance = MAX(min_distance, z_min); + max_distance = MIN(max_distance, z_max); + } + } + + float range = max_distance - min_distance; int splits = 0; switch (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) { @@ -902,9 +939,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons float distances[5]; - distances[0] = p_cam_projection.get_z_near(); + distances[0] = min_distance; for (int i = 0; i < splits; i++) { - distances[i + 1] = p_cam_projection.get_z_near() + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; + distances[i + 1] = min_distance + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; }; distances[splits] = max_distance; @@ -984,8 +1021,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons { //camera viewport stuff - //this trick here is what stabilizes the shadow (make potential jaggies to not move) - //at the cost of some wasted resolution. Still the quality increase is very well worth it Vector3 center; @@ -1006,7 +1041,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons radius = d; } - radius *= texture_size / (texture_size - 2.0); //add a texel by each side, so stepified texture will always fit + radius *= texture_size / (texture_size - 2.0); //add a texel by each side if (i == 0) { first_radius = radius; @@ -1021,12 +1056,17 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons z_max_cam = z_vec.dot(center) + radius; z_min_cam = z_vec.dot(center) - radius; - float unit = radius * 2.0 / texture_size; + if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + float unit = radius * 2.0 / texture_size; - x_max_cam = Math::stepify(x_max_cam, unit); - x_min_cam = Math::stepify(x_min_cam, unit); - y_max_cam = Math::stepify(y_max_cam, unit); - y_min_cam = Math::stepify(y_min_cam, unit); + x_max_cam = Math::stepify(x_max_cam, unit); + x_min_cam = Math::stepify(x_min_cam, unit); + y_max_cam = Math::stepify(y_max_cam, unit); + y_min_cam = Math::stepify(y_min_cam, unit); + } } //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree @@ -1069,6 +1109,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } { + CameraMatrix ortho_camera; real_t half_x = (x_max_cam - x_min_cam) * 0.5; real_t half_y = (y_max_cam - y_min_cam) * 0.5; @@ -1375,7 +1416,7 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam gi_probe_update_list.add(&gi_probe->update_element); } - } else if ((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + } else if (((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { keep = true; @@ -2085,7 +2126,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co int success_count = 0; - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); for (int i = 0; i < p_leaf_count; i++) { @@ -2138,14 +2179,15 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co success_count++; } } - //print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - //print_line("valid cells: " + itos(success_count)); + + // print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); + // print_line("valid cells: " + itos(success_count)); } break; case VS::LIGHT_OMNI: case VS::LIGHT_SPOT: { - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); Vector3 light_pos = light_cache.transform.origin; Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); @@ -2244,8 +2286,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0); } } - //print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - + // print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); } break; } } @@ -2657,18 +2698,17 @@ void VisualServerScene::render_probes() { } break; case GI_UPDATE_STAGE_UPLOADING: { - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); for (int i = 0; i < (int)probe->dynamic.mipmaps_3d.size(); i++) { - int mmsize = probe->dynamic.mipmaps_3d[i].size(); PoolVector<uint8_t>::Read r = probe->dynamic.mipmaps_3d[i].read(); VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data, 0, probe->dynamic.grid_size[2] >> i, i, r.ptr()); } probe->dynamic.updating_stage = GI_UPDATE_STAGE_CHECK; - //print_line("UPLOAD TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + // print_line("UPLOAD TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); } break; } } diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index f24049be92..5cf941b93d 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -233,6 +233,7 @@ public: FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) FUNC2(light_directional_set_blend_splits, RID, bool) + FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 67b847d127..47a5f4c7f3 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1420,6 +1420,29 @@ Array VisualServer::mesh_surface_get_arrays(RID p_mesh, int p_surface) const { return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len); } +Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { + + Vector<PoolVector<uint8_t> > blend_shape_data = mesh_surface_get_blend_shapes(p_mesh, p_surface); + if (blend_shape_data.size() > 0) { + int vertex_len = mesh_surface_get_array_len(p_mesh, p_surface); + + PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh, p_surface); + int index_len = mesh_surface_get_array_index_len(p_mesh, p_surface); + + uint32_t format = mesh_surface_get_format(p_mesh, p_surface); + + Array blend_shape_array; + blend_shape_array.resize(blend_shape_data.size()); + for (int i = 0; i < blend_shape_data.size(); i++) { + blend_shape_array.set(i, _get_array_from_surface(format, blend_shape_data[i], vertex_len, index_data, index_len)); + } + + return blend_shape_array; + } else { + return Array(); + } +} + void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("force_draw"), &VisualServer::draw); diff --git a/servers/visual_server.h b/servers/visual_server.h index d516013ee2..72f36f6b65 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -267,6 +267,7 @@ public: virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const = 0; virtual Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const; + virtual Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0; virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0; @@ -406,6 +407,14 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + enum LightDirectionalShadowDepthRangeMode { + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, + + }; + + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + /* PROBE API */ virtual RID reflection_probe_create() = 0; @@ -620,6 +629,7 @@ public: ENV_BG_CLEAR_COLOR, ENV_BG_COLOR, ENV_BG_SKY, + ENV_BG_COLOR_SKY, ENV_BG_CANVAS, ENV_BG_KEEP, ENV_BG_MAX |