diff options
Diffstat (limited to 'servers/visual')
-rw-r--r-- | servers/visual/rasterizer.h | 31 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 79 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 25 | ||||
-rw-r--r-- | servers/visual/shader_types.cpp | 143 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 19 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.cpp | 332 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.h | 18 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 18 |
8 files changed, 575 insertions, 90 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index df41c3b5ce..c5c225a40a 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -112,6 +112,10 @@ public: SelfList<InstanceBase> dependency_item; + InstanceBase *lightmap_capture; + RID lightmap; + Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader + virtual void base_removed() = 0; virtual void base_changed() = 0; virtual void base_material_changed() = 0; @@ -126,6 +130,7 @@ public: depth_layer = 0; layer_mask = 1; baked_light = false; + lightmap_capture = NULL; } }; @@ -437,6 +442,32 @@ public: virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) = 0; virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) = 0; + /* LIGHTMAP CAPTURE */ + + struct LightmapCaptureOctree { + + enum { + CHILD_EMPTY = 0xFFFFFFFF + }; + + uint16_t light[6][3]; //anisotropic light + float alpha; + uint32_t children[8]; + }; + + virtual RID lightmap_capture_create() = 0; + virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; + virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) = 0; + virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; + virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; + virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; + virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; + virtual float lightmap_capture_get_energy(RID p_capture) const = 0; + virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const = 0; + /* PARTICLES */ virtual RID particles_create() = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index e10a57c571..c69bbb9343 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -755,12 +755,12 @@ void ShaderLanguage::clear() { } } -bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) { +bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) { if (p_builtin_types.has(p_identifier)) { if (r_data_type) { - *r_data_type = p_builtin_types[p_identifier]; + *r_data_type = p_builtin_types[p_identifier].type; } if (r_type) { *r_type = IDENTIFIER_BUILTIN_VAR; @@ -2008,7 +2008,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p return false; } -bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) { +bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) { TkPos pos = _get_tkpos(); Token tk = _get_token(); @@ -2261,7 +2261,48 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT return false; } -ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) { +bool ShaderLanguage::_is_operator_assign(Operator p_op) const { + switch (p_op) { + case OP_ASSIGN: + case OP_ASSIGN_ADD: + case OP_ASSIGN_SUB: + case OP_ASSIGN_MUL: + case OP_ASSIGN_DIV: + case OP_ASSIGN_MOD: + case OP_ASSIGN_SHIFT_LEFT: + case OP_ASSIGN_SHIFT_RIGHT: + case OP_ASSIGN_BIT_AND: + case OP_ASSIGN_BIT_OR: + case OP_ASSIGN_BIT_XOR: + return true; + default: + return false; + } + + return false; +} + +bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) { + + if (p_node->type == Node::TYPE_OPERATOR) { + + OperatorNode *op = static_cast<OperatorNode *>(p_node); + if (op->type == OP_INDEX) { + return _validate_assign(op->arguments[0], p_builtin_types); + } + } + + if (p_node->type == Node::TYPE_VARIABLE) { + + VariableNode *var = static_cast<VariableNode *>(p_node); + if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) { + return false; //ops not valid + } + } + return true; +} + +ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { Vector<Expression> expression; //Vector<TokenType> operators; @@ -2765,6 +2806,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Invalid base type for increment/decrement operator"); return NULL; } + + if (!_validate_assign(expr, p_builtin_types)) { + _set_error("Invalid use of increment/decrement operator in constant expression."); + return NULL; + } expr = op; } else { @@ -2948,6 +2994,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; + if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) { + + _set_error("Can't use increment/decrement operator in constant expression."); + return NULL; + } op->arguments.push_back(expression[i + 1].node); expression[i].is_op = false; @@ -3019,6 +3070,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_V(NULL); } + if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) { + + _set_error("Assignment to constant expression."); + return NULL; + } + if (expression[next_op + 1].is_op) { // this is not invalid and can really appear // but it becomes invalid anyway because no binary op @@ -3142,7 +3199,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha return p_node; } -ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) { +ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types); if (!expr) //errored @@ -3153,7 +3210,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_ return expr; } -Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) { +Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) { while (true) { @@ -3636,7 +3693,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct name = tk.text; - if (_find_identifier(NULL, Map<StringName, DataType>(), name)) { + if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -3660,7 +3717,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { - Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, DataType>()); + Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); if (!expr) return ERR_PARSE_ERROR; if (expr->type != Node::TYPE_CONSTANT) { @@ -3841,7 +3898,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (_find_identifier(NULL, Map<StringName, DataType>(), name)) { + if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -3852,7 +3909,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - Map<StringName, DataType> builtin_types; + Map<StringName, BuiltInInfo> builtin_types; if (p_functions.has(name)) { builtin_types = p_functions[name].built_ins; } @@ -4109,7 +4166,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) { - for (Map<StringName, DataType>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) { + for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) { matches.insert(E->key()); } } diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index e092bf931f..4cf8560990 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -537,8 +537,18 @@ public: static void get_keyword_list(List<String> *r_keywords); static void get_builtin_funcs(List<String> *r_keywords); + struct BuiltInInfo { + DataType type; + bool constant; + BuiltInInfo() {} + BuiltInInfo(DataType p_type, bool p_constant = false) { + type = p_type; + constant = p_constant; + } + }; + struct FunctionInfo { - Map<StringName, DataType> built_ins; + Map<StringName, BuiltInInfo> built_ins; bool can_discard; }; @@ -601,7 +611,10 @@ private: IDENTIFIER_BUILTIN_VAR, }; - bool _find_identifier(const BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL); + 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); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); @@ -625,14 +638,14 @@ private: static const BuiltinFuncDef builtin_func_defs[]; bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type); - bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL); + 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, DataType> &p_builtin_types); + 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, DataType> &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, DataType> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); + 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 Set<String> &p_render_modes, const Set<String> &p_shader_types); diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 7489ca7e3e..a25c5ca65e 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -45,6 +45,11 @@ const Set<String> &ShaderTypes::get_types() { ShaderTypes *ShaderTypes::singleton = NULL; +static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) { + + return ShaderLanguage::BuiltInInfo(p_type, true); +} + ShaderTypes::ShaderTypes() { singleton = this; @@ -58,32 +63,32 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = ShaderLanguage::TYPE_INT; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].can_discard = false; //builtins shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + 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["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; + 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["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT; @@ -103,33 +108,33 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SIDE"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SIDE"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].can_discard = true; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; - - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); 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; @@ -177,38 +182,38 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4; @@ -216,8 +221,8 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_SHADOW"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_vertex_transform"); @@ -237,16 +242,16 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = ShaderLanguage::TYPE_UINT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = ShaderLanguage::TYPE_INT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = ShaderLanguage::TYPE_UINT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[VS::SHADER_PARTICLES].functions["vertex"].can_discard = false; shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard"); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index d843c443a2..a0e79e9d3e 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -361,6 +361,24 @@ public: BIND2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &) BIND1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID) + /* LIGHTMAP CAPTURE */ + + BIND0R(RID, lightmap_capture_create) + + BIND2(lightmap_capture_set_bounds, RID, const AABB &) + BIND1RC(AABB, lightmap_capture_get_bounds, RID) + + BIND2(lightmap_capture_set_octree, RID, const PoolVector<uint8_t> &) + BIND1RC(PoolVector<uint8_t>, lightmap_capture_get_octree, RID) + + BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) + BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) + BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int) + BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) + + BIND2(lightmap_capture_set_energy, RID, float) + BIND1RC(float, lightmap_capture_get_energy, RID) + /* PARTICLES */ BIND0R(RID, particles_create) @@ -504,6 +522,7 @@ public: BIND3(instance_set_blend_shape_weight, RID, int, float) BIND3(instance_set_surface_material, RID, int, RID) BIND2(instance_set_visible, RID, bool) + BIND3(instance_set_use_lightmap, RID, RID, RID) BIND2(instance_set_custom_aabb, RID, AABB) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index dde69eedd3..22be2f6ff9 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -133,6 +133,19 @@ 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_LIGHTMAP_CAPTURE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + InstanceLightmapCaptureData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->lightmap_captures.push_back(B); + + List<InstanceLightmapCaptureData::PairInfo>::Element *E = lightmap_capture->geometries.push_back(pinfo); + ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + + 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)) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); @@ -193,6 +206,16 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance reflection_probe->geometries.erase(E); geom->reflection_dirty = true; + } else if (B->base_type == VS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + List<InstanceLightmapCaptureData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapCaptureData::PairInfo>::Element *>(udata); + + geom->lightmap_captures.erase(E->get().L); + lightmap_capture->geometries.erase(E); + ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { @@ -344,6 +367,14 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { reflection_probe_render_list.remove(&reflection_probe->update_list); } } break; + case VS::INSTANCE_LIGHTMAP_CAPTURE: { + + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(instance->base_data); + //erase dependencies, since no longer a lightmap + while (lightmap_capture->users.front()) { + instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID()); + } + } break; case VS::INSTANCE_GI_PROBE: { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); @@ -355,6 +386,14 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { VSG::storage->free(gi_probe->dynamic.probe_data); } + if (instance->lightmap_capture) { + Instance *capture = (Instance *)instance->lightmap_capture; + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(capture->base_data); + lightmap_capture->users.erase(instance); + instance->lightmap_capture = NULL; + instance->lightmap = RID(); + } + VSG::scene_render->free(gi_probe->probe_instance); } break; @@ -412,6 +451,12 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { reflection_probe->instance = VSG::scene_render->reflection_probe_instance_create(p_base); } break; + case VS::INSTANCE_LIGHTMAP_CAPTURE: { + + InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData); + instance->base_data = lightmap_capture; + //lightmap_capture->instance = VSG::scene_render->lightmap_capture_instance_create(p_base); + } break; case VS::INSTANCE_GI_PROBE: { InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); @@ -591,6 +636,12 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { } } break; + case VS::INSTANCE_LIGHTMAP_CAPTURE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? VS::INSTANCE_GEOMETRY_MASK : 0); + } + + } break; case VS::INSTANCE_GI_PROBE: { if (instance->octree_id && instance->scenario) { instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_GI_PROBE, p_visible ? (VS::INSTANCE_GEOMETRY_MASK | (1 << VS::INSTANCE_LIGHT)) : 0); @@ -599,11 +650,35 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { } break; } } - inline bool is_geometry_instance(VisualServer::InstanceType p_type) { return p_type == VS::INSTANCE_MESH || p_type == VS::INSTANCE_MULTIMESH || p_type == VS::INSTANCE_PARTICLES || p_type == VS::INSTANCE_IMMEDIATE; } +void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) { + + Instance *instance = instance_owner.get(p_instance); + ERR_FAIL_COND(!instance); + ERR_FAIL_COND(!is_geometry_instance(instance->base_type)); + + if (instance->lightmap_capture) { + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data); + lightmap_capture->users.erase(instance); + instance->lightmap = RID(); + instance->lightmap_capture = NULL; + } + + if (p_lightmap_instance.is_valid()) { + Instance *lightmap_instance = instance_owner.get(p_lightmap_instance); + ERR_FAIL_COND(!lightmap_instance); + ERR_FAIL_COND(lightmap_instance->base_type != VS::INSTANCE_LIGHTMAP_CAPTURE); + instance->lightmap_capture = lightmap_instance; + + InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data); + lightmap_capture->users.insert(instance); + instance->lightmap = p_lightmap; + } +} + void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { Instance *instance = instance_owner.get(p_instance); @@ -811,6 +886,15 @@ void VisualServerScene::_update_instance(Instance *p_instance) { light->shadow_dirty = true; } } + + if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) { + //affected by lightmap captures, must update capture info! + _update_instance_lightmap_captures(p_instance); + } else { + if (!p_instance->lightmap_capture_data.empty()) { + !p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data + } + } } p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; @@ -832,7 +916,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) { uint32_t pairable_mask = 0; bool pairable = false; - if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) { + if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == VS::INSTANCE_LIGHTMAP_CAPTURE) { pairable_mask = p_instance->visible ? VS::INSTANCE_GEOMETRY_MASK : 0; pairable = true; @@ -917,6 +1001,11 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base); } break; + case VisualServer::INSTANCE_LIGHTMAP_CAPTURE: { + + new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base); + + } break; default: {} } @@ -928,6 +1017,237 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { p_instance->aabb = new_aabb; } +_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) { + + static const Vector3 aniso_normal[6] = { + Vector3(-1, 0, 0), + Vector3(1, 0, 0), + Vector3(0, -1, 0), + Vector3(0, 1, 0), + Vector3(0, 0, -1), + Vector3(0, 0, 1) + }; + + int size = 1 << (p_cell_subdiv - 1); + + int clamp_v = size - 1; + //first of all, clamp + Vector3 pos; + pos.x = CLAMP(p_pos.x, 0, clamp_v); + pos.y = CLAMP(p_pos.y, 0, clamp_v); + pos.z = CLAMP(p_pos.z, 0, clamp_v); + + float level = (p_cell_subdiv - 1) - p_level; + + int target_level; + float level_filter; + if (level <= 0.0) { + level_filter = 0; + target_level = 0; + } else { + target_level = Math::ceil(level); + level_filter = target_level - level; + } + + Vector3 color[2][8]; + float alpha[2][8]; + zeromem(alpha, sizeof(float) * 2 * 8); + + //find cell at given level first + + for (int c = 0; c < 2; c++) { + + int current_level = MAX(0, target_level - c); + int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level; + + for (int n = 0; n < 8; n++) { + + int x = int(pos.x); + int y = int(pos.y); + int z = int(pos.z); + + if (n & 1) + x += level_cell_size; + if (n & 2) + y += level_cell_size; + if (n & 4) + z += level_cell_size; + + int ofs_x = 0; + int ofs_y = 0; + int ofs_z = 0; + + x = CLAMP(x, 0, clamp_v); + y = CLAMP(y, 0, clamp_v); + z = CLAMP(z, 0, clamp_v); + + int half = size / 2; + uint32_t cell = 0; + for (int i = 0; i < current_level; i++) { + + const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell]; + + int child = 0; + if (x >= ofs_x + half) { + child |= 1; + ofs_x += half; + } + if (y >= ofs_y + half) { + child |= 2; + ofs_y += half; + } + if (z >= ofs_z + half) { + child |= 4; + ofs_z += half; + } + + cell = bc->children[child]; + if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) + break; + + half >>= 1; + } + + if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) { + alpha[c][n] = 0; + } else { + alpha[c][n] = p_octree[cell].alpha; + + for (int i = 0; i < 6; i++) { + //anisotropic read light + float amount = p_dir.dot(aniso_normal[i]); + if (amount < 0) + amount = 0; + color[c][n].x += p_octree[cell].light[i][0] / 1024.0 * amount; + color[c][n].y += p_octree[cell].light[i][1] / 1024.0 * amount; + color[c][n].z += p_octree[cell].light[i][2] / 1024.0 * amount; + } + } + + //print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]); + } + } + + float target_level_size = size >> target_level; + Vector3 pos_fract[2]; + + pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size; + pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size; + pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size; + + target_level_size = size >> MAX(0, target_level - 1); + + pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size; + pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size; + pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size; + + float alpha_interp[2]; + Vector3 color_interp[2]; + + for (int i = 0; i < 2; i++) { + + Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x); + Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x); + Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y); + + Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x); + Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x); + Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y); + + color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z); + + float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x); + float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x); + float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y); + + float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x); + float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x); + float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y); + + alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z); + } + + r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter); + r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter); + + // print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha)); +} + +_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) { + + float bias = 0.0; //no need for bias here + float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length(); + + float dist = bias; + float alpha = 0.0; + Vector3 color; + + Vector3 scolor; + float salpha; + + while (dist < max_distance && alpha < 0.95) { + float diameter = MAX(1.0, 2.0 * p_aperture * dist); + _light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha); + float a = (1.0 - alpha); + color += scolor * a; + alpha += a * salpha; + dist += diameter * 0.5; + } + + return Color(color.x, color.y, color.z, alpha); +} + +void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance) { + + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + + static const Vector3 cone_traces[12] = { + Vector3(0, 0, 1), + Vector3(0.866025, 0, 0.5), + Vector3(0.267617, 0.823639, 0.5), + Vector3(-0.700629, 0.509037, 0.5), + Vector3(-0.700629, -0.509037, 0.5), + Vector3(0.267617, -0.823639, 0.5), + Vector3(0, 0, -1), + Vector3(0.866025, 0, -0.5), + Vector3(0.267617, 0.823639, -0.5), + Vector3(-0.700629, 0.509037, -0.5), + Vector3(-0.700629, -0.509037, -0.5), + Vector3(0.267617, -0.823639, -0.5) + }; + + float cone_aperture = 0.577; // tan(angle) 60 degrees + + if (p_instance->lightmap_capture_data.empty()) { + p_instance->lightmap_capture_data.resize(12); + } + + //print_line("update captures for pos: " + p_instance->transform.origin); + + zeromem(p_instance->lightmap_capture_data.ptrw(), 12 * sizeof(Color)); + //this could use some sort of blending.. + for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + const PoolVector<RasterizerStorage::LightmapCaptureOctree> *octree = VSG::storage->lightmap_capture_get_octree_ptr(E->get()->base); + //print_line("octree size: " + itos(octree->size())); + if (octree->size() == 0) + continue; + Transform to_cell_xform = VSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base); + int cell_subdiv = VSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base); + to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse(); + + PoolVector<RasterizerStorage::LightmapCaptureOctree>::Read octree_r = octree->read(); + + Vector3 pos = to_cell_xform.xform(p_instance->transform.origin); + + for (int i = 0; i < 12; i++) { + + Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized(); + Color capture = _light_capture_voxel_cone_trace(octree_r.ptr(), pos, dir, cone_aperture, cell_subdiv); + p_instance->lightmap_capture_data[i] += capture; + } + } +} + void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); @@ -2188,6 +2508,8 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co InstanceGIProbeData::LocalData *light = &local_data[idx]; Vector3 to(light->pos[0] + 0.5, light->pos[1] + 0.5, light->pos[2] + 0.5); + to += -light_axis.sign() * 0.47; //make it more likely to receive a ray + Vector3 norm( (((cells[idx].normal >> 16) & 0xFF) / 255.0) * 2.0 - 1.0, (((cells[idx].normal >> 8) & 0xFF) / 255.0) * 2.0 - 1.0, @@ -2254,6 +2576,8 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co InstanceGIProbeData::LocalData *light = &local_data[idx]; Vector3 to(light->pos[0] + 0.5, light->pos[1] + 0.5, light->pos[2] + 0.5); + to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray + Vector3 norm( (((cells[idx].normal >> 16) & 0xFF) / 255.0) * 2.0 - 1.0, (((cells[idx].normal >> 8) & 0xFF) / 255.0) * 2.0 - 1.0, @@ -2927,12 +3251,12 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) { } } + _instance_update_list.remove(&p_instance->update_item); + _update_instance(p_instance); p_instance->update_aabb = false; p_instance->update_materials = false; - - _instance_update_list.remove(&p_instance->update_item); } void VisualServerScene::update_dirty_instances() { diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 9e4701de65..4b0c4af09d 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -281,6 +281,8 @@ public: List<Instance *> gi_probes; bool gi_probes_dirty; + List<Instance *> lightmap_captures; + InstanceGeometryData() { lighting_dirty = false; @@ -445,6 +447,20 @@ public: SelfList<InstanceGIProbeData>::List gi_probe_update_list; + struct InstanceLightmapCaptureData : public InstanceBaseData { + + struct PairInfo { + List<Instance *>::Element *L; //iterator in geometry + Instance *geometry; + }; + List<PairInfo> geometries; + + Set<Instance *> users; + + InstanceLightmapCaptureData() { + } + }; + Instance *instance_cull_result[MAX_INSTANCE_CULL]; Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps Instance *light_cull_result[MAX_LIGHTS_CULLED]; @@ -466,6 +482,7 @@ public: 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); + virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap); virtual void instance_set_custom_aabb(RID p_insatnce, AABB aabb); @@ -489,6 +506,7 @@ public: _FORCE_INLINE_ void _update_instance(Instance *p_instance); _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 94f450c024..cb6f67474e 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -294,6 +294,22 @@ public: FUNC2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &) FUNC1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID) + /* LIGHTMAP CAPTURE */ + + FUNCRID(lightmap_capture) + + FUNC2(lightmap_capture_set_bounds, RID, const AABB &) + FUNC1RC(AABB, lightmap_capture_get_bounds, RID) + + FUNC2(lightmap_capture_set_octree, RID, const PoolVector<uint8_t> &) + FUNC1RC(PoolVector<uint8_t>, lightmap_capture_get_octree, RID) + FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) + FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) + FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int) + FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) + FUNC2(lightmap_capture_set_energy, RID, float) + FUNC1RC(float, lightmap_capture_get_energy, RID) + /* PARTICLES */ FUNCRID(particles) @@ -425,6 +441,8 @@ public: FUNC3(instance_set_blend_shape_weight, RID, int, float) FUNC3(instance_set_surface_material, RID, int, RID) FUNC2(instance_set_visible, RID, bool) + FUNC3(instance_set_use_lightmap, RID, RID, RID) + FUNC2(instance_set_custom_aabb, RID, AABB) FUNC2(instance_attach_skeleton, RID, RID) |