GLES2 Compression on Blend Shapes Fix

When compressed vertex positions are used in a blend shapes mesh, we
need to make sure we set the w-component of the position vector to 1.0

When octahedral compression is used on normals/tangents, they need to be
converted to cartesian floats to be used for blend shapes

This conversion also changes the number of components of that vertex
attribute, which caused issues because previously there was an
assumption that you had the same number of components in the blend shape
buffer as you did in the original mesh's buffer (which is not true for
oct norm/tang)
This commit is contained in:
Omar El Sheikh 2022-03-06 10:57:05 -05:00
parent b81251d4a9
commit 733a84f7a4
2 changed files with 124 additions and 34 deletions

View file

@ -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;

View file

@ -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: {