diff options
Diffstat (limited to 'drivers/gles3/storage/mesh_storage.cpp')
-rw-r--r-- | drivers/gles3/storage/mesh_storage.cpp | 308 |
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); } } |