You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Implement Particle Trails
-Enable the trails and set the length in seconds -Provide a mesh with a skeleton and a skin -Or, alternatively use one of the built-in TubeTrailMesh/RibbonTrailMesh -Works deterministically -Fixed particle collisions (were broken) -Not working in 2D yet (that will happen next)
This commit is contained in:
@@ -466,6 +466,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant));
|
||||
|
||||
uint32_t instance_count = surf->owner->instance_count > 1 ? surf->owner->instance_count : element_info.repeat;
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS) {
|
||||
instance_count /= surf->owner->trail_steps;
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
|
||||
i += element_info.repeat - 1; //skip equal elements
|
||||
}
|
||||
@@ -2379,9 +2383,13 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_particle_trails) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS;
|
||||
}
|
||||
|
||||
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
|
||||
void *surface_shadow = nullptr;
|
||||
if (!p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
|
||||
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
|
||||
material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
|
||||
|
||||
@@ -2550,7 +2558,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
|
||||
}
|
||||
}
|
||||
|
||||
ginstance->instance_count = storage->particles_get_amount(ginstance->data->base);
|
||||
ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
|
||||
|
||||
} break;
|
||||
|
||||
@@ -2564,42 +2572,26 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
|
||||
|
||||
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
|
||||
uint32_t stride;
|
||||
if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
|
||||
stride = 2;
|
||||
} else {
|
||||
stride = 3;
|
||||
}
|
||||
if (storage->multimesh_uses_colors(ginstance->data->base)) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
|
||||
stride += 1;
|
||||
}
|
||||
if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
|
||||
stride += 1;
|
||||
}
|
||||
|
||||
ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
|
||||
ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
|
||||
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
|
||||
uint32_t stride;
|
||||
if (false) { // 2D particles
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
|
||||
stride = 2;
|
||||
} else {
|
||||
stride = 3;
|
||||
}
|
||||
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
|
||||
stride += 1;
|
||||
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
|
||||
stride += 1;
|
||||
|
||||
ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
|
||||
//for particles, stride is the trail size
|
||||
ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
|
||||
|
||||
if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
|
||||
store_transform = false;
|
||||
@@ -2608,7 +2600,6 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
|
||||
|
||||
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
|
||||
if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON;
|
||||
ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
if (ginstance->data->dirty_dependencies) {
|
||||
storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
|
||||
@@ -2643,6 +2634,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
|
||||
switch (p_notification) {
|
||||
case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
|
||||
case RendererStorage::DEPENDENCY_CHANGED_MESH:
|
||||
case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
|
||||
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
|
||||
case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
|
||||
static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
|
||||
|
||||
@@ -196,9 +196,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16,
|
||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7,
|
||||
INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
|
||||
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
|
||||
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
|
||||
};
|
||||
|
||||
struct SceneState {
|
||||
@@ -398,6 +398,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
FLAG_USES_DEPTH_TEXTURE = 8192,
|
||||
FLAG_USES_NORMAL_TEXTURE = 16384,
|
||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
|
||||
FLAG_USES_PARTICLE_TRAILS = 65536,
|
||||
};
|
||||
|
||||
union {
|
||||
@@ -453,6 +454,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
uint32_t layer_mask = 1;
|
||||
RID transforms_uniform_set;
|
||||
uint32_t instance_count = 0;
|
||||
uint32_t trail_steps = 1;
|
||||
RID mesh_instance;
|
||||
bool can_sdfgi = false;
|
||||
//used during setup
|
||||
|
||||
@@ -73,6 +73,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||
uses_time = false;
|
||||
writes_modelview_or_projection = false;
|
||||
uses_world_coordinates = false;
|
||||
uses_particle_trails = false;
|
||||
|
||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||
|
||||
@@ -101,6 +102,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
|
||||
|
||||
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
|
||||
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
|
||||
@@ -714,6 +716,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
|
||||
actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
|
||||
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
|
||||
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
|
||||
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
|
||||
|
||||
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ public:
|
||||
bool uses_discard;
|
||||
bool uses_roughness;
|
||||
bool uses_normal;
|
||||
bool uses_particle_trails;
|
||||
|
||||
bool unshaded;
|
||||
bool uses_vertex;
|
||||
|
||||
Reference in New Issue
Block a user