mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									a1cc6b45dc
								
							
						
					
					
						commit
						479391ef54
					
				
					 18 changed files with 395 additions and 308 deletions
				
			
		|  | @ -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; | ||||
| 				RID mesh; | ||||
| 				RID mesh_instance; | ||||
| 				RID texture; | ||||
| 				Color modulate(1, 1, 1, 1); | ||||
| 				float world_backup[6]; | ||||
| 				int instance_count = 1; | ||||
| 
 | ||||
| #if 0 | ||||
| 			case Item::Command::TYPE_MESH: { | ||||
| 				Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(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); | ||||
| 				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); | ||||
| 				if (c->type == Item::Command::TYPE_MESH) { | ||||
| 					const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(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<const Item::CommandMultiMesh *>(c); | ||||
| 					RID multimesh = mm->multimesh; | ||||
| 					mesh = storage->multimesh_get_mesh(multimesh); | ||||
| 					texture = mm->texture; | ||||
| 
 | ||||
| 				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 (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); | ||||
| 						} | ||||
| 
 | ||||
| 						glBindVertexArray(0); | ||||
| 					if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { | ||||
| 						break; | ||||
| 					} | ||||
| 
 | ||||
| 					instance_count = storage->multimesh_get_instances_to_draw(multimesh); | ||||
| 
 | ||||
| 					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; | ||||
| 					} | ||||
| 					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<const Item::CommandParticles *>(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); | ||||
| 
 | ||||
| 					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); | ||||
| 
 | ||||
| 					push_constant.flags |= divisor; | ||||
| 					instance_count /= divisor; | ||||
| 
 | ||||
| 					push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; | ||||
| 					push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; | ||||
| 
 | ||||
| 					mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
 | ||||
| 					texture = pt->texture; | ||||
| 				} | ||||
| 				state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); | ||||
| 
 | ||||
| 			} break; | ||||
| 			case Item::Command::TYPE_MULTIMESH: { | ||||
| 				Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(c); | ||||
| 
 | ||||
| 				RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); | ||||
| 
 | ||||
| 				if (!multi_mesh) | ||||
| 				if (mesh.is_null()) { | ||||
| 					break; | ||||
| 
 | ||||
| 				RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); | ||||
| 
 | ||||
| 				if (!mesh_data) | ||||
| 					break; | ||||
| 
 | ||||
| 				RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); | ||||
| 
 | ||||
| 				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); | ||||
| 
 | ||||
| 				if (texture) { | ||||
| 					Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); | ||||
| 					state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); | ||||
| 				} | ||||
| 
 | ||||
| 				int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); | ||||
| 				_bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); | ||||
| 
 | ||||
| 				if (amount == -1) { | ||||
| 					amount = multi_mesh->size; | ||||
| 				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 }; | ||||
| 
 | ||||
| 				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; | ||||
| 
 | ||||
| 				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; | ||||
| 					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->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; | ||||
| 					RID index_array = storage->mesh_surface_get_index_array(surface, 0); | ||||
| 
 | ||||
| 						} 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; | ||||
| 					if (index_array.is_valid()) { | ||||
| 						RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array); | ||||
| 					} | ||||
| 
 | ||||
| 					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); | ||||
| 					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)); | ||||
| 
 | ||||
| 						} 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; | ||||
| 					} | ||||
| 
 | ||||
| 					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); | ||||
| 					} | ||||
| 
 | ||||
| 					glBindVertexArray(0); | ||||
| 					RD::get_singleton()->draw_list_draw(p_draw_list, index_array.is_valid(), instance_count); | ||||
| 				} | ||||
| 
 | ||||
| 				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); | ||||
| 				for (int j = 0; j < 6; j++) { | ||||
| 					push_constant.world[j] = world_backup[j]; | ||||
| 				} | ||||
| 
 | ||||
| 			} break; | ||||
| 			case Item::Command::TYPE_PARTICLES: { | ||||
| 				Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(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(); | ||||
| 
 | ||||
| 					state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); | ||||
| 				} | ||||
| 
 | ||||
| 				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); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				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<const Item::CommandTransform *>(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<const Item::CommandMesh *>(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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 reduz
						reduz