diff options
Diffstat (limited to 'servers/rendering_server.cpp')
-rw-r--r-- | servers/rendering_server.cpp | 122 |
1 files changed, 82 insertions, 40 deletions
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index ccddaae131..78b5656a74 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -323,16 +323,18 @@ RID RenderingServer::get_white_texture() { } void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r_angle, Vector3 &r_axis) { - Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z); + Vector3 normal = p_normal.normalized(); + Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z).normalized(); float d = p_tangent.w; - Vector3 binormal = p_normal.cross(tangent); + Vector3 binormal = normal.cross(tangent).normalized(); + real_t angle; - r_angle = Math::acos((tangent.x + binormal.y + p_normal.z - 1.0) / 2.0); - float denom = 2.0 * Math::sin(r_angle); - r_axis.x = (p_normal.y - binormal.z) / denom; - r_axis.y = (tangent.z - p_normal.x) / denom; - r_axis.z = (binormal.x - tangent.y) / denom; - r_axis.normalize(); + Basis tbn = Basis(); + tbn.rows[0] = tangent; + tbn.rows[1] = binormal; + tbn.rows[2] = normal; + tbn.get_axis_angle(r_axis, angle); + r_angle = float(angle); if (d < 0.0) { r_angle = CLAMP((1.0 - r_angle / Math_PI) * 0.5, 0.0, 0.49999); @@ -346,13 +348,11 @@ void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r void _get_tbn_from_axis_angle(const Vector3 &p_axis, float p_angle, Vector3 &r_normal, Vector4 &r_tangent) { float binormal_sign = p_angle > 0.5 ? 1.0 : -1.0; float angle = Math::abs(p_angle * 2.0 - 1.0) * Math_PI; - float c = cos(angle); - float s = sin(angle); - Vector3 omc_axis = (1.0 - c) * p_axis; - Vector3 s_axis = s * p_axis; - Vector3 tan = omc_axis.x * p_axis + Vector3(c, -s_axis.z, s_axis.y); + + Basis tbn = Basis(p_axis, angle); + Vector3 tan = tbn.rows[0]; r_tangent = Vector4(tan.x, tan.y, tan.z, binormal_sign); - r_normal = omc_axis.z * p_axis + Vector3(-s_axis.y, s_axis.x, c); + r_normal = tbn.rows[2]; } Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_normal_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb, Vector4 &r_uv_scale) { @@ -400,7 +400,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint max_val = max_val.abs().max(min_val.abs()); max_val2 = max_val2.abs().max(min_val2.abs()); - r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0); + if (min_val.x >= 0.0 && min_val2.x >= 0.0 && max_val.x <= 1.0 && max_val2.x <= 1.0 && + min_val.y >= 0.0 && min_val2.y >= 0.0 && max_val.y <= 1.0 && max_val2.y <= 1.0) { + // When all channels are in the 0-1 range, we will compress to 16-bit without scaling to + // preserve the bits as best as possible. + r_uv_scale = Vector4(0.0, 0.0, 0.0, 0.0); + } else { + r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0); + } } for (int ai = 0; ai < RS::ARRAY_MAX; ai++) { @@ -441,16 +448,15 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint const Vector3 *src = array.ptr(); - // Setting vertices means regenerating the AABB. - AABB aabb; + r_aabb = AABB(); if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) { // First we need to generate the AABB for the entire surface. for (int i = 0; i < p_vertex_array_len; i++) { if (i == 0) { - aabb = AABB(src[i], SMALL_VEC3); + r_aabb = AABB(src[i], SMALL_VEC3); } else { - aabb.expand_to(src[i]); + r_aabb.expand_to(src[i]); } } @@ -459,7 +465,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint if (!using_normals_tangents) { // Early out if we are only setting vertex positions. for (int i = 0; i < p_vertex_array_len; i++) { - Vector3 pos = (src[i] - aabb.position) / aabb.size; + 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), @@ -507,7 +513,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint // Store vertex position + angle. { - Vector3 pos = (src[i] - aabb.position) / aabb.size; + 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), @@ -543,7 +549,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint // Store vertex position + angle. { - Vector3 pos = (src[i] - aabb.position) / aabb.size; + 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), @@ -562,14 +568,12 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 3); if (i == 0) { - aabb = AABB(src[i], SMALL_VEC3); + r_aabb = AABB(src[i], SMALL_VEC3); } else { - aabb.expand_to(src[i]); + r_aabb.expand_to(src[i]); } } } - - r_aabb = aabb; } } break; @@ -673,8 +677,11 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { for (int i = 0; i < p_vertex_array_len; i++) { Vector2 vec = src[i]; - // Normalize into 0-1 from possible range -uv_scale - uv_scale. - vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5); + if (!r_uv_scale.is_zero_approx()) { + // Normalize into 0-1 from possible range -uv_scale - uv_scale. + vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5); + } + uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) }; memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4); } @@ -698,8 +705,10 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { for (int i = 0; i < p_vertex_array_len; i++) { Vector2 vec = src[i]; - // Normalize into 0-1 from possible range -uv_scale - uv_scale. - vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5); + if (!r_uv_scale.is_zero_approx()) { + // Normalize into 0-1 from possible range -uv_scale - uv_scale. + vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5); + } uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) }; memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4); } @@ -1194,7 +1203,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY; } - if (format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) { + if ((format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) { // 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."); @@ -1314,7 +1323,7 @@ void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_p mesh_add_surface(p_mesh, sd); } -Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const { +Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const { uint32_t offsets[RS::ARRAY_MAX]; uint32_t vertex_elem_size; @@ -1399,7 +1408,7 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t tangentsw[j * 4 + 3] = tan.w; } ret[RS::ARRAY_NORMAL] = normals; - ret[RS::ARRAY_FORMAT_TANGENT] = tangents; + ret[RS::ARRAY_TANGENT] = tangents; } else { for (int j = 0; j < p_vertex_len; j++) { @@ -1472,7 +1481,12 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) { for (int j = 0; j < p_vertex_len; j++) { const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]); - w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0); + Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0); + if (!p_uv_scale.is_zero_approx()) { + vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.x, p_uv_scale.y); + } + + w[j] = vec; } } else { for (int j = 0; j < p_vertex_len; j++) { @@ -1492,7 +1506,11 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) { for (int j = 0; j < p_vertex_len; j++) { const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]); - w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0); + Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0); + if (!p_uv_scale.is_zero_approx()) { + vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.z, p_uv_scale.w); + } + w[j] = vec; } } else { for (int j = 0; j < p_vertex_len; j++) { @@ -1689,7 +1707,7 @@ TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mes for (uint32_t i = 0; i < blend_shape_count; i++) { Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor); Vector<uint8_t> unused; - blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb)); + blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb, sd.uv_scale)); } return blend_shape_array; @@ -1711,7 +1729,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p uint64_t format = p_data.format; - return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb); + return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb, p_data.uv_scale); } #if 0 Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { @@ -2036,15 +2054,39 @@ Vector<uint8_t> _convert_surface_version_1_to_surface_version_2(uint64_t p_forma return new_vertex_data; } +#ifdef TOOLS_ENABLED +void RenderingServer::set_surface_upgrade_callback(SurfaceUpgradeCallback p_callback) { + surface_upgrade_callback = p_callback; +} + +void RenderingServer::set_warn_on_surface_upgrade(bool p_warn) { + warn_on_surface_upgrade = p_warn; +} +#endif + #ifndef DISABLE_DEPRECATED -void RenderingServer::_fix_surface_compatibility(SurfaceData &p_surface) { +void RenderingServer::fix_surface_compatibility(SurfaceData &p_surface, const String &p_path) { uint64_t surface_version = p_surface.format & (ARRAY_FLAG_FORMAT_VERSION_MASK << ARRAY_FLAG_FORMAT_VERSION_SHIFT); ERR_FAIL_COND_MSG(surface_version > ARRAY_FLAG_FORMAT_CURRENT_VERSION, "Cannot convert surface with version provided (" + itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + ") to current version (" + itos((RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + ")"); +#ifdef TOOLS_ENABLED + // Editor callback to ask user about re-saving all meshes. + if (surface_upgrade_callback && warn_on_surface_upgrade) { + surface_upgrade_callback(); + } + + if (warn_on_surface_upgrade) { + WARN_PRINT_ONCE_ED("At least one surface uses an old surface format and needs to be upgraded. The upgrade happens automatically at load time every time until the mesh is saved again or re-imported. Once saved (or re-imported), this mesh will be incompatible with earlier versions of Godot."); + + if (!p_path.is_empty()) { + WARN_PRINT("A surface of " + p_path + " uses an old surface format and needs to be upgraded."); + } + } +#endif + if (surface_version == ARRAY_FLAG_FORMAT_VERSION_1) { // The only difference for now is that Version 1 uses interleaved vertex positions while version 2 does not. // I.e. PNTPNTPNT -> PPPNTNTNT. - WARN_PRINT_ED("Upgrading mesh from older surface format. Once saved again (or re-imported), this mesh will be incompatible with earlier versions of Godot."); int vertex_size = 0; int normal_size = 0; @@ -3345,7 +3387,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"), 2); GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0); - GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/shadow_atlas/size", PROPERTY_HINT_RANGE, "128,16384"), 2048); // Number of commands that can be drawn per frame. GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384); |