summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorreduz <reduzio@gmail.com>2021-01-25 12:20:11 -0300
committerreduz <reduzio@gmail.com>2021-01-25 15:03:15 -0300
commit51d8e32c937f9e0fd75ce86b0d48848255723bd4 (patch)
treec65ed356cc9b4fd634a15827a12cecb7e0e05b05 /editor
parentc5c9517e1e03175e9cdc483d3dce27fc531af2be (diff)
Implement shadow meshes
-When importing, a vertex-only version of the mesh is created. -This version is used when rendering shadows, and improves performance by reducing bandwidth -It's automatic, but can optionally be used by users, in case they want to make special versions of geometry for shadow casting.
Diffstat (limited to 'editor')
-rw-r--r--editor/import/resource_importer_scene.cpp12
-rw-r--r--editor/import/resource_importer_scene.h2
-rw-r--r--editor/import/scene_importer_mesh.cpp102
-rw-r--r--editor/import/scene_importer_mesh.h5
4 files changed, 117 insertions, 4 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index ead1f7c3e9..9944712931 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1129,6 +1129,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
@@ -1221,7 +1222,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
return importer->import_animation(p_path, p_flags, p_bake_fps);
}
-void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods) {
+void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes) {
EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
if (src_mesh_node) {
//is mesh
@@ -1237,8 +1238,12 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods)
if (p_generate_lods) {
src_mesh_node->get_mesh()->generate_lods();
}
+ if (p_create_shadow_meshes) {
+ src_mesh_node->get_mesh()->create_shadow_mesh();
+ }
}
mesh = src_mesh_node->get_mesh()->get_mesh();
+
if (mesh.is_valid()) {
mesh_node->set_mesh(mesh);
for (int i = 0; i < mesh->get_surface_count(); i++) {
@@ -1252,7 +1257,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods)
}
for (int i = 0; i < p_node->get_child_count(); i++) {
- _generate_meshes(p_node->get_child(i), p_generate_lods);
+ _generate_meshes(p_node->get_child(i), p_generate_lods, p_create_shadow_meshes);
}
}
Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
@@ -1348,8 +1353,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
bool gen_lods = bool(p_options["meshes/generate_lods"]);
+ bool create_shadow_meshes = bool(p_options["meshes/create_shadow_meshes"]);
- _generate_meshes(scene, gen_lods);
+ _generate_meshes(scene, gen_lods, create_shadow_meshes);
err = OK;
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 66c317f858..aced0226ff 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -121,7 +121,7 @@ class ResourceImporterScene : public ResourceImporter {
};
void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner);
- void _generate_meshes(Node *p_node, bool p_generate_lods);
+ void _generate_meshes(Node *p_node, bool p_generate_lods, bool p_create_shadow_meshes);
public:
static ResourceImporterScene *get_singleton() { return singleton; }
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index 620437af0e..78a7cd84f1 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -250,6 +250,11 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() {
mesh->surface_set_name(mesh->get_surface_count() - 1, surfaces[i].name);
}
}
+
+ if (shadow_mesh.is_valid()) {
+ Ref<ArrayMesh> shadow = shadow_mesh->get_mesh();
+ mesh->set_shadow_mesh(shadow);
+ }
}
return mesh;
@@ -261,6 +266,103 @@ void EditorSceneImporterMesh::clear() {
mesh.unref();
}
+void EditorSceneImporterMesh::create_shadow_mesh() {
+ if (shadow_mesh.is_valid()) {
+ shadow_mesh.unref();
+ }
+
+ //no shadow mesh for blendshapes
+ if (blend_shapes.size() > 0) {
+ return;
+ }
+ //no shadow mesh for skeletons
+ for (int i = 0; i < surfaces.size(); i++) {
+ if (surfaces[i].arrays[RS::ARRAY_BONES].get_type() != Variant::NIL) {
+ return;
+ }
+ if (surfaces[i].arrays[RS::ARRAY_WEIGHTS].get_type() != Variant::NIL) {
+ return;
+ }
+ }
+
+ shadow_mesh.instance();
+
+ for (int i = 0; i < surfaces.size(); i++) {
+ LocalVector<int> vertex_remap;
+ Vector<Vector3> new_vertices;
+ Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX];
+ int vertex_count = vertices.size();
+ {
+ Map<Vector3, int> unique_vertices;
+ const Vector3 *vptr = vertices.ptr();
+ for (int j = 0; j < vertex_count; j++) {
+ Vector3 v = vptr[j];
+
+ Map<Vector3, int>::Element *E = unique_vertices.find(v);
+
+ if (E) {
+ vertex_remap.push_back(E->get());
+ } else {
+ int vcount = unique_vertices.size();
+ unique_vertices[v] = vcount;
+ vertex_remap.push_back(vcount);
+ new_vertices.push_back(v);
+ }
+ }
+ }
+
+ Array new_surface;
+ new_surface.resize(RS::ARRAY_MAX);
+ Dictionary lods;
+
+ // print_line("original vertex count: " + itos(vertices.size()) + " new vertex count: " + itos(new_vertices.size()));
+
+ new_surface[RS::ARRAY_VERTEX] = new_vertices;
+
+ Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX];
+ if (indices.size()) {
+ int index_count = indices.size();
+ const int *index_rptr = indices.ptr();
+ Vector<int> new_indices;
+ new_indices.resize(indices.size());
+ int *index_wptr = new_indices.ptrw();
+
+ for (int j = 0; j < index_count; j++) {
+ int index = index_rptr[j];
+ ERR_FAIL_INDEX(index, vertex_count);
+ index_wptr[j] = vertex_remap[index];
+ }
+
+ new_surface[RS::ARRAY_INDEX] = new_indices;
+
+ // Make sure the same LODs as the full version are used.
+ // This makes it more coherent between rendered model and its shadows.
+ for (int j = 0; j < surfaces[i].lods.size(); j++) {
+ indices = surfaces[i].lods[j].indices;
+
+ index_count = indices.size();
+ index_rptr = indices.ptr();
+ new_indices.resize(indices.size());
+ index_wptr = new_indices.ptrw();
+
+ for (int k = 0; k < index_count; k++) {
+ int index = index_rptr[j];
+ ERR_FAIL_INDEX(index, vertex_count);
+ index_wptr[j] = vertex_remap[index];
+ }
+
+ lods[surfaces[i].lods[j].distance] = new_indices;
+ }
+ }
+
+ shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name);
+ }
+}
+
+Ref<EditorSceneImporterMesh> EditorSceneImporterMesh::get_shadow_mesh() const {
+ return shadow_mesh;
+}
+
void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) {
clear();
if (p_data.has("blend_shape_names")) {
diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h
index 2adeb76b6c..42507cbe8c 100644
--- a/editor/import/scene_importer_mesh.h
+++ b/editor/import/scene_importer_mesh.h
@@ -61,6 +61,8 @@ class EditorSceneImporterMesh : public Resource {
Ref<ArrayMesh> mesh;
+ Ref<EditorSceneImporterMesh> shadow_mesh;
+
protected:
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
@@ -89,6 +91,9 @@ public:
void generate_lods();
+ void create_shadow_mesh();
+ Ref<EditorSceneImporterMesh> get_shadow_mesh() const;
+
bool has_mesh() const;
Ref<ArrayMesh> get_mesh();
void clear();