Make 2D particles work OOTB (again)

This commit is contained in:
JFonS 2018-11-13 18:19:16 +01:00
parent 7f347cc31a
commit cbfb7bd613
8 changed files with 95 additions and 22 deletions

View file

@ -967,6 +967,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
//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;
@ -977,6 +978,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
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) {
@ -1066,6 +1069,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
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);

View file

@ -138,6 +138,11 @@ void main() {
highp vec4 outvec = vec4(vertex, 0.0, 1.0);
#endif
#ifdef USE_PARTICLES
//scale by texture size
outvec.xy /= color_texpixel_size;
#endif
#define extra_matrix extra_matrix_instance
{

View file

@ -123,8 +123,6 @@ void CanvasItemMaterial::_update_shader() {
code += "\tfloat h_frames = float(particles_anim_h_frames);\n";
code += "\tfloat v_frames = float(particles_anim_v_frames);\n";
code += "\tVERTEX.xy /= TEXTURE_PIXEL_SIZE * vec2(h_frames, v_frames);\n";
code += "\tint total_frames = particles_anim_h_frames * particles_anim_v_frames;\n";
code += "\tint frame = int(float(total_frames) * INSTANCE_CUSTOM.z);\n";
code += "\tif (particles_anim_loop) {\n";

View file

@ -153,13 +153,19 @@ CPUParticles2D::DrawOrder CPUParticles2D::get_draw_order() const {
return draw_order;
}
void CPUParticles2D::_generate_mesh_texture() {
void CPUParticles2D::_update_mesh_texture() {
Size2 tex_size;
if (texture.is_valid()) {
tex_size = texture->get_size();
} else {
tex_size = Size2(1, 1);
}
PoolVector<Vector2> vertices;
vertices.push_back(Vector2(-0.5, -0.5));
vertices.push_back(Vector2(0.5, -0.5));
vertices.push_back(Vector2(0.5, 0.5));
vertices.push_back(Vector2(-0.5, 0.5));
vertices.push_back(-tex_size * 0.5);
vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, 0));
vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, tex_size.y));
vertices.push_back(-tex_size * 0.5 + Vector2(0, tex_size.y));
PoolVector<Vector2> uvs;
uvs.push_back(Vector2(0, 0));
uvs.push_back(Vector2(1, 0));
@ -193,6 +199,7 @@ void CPUParticles2D::set_texture(const Ref<Texture> &p_texture) {
texture = p_texture;
update();
_update_mesh_texture();
}
Ref<Texture> CPUParticles2D::get_texture() const {
@ -234,9 +241,12 @@ String CPUParticles2D::get_configuration_warning() const {
CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr());
if (get_material().is_null() || (mat && !mat->get_particles_animation())) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.");
if (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 ||
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid()) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.");
}
}
return warnings;
@ -1396,7 +1406,7 @@ CPUParticles2D::CPUParticles2D() {
update_mutex = Mutex::create();
#endif
_generate_mesh_texture();
_update_mesh_texture();
}
CPUParticles2D::~CPUParticles2D() {

View file

@ -177,7 +177,7 @@ private:
void _update_render_thread();
void _generate_mesh_texture();
void _update_mesh_texture();
protected:
static void _bind_methods();
@ -222,15 +222,6 @@ public:
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
void set_h_frames(int p_frames);
int get_h_frames();
void set_v_frames(int p_frames);
int get_v_frames();
void set_loop_animation(bool p_loop);
bool get_loop_animation() const;
void set_normalmap(const Ref<Texture> &p_normalmap);
Ref<Texture> get_normalmap() const;

View file

@ -219,6 +219,20 @@ String Particles2D::get_configuration_warning() const {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted.");
} else {
CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr());
if (get_material().is_null() || (mat && !mat->get_particles_animation())) {
const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr());
if (process &&
(process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 ||
process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.");
}
}
}
return warnings;

View file

@ -198,6 +198,35 @@ String CPUParticles::get_configuration_warning() const {
String warnings;
bool mesh_found = false;
bool anim_material_found = false;
if (get_mesh().is_valid()) {
mesh_found = true;
for (int j = 0; j < get_mesh()->get_surface_count(); j++) {
anim_material_found = Object::cast_to<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != NULL;
SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_mesh()->surface_get_material(j).ptr());
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
}
}
anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL;
SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_material_override().ptr());
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
if (!mesh_found) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("Nothing is visible because no mesh has not been assigned.");
}
if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 ||
get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("CPUParticles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled.");
}
return warnings;
}

View file

@ -29,6 +29,7 @@
/*************************************************************************/
#include "particles.h"
#include "scene/resources/particles_material.h"
#include "servers/visual_server.h"
@ -226,15 +227,27 @@ String Particles::get_configuration_warning() const {
String warnings;
bool meshes_found = false;
bool anim_material_found = false;
for (int i = 0; i < draw_passes.size(); i++) {
if (draw_passes[i].is_valid()) {
meshes_found = true;
break;
for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) {
anim_material_found = Object::cast_to<ShaderMaterial>(draw_passes[i]->surface_get_material(j).ptr()) != NULL;
SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(draw_passes[i]->surface_get_material(j).ptr());
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
}
if (meshes_found && anim_material_found) break;
}
}
anim_material_found = anim_material_found || Object::cast_to<ShaderMaterial>(get_material_override().ptr()) != NULL;
SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(get_material_override().ptr());
anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES);
if (!meshes_found) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes.");
}
@ -242,6 +255,15 @@ String Particles::get_configuration_warning() const {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted.");
} else {
const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr());
if (!anim_material_found && process &&
(process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 ||
process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) {
if (warnings != String())
warnings += "\n";
warnings += "- " + TTR("Particles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled.");
}
}
return warnings;