diff options
23 files changed, 315 insertions, 136 deletions
diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index d6da4bc248..249e2a8f80 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -86,6 +86,7 @@ [/codeblocks] Keep in mind that section and property names can't contain spaces. Anything after a space will be ignored on save and on load. ConfigFiles can also contain manually written comment lines starting with a semicolon ([code];[/code]). Those lines will be ignored when parsing the file. Note that comments will be lost when saving the ConfigFile. This can still be useful for dedicated server configuration files, which are typically never overwritten without explicit user action. + [b]Note:[/b] The file extension given to a ConfigFile does not have any impact on its formatting or behavior. By convention, the [code].cfg[/code] extension is used here, but any other extension such as [code].ini[/code] is also valid. Since neither [code].cfg[/code] nor [code].ini[/code] are standardized, Godot's ConfigFile formatting may differ from files written by other programs. </description> <tutorials> </tutorials> diff --git a/doc/classes/EditorSceneImporterMesh.xml b/doc/classes/EditorSceneImporterMesh.xml index b0f233da2f..c0c53ff255 100644 --- a/doc/classes/EditorSceneImporterMesh.xml +++ b/doc/classes/EditorSceneImporterMesh.xml @@ -27,6 +27,7 @@ }" /> <argument index="4" name="material" type="Material" default="null" /> <argument index="5" name="name" type="String" default="""" /> + <argument index="6" name="flags" type="int" default="0" /> <description> Creates a new surface, analogous to [method ArrayMesh.add_surface_from_arrays]. Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface. @@ -94,6 +95,13 @@ Returns the amount of surfaces that the mesh holds. </description> </method> + <method name="get_surface_format" qualifiers="const"> + <return type="int" /> + <argument index="0" name="surface_idx" type="int" /> + <description> + Returns the format of the surface that the mesh holds. + </description> + </method> <method name="get_surface_lod_count" qualifiers="const"> <return type="int" /> <argument index="0" name="surface_idx" type="int" /> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index 8b399f64c9..36590093bd 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -37,7 +37,7 @@ <method name="get_frames_drawn"> <return type="int" /> <description> - Returns the total number of frames drawn. If the render loop is disabled with [code]--disable-render-loop[/code] via command line, this returns [code]0[/code]. See also [method get_process_frames]. + Returns the total number of frames drawn. On headless platforms, or if the render loop is disabled with [code]--disable-render-loop[/code] via command line, [method get_frames_drawn] always returns [code]0[/code]. See [method get_process_frames]. </description> </method> <method name="get_frames_per_second" qualifiers="const"> @@ -67,7 +67,13 @@ <method name="get_physics_frames" qualifiers="const"> <return type="int" /> <description> - Returns the total number of frames passed since engine initialization which is advanced on each [b]physics frame[/b]. + Returns the total number of frames passed since engine initialization which is advanced on each [b]physics frame[/b]. See also [method get_process_frames]. + [method get_physics_frames] can be used to run expensive logic less often without relying on a [Timer]: + [codeblock] + func _physics_process(_delta): + if Engine.get_physics_frames() % 2 == 0: + pass # Run expensive logic only once every 2 physics frames here. + [/codeblock] </description> </method> <method name="get_physics_interpolation_fraction" qualifiers="const"> @@ -79,7 +85,13 @@ <method name="get_process_frames" qualifiers="const"> <return type="int" /> <description> - Returns the total number of frames passed since engine initialization which is advanced on each [b]process frame[/b], regardless of whether the render loop is enabled. See also [method get_frames_drawn]. + Returns the total number of frames passed since engine initialization which is advanced on each [b]process frame[/b], regardless of whether the render loop is enabled. See also [method get_frames_drawn] and [method get_physics_frames]. + [method get_process_frames] can be used to run expensive logic less often without relying on a [Timer]: + [codeblock] + func _process(_delta): + if Engine.get_process_frames() % 2 == 0: + pass # Run expensive logic only once every 2 process (render) frames here. + [/codeblock] </description> </method> <method name="get_singleton" qualifiers="const"> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index bfa55c2d35..c774528a39 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -210,6 +210,8 @@ </constant> <constant name="ARRAY_FORMAT_CUSTOM_BASE" value="13" enum="ArrayFormat"> </constant> + <constant name="ARRAY_FORMAT_CUSTOM_BITS" value="3" enum="ArrayFormat"> + </constant> <constant name="ARRAY_FORMAT_CUSTOM0_SHIFT" value="13" enum="ArrayFormat"> </constant> <constant name="ARRAY_FORMAT_CUSTOM1_SHIFT" value="16" enum="ArrayFormat"> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index c9e9a0699c..ed045f8390 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -92,12 +92,12 @@ Calls the [code]method[/code] on the object and returns the result. This method supports a variable number of arguments, so parameters are passed as a comma separated list. Example: [codeblocks] [gdscript] - var node = Node2D.new() - node.call("set", "position", Vector2(42, 0)) + var node = Node3D.new() + node.call("rotate", Vector3(1.0, 0.0, 0.0), 1.571) [/gdscript] [csharp] - var node = new Node2D(); - node.Call("set", "position", new Vector2(42, 0)); + var node = new Node3D(); + node.Call("rotate", new Vector3(1f, 0f, 0f), 1.571f); [/csharp] [/codeblocks] [b]Note:[/b] In C#, the method name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined methods where you should use the same convention as in the C# source (typically PascalCase). @@ -110,12 +110,12 @@ Calls the [code]method[/code] on the object during idle time. This method supports a variable number of arguments, so parameters are passed as a comma separated list. Example: [codeblocks] [gdscript] - var node = Node2D.new() - node.call_deferred("set", "position", Vector2(42, 0)) + var node = Node3D.new() + node.call_deferred("rotate", Vector3(1.0, 0.0, 0.0), 1.571) [/gdscript] [csharp] - var node = new Node2D(); - node.CallDeferred("set", "position", new Vector2(42, 0)); + var node = new Node3D(); + node.CallDeferred("rotate", new Vector3(1f, 0f, 0f), 1.571f); [/csharp] [/codeblocks] [b]Note:[/b] In C#, the method name must be specified as snake_case if it is defined by a built-in Godot node. This doesn't apply to user-defined methods where you should use the same convention as in the C# source (typically PascalCase). @@ -129,12 +129,12 @@ Calls the [code]method[/code] on the object and returns the result. Contrarily to [method call], this method does not support a variable number of arguments but expects all parameters to be via a single [Array]. [codeblocks] [gdscript] - var node = Node2D.new() - node.callv("set", ["position", Vector2(42, 0)]) + var node = Node3D.new() + node.callv("rotate", [Vector3(1.0, 0.0, 0.0), 1.571]) [/gdscript] [csharp] - var node = new Node2D(); - node.Callv("set", new Godot.Collections.Array { "position", new Vector2(42, 0) }); + var node = new Node3D(); + node.Callv("rotate", new Godot.Collections.Array { new Vector3(1f, 0f, 0f), 1.571f }); [/csharp] [/codeblocks] </description> @@ -331,7 +331,8 @@ <method name="get_class" qualifiers="const"> <return type="String" /> <description> - Returns the object's class as a [String]. + Returns the object's class as a [String]. See also [method is_class]. + [b]Note:[/b] [method get_class] does not take [code]class_name[/code] declarations into account. If the object has a [code]class_name[/code] defined, the base class name will be returned instead. </description> </method> <method name="get_incoming_connections" qualifiers="const"> @@ -441,7 +442,8 @@ <return type="bool" /> <argument index="0" name="class" type="String" /> <description> - Returns [code]true[/code] if the object inherits from the given [code]class[/code]. + Returns [code]true[/code] if the object inherits from the given [code]class[/code]. See also [method get_class]. + [b]Note:[/b] [method is_class] does not take [code]class_name[/code] declarations into account. If the object has a [code]class_name[/code] defined, [method is_class] will return [code]false[/code] for that name. </description> </method> <method name="is_connected" qualifiers="const"> diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 38ec79c45f..cf0b725cfc 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -813,7 +813,7 @@ class RenderingDeviceVulkan : public RenderingDevice { // When using split command lists, this is // implemented internally using secondary command // buffers. As they can be created in threads, - // each needs it's own command pool. + // each needs its own command pool. struct SplitDrawListAllocator { VkCommandPool command_pool = VK_NULL_HANDLE; diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index 06f373c54f..d8248e2670 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -33,6 +33,8 @@ #include "core/math/math_defs.h" #include "scene/resources/surface_tool.h" +#include <cstdint> + void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { ERR_FAIL_COND(surfaces.size() > 0); blend_shapes.push_back(p_name); @@ -55,13 +57,14 @@ Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { return blend_shape_mode; } -void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) { +void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) { ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); Surface s; s.primitive = p_primitive; s.arrays = p_arrays; s.name = p_name; + s.flags = p_flags; Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX]; int vertex_count = vertex_array.size(); @@ -138,6 +141,11 @@ float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) co return surfaces[p_surface].lods[p_lod].distance; } +uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); + return surfaces[p_surface].flags; +} + Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); return surfaces[p_surface].material; @@ -283,7 +291,7 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) { } } - mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods); + mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods, surfaces[i].flags); if (surfaces[i].material.is_valid()) { mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material); } @@ -398,7 +406,7 @@ void EditorSceneImporterMesh::create_shadow_mesh() { } } - shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name); + shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name, surfaces[i].flags); } } @@ -436,7 +444,11 @@ void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { if (s.has("material")) { material = s["material"]; } - add_surface(prim, arr, blend_shapes, lods, material, name); + uint32_t flags = 0; + if (s.has("flags")) { + flags = s["flags"]; + } + add_surface(prim, arr, blend_shapes, lods, material, name, flags); } } } @@ -473,6 +485,10 @@ Dictionary EditorSceneImporterMesh::_get_data() const { d["name"] = surfaces[i].name; } + if (surfaces[i].flags != 0) { + d["flags"] = surfaces[i].flags; + } + surface_arr.push_back(d); } data["surfaces"] = surface_arr; @@ -833,7 +849,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); @@ -844,6 +860,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format); ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material); diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h index e57e479d8e..c8e25244fa 100644 --- a/editor/import/scene_importer_mesh.h +++ b/editor/import/scene_importer_mesh.h @@ -36,6 +36,9 @@ #include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/navigation_mesh.h" + +#include <cstdint> + // The following classes are used by importers instead of ArrayMesh and MeshInstance3D // so the data is not registered (hence, quality loss), importing happens faster and // its easier to modify before saving @@ -57,6 +60,7 @@ class EditorSceneImporterMesh : public Resource { Vector<LOD> lods; Ref<Material> material; String name; + uint32_t flags = 0; }; Vector<Surface> surfaces; Vector<String> blend_shapes; @@ -80,7 +84,7 @@ public: int get_blend_shape_count() const; String get_blend_shape_name(int p_blend_shape) const; - void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String()); + void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String(), const uint32_t p_flags = 0); int get_surface_count() const; void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode); @@ -95,6 +99,7 @@ public: Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const; float get_surface_lod_size(int p_surface, int p_lod) const; Ref<Material> get_surface_material(int p_surface) const; + uint32_t get_surface_format(int p_surface) const; void set_surface_material(int p_surface, const Ref<Material> &p_material); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index d307bda85c..db324e23b7 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -48,6 +48,7 @@ #include "core/io/file_access.h" #include "core/io/json.h" #include "core/math/disjoint_set.h" +#include "core/math/vector2.h" #include "core/variant/typed_array.h" #include "core/variant/variant.h" #include "core/version.h" @@ -61,7 +62,7 @@ #include "scene/resources/surface_tool.h" #include "modules/modules_enabled.gen.h" -#include <cstdint> + #ifdef MODULE_CSG_ENABLED #include "modules/csg/csg_shape.h" #endif // MODULE_CSG_ENABLED @@ -71,6 +72,7 @@ #include <stdio.h> #include <stdlib.h> +#include <cstdint> #include <limits> Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) { @@ -2171,11 +2173,14 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } Array array = import_mesh->get_surface_arrays(surface_i); + uint32_t format = import_mesh->get_surface_format(surface_i); + int32_t vertex_num = 0; Dictionary attributes; { Vector<Vector3> a = array[Mesh::ARRAY_VERTEX]; ERR_FAIL_COND_V(!a.size(), ERR_INVALID_DATA); attributes["POSITION"] = _encode_accessor_as_vec3(state, a, true); + vertex_num = a.size(); } { Vector<real_t> a = array[Mesh::ARRAY_TANGENT]; @@ -2218,6 +2223,58 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true); } } + for (int custom_i = 0; custom_i < 3; custom_i++) { + Vector<float> a = array[Mesh::ARRAY_CUSTOM0 + custom_i]; + if (a.size()) { + int num_channels = 4; + int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS; + switch ((format >> custom_shift) & Mesh::ARRAY_FORMAT_CUSTOM_MASK) { + case Mesh::ARRAY_CUSTOM_R_FLOAT: + num_channels = 1; + break; + case Mesh::ARRAY_CUSTOM_RG_FLOAT: + num_channels = 2; + break; + case Mesh::ARRAY_CUSTOM_RGB_FLOAT: + num_channels = 3; + break; + case Mesh::ARRAY_CUSTOM_RGBA_FLOAT: + num_channels = 4; + break; + } + int texcoord_i = 2 + 2 * custom_i; + String gltf_texcoord_key; + for (int prev_texcoord_i = 0; prev_texcoord_i < texcoord_i; prev_texcoord_i++) { + gltf_texcoord_key = vformat("TEXCOORD_%d", prev_texcoord_i); + if (!attributes.has(gltf_texcoord_key)) { + Vector<Vector2> empty; + empty.resize(vertex_num); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true); + } + } + + LocalVector<Vector2> first_channel; + first_channel.resize(vertex_num); + LocalVector<Vector2> second_channel; + second_channel.resize(vertex_num); + for (int32_t vert_i = 0; vert_i < vertex_num; vert_i++) { + float u = a[vert_i * num_channels + 0]; + float v = (num_channels == 1 ? 0.0f : a[vert_i * num_channels + 1]); + first_channel[vert_i] = Vector2(u, v); + u = 0; + v = 0; + if (num_channels >= 3) { + u = a[vert_i * num_channels + 2]; + v = (num_channels == 3 ? 0.0f : a[vert_i * num_channels + 3]); + second_channel[vert_i] = Vector2(u, v); + } + } + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, first_channel, true); + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); + attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, second_channel, true); + } + } { Vector<Color> a = array[Mesh::ARRAY_COLOR]; if (a.size()) { @@ -2253,13 +2310,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { - int32_t vertex_count = vertex_array.size(); Vector<Color> joints_0; - joints_0.resize(vertex_count); + joints_0.resize(vertex_num); Vector<Color> joints_1; - joints_1.resize(vertex_count); + joints_1.resize(vertex_num); int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { Color joint_0; joint_0.r = a[vertex_i * weights_8_count + 0]; joint_0.g = a[vertex_i * weights_8_count + 1]; @@ -2289,13 +2345,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { } attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, attribs, true); } else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) { - int32_t vertex_count = vertex_array.size(); Vector<Color> weights_0; - weights_0.resize(vertex_count); + weights_0.resize(vertex_num); Vector<Color> weights_1; - weights_1.resize(vertex_count); + weights_1.resize(vertex_num); int32_t weights_8_count = JOINT_GROUP_SIZE * 2; - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { Color weight_0; weight_0.r = a[vertex_i * weights_8_count + 0]; weight_0.g = a[vertex_i * weights_8_count + 1]; @@ -2459,7 +2514,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR); Array primitives = d["primitives"]; - const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); + const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : + Dictionary(); Ref<EditorSceneImporterMesh> import_mesh; import_mesh.instantiate(); String mesh_name = "mesh"; @@ -2469,6 +2525,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name))); for (int j = 0; j < primitives.size(); j++) { + uint32_t flags = 0; Dictionary p = primitives[j]; Array array; @@ -2500,8 +2557,11 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR); + int32_t vertex_num = 0; if (a.has("POSITION")) { - array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true); + PackedVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true); + array[Mesh::ARRAY_VERTEX] = vertices; + vertex_num = vertices.size(); } if (a.has("NORMAL")) { array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true); @@ -2515,6 +2575,60 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { if (a.has("TEXCOORD_1")) { array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true); } + for (int custom_i = 0; custom_i < 3; custom_i++) { + Vector<float> cur_custom; + Vector<Vector2> texcoord_first; + Vector<Vector2> texcoord_second; + + int texcoord_i = 2 + 2 * custom_i; + String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i); + int num_channels = 0; + if (a.has(gltf_texcoord_key)) { + texcoord_first = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + num_channels = 2; + } + gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1); + if (a.has(gltf_texcoord_key)) { + texcoord_second = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true); + num_channels = 4; + } + if (!num_channels) { + break; + } + if (num_channels == 2 || num_channels == 4) { + cur_custom.resize(vertex_num * num_channels); + for (int32_t uv_i = 0; uv_i < texcoord_first.size() && uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 0] = texcoord_first[uv_i].x; + cur_custom.write[uv_i * num_channels + 1] = texcoord_first[uv_i].y; + } + // Vector.resize seems to not zero-initialize. Ensure all unused elements are 0: + for (int32_t uv_i = texcoord_first.size(); uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 0] = 0; + cur_custom.write[uv_i * num_channels + 1] = 0; + } + } + if (num_channels == 4) { + for (int32_t uv_i = 0; uv_i < texcoord_second.size() && uv_i < vertex_num; uv_i++) { + // num_channels must be 4 + cur_custom.write[uv_i * num_channels + 2] = texcoord_second[uv_i].x; + cur_custom.write[uv_i * num_channels + 3] = texcoord_second[uv_i].y; + } + // Vector.resize seems to not zero-initialize. Ensure all unused elements are 0: + for (int32_t uv_i = texcoord_second.size(); uv_i < vertex_num; uv_i++) { + cur_custom.write[uv_i * num_channels + 2] = 0; + cur_custom.write[uv_i * num_channels + 3] = 0; + } + } + if (cur_custom.size() > 0) { + array[Mesh::ARRAY_CUSTOM0 + custom_i] = cur_custom; + int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS; + if (num_channels == 2) { + flags |= Mesh::ARRAY_CUSTOM_RG_FLOAT << custom_shift; + } else { + flags |= Mesh::ARRAY_CUSTOM_RGBA_FLOAT << custom_shift; + } + } + } if (a.has("COLOR_0")) { array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true); has_vertex_color = true; @@ -2526,10 +2640,9 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { PackedInt32Array joints_1 = _decode_accessor_as_ints(state, a["JOINTS_1"], true); ERR_FAIL_COND_V(joints_0.size() != joints_0.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; - int32_t vertex_count = joints_0.size() / JOINT_GROUP_SIZE; Vector<int> joints; - joints.resize(vertex_count * weight_8_count); - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + joints.resize(vertex_num * weight_8_count); + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { joints.write[vertex_i * weight_8_count + 0] = joints_0[vertex_i * JOINT_GROUP_SIZE + 0]; joints.write[vertex_i * weight_8_count + 1] = joints_0[vertex_i * JOINT_GROUP_SIZE + 1]; joints.write[vertex_i * weight_8_count + 2] = joints_0[vertex_i * JOINT_GROUP_SIZE + 2]; @@ -2568,9 +2681,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { Vector<float> weights; ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA); int32_t weight_8_count = JOINT_GROUP_SIZE * 2; - int32_t vertex_count = weights_0.size() / JOINT_GROUP_SIZE; - weights.resize(vertex_count * weight_8_count); - for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) { + weights.resize(vertex_num * weight_8_count); + for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) { weights.write[vertex_i * weight_8_count + 0] = weights_0[vertex_i * JOINT_GROUP_SIZE + 0]; weights.write[vertex_i * weight_8_count + 1] = weights_0[vertex_i * JOINT_GROUP_SIZE + 1]; weights.write[vertex_i * weight_8_count + 2] = weights_0[vertex_i * JOINT_GROUP_SIZE + 2]; @@ -2798,7 +2910,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { mat = mat3d; } - import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String()); + import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String(), flags); } Vector<float> blend_weights; @@ -2954,6 +3066,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat } } } else { // Relative path to an external image file. + uri = uri.uri_decode(); uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows. // ResourceLoader will rely on the file extension to use the relevant loader. // The spec says that if mimeType is defined, it should take precedence (e.g. @@ -4897,7 +5010,7 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshIns if (p_mesh_instance->get_material_override().is_valid()) { mat = p_mesh_instance->get_material_override(); } - import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name); + import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name, godot_mesh->surface_get_format(surface_i)); } for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) { blend_weights.write[blend_i] = 0.0f; diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub index 2f04f1833e..5cc9d8ee8b 100644 --- a/modules/lightmapper_rd/SCsub +++ b/modules/lightmapper_rd/SCsub @@ -7,6 +7,9 @@ env_lightmapper_rd = env_modules.Clone() env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl") env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl") env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl") +env_lightmapper_rd.Depends("lm_raster.glsl.gen.h", "lm_common_inc.glsl") +env_lightmapper_rd.Depends("lm_compute.glsl.gen.h", "lm_common_inc.glsl") +env_lightmapper_rd.Depends("lm_blendseams.glsl.gen.h", "lm_common_inc.glsl") # Godot source files env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index fe941e25e7..ba4ef3be8d 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -274,13 +274,12 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ return BAKE_OK; } -void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { +void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { HashMap<Vertex, uint32_t, VertexHash> vertex_map; //fill triangles array and vertex array LocalVector<Triangle> triangles; LocalVector<Vertex> vertex_array; - LocalVector<Box> box_array; LocalVector<Seam> seams; slice_triangle_count.resize(atlas_slices); @@ -387,16 +386,13 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i } } - Box box; - box.min_bounds[0] = taabb.position.x; - box.min_bounds[1] = taabb.position.y; - box.min_bounds[2] = taabb.position.z; - box.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); - box.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); - box.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); - box.pad0 = box.pad1 = 0; //make valgrind not complain - box_array.push_back(box); - + t.min_bounds[0] = taabb.position.x; + t.min_bounds[1] = taabb.position.y; + t.min_bounds[2] = taabb.position.z; + t.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); + t.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); + t.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); + t.pad0 = t.pad1 = 0; //make valgrind not complain triangles.push_back(t); slice_triangle_count.write[t.slice]++; } @@ -505,9 +501,6 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i Vector<uint8_t> tb = triangles.to_byte_array(); triangle_buffer = rd->storage_buffer_create(tb.size(), tb); - Vector<uint8_t> bb = box_array.to_byte_array(); - box_buffer = rd->storage_buffer_create(bb.size(), bb); - Vector<uint8_t> tib = triangle_indices.to_byte_array(); triangle_cell_indices_buffer = rd->storage_buffer_create(tib.size(), tib); @@ -755,7 +748,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d Vector<int> slice_triangle_count; RID vertex_buffer; RID triangle_buffer; - RID box_buffer; RID lights_buffer; RID triangle_cell_indices_buffer; RID grid_texture; @@ -767,14 +759,13 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d #define FREE_BUFFERS \ rd->free(vertex_buffer); \ rd->free(triangle_buffer); \ - rd->free(box_buffer); \ rd->free(lights_buffer); \ rd->free(triangle_cell_indices_buffer); \ rd->free(grid_texture); \ rd->free(seams_buffer); \ rd->free(probe_positions_buffer); - _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, box_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata); + _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata); if (p_step_function) { p_step_function(0.47, TTR("Preparing shaders"), p_bake_userdata, true); @@ -828,62 +819,55 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(box_buffer); - base_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 4; u.ids.push_back(triangle_cell_indices_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 5; + u.binding = 4; u.ids.push_back(lights_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 6; + u.binding = 5; u.ids.push_back(seams_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 7; + u.binding = 6; u.ids.push_back(probe_positions_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 8; + u.binding = 7; u.ids.push_back(grid_texture); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 9; + u.binding = 8; u.ids.push_back(albedo_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 10; + u.binding = 9; u.ids.push_back(emission_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 11; + u.binding = 10; u.ids.push_back(sampler); base_uniforms.push_back(u); } diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index 7ab7f34464..a6a3740051 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -157,16 +157,13 @@ class LightmapperRD : public Lightmapper { } }; - struct Box { + struct Triangle { + uint32_t indices[3] = {}; + uint32_t slice = 0; float min_bounds[3] = {}; float pad0 = 0.0; float max_bounds[3] = {}; float pad1 = 0.0; - }; - - struct Triangle { - uint32_t indices[3] = {}; - uint32_t slice = 0; bool operator<(const Triangle &p_triangle) const { return slice < p_triangle.slice; } @@ -231,7 +228,7 @@ class LightmapperRD : public Lightmapper { Vector<Color> probe_values; BakeError _blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata); - void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata); + void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata); void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform); public: diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl index 1581639036..22172d50e4 100644 --- a/modules/lightmapper_rd/lm_common_inc.glsl +++ b/modules/lightmapper_rd/lm_common_inc.glsl @@ -16,26 +16,18 @@ vertices; struct Triangle { uvec3 indices; uint slice; -}; - -layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { - Triangle data[]; -} -triangles; - -struct Box { vec3 min_bounds; uint pad0; vec3 max_bounds; uint pad1; }; -layout(set = 0, binding = 3, std430) restrict readonly buffer Boxes { - Box data[]; +layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { + Triangle data[]; } -boxes; +triangles; -layout(set = 0, binding = 4, std430) restrict readonly buffer GridIndices { +layout(set = 0, binding = 3, std430) restrict readonly buffer GridIndices { uint data[]; } grid_indices; @@ -63,7 +55,7 @@ struct Light { uint pad[3]; }; -layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { +layout(set = 0, binding = 4, std430) restrict readonly buffer Lights { Light data[]; } lights; @@ -73,19 +65,19 @@ struct Seam { uvec2 b; }; -layout(set = 0, binding = 6, std430) restrict readonly buffer Seams { +layout(set = 0, binding = 5, std430) restrict readonly buffer Seams { Seam data[]; } seams; -layout(set = 0, binding = 7, std430) restrict readonly buffer Probes { +layout(set = 0, binding = 6, std430) restrict readonly buffer Probes { vec4 data[]; } probe_positions; -layout(set = 0, binding = 8) uniform utexture3D grid; +layout(set = 0, binding = 7) uniform utexture3D grid; -layout(set = 0, binding = 9) uniform texture2DArray albedo_tex; -layout(set = 0, binding = 10) uniform texture2DArray emission_tex; +layout(set = 0, binding = 8) uniform texture2DArray albedo_tex; +layout(set = 0, binding = 9) uniform texture2DArray emission_tex; -layout(set = 0, binding = 11) uniform sampler linear_sampler; +layout(set = 0, binding = 10) uniform sampler linear_sampler; diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index 9ca40535f9..a71652d5c4 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -160,18 +160,19 @@ bool trace_ray(vec3 p_from, vec3 p_to uint tidx = grid_indices.data[cell_data.y + i]; //Ray-Box test - vec3 t0 = (boxes.data[tidx].min_bounds - p_from) * inv_dir; - vec3 t1 = (boxes.data[tidx].max_bounds - p_from) * inv_dir; + Triangle triangle = triangles.data[tidx]; + vec3 t0 = (triangle.min_bounds - p_from) * inv_dir; + vec3 t1 = (triangle.max_bounds - p_from) * inv_dir; vec3 tmin = min(t0, t1), tmax = max(t0, t1); - if (max(tmin.x, max(tmin.y, tmin.z)) <= min(tmax.x, min(tmax.y, tmax.z))) { + if (max(tmin.x, max(tmin.y, tmin.z)) > min(tmax.x, min(tmax.y, tmax.z))) { continue; //ray box failed } //prepare triangle vertices - vec3 vtx0 = vertices.data[triangles.data[tidx].indices.x].position; - vec3 vtx1 = vertices.data[triangles.data[tidx].indices.y].position; - vec3 vtx2 = vertices.data[triangles.data[tidx].indices.z].position; + vec3 vtx0 = vertices.data[triangle.indices.x].position; + vec3 vtx1 = vertices.data[triangle.indices.y].position; + vec3 vtx2 = vertices.data[triangle.indices.z].position; #if defined(MODE_UNOCCLUDE) vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2))); diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index d911f6461c..7433c865f5 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -123,8 +123,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr // AutoLoads OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { - const ProjectSettings::AutoloadInfo &info = E.value; + for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { + const ProjectSettings::AutoloadInfo &info = E.value(); suggestions.push_back(quoted("/root/" + String(info.name))); } } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index a352953c4b..eea5ca9895 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -37,7 +37,7 @@ #include "core/templates/pair.h" #include "scene/2d/camera_2d.h" #include "scene/2d/collision_object_2d.h" -#include "scene/2d/listener_2d.cpp" +#include "scene/2d/listener_2d.h" #ifndef _3D_DISABLED #include "scene/3d/camera_3d.h" #include "scene/3d/collision_object_3d.h" diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index ad589a605e..71d0c69d55 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -543,6 +543,7 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BITS); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT); BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 27b0eb098b..aa4ed1cb13 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -105,6 +105,7 @@ public: ARRAY_FORMAT_BLEND_SHAPE_MASK = RS::ARRAY_FORMAT_BLEND_SHAPE_MASK, ARRAY_FORMAT_CUSTOM_BASE = RS::ARRAY_FORMAT_CUSTOM_BASE, + ARRAY_FORMAT_CUSTOM_BITS = RS::ARRAY_FORMAT_CUSTOM_BITS, ARRAY_FORMAT_CUSTOM0_SHIFT = RS::ARRAY_FORMAT_CUSTOM0_SHIFT, ARRAY_FORMAT_CUSTOM1_SHIFT = RS::ARRAY_FORMAT_CUSTOM1_SHIFT, ARRAY_FORMAT_CUSTOM2_SHIFT = RS::ARRAY_FORMAT_CUSTOM2_SHIFT, diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 875aa30824..d5e370568d 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -409,7 +409,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 4 + 0] = CLAMP(int32_t(c.r * 255.0), 0, 255); w[idx * 4 + 1] = CLAMP(int32_t(c.g * 255.0), 0, 255); w[idx * 4 + 2] = CLAMP(int32_t(c.b * 255.0), 0, 255); @@ -426,7 +426,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 4 + 0] = uint8_t(int8_t(CLAMP(int32_t(c.r * 127.0), -128, 127))); w[idx * 4 + 1] = uint8_t(int8_t(CLAMP(int32_t(c.g * 127.0), -128, 127))); w[idx * 4 + 2] = uint8_t(int8_t(CLAMP(int32_t(c.b * 127.0), -128, 127))); @@ -443,7 +443,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 2 + 0] = Math::make_half_float(c.r); w[idx * 2 + 1] = Math::make_half_float(c.g); } @@ -458,7 +458,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 4 + 0] = Math::make_half_float(c.r); w[idx * 4 + 1] = Math::make_half_float(c.g); w[idx * 4 + 2] = Math::make_half_float(c.b); @@ -475,7 +475,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx] = c.r; } @@ -489,7 +489,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 2 + 0] = c.r; w[idx * 2 + 1] = c.g; } @@ -504,7 +504,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 3 + 0] = c.r; w[idx * 3 + 1] = c.g; w[idx * 3 + 2] = c.b; @@ -520,7 +520,7 @@ Array SurfaceTool::commit_to_arrays() { for (uint32_t idx = 0; idx < vertex_array.size(); idx++) { const Vertex &v = vertex_array[idx]; - const Color &c = v.custom[idx]; + const Color &c = v.custom[fmt]; w[idx * 4 + 0] = c.r; w[idx * 4 + 1] = c.g; w[idx * 4 + 2] = c.b; @@ -679,6 +679,9 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, Local _create_list_from_arrays(arr, r_vertex, r_index, lformat); } +static const uint32_t custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 }; +static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; + void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, LocalVector<SurfaceTool::Vertex> &ret, uint32_t *r_format) { ret.clear(); @@ -733,8 +736,6 @@ void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays if (warr.size()) { lformat |= RS::ARRAY_FORMAT_WEIGHTS; } - static const uint32_t custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 }; - static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { ERR_CONTINUE_MSG(p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_BYTE_ARRAY, "Extracting Byte/Half formats is not supported"); @@ -832,6 +833,12 @@ void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) { clear(); primitive = Mesh::PRIMITIVE_TRIANGLES; _create_list_from_arrays(p_arrays, &vertex_array, &index_array, format); + + for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) { + if (format & custom_mask[j]) { + last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK); + } + } } void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) { @@ -841,6 +848,12 @@ void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) { primitive = p_existing->surface_get_primitive_type(p_surface); _create_list(p_existing, p_surface, &vertex_array, &index_array, format); material = p_existing->surface_get_material(p_surface); + + for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) { + if (format & custom_mask[j]) { + last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK); + } + } } void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name) { @@ -863,6 +876,12 @@ void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_sur Array mesh = arr[shape_idx]; ERR_FAIL_COND(mesh.size() != RS::ARRAY_MAX); _create_list_from_arrays(arr[shape_idx], &vertex_array, &index_array, format); + + for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) { + if (format & custom_mask[j]) { + last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK); + } + } } void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform3D &p_xform) { @@ -878,6 +897,16 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const LocalVector<int> nindices; _create_list(p_existing, p_surface, &nvertices, &nindices, nformat); format |= nformat; + + for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) { + if (format & custom_mask[j]) { + CustomFormat new_format = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK); + if (last_custom_format[j] != CUSTOM_MAX && last_custom_format[j] != new_format) { + WARN_PRINT(vformat("Custom %d format %d mismatch when appending format %d", j, last_custom_format[j], new_format)); + } + last_custom_format[j] = new_format; + } + } int vfrom = vertex_array.size(); for (uint32_t vi = 0; vi < nvertices.size(); vi++) { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index a24860996c..d0f02b44cb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -601,10 +601,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.usage_defines["UV2"] = "#define UV2_USED\n"; actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; - actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; - actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; - actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; - actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 14b3b6d9aa..cd314d8c56 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -593,10 +593,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.usage_defines["UV2"] = "#define UV2_USED\n"; actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; - actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; - actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; - actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; - actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 647c348d9f..3c66fadbe9 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1086,7 +1086,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } } - RID material = ci->material; + RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_null() && ci->canvas_group != nullptr) { material = default_canvas_group_material; @@ -1354,8 +1354,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } } - if (ci->material.is_valid()) { - MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RendererStorageRD::SHADER_TYPE_2D); + RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; + + if (material.is_valid()) { + MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -1375,7 +1377,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { // uniform set may be gone because a dependency was erased. In this case, it will happen // if a texture is deleted, so just re-create it. - storage->material_force_update_textures(ci->material, RendererStorageRD::SHADER_TYPE_2D); + storage->material_force_update_textures(material, RendererStorageRD::SHADER_TYPE_2D); } } } diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index db0011aa60..5f349e5e33 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -500,7 +500,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint case RS::ARRAY_CUSTOM1: case RS::ARRAY_CUSTOM2: case RS::ARRAY_CUSTOM3: { - uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - ai))) & ARRAY_FORMAT_CUSTOM_MASK; + uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (ai - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK; switch (type) { case ARRAY_CUSTOM_RGBA8_UNORM: case ARRAY_CUSTOM_RGBA8_SNORM: @@ -541,14 +541,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); Vector<float> array = p_arrays[ai]; - int32_t s = ARRAY_CUSTOM_R_FLOAT - ai + 1; + int32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1; ERR_FAIL_COND_V(array.size() != p_vertex_array_len * s, ERR_INVALID_PARAMETER); const float *src = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], 4 * s); + memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], sizeof(float) * s); } } break; default: { @@ -938,6 +938,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } + for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) { + // include custom array format type. + if (format & (1 << (ARRAY_CUSTOM0 + i))) { + format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format; + } + } + uint32_t offsets[RS::ARRAY_MAX]; uint32_t vertex_element_size; @@ -1191,7 +1198,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t case RS::ARRAY_CUSTOM1: case RS::ARRAY_CUSTOM2: case RS::ARRAY_CUSTOM3: { - uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - i))) & ARRAY_FORMAT_CUSTOM_MASK; + uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (i - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK; switch (type) { case ARRAY_CUSTOM_RGBA8_UNORM: case ARRAY_CUSTOM_RGBA8_SNORM: @@ -1219,6 +1226,8 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t uint32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1; Vector<float> arr; + arr.resize(s * p_vertex_len); + float *w = arr.ptrw(); for (int j = 0; j < p_vertex_len; j++) { |