Remove requirement to have vertex positions when creating a mesh. Meshes can now be constructed from an index buffer alone
This commit is contained in:
parent
b35ff86c17
commit
bbbcdd725a
|
@ -867,7 +867,6 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
|||
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.matrix[2][0], cm.matrix[0][0], cm.matrix[2][1], cm.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||
|
||||
// Bind a vertex array or else OpenGL complains. We won't actually use it
|
||||
glBindVertexArray(sky_globals.screen_triangle_array);
|
||||
|
||||
glViewport(0, 0, sky->radiance_size, sky->radiance_size);
|
||||
|
@ -2150,7 +2149,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
index_array_gl = mesh_storage->mesh_surface_get_index_buffer(mesh_surface, surf->lod_index);
|
||||
|
||||
if (prev_vertex_array_gl != vertex_array_gl) {
|
||||
glBindVertexArray(vertex_array_gl);
|
||||
if (vertex_array_gl != 0) {
|
||||
glBindVertexArray(vertex_array_gl);
|
||||
}
|
||||
prev_vertex_array_gl = vertex_array_gl;
|
||||
}
|
||||
|
||||
|
|
|
@ -1450,8 +1450,8 @@ MaterialStorage::MaterialStorage() {
|
|||
actions.renames["UV2"] = "uv2_interp";
|
||||
actions.renames["COLOR"] = "color_interp";
|
||||
actions.renames["POINT_SIZE"] = "gl_PointSize";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
|
||||
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceID";
|
||||
actions.renames["VERTEX_ID"] = "gl_VertexID";
|
||||
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
|
||||
|
|
|
@ -186,11 +186,13 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
s->format = p_surface.format;
|
||||
s->primitive = p_surface.primitive;
|
||||
|
||||
glGenBuffers(1, &s->vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
|
||||
glBufferData(GL_ARRAY_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);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
s->vertex_buffer_size = p_surface.vertex_data.size();
|
||||
if (p_surface.vertex_data.size()) {
|
||||
glGenBuffers(1, &s->vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
|
||||
glBufferData(GL_ARRAY_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);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
s->vertex_buffer_size = p_surface.vertex_data.size();
|
||||
}
|
||||
|
||||
if (p_surface.attribute_data.size()) {
|
||||
glGenBuffers(1, &s->attribute_buffer);
|
||||
|
@ -214,7 +216,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
}
|
||||
|
||||
if (p_surface.index_count) {
|
||||
bool is_index_16 = p_surface.vertex_count <= 65536;
|
||||
bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
|
||||
glGenBuffers(1, &s->index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW);
|
||||
|
@ -238,6 +240,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(!p_surface.index_count && !p_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.
|
||||
|
||||
|
@ -340,7 +344,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
|
|||
|
||||
RS::SurfaceData sd;
|
||||
sd.format = s.format;
|
||||
sd.vertex_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
|
||||
if (s.vertex_buffer != 0) {
|
||||
sd.vertex_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
|
||||
}
|
||||
|
||||
if (s.attribute_buffer != 0) {
|
||||
sd.attribute_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size);
|
||||
|
|
|
@ -75,7 +75,7 @@ struct Mesh {
|
|||
// Cache vertex arrays so they can be created
|
||||
struct Version {
|
||||
uint32_t input_mask = 0;
|
||||
GLuint vertex_array;
|
||||
GLuint vertex_array = 0;
|
||||
|
||||
Attrib attribs[RS::ARRAY_MAX];
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ struct Mesh {
|
|||
float edge_length = 0.0;
|
||||
uint32_t index_count = 0;
|
||||
uint32_t index_buffer_size = 0;
|
||||
GLuint index_buffer;
|
||||
GLuint index_buffer = 0;
|
||||
};
|
||||
|
||||
LOD *lods = nullptr;
|
||||
|
@ -175,7 +175,7 @@ struct MultiMesh {
|
|||
bool *data_cache_dirty_regions = nullptr;
|
||||
uint32_t data_cache_used_dirty_regions = 0;
|
||||
|
||||
GLuint buffer;
|
||||
GLuint buffer = 0;
|
||||
|
||||
bool dirty = false;
|
||||
MultiMesh *dirty_list = nullptr;
|
||||
|
@ -362,7 +362,7 @@ public:
|
|||
_FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
|
||||
return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||
return (s->vertex_count <= 65536 && s->vertex_count > 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
// Use this to cache Vertex Array Objects so they are only generated once
|
||||
|
|
|
@ -7805,12 +7805,6 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
|
|||
ERR_FAIL_COND_MSG(!dl->validation.index_array_size,
|
||||
"Draw command requested indices, but no index buffer was set.");
|
||||
|
||||
if (dl->validation.pipeline_vertex_format != INVALID_ID) {
|
||||
// Uses vertices, do some vertex validations.
|
||||
ERR_FAIL_COND_MSG(dl->validation.vertex_array_size < dl->validation.index_array_max_index,
|
||||
"Index array references (max index: " + itos(dl->validation.index_array_max_index) + ") indices beyond the vertex array size (" + itos(dl->validation.vertex_array_size) + ").");
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices,
|
||||
"The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
|
||||
#endif
|
||||
|
|
|
@ -201,7 +201,9 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
|
|||
continue;
|
||||
}
|
||||
int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i);
|
||||
if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3)) {
|
||||
if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) ||
|
||||
(primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3) ||
|
||||
(surface_get_format(i) & ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) {
|
||||
// Error was already shown, just skip (including zero).
|
||||
continue;
|
||||
}
|
||||
|
@ -211,6 +213,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
|
|||
|
||||
int vc = surface_get_array_len(i);
|
||||
Vector<Vector3> vertices = a[ARRAY_VERTEX];
|
||||
ERR_FAIL_COND_V(vertices.is_empty(), Ref<TriangleMesh>());
|
||||
const Vector3 *vr = vertices.ptr();
|
||||
|
||||
int32_t from_index = widx / 3;
|
||||
|
|
|
@ -144,6 +144,7 @@ public:
|
|||
ARRAY_FLAG_USE_DYNAMIC_UPDATE = RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE,
|
||||
ARRAY_FLAG_USE_8_BONE_WEIGHTS = RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS,
|
||||
|
||||
ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY,
|
||||
};
|
||||
|
||||
virtual int get_surface_count() const;
|
||||
|
|
|
@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
|
||||
bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
|
||||
|
||||
s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
|
||||
s->vertex_buffer_size = p_surface.vertex_data.size();
|
||||
if (p_surface.vertex_data.size()) {
|
||||
s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
|
||||
s->vertex_buffer_size = p_surface.vertex_data.size();
|
||||
}
|
||||
|
||||
if (p_surface.attribute_data.size()) {
|
||||
s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
|
||||
|
@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
}
|
||||
|
||||
if (p_surface.index_count) {
|
||||
bool is_index_16 = p_surface.vertex_count <= 65536;
|
||||
bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
|
||||
|
||||
s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
|
||||
s->index_count = p_surface.index_count;
|
||||
|
@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(!p_surface.index_count && !p_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.
|
||||
|
||||
|
@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
RD::Uniform u;
|
||||
u.binding = 0;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.append_id(s->vertex_buffer);
|
||||
if (s->vertex_buffer.is_valid()) {
|
||||
u.append_id(s->vertex_buffer);
|
||||
} else {
|
||||
u.append_id(default_rd_storage_buffer);
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
|
@ -470,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i
|
|||
ERR_FAIL_COND(!mesh);
|
||||
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
|
||||
ERR_FAIL_COND(p_data.size() == 0);
|
||||
ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null());
|
||||
uint64_t data_size = p_data.size();
|
||||
const uint8_t *r = p_data.ptr();
|
||||
|
||||
|
@ -527,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
|
|||
|
||||
RS::SurfaceData sd;
|
||||
sd.format = s.format;
|
||||
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
|
||||
if (s.vertex_buffer.is_valid()) {
|
||||
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
|
||||
}
|
||||
if (s.attribute_buffer.is_valid()) {
|
||||
sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
|
||||
}
|
||||
|
@ -705,7 +716,9 @@ void MeshStorage::mesh_clear(RID p_mesh) {
|
|||
ERR_FAIL_COND(!mesh);
|
||||
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
||||
Mesh::Surface &s = *mesh->surfaces[i];
|
||||
RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
|
||||
if (s.vertex_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
|
||||
}
|
||||
if (s.attribute_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(s.attribute_buffer);
|
||||
}
|
||||
|
@ -851,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
|
|||
}
|
||||
|
||||
MeshInstance::Surface s;
|
||||
if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
|
||||
if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
|
||||
//surface warrants transform
|
||||
s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
|
||||
|
||||
|
|
|
@ -627,7 +627,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
|
|||
const int *src = indices.ptr();
|
||||
|
||||
for (int i = 0; i < p_index_array_len; i++) {
|
||||
if (p_vertex_array_len < (1 << 16)) {
|
||||
if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) {
|
||||
uint16_t v = src[i];
|
||||
|
||||
memcpy(&iw[i * 2], &v, 2);
|
||||
|
@ -836,9 +836,8 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
|
|||
break;
|
||||
}
|
||||
/* determine whether using 16 or 32 bits indices */
|
||||
if (p_vertex_len >= (1 << 16)) {
|
||||
if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) {
|
||||
elem_size = 4;
|
||||
|
||||
} else {
|
||||
elem_size = 2;
|
||||
}
|
||||
|
@ -909,8 +908,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
|
|||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory
|
||||
|
||||
if (p_blend_shapes.size()) {
|
||||
// Validate format for morphs.
|
||||
for (int i = 0; i < p_blend_shapes.size(); i++) {
|
||||
|
@ -944,6 +941,12 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
|
|||
uint32_t mask = (1 << ARRAY_MAX) - 1;
|
||||
format |= (~mask) & p_compress_format; // Make the full format.
|
||||
|
||||
if ((format & RS::ARRAY_FORMAT_VERTEX) == 0 && !(format & RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) {
|
||||
ERR_PRINT("Mesh created without vertex array. This mesh will not be visible with the default shader. If using an empty vertex array is intentional, create the mesh with the ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY flag to silence this error.");
|
||||
// Set the flag here after warning to suppress errors down the pipeline.
|
||||
format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY;
|
||||
}
|
||||
|
||||
int vertex_array_size = vertex_element_size * array_len;
|
||||
int attrib_array_size = attrib_element_size * array_len;
|
||||
int skin_array_size = skin_element_size * array_len;
|
||||
|
@ -1378,7 +1381,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
|
|||
Vector<uint8_t> attrib_data = p_data.attribute_data;
|
||||
Vector<uint8_t> skin_data = p_data.skin_data;
|
||||
|
||||
ERR_FAIL_COND_V(vertex_data.size() == 0, Array());
|
||||
ERR_FAIL_COND_V(vertex_data.size() == 0 && (p_data.format & RS::ARRAY_FORMAT_VERTEX), Array());
|
||||
int vertex_len = p_data.vertex_count;
|
||||
|
||||
Vector<uint8_t> index_data = p_data.index_data;
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
|
||||
enum ArrayFormat {
|
||||
/* ARRAY FORMAT FLAGS */
|
||||
ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory
|
||||
ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX,
|
||||
ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
|
||||
ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
|
||||
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
|
||||
|
@ -262,17 +262,19 @@ public:
|
|||
|
||||
ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1),
|
||||
ARRAY_FORMAT_CUSTOM_BITS = 3,
|
||||
ARRAY_FORMAT_CUSTOM_MASK = 0x7,
|
||||
ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0),
|
||||
ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS),
|
||||
ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2),
|
||||
ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3),
|
||||
|
||||
ARRAY_FORMAT_CUSTOM_MASK = 0x7,
|
||||
ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12),
|
||||
|
||||
ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0),
|
||||
ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1),
|
||||
ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2),
|
||||
|
||||
ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = 1 << (ARRAY_INDEX + 1 + 15),
|
||||
};
|
||||
|
||||
enum PrimitiveType {
|
||||
|
|
Loading…
Reference in New Issue