summaryrefslogtreecommitdiffstats
path: root/drivers/gles3/storage/mesh_storage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/storage/mesh_storage.cpp')
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp308
1 files changed, 188 insertions, 120 deletions
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index cc6031fa57..ae04b63cfe 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -117,34 +117,40 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
uint32_t skin_stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
- if ((p_surface.format & (1 << i))) {
+ if ((p_surface.format & (1ULL << i))) {
switch (i) {
case RS::ARRAY_VERTEX: {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ if ((p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) || (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
stride += sizeof(float) * 2;
} else {
stride += sizeof(float) * 3;
}
-
} break;
case RS::ARRAY_NORMAL: {
stride += sizeof(uint16_t) * 2;
} break;
case RS::ARRAY_TANGENT: {
- stride += sizeof(uint16_t) * 2;
-
+ if (!(p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ stride += sizeof(uint16_t) * 2;
+ }
} break;
case RS::ARRAY_COLOR: {
attrib_stride += sizeof(uint32_t);
} break;
case RS::ARRAY_TEX_UV: {
- attrib_stride += sizeof(float) * 2;
-
+ if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attrib_stride += sizeof(uint16_t) * 2;
+ } else {
+ attrib_stride += sizeof(float) * 2;
+ }
} break;
case RS::ARRAY_TEX_UV2: {
- attrib_stride += sizeof(float) * 2;
-
+ if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attrib_stride += sizeof(uint16_t) * 2;
+ } else {
+ attrib_stride += sizeof(float) * 2;
+ }
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -185,92 +191,121 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
#endif
+ uint64_t surface_version = p_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
+ RS::SurfaceData new_surface = p_surface;
+#ifdef DISABLE_DEPRECATED
+
+ ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION, "Surface version provided (" + itos(int(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT)) + ") does not match current version (" + itos(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) + ")");
+
+#else
+
+ if (surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION)) {
+ RS::_fix_surface_compatibility(new_surface);
+ surface_version = new_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
+ ERR_FAIL_COND_MSG(surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION),
+ "Surface version provided (" +
+ itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
+ ") does not match current version (" +
+ itos((uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION) >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
+ ")");
+ }
+#endif
+
Mesh::Surface *s = memnew(Mesh::Surface);
- s->format = p_surface.format;
- s->primitive = p_surface.primitive;
+ s->format = new_surface.format;
+ s->primitive = new_surface.primitive;
- if (p_surface.vertex_data.size()) {
+ if (new_surface.vertex_data.size()) {
glGenBuffers(1, &s->vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer");
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, new_surface.vertex_data.size(), new_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer");
+ s->vertex_buffer_size = new_surface.vertex_data.size();
}
- if (p_surface.attribute_data.size()) {
+ if (new_surface.attribute_data.size()) {
glGenBuffers(1, &s->attribute_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->attribute_buffer, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh attribute buffer");
- s->attribute_buffer_size = p_surface.attribute_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->attribute_buffer, new_surface.attribute_data.size(), new_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh attribute buffer");
+ s->attribute_buffer_size = new_surface.attribute_data.size();
}
- if (p_surface.skin_data.size()) {
+ if (new_surface.skin_data.size()) {
glGenBuffers(1, &s->skin_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->skin_buffer, p_surface.skin_data.size(), p_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh skin buffer");
- s->skin_buffer_size = p_surface.skin_data.size();
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->skin_buffer, new_surface.skin_data.size(), new_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh skin buffer");
+ s->skin_buffer_size = new_surface.skin_data.size();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
- s->vertex_count = p_surface.vertex_count;
+ s->vertex_count = new_surface.vertex_count;
- if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
+ if (new_surface.format & RS::ARRAY_FORMAT_BONES) {
mesh->has_bone_weights = true;
}
- if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
+ if (new_surface.index_count) {
+ bool is_index_16 = new_surface.vertex_count <= 65536 && new_surface.vertex_count > 0;
glGenBuffers(1, &s->index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer, new_surface.index_data.size(), new_surface.index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
- s->index_count = p_surface.index_count;
- s->index_buffer_size = p_surface.index_data.size();
+ s->index_count = new_surface.index_count;
+ s->index_buffer_size = new_surface.index_data.size();
- if (p_surface.lods.size()) {
- s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
- s->lod_count = p_surface.lods.size();
+ if (new_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, new_surface.lods.size());
+ s->lod_count = new_surface.lods.size();
- for (int i = 0; i < p_surface.lods.size(); i++) {
+ for (int i = 0; i < new_surface.lods.size(); i++) {
glGenBuffers(1, &s->lods[i].index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer, p_surface.lods[i].index_data.size(), p_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer LOD[" + itos(i) + "]");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer, new_surface.lods[i].index_data.size(), new_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer LOD[" + itos(i) + "]");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
- s->lods[i].edge_length = p_surface.lods[i].edge_length;
- s->lods[i].index_count = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
- s->lods[i].index_buffer_size = p_surface.lods[i].index_data.size();
+ s->lods[i].edge_length = new_surface.lods[i].edge_length;
+ s->lods[i].index_count = new_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer_size = new_surface.lods[i].index_data.size();
}
}
}
- ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+ ERR_FAIL_COND_MSG(!new_surface.index_count && !new_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
- s->aabb = p_surface.aabb;
- s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+ s->aabb = new_surface.aabb;
+ s->bone_aabbs = new_surface.bone_aabbs; //only really useful for returning them.
- if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
+ s->uv_scale = new_surface.uv_scale;
+
+ if (new_surface.skin_data.size() || mesh->blend_shape_count > 0) {
// Size must match the size of the vertex array.
- int size = p_surface.vertex_data.size();
+ int size = new_surface.vertex_data.size();
int vertex_size = 0;
- int stride = 0;
+ int position_stride = 0;
+ int normal_tangent_stride = 0;
int normal_offset = 0;
int tangent_offset = 0;
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_VERTEX))) {
+ if (new_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
vertex_size = 2;
+ position_stride = sizeof(float) * vertex_size;
} else {
- vertex_size = 3;
+ if (new_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ vertex_size = 4;
+ position_stride = sizeof(uint16_t) * vertex_size;
+ } else {
+ vertex_size = 3;
+ position_stride = sizeof(float) * vertex_size;
+ }
}
- stride = sizeof(float) * vertex_size;
}
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
- normal_offset = stride;
- stride += sizeof(uint16_t) * 2;
+ if ((new_surface.format & (1ULL << RS::ARRAY_NORMAL))) {
+ normal_offset = position_stride * s->vertex_count;
+ normal_tangent_stride += sizeof(uint16_t) * 2;
}
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
- tangent_offset = stride;
- stride += sizeof(uint16_t) * 2;
+ if ((new_surface.format & (1ULL << RS::ARRAY_TANGENT))) {
+ tangent_offset = normal_offset + normal_tangent_stride;
+ normal_tangent_stride += sizeof(uint16_t) * 2;
}
if (mesh->blend_shape_count > 0) {
@@ -282,54 +317,38 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindVertexArray(s->blend_shapes[i].vertex_array);
glGenBuffers(1, &s->blend_shapes[i].vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer, size, p_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh blend shape buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer, size, new_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh blend shape buffer");
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_VERTEX))) {
glEnableVertexAttribArray(RS::ARRAY_VERTEX + 3);
- glVertexAttribPointer(RS::ARRAY_VERTEX + 3, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(RS::ARRAY_VERTEX + 3, vertex_size, GL_FLOAT, GL_FALSE, position_stride, CAST_INT_TO_UCHAR_PTR(0));
}
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
+ if ((new_surface.format & (1ULL << RS::ARRAY_NORMAL))) {
+ // Normal and tangent are packed into the same attribute.
glEnableVertexAttribArray(RS::ARRAY_NORMAL + 3);
- glVertexAttribPointer(RS::ARRAY_NORMAL + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
+ glVertexAttribPointer(RS::ARRAY_NORMAL + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, normal_tangent_stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
}
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
+ if ((p_surface.format & (1ULL << RS::ARRAY_TANGENT))) {
glEnableVertexAttribArray(RS::ARRAY_TANGENT + 3);
- glVertexAttribPointer(RS::ARRAY_TANGENT + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
+ glVertexAttribPointer(RS::ARRAY_TANGENT + 3, 2, GL_UNSIGNED_SHORT, GL_TRUE, normal_tangent_stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
}
}
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
- // Create a vertex array to use for skeleton/blend shapes.
- glGenVertexArrays(1, &s->skeleton_vertex_array);
- glBindVertexArray(s->skeleton_vertex_array);
- glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
-
- if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) {
- glEnableVertexAttribArray(RS::ARRAY_VERTEX);
- glVertexAttribPointer(RS::ARRAY_VERTEX, vertex_size, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
- }
- if ((p_surface.format & (1 << RS::ARRAY_NORMAL))) {
- glEnableVertexAttribArray(RS::ARRAY_NORMAL);
- glVertexAttribPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(normal_offset));
- }
- if ((p_surface.format & (1 << RS::ARRAY_TANGENT))) {
- glEnableVertexAttribArray(RS::ARRAY_TANGENT);
- glVertexAttribPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(tangent_offset));
- }
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (mesh->surface_count == 0) {
- mesh->aabb = p_surface.aabb;
+ mesh->aabb = new_surface.aabb;
} else {
- mesh->aabb.merge_with(p_surface.aabb);
+ mesh->aabb.merge_with(new_surface.aabb);
}
mesh->skeleton_aabb_version = 0;
- s->material = p_surface.material;
+ s->material = new_surface.material;
mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
mesh->surfaces[mesh->surface_count] = s;
@@ -479,6 +498,8 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
}
}
+ sd.uv_scale = s.uv_scale;
+
return sd;
}
@@ -696,10 +717,6 @@ void MeshStorage::mesh_clear(RID p_mesh) {
}
memdelete_arr(s.blend_shapes);
}
- if (s.skeleton_vertex_array != 0) {
- glDeleteVertexArrays(1, &s.skeleton_vertex_array);
- s.skeleton_vertex_array = 0;
- }
memdelete(mesh->surfaces[i]);
}
@@ -720,15 +737,16 @@ void MeshStorage::mesh_clear(RID p_mesh) {
}
}
-void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
+void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, MeshInstance::Surface *mis) {
Mesh::Surface::Attrib attribs[RS::ARRAY_MAX];
+ int position_stride = 0; // Vertex position only.
+ int normal_tangent_stride = 0;
int attributes_stride = 0;
- int vertex_stride = 0;
int skin_stride = 0;
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
- if (!(s->format & (1 << i))) {
+ if (!(s->format & (1ULL << i))) {
attribs[i].enabled = false;
attribs[i].integer = false;
continue;
@@ -739,29 +757,55 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
switch (i) {
case RS::ARRAY_VERTEX: {
- attribs[i].offset = vertex_stride;
+ attribs[i].offset = 0;
+ attribs[i].type = GL_FLOAT;
+ attribs[i].normalized = GL_FALSE;
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
attribs[i].size = 2;
+ position_stride = attribs[i].size * sizeof(float);
} else {
- attribs[i].size = 3;
+ if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ attribs[i].size = 4;
+ position_stride = attribs[i].size * sizeof(uint16_t);
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].size = 3;
+ position_stride = attribs[i].size * sizeof(float);
+ }
}
- attribs[i].type = GL_FLOAT;
- vertex_stride += attribs[i].size * sizeof(float);
- attribs[i].normalized = GL_FALSE;
} break;
case RS::ARRAY_NORMAL: {
- attribs[i].offset = vertex_stride;
- attribs[i].size = 2;
+ if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
+ attribs[i].size = 2;
+ normal_tangent_stride += 2 * attribs[i].size;
+ } else {
+ attribs[i].size = 4;
+ // A small trick here: if we are uncompressed and we have normals, but no tangents. We need
+ // the shader to think there are 4 components to "axis_tangent_attrib". So we give a size of 4,
+ // but a stride based on only having 2 elements.
+ if (!(s->format & RS::ARRAY_FORMAT_TANGENT)) {
+ normal_tangent_stride += (mis ? sizeof(float) : sizeof(uint16_t)) * 2;
+ } else {
+ normal_tangent_stride += (mis ? sizeof(float) : sizeof(uint16_t)) * 4;
+ }
+ }
+
+ if (mis) {
+ // Transform feedback has interleave all or no attributes. It can't mix interleaving.
+ attribs[i].offset = position_stride;
+ normal_tangent_stride += position_stride;
+ position_stride = normal_tangent_stride;
+ } else {
+ attribs[i].offset = position_stride * s->vertex_count;
+ }
attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
- vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
- attribs[i].offset = vertex_stride;
- attribs[i].size = 2;
- attribs[i].type = (mis ? GL_FLOAT : GL_UNSIGNED_SHORT);
- vertex_stride += sizeof(uint16_t) * 2 * (mis ? 2 : 1);
- attribs[i].normalized = GL_TRUE;
+ // We never use the tangent attribute. It is always packed in ARRAY_NORMAL, or ARRAY_VERTEX.
+ attribs[i].enabled = false;
+ attribs[i].integer = false;
} break;
case RS::ARRAY_COLOR: {
attribs[i].offset = attributes_stride;
@@ -773,16 +817,28 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
case RS::ARRAY_TEX_UV: {
attribs[i].offset = attributes_stride;
attribs[i].size = 2;
- attribs[i].type = GL_FLOAT;
- attributes_stride += 2 * sizeof(float);
- attribs[i].normalized = GL_FALSE;
+ if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attributes_stride += 2 * sizeof(uint16_t);
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].type = GL_FLOAT;
+ attributes_stride += 2 * sizeof(float);
+ attribs[i].normalized = GL_FALSE;
+ }
} break;
case RS::ARRAY_TEX_UV2: {
attribs[i].offset = attributes_stride;
attribs[i].size = 2;
- attribs[i].type = GL_FLOAT;
- attributes_stride += 2 * sizeof(float);
- attribs[i].normalized = GL_FALSE;
+ if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ attributes_stride += 2 * sizeof(uint16_t);
+ attribs[i].normalized = GL_TRUE;
+ } else {
+ attribs[i].type = GL_FLOAT;
+ attributes_stride += 2 * sizeof(float);
+ attribs[i].normalized = GL_FALSE;
+ }
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -828,7 +884,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
continue;
}
if (i <= RS::ARRAY_TANGENT) {
- attribs[i].stride = vertex_stride;
+ attribs[i].stride = (i == RS::ARRAY_VERTEX) ? position_stride : normal_tangent_stride;
if (mis) {
glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer);
} else {
@@ -946,7 +1002,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
// Cache surface properties
s.format_cache = mesh->surfaces[p_surface]->format;
- if ((s.format_cache & (1 << RS::ARRAY_VERTEX))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_VERTEX))) {
if (s.format_cache & RS::ARRAY_FLAG_USE_2D_VERTICES) {
s.vertex_size_cache = 2;
} else {
@@ -954,25 +1010,27 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
s.vertex_stride_cache = sizeof(float) * s.vertex_size_cache;
}
- if ((s.format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_NORMAL))) {
s.vertex_normal_offset_cache = s.vertex_stride_cache;
s.vertex_stride_cache += sizeof(uint32_t) * 2;
}
- if ((s.format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((s.format_cache & (1ULL << RS::ARRAY_TANGENT))) {
s.vertex_tangent_offset_cache = s.vertex_stride_cache;
s.vertex_stride_cache += sizeof(uint32_t) * 2;
}
+ int buffer_size = s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count;
+
// Buffer to be used for rendering. Final output of skeleton and blend shapes.
glGenBuffers(1, &s.vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance vertex buffer");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffer, buffer_size, nullptr, GL_DYNAMIC_DRAW, "MeshInstance vertex buffer");
if (mesh->blend_shape_count > 0) {
// Ping-Pong buffers for processing blendshapes.
glGenBuffers(2, s.vertex_buffers);
for (uint32_t i = 0; i < 2; i++) {
glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffers[i]);
- GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffers[i], s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance process buffer[" + itos(i) + "]");
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffers[i], buffer_size, nullptr, GL_DYNAMIC_DRAW, "MeshInstance process buffer[" + itos(i) + "]");
}
}
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
@@ -1011,19 +1069,19 @@ void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, c
void MeshStorage::_blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface) {
glBindBuffer(GL_ARRAY_BUFFER, p_mi->surfaces[p_surface].vertex_buffers[0]);
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_VERTEX))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_VERTEX))) {
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
glVertexAttribPointer(RS::ARRAY_VERTEX, p_mi->surfaces[p_surface].vertex_size_cache, GL_FLOAT, GL_FALSE, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(0));
} else {
glDisableVertexAttribArray(RS::ARRAY_VERTEX);
}
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
glEnableVertexAttribArray(RS::ARRAY_NORMAL);
glVertexAttribIPointer(RS::ARRAY_NORMAL, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_normal_offset_cache));
} else {
glDisableVertexAttribArray(RS::ARRAY_NORMAL);
}
- if ((p_mi->surfaces[p_surface].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((p_mi->surfaces[p_surface].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
glEnableVertexAttribArray(RS::ARRAY_TANGENT);
glVertexAttribIPointer(RS::ARRAY_TANGENT, 2, GL_UNSIGNED_INT, p_mi->surfaces[p_surface].vertex_stride_cache, CAST_INT_TO_UCHAR_PTR(p_mi->surfaces[p_surface].vertex_tangent_offset_cache));
} else {
@@ -1091,7 +1149,7 @@ void MeshStorage::update_mesh_instances() {
}
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].vertex_buffer == 0 || mi->mesh->surfaces[i]->skeleton_vertex_array == 0) {
+ if (mi->surfaces[i].vertex_buffer == 0) {
continue;
}
@@ -1106,10 +1164,10 @@ void MeshStorage::update_mesh_instances() {
specialization |= array_is_2d ? SkeletonShaderGLES3::MODE_2D : 0;
specialization |= SkeletonShaderGLES3::USE_BLEND_SHAPES;
if (!array_is_2d) {
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
specialization |= SkeletonShaderGLES3::USE_NORMAL;
}
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
specialization |= SkeletonShaderGLES3::USE_TANGENT;
}
}
@@ -1123,7 +1181,12 @@ void MeshStorage::update_mesh_instances() {
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ GLuint vertex_array_gl = 0;
+ uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
+ mask = ~mask;
+ uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+ mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
+ glBindVertexArray(vertex_array_gl);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[0]);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, mi->mesh->surfaces[i]->vertex_count);
@@ -1210,10 +1273,10 @@ void MeshStorage::update_mesh_instances() {
specialization |= SkeletonShaderGLES3::FINAL_PASS;
specialization |= use_8_weights ? SkeletonShaderGLES3::USE_EIGHT_WEIGHTS : 0;
if (!array_is_2d) {
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_NORMAL))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_NORMAL))) {
specialization |= SkeletonShaderGLES3::USE_NORMAL;
}
- if ((mi->surfaces[i].format_cache & (1 << RS::ARRAY_TANGENT))) {
+ if ((mi->surfaces[i].format_cache & (1ULL << RS::ARRAY_TANGENT))) {
specialization |= SkeletonShaderGLES3::USE_TANGENT;
}
}
@@ -1233,7 +1296,12 @@ void MeshStorage::update_mesh_instances() {
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_Y, inverse_transform[1], skeleton_shader.shader_version, variant, specialization);
skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization);
- glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array);
+ GLuint vertex_array_gl = 0;
+ uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
+ mask = ~mask;
+ uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+ mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
+ glBindVertexArray(vertex_array_gl);
_compute_skeleton(mi, sk, i);
}
}