summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclayjohn <claynjohn@gmail.com>2023-10-31 15:51:07 +0100
committerclayjohn <claynjohn@gmail.com>2023-11-01 22:40:42 +0100
commitd1043a5f930513aa4b48b014ec7961cad48b0560 (patch)
tree9db1971e8d3b8f33cfc5947628bc454031be065d
parent6afd320984cf14198368cc6c53752813a02169e3 (diff)
downloadredot-engine-d1043a5f930513aa4b48b014ec7961cad48b0560.tar.gz
Enhance checks and user experience around tangents.
Ensure `ensure_tangents` option actually creates tangent array. Even if it is just a dummy array. Allow mesh to generate its own tangents when using compression. This allows users to compress meshes without tangents. Warn users if they are trying to read from tangents without providing tangents.
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp5
-rw-r--r--drivers/gles3/storage/material_storage.cpp2
-rw-r--r--editor/import/editor_import_collada.cpp13
-rw-r--r--editor/import/resource_importer_obj.cpp14
-rw-r--r--modules/gltf/gltf_document.cpp23
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp5
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp11
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp5
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp11
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h1
-rw-r--r--servers/rendering_server.cpp55
12 files changed, 127 insertions, 19 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 21e14c1ec9..6e8fdd91dc 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -259,6 +259,11 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
sdcache->sort.shader_id = p_shader_id;
sdcache->sort.geometry_id = p_mesh.get_local_index();
sdcache->sort.priority = p_material->priority;
+
+ GLES3::Mesh::Surface *s = reinterpret_cast<GLES3::Mesh::Surface *>(sdcache->surface);
+ if (p_material->shader_data->uses_tangent && !(s->format & RS::ARRAY_FORMAT_TANGENT)) {
+ WARN_PRINT_ED("Attempting to use a shader that requires tangents with a mesh that doesn't contain tangents. Ensure that meshes are imported with the 'ensure_tangents' option. If creating your own meshes, add an `ARRAY_TANGENT` array (when using ArrayMesh) or call `generate_tangents()` (when using SurfaceTool).");
+ }
}
void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material_data, RID p_mat_src, RID p_mesh) {
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index b3a3506d40..a3ed75c703 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -2924,6 +2924,8 @@ void SceneShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
actions.usage_flag_pointers["COLOR"] = &uses_color;
actions.usage_flag_pointers["UV"] = &uses_uv;
actions.usage_flag_pointers["UV2"] = &uses_uv2;
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index de9daddd38..3f7ed8ab8b 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -925,6 +925,9 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p
mesh_flags = RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
}
+ // We can't generate tangents without UVs, so create dummy tangents.
+ bool generate_dummy_tangents = (!binormal_src || !tangent_src) && !uv_src && force_make_tangents;
+
Ref<SurfaceTool> surftool;
surftool.instantiate();
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
@@ -934,6 +937,14 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p
surftool->set_normal(vertex_array[k].normal);
if (binormal_src && tangent_src) {
surftool->set_tangent(vertex_array[k].tangent);
+ } else if (generate_dummy_tangents) {
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(vertex_array[k].normal);
+ surftool->set_tangent(Plane(tan.x, tan.y, tan.z, 1.0));
+ }
+ } else {
+ // No normals, use a dummy normal since normals will be generated.
+ if (generate_dummy_tangents) {
+ surftool->set_tangent(Plane(1.0, 0.0, 0.0, 1.0));
}
}
if (uv_src) {
@@ -985,7 +996,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p
surftool->generate_tangents();
}
- if (!binormal_src || !(tangent_src || generate_tangents) || p_mesh->get_blend_shape_count() != 0 || p_skin_controller) {
+ if (p_mesh->get_blend_shape_count() != 0 || p_skin_controller) {
// Can't compress if attributes missing or if using vertex weights.
mesh_flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
}
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 646831ca24..082e78fdbe 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -327,6 +327,17 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
}
ERR_FAIL_INDEX_V(norm, normals.size(), ERR_FILE_CORRUPT);
surf_tool->set_normal(normals[norm]);
+ if (generate_tangents && uvs.is_empty()) {
+ // We can't generate tangents without UVs, so create dummy tangents.
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normals[norm]);
+ surf_tool->set_tangent(Plane(tan.x, tan.y, tan.z, 1.0));
+ }
+ } else {
+ // No normals, use a dummy normal since normals will be generated.
+ if (generate_tangents && uvs.is_empty()) {
+ // We can't generate tangents without UVs, so create dummy tangents.
+ surf_tool->set_tangent(Plane(1.0, 0.0, 0.0, 1.0));
+ }
}
if (face[idx].size() >= 2 && !face[idx][1].is_empty()) {
@@ -383,9 +394,6 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
if (generate_tangents && uvs.size()) {
surf_tool->generate_tangents();
- } else {
- // We need tangents in order to compress vertex data. So disable if tangents aren't generated.
- mesh_flags = 0;
}
surf_tool->index();
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index ecfb035b82..90280e0372 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -2797,9 +2797,26 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
array[Mesh::ARRAY_INDEX] = indices;
}
- bool generate_tangents = p_state->force_generate_tangents && (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("TEXCOORD_0") && a.has("NORMAL"));
+ bool generate_tangents = p_state->force_generate_tangents && (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("NORMAL"));
+
+ if (generate_tangents && !a.has("TEXCOORD_0")) {
+ // If we don't have UVs we provide a dummy tangent array.
+ Vector<float> tangents;
+ tangents.resize(vertex_num * 4);
+ float *tangentsw = tangents.ptrw();
+
+ Vector<Vector3> normals = array[Mesh::ARRAY_NORMAL];
+ for (int k = 0; k < vertex_num; k++) {
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normals[k]);
+ tangentsw[k * 4 + 0] = tan.x;
+ tangentsw[k * 4 + 1] = tan.y;
+ tangentsw[k * 4 + 2] = tan.z;
+ tangentsw[k * 4 + 3] = 1.0;
+ }
+ array[Mesh::ARRAY_TANGENT] = tangents;
+ }
- if (p_state->force_disable_compression || !a.has("POSITION") || !a.has("NORMAL") || !(a.has("TANGENT") || generate_tangents) || p.has("targets") || (a.has("JOINTS_0") || a.has("JOINTS_1"))) {
+ if (p_state->force_disable_compression || !a.has("POSITION") || !a.has("NORMAL") || p.has("targets") || (a.has("JOINTS_0") || a.has("JOINTS_1"))) {
flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
}
@@ -2810,7 +2827,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
mesh_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
}
mesh_surface_tool->index();
- if (generate_tangents) {
+ if (generate_tangents && a.has("TEXCOORD_0")) {
//must generate mikktspace tangents.. ergh..
mesh_surface_tool->generate_tangents();
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 270a34d541..e5467ea72d 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -3707,6 +3707,11 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->sort.priority = p_material->priority;
sdcache->sort.uses_projector = ginstance->using_projectors;
sdcache->sort.uses_softshadow = ginstance->using_softshadows;
+
+ uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(sdcache->surface);
+ if (p_material->shader_data->uses_tangent && !(format & RS::ARRAY_FORMAT_TANGENT)) {
+ WARN_PRINT_ED("Attempting to use a shader that requires tangents with a mesh that doesn't contain tangents. Ensure that meshes are imported with the 'ensure_tangents' option. If creating your own meshes, add an `ARRAY_TANGENT` array (when using ArrayMesh) or call `generate_tangents()` (when using SurfaceTool).");
+ }
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
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 9676474a66..5134f4d545 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
@@ -65,6 +65,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uses_discard = false;
uses_roughness = false;
uses_normal = false;
+ uses_tangent = false;
+ bool uses_normal_map = false;
bool wireframe = false;
unshaded = false;
@@ -121,11 +123,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
- actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
+
actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
@@ -150,6 +157,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uses_normal_texture = gen_code.uses_normal_roughness_texture;
uses_vertex_time = gen_code.uses_vertex_time;
uses_fragment_time = gen_code.uses_fragment_time;
+ uses_normal |= uses_normal_map;
+ uses_tangent |= uses_normal_map;
#if 0
print_line("**compiling shader:");
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 0739cd9f86..3b83b2b582 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -165,6 +165,7 @@ public:
bool uses_discard = false;
bool uses_roughness = false;
bool uses_normal = false;
+ bool uses_tangent = false;
bool uses_particle_trails = false;
bool unshaded = false;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index a6a32d9e86..99b416d575 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -2508,6 +2508,11 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->sort.geometry_id = p_mesh.get_local_index();
// sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
sdcache->sort.priority = p_material->priority;
+
+ uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(sdcache->surface);
+ if (p_material->shader_data->uses_tangent && !(format & RS::ARRAY_FORMAT_TANGENT)) {
+ WARN_PRINT_ED("Attempting to use a shader that requires tangents with a mesh that doesn't contain tangents. Ensure that meshes are imported with the 'ensure_tangents' option. If creating your own meshes, add an `ARRAY_TANGENT` array (when using ArrayMesh) or call `generate_tangents()` (when using SurfaceTool).");
+ }
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
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 b2c0d4b1bd..f1cec0e07c 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
@@ -67,6 +67,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_discard = false;
uses_roughness = false;
uses_normal = false;
+ uses_tangent = false;
+ bool uses_normal_map = false;
bool wireframe = false;
unshaded = false;
@@ -122,7 +124,12 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
- actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
+
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
@@ -150,6 +157,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_screen_texture = gen_code.uses_screen_texture;
uses_depth_texture = gen_code.uses_depth_texture;
uses_normal_texture = gen_code.uses_normal_roughness_texture;
+ uses_normal |= uses_normal_map;
+ uses_tangent |= uses_normal_map;
#ifdef DEBUG_ENABLED
if (uses_sss) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 5c76d89247..da189c6f67 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -119,6 +119,7 @@ public:
bool uses_discard = false;
bool uses_roughness = false;
bool uses_normal = false;
+ bool uses_tangent = false;
bool uses_particle_trails = false;
bool unshaded = false;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index eb940cdd56..e65944bcba 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -460,9 +460,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
}
}
- bool using_normals_tangents = (p_format & RS::ARRAY_FORMAT_NORMAL) && (p_format & RS::ARRAY_FORMAT_TANGENT);
-
- if (!using_normals_tangents) {
+ if (!(p_format & RS::ARRAY_FORMAT_NORMAL)) {
// Early out if we are only setting vertex positions.
for (int i = 0; i < p_vertex_array_len; i++) {
Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
@@ -480,13 +478,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
// Validate normal and tangent arrays.
ERR_FAIL_COND_V(p_arrays[RS::ARRAY_NORMAL].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER);
- Variant::Type tangent_type = p_arrays[RS::ARRAY_TANGENT].get_type();
- ERR_FAIL_COND_V(tangent_type != Variant::PACKED_FLOAT32_ARRAY && tangent_type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
Vector<Vector3> normal_array = p_arrays[RS::ARRAY_NORMAL];
ERR_FAIL_COND_V(normal_array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER);
const Vector3 *normal_src = normal_array.ptr();
+ Variant::Type tangent_type = p_arrays[RS::ARRAY_TANGENT].get_type();
+ ERR_FAIL_COND_V(tangent_type != Variant::PACKED_FLOAT32_ARRAY && tangent_type != Variant::PACKED_FLOAT64_ARRAY && tangent_type != Variant::NIL, ERR_INVALID_PARAMETER);
+
// We need a different version if using double precision tangents.
if (tangent_type == Variant::PACKED_FLOAT32_ARRAY) {
Vector<float> tangent_array = p_arrays[RS::ARRAY_TANGENT];
@@ -524,7 +523,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(uint16_t) * 4);
}
}
- } else { // PACKED_FLOAT64_ARRAY
+ } else if (tangent_type == Variant::PACKED_FLOAT64_ARRAY) {
Vector<double> tangent_array = p_arrays[RS::ARRAY_TANGENT];
ERR_FAIL_COND_V(tangent_array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
const double *tangent_src = tangent_array.ptr();
@@ -560,6 +559,40 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(uint16_t) * 4);
}
}
+ } else { // No tangent array.
+ // Set data for vertex, normal, and tangent.
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ float angle;
+ Vector3 axis;
+ // Generate an arbitrary vector that is tangential to normal.
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normal_src[i].normalized());
+ Vector4 tangent = Vector4(tan.x, tan.y, tan.z, 1.0);
+ _get_axis_angle(normal_src[i], tangent, angle, axis);
+
+ // Store axis.
+ {
+ Vector2 res = axis.octahedron_encode();
+ uint16_t vector[2] = {
+ (uint16_t)CLAMP(res.x * 65535, 0, 65535),
+ (uint16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[RS::ARRAY_NORMAL] + i * p_normal_stride], vector, 4);
+ }
+
+ // Store vertex position + angle.
+ {
+ Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
+ uint16_t vector[4] = {
+ (uint16_t)CLAMP(pos.x * 65535, 0, 65535),
+ (uint16_t)CLAMP(pos.y * 65535, 0, 65535),
+ (uint16_t)CLAMP(pos.z * 65535, 0, 65535),
+ (uint16_t)CLAMP(angle * 65535, 0, 65535)
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(uint16_t) * 4);
+ }
+ }
}
} else {
for (int i = 0; i < p_vertex_array_len; i++) {
@@ -1207,7 +1240,11 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
// If using normals or tangents, then we need all three.
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_VERTEX), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using normals or tangents without vertex array.");
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_NORMAL), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using tangents without normal array.");
- ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_TANGENT), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using normals without tangent array.");
+ }
+
+ if ((format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && !(format & RS::ARRAY_FORMAT_TANGENT)) {
+ // If no tangent array provided, we will generate one.
+ format |= RS::ARRAY_FORMAT_TANGENT;
}
int vertex_array_size = (vertex_element_size + normal_element_size) * array_len;
@@ -1368,10 +1405,8 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
Vector3 *w = arr_3d.ptrw();
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
- bool using_normals_tangents = (p_format & RS::ARRAY_FORMAT_NORMAL) && (p_format & RS::ARRAY_FORMAT_TANGENT);
-
// We only have vertices to read, so just read them and skip everything else.
- if (!using_normals_tangents) {
+ if (!(p_format & RS::ARRAY_FORMAT_NORMAL)) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&r[j * vertex_elem_size + offsets[i]]);
Vector3 vec = Vector3(float(v[0]) / 65535.0, float(v[1]) / 65535.0, float(v[2]) / 65535.0);