Browse Source

Merge pull request #58838 from The-O-King/gles2_blend_shapes_oct

GLES2 Compression on Blend Shapes Fix
Rémi Verschelde 3 years ago
parent
commit
d93a4a8885
2 changed files with 124 additions and 34 deletions
  1. 18 2
      drivers/gles2/rasterizer_scene_gles2.cpp
  2. 106 32
      drivers/gles2/rasterizer_storage_gles2.cpp

+ 18 - 2
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -1480,7 +1480,21 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
 
 					if (!s->blend_shape_data.empty() && i != VS::ARRAY_BONES && s->blend_shape_buffer_size > 0) {
 						glBindBuffer(GL_ARRAY_BUFFER, s->blend_shape_buffer_id);
-						glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, GL_FLOAT, GL_FALSE, 8 * 4 * sizeof(float), CAST_INT_TO_UCHAR_PTR(i * 4 * sizeof(float)));
+						// When using octahedral compression (2 component normal/tangent)
+						// decompression changes the component count to 3/4
+						int size;
+						switch (i) {
+							case VS::ARRAY_NORMAL: {
+								size = 3;
+							} break;
+							case VS::ARRAY_TANGENT: {
+								size = 4;
+							} break;
+							default:
+								size = s->attribs[i].size;
+						}
+
+						glVertexAttribPointer(s->attribs[i].index, size, GL_FLOAT, GL_FALSE, 8 * 4 * sizeof(float), CAST_INT_TO_UCHAR_PTR(i * 4 * sizeof(float)));
 
 					} else {
 						glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id);
@@ -2508,7 +2522,9 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 		state.scene_shader.set_conditional(SceneShaderGLES2::USE_PHYSICAL_LIGHT_ATTENUATION, storage->config.use_physical_light_attenuation);
 
-		bool octahedral_compression = e->instance->base_type != VS::INSTANCE_IMMEDIATE && ((RasterizerStorageGLES2::Surface *)e->geometry)->format & VisualServer::ArrayFormat::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION;
+		bool octahedral_compression = e->instance->base_type != VS::INSTANCE_IMMEDIATE &&
+				((RasterizerStorageGLES2::Surface *)e->geometry)->format & VisualServer::ArrayFormat::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION &&
+				(((RasterizerStorageGLES2::Surface *)e->geometry)->blend_shape_data.empty() || ((RasterizerStorageGLES2::Surface *)e->geometry)->blend_shape_buffer_size == 0);
 		if (octahedral_compression != prev_octahedral_compression) {
 			state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_OCTAHEDRAL_COMPRESSION, octahedral_compression);
 			rebind = true;

+ 106 - 32
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -3797,6 +3797,7 @@ void RasterizerStorageGLES2::update_dirty_blend_shapes() {
 										wr[0] = Math::halfptr_to_float(&((uint16_t *)rd)[0]) * base_weight;
 										wr[1] = Math::halfptr_to_float(&((uint16_t *)rd)[1]) * base_weight;
 										wr[2] = Math::halfptr_to_float(&((uint16_t *)rd)[2]) * base_weight;
+										wr[3] = 1.0f;
 									} else {
 										float a[3] = { 0 };
 										a[0] = wr[0] = rd[0] * base_weight;
@@ -3806,27 +3807,63 @@ void RasterizerStorageGLES2::update_dirty_blend_shapes() {
 									}
 								} break;
 								case VS::ARRAY_NORMAL: {
-									if (s->format & VS::ARRAY_COMPRESS_NORMAL) {
-										wr[0] = (((int8_t *)rd)[0] / 127.0) * base_weight;
-										wr[1] = (((int8_t *)rd)[1] / 127.0) * base_weight;
-										wr[2] = (((int8_t *)rd)[2] / 127.0) * base_weight;
+									if (s->format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
+										if (s->format & VS::ARRAY_COMPRESS_NORMAL && s->format & VS::ARRAY_FORMAT_TANGENT && s->format & VS::ARRAY_COMPRESS_TANGENT) {
+											Vector2 oct(((int8_t *)rd)[0] / 127.0, ((int8_t *)rd)[1] / 127.0);
+											Vector3 vec = VS::oct_to_norm(oct);
+											wr[0] = vec.x * base_weight;
+											wr[1] = vec.y * base_weight;
+											wr[2] = vec.z * base_weight;
+										} else {
+											Vector2 oct(((int16_t *)rd)[0] / 32767.0, ((int16_t *)rd)[1] / 32767.0);
+											Vector3 vec = VS::oct_to_norm(oct);
+											wr[0] = vec.x * base_weight;
+											wr[1] = vec.y * base_weight;
+											wr[2] = vec.z * base_weight;
+										}
 									} else {
-										wr[0] = rd[0] * base_weight;
-										wr[1] = rd[1] * base_weight;
-										wr[2] = rd[2] * base_weight;
+										if (s->format & VS::ARRAY_COMPRESS_NORMAL) {
+											wr[0] = (((int8_t *)rd)[0] / 127.0) * base_weight;
+											wr[1] = (((int8_t *)rd)[1] / 127.0) * base_weight;
+											wr[2] = (((int8_t *)rd)[2] / 127.0) * base_weight;
+										} else {
+											wr[0] = rd[0] * base_weight;
+											wr[1] = rd[1] * base_weight;
+											wr[2] = rd[2] * base_weight;
+										}
 									}
 								} break;
 								case VS::ARRAY_TANGENT: {
-									if (s->format & VS::ARRAY_COMPRESS_TANGENT) {
-										wr[0] = (((int8_t *)rd)[0] / 127.0) * base_weight;
-										wr[1] = (((int8_t *)rd)[1] / 127.0) * base_weight;
-										wr[2] = (((int8_t *)rd)[2] / 127.0) * base_weight;
-										wr[3] = (((int8_t *)rd)[3] / 127.0) * base_weight;
+									if (s->format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
+										if (s->format & VS::ARRAY_COMPRESS_TANGENT && s->format & VS::ARRAY_FORMAT_NORMAL && s->format & VS::ARRAY_COMPRESS_NORMAL) {
+											Vector2 oct(((int8_t *)rd)[0] / 127.0, ((int8_t *)rd)[1] / 127.0);
+											float sign;
+											Vector3 vec = VS::oct_to_tangent(oct, &sign);
+											wr[0] = vec.x * base_weight;
+											wr[1] = vec.y * base_weight;
+											wr[2] = vec.z * base_weight;
+											wr[3] = sign * base_weight;
+										} else {
+											Vector2 oct(((int16_t *)rd)[0] / 32767.0, ((int16_t *)rd)[1] / 32767.0);
+											float sign;
+											Vector3 vec = VS::oct_to_tangent(oct, &sign);
+											wr[0] = vec.x * base_weight;
+											wr[1] = vec.y * base_weight;
+											wr[2] = vec.z * base_weight;
+											wr[3] = sign * base_weight;
+										}
 									} else {
-										wr[0] = rd[0] * base_weight;
-										wr[1] = rd[1] * base_weight;
-										wr[2] = rd[2] * base_weight;
-										wr[3] = rd[3] * base_weight;
+										if (s->format & VS::ARRAY_COMPRESS_TANGENT) {
+											wr[0] = (((int8_t *)rd)[0] / 127.0) * base_weight;
+											wr[1] = (((int8_t *)rd)[1] / 127.0) * base_weight;
+											wr[2] = (((int8_t *)rd)[2] / 127.0) * base_weight;
+											wr[3] = (((int8_t *)rd)[3] / 127.0) * base_weight;
+										} else {
+											wr[0] = rd[0] * base_weight;
+											wr[1] = rd[1] * base_weight;
+											wr[2] = rd[2] * base_weight;
+											wr[3] = rd[3] * base_weight;
+										}
 									}
 								} break;
 								case VS::ARRAY_COLOR: {
@@ -3891,6 +3928,7 @@ void RasterizerStorageGLES2::update_dirty_blend_shapes() {
 											wr[0] += Math::halfptr_to_float(&((uint16_t *)br)[0]) * weight;
 											wr[1] += Math::halfptr_to_float(&((uint16_t *)br)[1]) * weight;
 											wr[2] += Math::halfptr_to_float(&((uint16_t *)br)[2]) * weight;
+											wr[3] = 1.0f;
 										} else {
 											wr[0] += br[0] * weight;
 											wr[1] += br[1] * weight;
@@ -3898,27 +3936,63 @@ void RasterizerStorageGLES2::update_dirty_blend_shapes() {
 										}
 									} break;
 									case VS::ARRAY_NORMAL: {
-										if (s->format & VS::ARRAY_COMPRESS_NORMAL) {
-											wr[0] += (float(((int8_t *)br)[0]) / 127.0) * weight;
-											wr[1] += (float(((int8_t *)br)[1]) / 127.0) * weight;
-											wr[2] += (float(((int8_t *)br)[2]) / 127.0) * weight;
+										if (s->format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
+											if (s->format & VS::ARRAY_COMPRESS_NORMAL && s->format & VS::ARRAY_FORMAT_TANGENT && s->format & VS::ARRAY_COMPRESS_TANGENT) {
+												Vector2 oct(((int8_t *)br)[0] / 127.0, ((int8_t *)br)[1] / 127.0);
+												Vector3 vec = VS::oct_to_norm(oct);
+												wr[0] += vec.x * weight;
+												wr[1] += vec.y * weight;
+												wr[2] += vec.z * weight;
+											} else {
+												Vector2 oct(((int16_t *)br)[0] / 32767.0, ((int16_t *)br)[1] / 32767.0);
+												Vector3 vec = VS::oct_to_norm(oct);
+												wr[0] += vec.x * weight;
+												wr[1] += vec.y * weight;
+												wr[2] += vec.z * weight;
+											}
 										} else {
-											wr[0] += br[0] * weight;
-											wr[1] += br[1] * weight;
-											wr[2] += br[2] * weight;
+											if (s->format & VS::ARRAY_COMPRESS_NORMAL) {
+												wr[0] += (float(((int8_t *)br)[0]) / 127.0) * weight;
+												wr[1] += (float(((int8_t *)br)[1]) / 127.0) * weight;
+												wr[2] += (float(((int8_t *)br)[2]) / 127.0) * weight;
+											} else {
+												wr[0] += br[0] * weight;
+												wr[1] += br[1] * weight;
+												wr[2] += br[2] * weight;
+											}
 										}
 									} break;
 									case VS::ARRAY_TANGENT: {
-										if (s->format & VS::ARRAY_COMPRESS_TANGENT) {
-											wr[0] += (float(((int8_t *)br)[0]) / 127.0) * weight;
-											wr[1] += (float(((int8_t *)br)[1]) / 127.0) * weight;
-											wr[2] += (float(((int8_t *)br)[2]) / 127.0) * weight;
-											wr[3] = (float(((int8_t *)br)[3]) / 127.0);
+										if (s->format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
+											if (s->format & VS::ARRAY_COMPRESS_TANGENT && s->format & VS::ARRAY_FORMAT_NORMAL && s->format & VS::ARRAY_COMPRESS_NORMAL) {
+												Vector2 oct(((int8_t *)br)[0] / 127.0, ((int8_t *)br)[1] / 127.0);
+												float sign;
+												Vector3 vec = VS::oct_to_tangent(oct, &sign);
+												wr[0] += vec.x * weight;
+												wr[1] += vec.y * weight;
+												wr[2] += vec.z * weight;
+												wr[3] = sign * weight;
+											} else {
+												Vector2 oct(((int16_t *)rd)[0] / 32767.0, ((int16_t *)rd)[1] / 32767.0);
+												float sign;
+												Vector3 vec = VS::oct_to_tangent(oct, &sign);
+												wr[0] += vec.x * weight;
+												wr[1] += vec.y * weight;
+												wr[2] += vec.z * weight;
+												wr[3] = sign * weight;
+											}
 										} else {
-											wr[0] += br[0] * weight;
-											wr[1] += br[1] * weight;
-											wr[2] += br[2] * weight;
-											wr[3] = br[3];
+											if (s->format & VS::ARRAY_COMPRESS_TANGENT) {
+												wr[0] += (float(((int8_t *)br)[0]) / 127.0) * weight;
+												wr[1] += (float(((int8_t *)br)[1]) / 127.0) * weight;
+												wr[2] += (float(((int8_t *)br)[2]) / 127.0) * weight;
+												wr[3] = (float(((int8_t *)br)[3]) / 127.0);
+											} else {
+												wr[0] += br[0] * weight;
+												wr[1] += br[1] * weight;
+												wr[2] += br[2] * weight;
+												wr[3] = br[3];
+											}
 										}
 									} break;
 									case VS::ARRAY_COLOR: {