Просмотр исходного кода

Particles properly update the shadow maps, closes #8815

Juan Linietsky 8 лет назад
Родитель
Сommit
e11fae0bbf

+ 19 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -5258,6 +5258,23 @@ void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, c
 	particles->emission_transform = p_transform;
 }
 
+int RasterizerStorageGLES3::particles_get_draw_passes(RID p_particles) const {
+
+	const Particles *particles = particles_owner.getornull(p_particles);
+	ERR_FAIL_COND_V(!particles, 0);
+
+	return particles->draw_passes.size();
+}
+
+RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+
+	const Particles *particles = particles_owner.getornull(p_particles);
+	ERR_FAIL_COND_V(!particles, RID());
+	ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+	return particles->draw_passes[p_pass];
+}
+
 void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_delta) {
 
 	float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime) * particles->speed_scale, (float)1.0);
@@ -5452,6 +5469,8 @@ void RasterizerStorageGLES3::update_particles() {
 
 			particles->particle_valid_histories[0] = true;
 		}
+
+		particles->instance_change_notify(); //make sure shadows are updated
 	}
 
 	glDisable(GL_RASTERIZER_DISCARD);

+ 3 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -1149,6 +1149,9 @@ public:
 	virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform);
 	void _particles_process(Particles *p_particles, float p_delta);
 
+	virtual int particles_get_draw_passes(RID p_particles) const;
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
+
 	/* INSTANCE */
 
 	virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);

+ 3 - 0
servers/visual/rasterizer.h

@@ -465,6 +465,9 @@ public:
 
 	virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0;
 
+	virtual int particles_get_draw_passes(RID p_particles) const = 0;
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
+
 	/* RENDER TARGET */
 
 	enum RenderTargetFlags {

+ 30 - 0
servers/visual/visual_server_scene.cpp

@@ -3323,6 +3323,36 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
 					} else {
 						can_cast_shadows = false;
 					}
+				} else if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
+
+					bool cast_shadows = false;
+
+					int dp = VSG::storage->particles_get_draw_passes(p_instance->base);
+
+					for (int i = 0; i < dp; i++) {
+
+						RID mesh = VSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
+
+						int sc = VSG::storage->mesh_get_surface_count(mesh);
+						for (int j = 0; j < sc; j++) {
+
+							RID mat = VSG::storage->mesh_surface_get_material(mesh, j);
+
+							if (!mat.is_valid()) {
+								cast_shadows = true;
+								break;
+							}
+
+							if (VSG::storage->material_casts_shadows(mat)) {
+								cast_shadows = true;
+								break;
+							}
+						}
+					}
+
+					if (!cast_shadows) {
+						can_cast_shadows = false;
+					}
 				}
 			}