diff options
author | Omar El Sheikh <techmanozmar@gmail.com> | 2022-02-22 18:10:09 -0500 |
---|---|---|
committer | Omar El Sheikh <techmanozmar@gmail.com> | 2022-08-13 08:09:32 -0700 |
commit | 78881b3cc3a389c21c1417ad05840e80a234e2d7 (patch) | |
tree | e5b11b00aee94987c1ce7415bafeff01d33b2a25 /servers | |
parent | f2a61684143af02a8cbe7002645af817607f9bd6 (diff) |
Octahedral Normal/Tangent Compression
Implementation of Octahedral normal compression into Godot 4.0
Diffstat (limited to 'servers')
4 files changed, 54 insertions, 42 deletions
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index e9515c7670..6b4e4a5a16 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib; //only for pure render depth when normal is not used #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib; #endif #if defined(COLOR_USED) @@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +vec3 oct_to_vec3(vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + /* Varyings */ layout(location = 0) out vec3 vertex_interp; @@ -231,12 +238,13 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc vec3 vertex = vertex_attrib; #ifdef NORMAL_USED - vec3 normal = normal_attrib * 2.0 - 1.0; + vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; - float binormalf = tangent_attrib.a * 2.0 - 1.0; + vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; + vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + float binormalf = sign(signed_tangent_attrib.y); vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 6548793bee..0960533917 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib; //only for pure render depth when normal is not used #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib; #endif #if defined(COLOR_USED) @@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +vec3 oct_to_vec3(vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + /* Varyings */ layout(location = 0) highp out vec3 vertex_interp; @@ -229,12 +236,13 @@ void main() { vec3 vertex = vertex_attrib; #ifdef NORMAL_USED - vec3 normal = normal_attrib * 2.0 - 1.0; + vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; - float binormalf = tangent_attrib.a * 2.0 - 1.0; + vec3 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; + vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + float binormalf = sign(signed_tangent_attrib.y); vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index dc3f35f942..71cfb32828 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1057,10 +1057,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } break; case RS::ARRAY_NORMAL: { vd.offset = stride; + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + stride += sizeof(uint16_t) * 2; - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - - stride += sizeof(uint32_t); if (mis) { buffer = mis->vertex_buffer; } else { @@ -1069,9 +1068,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } break; case RS::ARRAY_TANGENT: { vd.offset = stride; + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + stride += sizeof(uint16_t) * 2; - vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - stride += sizeof(uint32_t); if (mis) { buffer = mis->vertex_buffer; } else { diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a54d4f0384..f79c4ac54c 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -398,16 +398,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector3 *src = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - Vector3 n = src[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - - uint32_t value = 0; - value |= CLAMP(int(n.x * 1023.0), 0, 1023); - value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; - value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + Vector2 res = src[i].octahedron_encode(); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } - } break; case RS::ARRAY_TANGENT: { @@ -416,33 +414,32 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint if (type == Variant::PACKED_FLOAT32_ARRAY) { Vector<float> array = p_arrays[ai]; ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); - const float *src = array.ptr(); + const float *src_ptr = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - uint32_t value = 0; - value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023); - value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; - value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; - if (src[i * 4 + 3] > 0) { - value |= 3UL << 30; - } - - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]); + Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; + + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } } else { // PACKED_FLOAT64_ARRAY Vector<double> array = p_arrays[ai]; ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); - const double *src = array.ptr(); + const double *src_ptr = array.ptr(); for (int i = 0; i < p_vertex_array_len; i++) { - uint32_t value = 0; - value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023); - value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; - value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; - if (src[i * 4 + 3] > 0) { - value |= 3UL << 30; - } - memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4); + const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]); + Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]); + int16_t vector[2] = { + (int16_t)CLAMP(res.x * 65535, 0, 65535), + (int16_t)CLAMP(res.y * 65535, 0, 65535), + }; + + memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4); } } } break; |