From 479391ef5405226fa110ac3f5823ecbc7d987b0c Mon Sep 17 00:00:00 2001 From: reduz Date: Mon, 10 May 2021 13:12:44 -0300 Subject: Fixes missng 2D engine bits -Mesh2D now works -MultiMesh2D now works -Polygon2D now works -Added hooks for processing 2D particles -Skeleton2D now works 2D particles still not working, but stuff needed for it is now implemented. --- .../renderer_rd/renderer_canvas_render_rd.cpp | 368 +++++++-------------- 1 file changed, 122 insertions(+), 246 deletions(-) (limited to 'servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp') diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 377b0fd72d..f448698976 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -705,286 +705,128 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { - ERR_PRINT("FIXME: Mesh, MultiMesh and Particles render commands are unimplemented currently, they need to be ported to the 4.0 rendering architecture."); -#ifndef _MSC_VER -#warning Item::Command types for Mesh, MultiMesh and Particles need to be implemented. -#endif - // See #if 0'ed code below to port from GLES3. - } break; - -#if 0 - case Item::Command::TYPE_MESH: { - Item::CommandMesh *mesh = static_cast(c); - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + RID mesh; + RID mesh_instance; + RID texture; + Color modulate(1, 1, 1, 1); + float world_backup[6]; + int instance_count = 1; + + for (int j = 0; j < 6; j++) { + world_backup[j] = push_constant.world[j]; } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); - if (mesh_data) { - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->array_id); - - glVertexAttrib4f(RS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); + if (c->type == Item::Command::TYPE_MESH) { + const Item::CommandMesh *m = static_cast(c); + mesh = m->mesh; + mesh_instance = m->mesh_instance; + texture = m->texture; + modulate = m->modulate; + _update_transform_2d_to_mat2x3(base_transform * m->transform, push_constant.world); + } else if (c->type == Item::Command::TYPE_MULTIMESH) { + const Item::CommandMultiMesh *mm = static_cast(c); + RID multimesh = mm->multimesh; + mesh = storage->multimesh_get_mesh(multimesh); + texture = mm->texture; + + if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { + break; + } - if (s->index_array_len) { - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } else { - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } + instance_count = storage->multimesh_get_instances_to_draw(multimesh); - glBindVertexArray(0); + RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); + push_constant.flags |= 1; //multimesh, trails disabled + if (storage->multimesh_uses_colors(multimesh)) { + push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; } - } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); + if (storage->multimesh_uses_custom_data(multimesh)) { + push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + } + } else if (c->type == Item::Command::TYPE_PARTICLES) { + const Item::CommandParticles *pt = static_cast(c); + ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D); + if (storage->particles_is_inactive(pt->particles)) { + break; + } + int dpc = storage->particles_get_draw_passes(pt->particles); + if (dpc == 0) { + break; //nothing to draw + } + uint32_t divisor = 1; + instance_count = storage->particles_get_amount(pt->particles, divisor); - } break; - case Item::Command::TYPE_MULTIMESH: { - Item::CommandMultiMesh *mmesh = static_cast(c); + RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); + push_constant.flags |= divisor; + instance_count /= divisor; - if (!multi_mesh) - break; + push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; + push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); + mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored + texture = pt->texture; + } - if (!mesh_data) + if (mesh.is_null()) { break; + } - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); + _bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != RS::MULTIMESH_CUSTOM_DATA_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); + uint32_t surf_count = storage->mesh_get_surface_count(mesh); + static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } + push_constant.modulation[0] = base_color.r * modulate.r; + push_constant.modulation[1] = base_color.g * modulate.g; + push_constant.modulation[2] = base_color.b * modulate.b; + push_constant.modulation[3] = base_color.a * modulate.a; - int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); - - if (amount == -1) { - amount = multi_mesh->size; + for (int j = 0; j < 4; j++) { + push_constant.src_rect[j] = 0; + push_constant.dst_rect[j] = 0; + push_constant.ninepatch_margins[j] = 0; } - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->instancing_array_id); + for (uint32_t j = 0; j < surf_count; j++) { + void *surface = storage->mesh_get_surface(mesh, j); - glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer + RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface); + ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX); - int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); - glVertexAttribDivisor(9, 1); + uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); - int color_ofs; + RID vertex_array; + RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID; - if (multi_mesh->transform_format == RS::MULTIMESH_TRANSFORM_3D) { - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); - glVertexAttribDivisor(10, 1); - color_ofs = 12 * 4; + if (mesh_instance.is_valid()) { + storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); } else { - glDisableVertexAttribArray(10); - glVertexAttrib4f(10, 0, 0, 1, 0); - color_ofs = 8 * 4; + storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); } - int custom_data_ofs = color_ofs; - - switch (multi_mesh->color_format) { - case RS::MULTIMESH_COLOR_NONE: { - glDisableVertexAttribArray(11); - glVertexAttrib4f(11, 1, 1, 1, 1); - } break; - case RS::MULTIMESH_COLOR_8BIT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4; - - } break; - case RS::MULTIMESH_COLOR_FLOAT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4 * 4; - } break; - } + RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - switch (multi_mesh->custom_data_format) { - case RS::MULTIMESH_CUSTOM_DATA_NONE: { - glDisableVertexAttribArray(12); - glVertexAttrib4f(12, 1, 1, 1, 1); - } break; - case RS::MULTIMESH_CUSTOM_DATA_8BIT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - - } break; - case RS::MULTIMESH_CUSTOM_DATA_FLOAT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - } break; - } + RID index_array = storage->mesh_surface_get_index_array(surface, 0); - if (s->index_array_len) { - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - } else { - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); + if (index_array.is_valid()) { + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array); } - glBindVertexArray(0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; - case Item::Command::TYPE_PARTICLES: { - Item::CommandParticles *particles_cmd = static_cast(c); - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); - if (!particles) - break; - - if (particles->inactive && !particles->emitting) - break; - - glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white - - RenderingServerDefault::redraw_request(); - - storage->particles_request_process(particles_cmd->particles); - //enable instancing - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); - } - - if (!particles->use_local_coords) { - Transform2D inv_xf; - inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); - inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); - inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y)); - inv_xf.affine_invert(); + RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, vertex_array); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); + RD::get_singleton()->draw_list_draw(p_draw_list, index_array.is_valid(), instance_count); } - glBindVertexArray(data.particle_quad_array); //use particle quad array - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer - - int stride = sizeof(float) * 4 * 6; - - int amount = particles->amount; - - if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_LIFETIME) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); - } else { - //split - int split = int(Math::ceil(particles->phase * particles->amount)); - - if (amount - split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); - } - - if (split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); - } + for (int j = 0; j < 6; j++) { + push_constant.world[j] = world_backup[j]; } - glBindVertexArray(0); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - } break; -#endif case Item::Command::TYPE_TRANSFORM: { const Item::CommandTransform *transform = static_cast(c); _update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world); @@ -1437,6 +1279,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p Item *canvas_group_owner = nullptr; + bool update_skeletons = false; + while (ci) { if (ci->copy_back_buffer && canvas_group_owner == nullptr) { backbuffer_copy = true; @@ -1472,9 +1316,27 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } } + if (ci->skeleton.is_valid()) { + const Item::Command *c = ci->commands; + + while (c) { + if (c->type == Item::Command::TYPE_MESH) { + const Item::CommandMesh *cm = static_cast(c); + if (cm->mesh_instance.is_valid()) { + storage->mesh_instance_check_for_update(cm->mesh_instance); + update_skeletons = true; + } + } + } + } + if (ci->canvas_group_owner != nullptr) { if (canvas_group_owner == nullptr) { //Canvas group begins here, render until before this item + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; @@ -1494,6 +1356,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } if (ci == canvas_group_owner) { + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true); item_count = 0; @@ -1506,6 +1373,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (backbuffer_copy) { //render anything pending, including clearing if no items + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; @@ -1518,6 +1389,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p items[item_count++] = ci; if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); //then reset item_count = 0; -- cgit v1.2.3