Merge pull request #116620 from QbieShay/qbe/rework-align-rotation
Improve options for orienting particles in space
This commit is contained in:
@@ -165,6 +165,13 @@
|
||||
The amount of time the particle's trail should represent (in seconds). Only effective if [member trail_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="transform_align" type="int" setter="set_transform_align" getter="get_transform_align" enum="GPUParticles3D.TransformAlign" default="0">
|
||||
The alignment of particles. Use this for billboarding and aligning to velocity.
|
||||
</member>
|
||||
<member name="transform_align_axis" type="int" setter="set_transform_align_axis" getter="get_transform_align_axis" enum="RenderingServer.ParticlesTransformAlignAxis">
|
||||
When using transform align local billboard, which axis to use for the billboarding. Supports only X or Y.
|
||||
</member>
|
||||
<member name="transform_align_channel_filter" type="int" setter="set_transform_align_channel_filter" getter="get_transform_align_channel_filter" enum="RenderingServer.ParticlesTransformAlignCustomSrc">
|
||||
In the case of billboarded particles, which custom channel to read from to calculate their angle.
|
||||
</member>
|
||||
<member name="use_fixed_seed" type="bool" setter="set_use_fixed_seed" getter="get_use_fixed_seed" default="false">
|
||||
If [code]true[/code], particles will use the same seed for every simulation using the seed defined in [member seed]. This is useful for situations where the visual outcome should be consistent across replays, for example when using Movie Maker mode.
|
||||
@@ -227,5 +234,8 @@
|
||||
<constant name="TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY" value="3" enum="TransformAlign">
|
||||
Align each particle's Z axis to face the camera and Y axis to the velocity vector.
|
||||
</constant>
|
||||
<constant name="TRANSFORM_ALIGN_LOCAL_BILLBOARD" value="4" enum="TransformAlign">
|
||||
Align each particle's Z axis to face the camera, while preserving a given axis (X or Y).
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
||||
@@ -321,6 +321,15 @@
|
||||
<member name="rotation_3d_min" type="Vector3" setter="set_rotation_3d_min" getter="get_rotation_3d_min">
|
||||
The minimum 3D orientation, in degrees. Works only in 3D and if [member use_rotation_3d] is enabled.
|
||||
</member>
|
||||
<member name="rotation_velocity_3d_curve" type="Texture2D" setter="set_rotation_velocity_3d_curve" getter="get_rotation_velocity_3d_curve">
|
||||
Rotation velocity curve over lifetime, per-axis. Enable [member use_rotation_velocity_3d] to use this.
|
||||
</member>
|
||||
<member name="rotation_velocity_3d_max" type="Vector3" setter="set_rotation_velocity_3d_max" getter="get_rotation_velocity_3d_max">
|
||||
Maximum 3D rotation velocity on the particle's local axis. Enable [member use_rotation_velocity_3d] to use this.
|
||||
</member>
|
||||
<member name="rotation_velocity_3d_min" type="Vector3" setter="set_rotation_velocity_3d_min" getter="get_rotation_velocity_3d_min">
|
||||
Minimum 3D rotation velocity on the particle's local axis. Enable [member use_rotation_velocity_3d] to use this.
|
||||
</member>
|
||||
<member name="scale_3d_max" type="Vector3" setter="set_scale_3d_max" getter="get_scale_3d_max">
|
||||
The maximum value of the random scale vector for each particle.
|
||||
Works only if [member use_scale_3d] is enabled.
|
||||
@@ -424,6 +433,9 @@
|
||||
<member name="use_rotation_3d" type="bool" setter="set_use_rotation_3d" getter="is_using_rotation_3d" default="false">
|
||||
Enable the usage of [member rotation_3d_min] and [member rotation_3d_max].
|
||||
</member>
|
||||
<member name="use_rotation_velocity_3d" type="bool" setter="set_using_rotation_velocity_3d" getter="is_using_rotation_velocity_3d" default="false">
|
||||
Enable 3D rotation velocity.
|
||||
</member>
|
||||
<member name="use_scale_3d" type="bool" setter="set_use_scale_3d" getter="is_using_scale_3d" default="false">
|
||||
Enable the usage of [member scale_3d_min] and [member scale_3d_max].
|
||||
</member>
|
||||
|
||||
@@ -3326,6 +3326,22 @@
|
||||
Sets the transform alignment for the particle system. Equivalent to [member GPUParticles3D.transform_align].
|
||||
</description>
|
||||
</method>
|
||||
<method name="particles_set_transform_align_axis">
|
||||
<return type="void" />
|
||||
<param index="0" name="particles" type="RID" />
|
||||
<param index="1" name="p_rotation_axis" type="int" enum="RenderingServer.ParticlesTransformAlignAxis" />
|
||||
<description>
|
||||
Sets which axis to use for transform alignment.
|
||||
</description>
|
||||
</method>
|
||||
<method name="particles_set_transform_align_channel_filter">
|
||||
<return type="void" />
|
||||
<param index="0" name="particles" type="RID" />
|
||||
<param index="1" name="channel_filter" type="int" enum="RenderingServer.ParticlesTransformAlignCustomSrc" />
|
||||
<description>
|
||||
When using Z-Billboarding, which CUSTOM channel to read from.
|
||||
</description>
|
||||
</method>
|
||||
<method name="particles_set_use_local_coordinates">
|
||||
<return type="void" />
|
||||
<param index="0" name="particles" type="RID" />
|
||||
@@ -5183,6 +5199,30 @@
|
||||
<constant name="PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY" value="3" enum="ParticlesTransformAlign">
|
||||
Align each particle's Z axis to face the camera and Y axis to the velocity vector.
|
||||
</constant>
|
||||
<constant name="PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD" value="4" enum="ParticlesTransformAlign">
|
||||
Billboard each particles around a local axis.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_CHANNEL_FILTER_DISABLED" value="0" enum="ParticlesTransformAlignCustomSrc">
|
||||
Do not read from CUSTOM when performing billboarding.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_CHANNEL_FILTER_X" value="1" enum="ParticlesTransformAlignCustomSrc">
|
||||
Read from [code]CUSTOM.x[/code] when performing billboarding and use it as an angle, in radians.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_CHANNEL_FILTER_Y" value="2" enum="ParticlesTransformAlignCustomSrc">
|
||||
Read from [code]CUSTOM.y[/code] when performing billboarding and use it as an angle, in radians.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_CHANNEL_FILTER_Z" value="3" enum="ParticlesTransformAlignCustomSrc">
|
||||
Read from [code]CUSTOM.z[/code] when performing billboarding and use it as an angle, in radians.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_CHANNEL_FILTER_W" value="4" enum="ParticlesTransformAlignCustomSrc">
|
||||
Read from [code]CUSTOM.w[/code] when performing billboarding and use it as an angle, in radians.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_AXIS_X" value="0" enum="ParticlesTransformAlignAxis">
|
||||
Use the X axis for local billboarding.
|
||||
</constant>
|
||||
<constant name="PARTICLES_ALIGN_AXIS_Y" value="1" enum="ParticlesTransformAlignAxis">
|
||||
Use the Y axis for local billboarding.
|
||||
</constant>
|
||||
<constant name="PARTICLES_EMIT_FLAG_POSITION" value="1">
|
||||
Particle starts at the specified position.
|
||||
</constant>
|
||||
|
||||
@@ -37,10 +37,24 @@ uniform highp uint align_mode;
|
||||
|
||||
uniform highp mat4 inv_emission_transform;
|
||||
|
||||
#define TRANSFORM_ALIGN_DISABLED uint(0)
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD uint(1)
|
||||
#define TRANSFORM_ALIGN_Y_TO_VELOCITY uint(2)
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY uint(3)
|
||||
uniform uint align_channel_filter;
|
||||
uniform uint align_axis;
|
||||
|
||||
#define ALIGN_DISABLED uint(0)
|
||||
#define ALIGN_BILLBOARD uint(1)
|
||||
#define ALIGN_Y_TO_VELOCITY uint(2)
|
||||
#define ALIGN_Z_BILLBOARD_Y_TO_VELOCITY uint(3)
|
||||
#define ALIGN_LOCAL_BILLBOARD uint(4)
|
||||
|
||||
#define CHANNEL_FILTER_NONE uint(0)
|
||||
#define CHANNEL_FILTER_X uint(1)
|
||||
#define CHANNEL_FILTER_Y uint(2)
|
||||
#define CHANNEL_FILTER_Z uint(3)
|
||||
#define CHANNEL_FILTER_W uint(4)
|
||||
|
||||
#define ALIGN_AXIS_X uint(0)
|
||||
#define ALIGN_AXIS_Y uint(1)
|
||||
#define ALIGN_AXIS_Z uint(2)
|
||||
|
||||
#define PARTICLE_FLAG_ACTIVE uint(1)
|
||||
|
||||
@@ -57,15 +71,46 @@ void main() {
|
||||
txform = transpose(mat4(xform_1, xform_2, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
|
||||
#endif
|
||||
|
||||
if (align_mode == TRANSFORM_ALIGN_DISABLED) {
|
||||
if (align_mode == ALIGN_DISABLED) {
|
||||
// nothing
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Z_BILLBOARD) {
|
||||
mat3 local = mat3(normalize(cross(align_up, sort_direction)), align_up, sort_direction);
|
||||
local = local * mat3(txform);
|
||||
txform[0].xyz = local[0];
|
||||
txform[1].xyz = local[1];
|
||||
txform[2].xyz = local[2];
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Y_TO_VELOCITY) {
|
||||
} else if (align_mode == ALIGN_BILLBOARD) {
|
||||
float angle = 0.;
|
||||
if (align_channel_filter == CHANNEL_FILTER_NONE) {
|
||||
mat3 local = mat3(normalize(cross(align_up, sort_direction)), align_up, sort_direction);
|
||||
local = local * mat3(txform);
|
||||
txform[0].xyz = local[0];
|
||||
txform[1].xyz = local[1];
|
||||
txform[2].xyz = local[2];
|
||||
} else {
|
||||
if (align_channel_filter == CHANNEL_FILTER_X) {
|
||||
angle = custom.x;
|
||||
|
||||
} else if (align_channel_filter == CHANNEL_FILTER_Y) {
|
||||
angle = custom.y;
|
||||
|
||||
} else if (align_channel_filter == CHANNEL_FILTER_Z) {
|
||||
angle = custom.z;
|
||||
|
||||
} else if (align_channel_filter == CHANNEL_FILTER_W) {
|
||||
angle = custom.w;
|
||||
}
|
||||
|
||||
vec3 axis = normalize(sort_direction);
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float oc = 1.0 - c;
|
||||
mat3 rotated = mat3(
|
||||
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s,
|
||||
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s,
|
||||
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c);
|
||||
vec3 new_up = rotated * align_up;
|
||||
mat3 local = mat3(normalize(cross(new_up, sort_direction)), new_up, sort_direction);
|
||||
local = local * mat3(txform);
|
||||
txform[0].xyz = local[0];
|
||||
txform[1].xyz = local[1];
|
||||
txform[2].xyz = local[2];
|
||||
}
|
||||
} else if (align_mode == ALIGN_Y_TO_VELOCITY) {
|
||||
vec3 v = velocity_flags.xyz;
|
||||
float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
|
||||
if (length(v) > 0.0) {
|
||||
@@ -78,7 +123,7 @@ void main() {
|
||||
txform[2].xyz = vec3(0.0, 0.0, 1.0) * s;
|
||||
txform[0].xyz *= s;
|
||||
txform[1].xyz *= s;
|
||||
} else if (align_mode == TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
} else if (align_mode == ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
vec3 sv = velocity_flags.xyz - sort_direction * dot(sort_direction, velocity_flags.xyz); //screen velocity
|
||||
|
||||
if (length(sv) == 0.0) {
|
||||
@@ -90,6 +135,32 @@ void main() {
|
||||
txform[0].xyz = normalize(cross(sv, sort_direction)) * length(txform[0]);
|
||||
txform[1].xyz = sv * length(txform[1]);
|
||||
txform[2].xyz = sort_direction * length(txform[2]);
|
||||
} else if (align_mode == ALIGN_LOCAL_BILLBOARD) {
|
||||
if (align_axis == ALIGN_AXIS_X) {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
txform[0].xyz = normalize(txform[0].xyz);
|
||||
txform[1].xyz = normalize(cross(sort_direction, txform[0].xyz));
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} else if (align_axis == ALIGN_AXIS_Y) {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
txform[1].xyz = normalize(txform[1].xyz);
|
||||
txform[0].xyz = normalize(cross(txform[1].xyz, sort_direction));
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
}
|
||||
}
|
||||
|
||||
txform[3].xyz += velocity_flags.xyz * frame_remainder;
|
||||
|
||||
@@ -323,6 +323,20 @@ void ParticlesStorage::particles_set_transform_align(RID p_particles, RSE::Parti
|
||||
particles->transform_align = p_transform_align;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_channel_filter) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
particles->transform_align_channel_filter = p_channel_filter;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
particles->transform_align_axis = p_rotation_axis;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
@@ -792,7 +806,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -960,6 +974,8 @@ void ParticlesStorage::_particles_update_instance_buffer(Particles *particles, c
|
||||
particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_MODE, uint32_t(particles->transform_align), particles_shader.copy_shader_version, variant, specialization);
|
||||
particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_UP, p_up_axis, particles_shader.copy_shader_version, variant, specialization);
|
||||
particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::SORT_DIRECTION, p_axis, particles_shader.copy_shader_version, variant, specialization);
|
||||
particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_AXIS, uint32_t(particles->transform_align_axis), particles_shader.copy_shader_version, variant, specialization);
|
||||
particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_CHANNEL_FILTER, uint32_t(particles->transform_align_channel_filter), particles_shader.copy_shader_version, variant, specialization);
|
||||
|
||||
glBindVertexArray(particles->back_vertex_array);
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->front_instance_buffer, 0, particles->instance_buffer_size_cache);
|
||||
@@ -1155,7 +1171,8 @@ void ParticlesStorage::update_particles() {
|
||||
|
||||
// Copy particles to instance buffer and pack Color/Custom.
|
||||
// We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD) {
|
||||
_particles_update_instance_buffer(particles, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0));
|
||||
|
||||
if (particles->draw_order == RSE::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME && particles->sort_buffer_filled) {
|
||||
|
||||
@@ -171,8 +171,10 @@ private:
|
||||
|
||||
RID process_material;
|
||||
uint32_t frame_counter = 0;
|
||||
RSE::ParticlesTransformAlign transform_align = RSE::PARTICLES_TRANSFORM_ALIGN_DISABLED;
|
||||
|
||||
RSE::ParticlesTransformAlign transform_align = RSE::PARTICLES_TRANSFORM_ALIGN_DISABLED;
|
||||
RSE::ParticlesTransformAlignAxis transform_align_axis = RSE::PARTICLES_ALIGN_AXIS_Y;
|
||||
RSE::ParticlesTransformAlignCustomSrc transform_align_channel_filter = RSE::PARTICLES_ALIGN_CHANNEL_FILTER_X;
|
||||
RSE::ParticlesDrawOrder draw_order = RSE::PARTICLES_DRAW_ORDER_INDEX;
|
||||
|
||||
Vector<RID> draw_passes;
|
||||
@@ -345,6 +347,9 @@ public:
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RSE::ParticlesTransformAlign p_transform_align) override;
|
||||
virtual void particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_channel_filter) override;
|
||||
virtual void particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) override;
|
||||
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
|
||||
|
||||
@@ -470,6 +470,15 @@ void GPUParticles3D::_validate_property(PropertyInfo &p_property) const {
|
||||
}
|
||||
} else if (p_property.name == "seed" && !use_fixed_seed) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
} else if (p_property.name == "transform_align_axis") {
|
||||
if (transform_align == TRANSFORM_ALIGN_DISABLED || transform_align == TRANSFORM_ALIGN_Z_BILLBOARD ||
|
||||
transform_align == TRANSFORM_ALIGN_Y_TO_VELOCITY || transform_align == TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "transform_align_channel_filter") {
|
||||
if (!(transform_align == TRANSFORM_ALIGN_Z_BILLBOARD)) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,7 +638,9 @@ Ref<Skin> GPUParticles3D::get_skin() const {
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_transform_align(TransformAlign p_align) {
|
||||
ERR_FAIL_INDEX(uint32_t(p_align), 4);
|
||||
if (p_align != transform_align) {
|
||||
notify_property_list_changed();
|
||||
}
|
||||
transform_align = p_align;
|
||||
RS::get_singleton()->particles_set_transform_align(particles, RSE::ParticlesTransformAlign(transform_align));
|
||||
}
|
||||
@@ -638,6 +649,25 @@ GPUParticles3D::TransformAlign GPUParticles3D::get_transform_align() const {
|
||||
return transform_align;
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_transform_align_channel_filter(RSE::ParticlesTransformAlignCustomSrc p_align_channel_filter) {
|
||||
ERR_FAIL_INDEX(uint32_t(p_align_channel_filter), uint32_t(RSE::ParticlesTransformAlignCustomSrc::PARTICLES_ALIGN_CHANNEL_FILTER_MAX));
|
||||
transform_align_channel_filter = p_align_channel_filter;
|
||||
RS::get_singleton()->particles_set_transform_align_channel_filter(particles, transform_align_channel_filter);
|
||||
}
|
||||
|
||||
RSE::ParticlesTransformAlignCustomSrc GPUParticles3D::get_transform_align_channel_filter() const {
|
||||
return transform_align_channel_filter;
|
||||
}
|
||||
|
||||
void GPUParticles3D::set_transform_align_axis(RSE::ParticlesTransformAlignAxis p_axis) {
|
||||
transform_align_axis = p_axis;
|
||||
RS::get_singleton()->particles_set_transform_align_axis(particles, p_axis);
|
||||
}
|
||||
|
||||
RSE::ParticlesTransformAlignAxis GPUParticles3D::get_transform_align_axis() const {
|
||||
return transform_align_axis;
|
||||
}
|
||||
|
||||
void GPUParticles3D::convert_from_particles(Node *p_particles) {
|
||||
CPUParticles3D *cpu_particles = Object::cast_to<CPUParticles3D>(p_particles);
|
||||
ERR_FAIL_NULL_MSG(cpu_particles, "Only CPUParticles3D nodes can be converted to GPUParticles3D.");
|
||||
@@ -809,6 +839,12 @@ void GPUParticles3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_transform_align", "align"), &GPUParticles3D::set_transform_align);
|
||||
ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_transform_align_channel_filter", "channel_filter"), &GPUParticles3D::set_transform_align_channel_filter);
|
||||
ClassDB::bind_method(D_METHOD("get_transform_align_channel_filter"), &GPUParticles3D::get_transform_align_channel_filter);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_transform_align_axis", "align"), &GPUParticles3D::set_transform_align_axis);
|
||||
ClassDB::bind_method(D_METHOD("get_transform_align_axis"), &GPUParticles3D::get_transform_align_axis);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &GPUParticles3D::convert_from_particles);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_amount_ratio", "ratio"), &GPUParticles3D::set_amount_ratio);
|
||||
@@ -843,7 +879,11 @@ void GPUParticles3D::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_visibility_aabb", "get_visibility_aabb");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime,View Depth"), "set_draw_order", "get_draw_order");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,Z-Billboard,Y to Velocity,Z-Billboard + Y to Velocity"), "set_transform_align", "get_transform_align");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,Billboard,Align to Velocity,Trails,Local Billboard"), "set_transform_align", "get_transform_align");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align_axis", PROPERTY_HINT_ENUM, "X,Y"), "set_transform_align_axis", "get_transform_align_axis");
|
||||
ADD_SUBGROUP("Advanced", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align_channel_filter", PROPERTY_HINT_ENUM, "Disabled,X,Y,Z,W"), "set_transform_align_channel_filter", "get_transform_align_channel_filter");
|
||||
|
||||
ADD_GROUP("Trails", "trail_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_trail_enabled", "is_trail_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime");
|
||||
@@ -873,6 +913,7 @@ void GPUParticles3D::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD);
|
||||
BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Y_TO_VELOCITY);
|
||||
BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY);
|
||||
BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_LOCAL_BILLBOARD);
|
||||
|
||||
ADD_PROPERTY_DEFAULT("seed", 0);
|
||||
}
|
||||
@@ -902,6 +943,8 @@ GPUParticles3D::GPUParticles3D() {
|
||||
set_speed_scale(1);
|
||||
set_collision_base_size(collision_base_size);
|
||||
set_transform_align(TRANSFORM_ALIGN_DISABLED);
|
||||
set_transform_align_channel_filter(RSE::ParticlesTransformAlignCustomSrc::PARTICLES_ALIGN_CHANNEL_FILTER_X);
|
||||
set_transform_align_axis(RSE::ParticlesTransformAlignAxis::PARTICLES_ALIGN_AXIS_Y);
|
||||
set_use_fixed_seed(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,10 +48,11 @@ public:
|
||||
};
|
||||
|
||||
enum TransformAlign {
|
||||
TRANSFORM_ALIGN_DISABLED,
|
||||
TRANSFORM_ALIGN_Z_BILLBOARD,
|
||||
TRANSFORM_ALIGN_Y_TO_VELOCITY,
|
||||
TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY
|
||||
TRANSFORM_ALIGN_DISABLED = RSE::PARTICLES_TRANSFORM_ALIGN_DISABLED,
|
||||
TRANSFORM_ALIGN_Z_BILLBOARD = RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD,
|
||||
TRANSFORM_ALIGN_Y_TO_VELOCITY = RSE::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY,
|
||||
TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY = RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY,
|
||||
TRANSFORM_ALIGN_LOCAL_BILLBOARD = RSE::PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -86,6 +87,9 @@ private:
|
||||
double trail_lifetime = 0.3;
|
||||
|
||||
TransformAlign transform_align = TRANSFORM_ALIGN_DISABLED;
|
||||
RSE::ParticlesTransformAlignCustomSrc transform_align_channel_filter = RSE::ParticlesTransformAlignCustomSrc::PARTICLES_ALIGN_CHANNEL_FILTER_X;
|
||||
RSE::ParticlesTransformAlignAxis transform_align_axis = RSE::ParticlesTransformAlignAxis::PARTICLES_ALIGN_AXIS_Y;
|
||||
bool transform_align_use_velocity = true;
|
||||
|
||||
Ref<Material> process_material;
|
||||
|
||||
@@ -183,6 +187,12 @@ public:
|
||||
void set_transform_align(TransformAlign p_align);
|
||||
TransformAlign get_transform_align() const;
|
||||
|
||||
void set_transform_align_channel_filter(RSE::ParticlesTransformAlignCustomSrc p_align_channel_filter);
|
||||
RSE::ParticlesTransformAlignCustomSrc get_transform_align_channel_filter() const;
|
||||
|
||||
void set_transform_align_axis(RSE::ParticlesTransformAlignAxis p_axis);
|
||||
RSE::ParticlesTransformAlignAxis get_transform_align_axis() const;
|
||||
|
||||
void restart(bool p_keep_seed = false);
|
||||
|
||||
void set_use_fixed_seed(bool p_use_fixed_seed);
|
||||
|
||||
@@ -107,6 +107,9 @@ void ParticleProcessMaterial::init_shaders() {
|
||||
shader_names->velocity_limit_curve = "velocity_limit_curve";
|
||||
shader_names->inherit_emitter_velocity_ratio = "inherit_emitter_velocity_ratio";
|
||||
shader_names->velocity_pivot = "velocity_pivot";
|
||||
shader_names->rotation_velocity_3d_max = "rotation_velocity_3d_max";
|
||||
shader_names->rotation_velocity_3d_min = "rotation_velocity_3d_min";
|
||||
shader_names->rotation_velocity_3d_curve = "rotation_velocity_3d_curve";
|
||||
|
||||
shader_names->emission_sphere_radius = "emission_sphere_radius";
|
||||
shader_names->emission_box_extents = "emission_box_extents";
|
||||
@@ -266,6 +269,14 @@ void ParticleProcessMaterial::_update_shader() {
|
||||
|
||||
code += "uniform vec3 velocity_pivot = vec3(0.0);\n";
|
||||
|
||||
if (using_rotation_velocity_3d) {
|
||||
code += "uniform vec3 rotation_velocity_3d_min = vec3(0.0);\n";
|
||||
code += "uniform vec3 rotation_velocity_3d_max = vec3(0.0);\n";
|
||||
if (rotation_velocity_3d_curve.is_valid()) {
|
||||
code += "uniform sampler2D rotation_velocity_3d_curve : repeat_disable;\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (tex_parameters[PARAM_SCALE_OVER_VELOCITY].is_valid()) {
|
||||
code += "uniform float scale_over_velocity_min = 0.0;\n";
|
||||
code += "uniform float scale_over_velocity_max = 5.0;\n";
|
||||
@@ -579,6 +590,9 @@ void ParticleProcessMaterial::_update_shader() {
|
||||
if (turbulence_enabled) {
|
||||
code += " float turb_influence;\n";
|
||||
}
|
||||
if (using_rotation_velocity_3d) {
|
||||
code += " vec3 rotation_velocity_3d;\n";
|
||||
}
|
||||
code += "};\n\n";
|
||||
|
||||
code += "struct PhysicalParameters {\n";
|
||||
@@ -613,6 +627,12 @@ void ParticleProcessMaterial::_update_shader() {
|
||||
code += " params.rotation_3d.z = mix(rotation_3d_min.z, rotation_3d_max.z, rand_from_seed(alt_seed));\n";
|
||||
code += " params.rotation_3d *= 3.14159 / 180.0;\n";
|
||||
}
|
||||
if (using_rotation_velocity_3d) {
|
||||
code += " params.rotation_velocity_3d.x = mix(rotation_velocity_3d_min.x, rotation_velocity_3d_max.x, rand_from_seed(alt_seed));\n";
|
||||
code += " params.rotation_velocity_3d.y = mix(rotation_velocity_3d_min.y, rotation_velocity_3d_max.y, rand_from_seed(alt_seed));\n";
|
||||
code += " params.rotation_velocity_3d.z = mix(rotation_velocity_3d_min.z, rotation_velocity_3d_max.z, rand_from_seed(alt_seed));\n";
|
||||
code += " params.rotation_velocity_3d *= 3.14159 / 180.0;\n";
|
||||
}
|
||||
code += "}\n\n";
|
||||
|
||||
code += "void calculate_initial_display_params(inout DisplayParameters params, inout uint alt_seed) {\n";
|
||||
@@ -1222,6 +1242,59 @@ void ParticleProcessMaterial::_update_shader() {
|
||||
code += " }\n";
|
||||
code += "\n";
|
||||
code += " CUSTOM.z = params.animation_offset + lifetime_percent * params.animation_speed;\n\n";
|
||||
if (using_rotation_velocity_3d && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
|
||||
if (rotation_velocity_3d_curve.is_valid()) {
|
||||
code += " dynamic_params.rotation_velocity_3d *= texture(rotation_velocity_3d_curve, vec2(lifetime_percent)).xyz;\n";
|
||||
}
|
||||
code += R"(
|
||||
if (length(dynamic_params.rotation_velocity_3d) > 0.0) {
|
||||
vec3 r = dynamic_params.rotation_velocity_3d * DELTA;
|
||||
vec4 origin = TRANSFORM[3];
|
||||
vec4 norm_axis = normalize(TRANSFORM[0]);
|
||||
float ux = norm_axis.x;
|
||||
float uy = norm_axis.y;
|
||||
float uz = norm_axis.z;
|
||||
float s = sin(r.x);
|
||||
float c = cos(r.x);
|
||||
float cm = 1.0 - c;
|
||||
mat4 rx = mat4(
|
||||
vec4(ux * ux * cm + c, ux * uy * cm - uz * s, ux * uz * cm + uy * s, 0.0),
|
||||
vec4(ux * uy * cm + uz * s, uy * uy * cm + c, uy * uz * cm - ux * s, 0.0),
|
||||
vec4(ux * uz * cm - uy * s, uy * uz * cm + ux * s, uz * uz * cm + c, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
norm_axis = normalize(TRANSFORM[1]);
|
||||
ux = norm_axis.x;
|
||||
uy = norm_axis.y;
|
||||
uz = norm_axis.z;
|
||||
s = sin(r.y);
|
||||
c = cos(r.y);
|
||||
cm = 1.0 - c;
|
||||
mat4 ry = mat4(
|
||||
vec4(ux * ux * cm + c, ux * uy * cm - uz * s, ux * uz * cm + uy * s, 0.0),
|
||||
vec4(ux * uy * cm + uz * s, uy * uy * cm + c, uy * uz * cm - ux * s, 0.0),
|
||||
vec4(ux * uz * cm - uy * s, uy * uz * cm + ux * s, uz * uz * cm + c, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
norm_axis = normalize(TRANSFORM[2]);
|
||||
ux = norm_axis.x;
|
||||
uy = norm_axis.y;
|
||||
uz = norm_axis.z;
|
||||
s = sin(r.z);
|
||||
c = cos(r.z);
|
||||
cm = 1.0 - c;
|
||||
mat4 rz = mat4(
|
||||
vec4(ux * ux * cm + c, ux * uy * cm - uz * s, ux * uz * cm + uy * s, 0.0),
|
||||
vec4(ux * uy * cm + uz * s, uy * uy * cm + c, uy * uz * cm - ux * s, 0.0),
|
||||
vec4(ux * uz * cm - uy * s, uy * uz * cm + ux * s, uz * uz * cm + c, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
TRANSFORM[3].xyz = vec3(0.);
|
||||
TRANSFORM = rz * ry * rx * TRANSFORM;
|
||||
TRANSFORM[3] = origin;
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
if (sub_emitter_mode != SUB_EMITTER_DISABLED && !RenderingServer::get_singleton()->is_low_end()) {
|
||||
code += " int emit_count = 0;\n";
|
||||
@@ -1873,6 +1946,7 @@ void ParticleProcessMaterial::set_use_scale_3d(const bool p_use_scale_3d) {
|
||||
use_scale_3d = p_use_scale_3d;
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool ParticleProcessMaterial::is_using_scale_3d() const {
|
||||
return use_scale_3d;
|
||||
}
|
||||
@@ -1936,6 +2010,46 @@ void ParticleProcessMaterial::set_rotation_3d_max(const Vector3 &p_rotation_3d_m
|
||||
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->rotation_3d_max, p_rotation_3d_max);
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_use_rotation_velocity_3d(bool p_use_rotation_velocity_3d) {
|
||||
using_rotation_velocity_3d = p_use_rotation_velocity_3d;
|
||||
_queue_shader_change();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
bool ParticleProcessMaterial::is_using_rotation_velocity_3d() const {
|
||||
return using_rotation_velocity_3d;
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_rotation_velocity_3d_min(const Vector3 &p_rotation_velocity_3d_min) {
|
||||
rotation_velocity_3d_min = p_rotation_velocity_3d_min;
|
||||
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->rotation_velocity_3d_min, p_rotation_velocity_3d_min);
|
||||
}
|
||||
|
||||
Vector3 ParticleProcessMaterial::get_rotation_velocity_3d_min() const {
|
||||
return rotation_velocity_3d_min;
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_rotation_velocity_3d_max(const Vector3 &p_rotation_velocity_3d_max) {
|
||||
rotation_velocity_3d_max = p_rotation_velocity_3d_max;
|
||||
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->rotation_velocity_3d_max, p_rotation_velocity_3d_max);
|
||||
}
|
||||
|
||||
Vector3 ParticleProcessMaterial::get_rotation_velocity_3d_max() const {
|
||||
return rotation_velocity_3d_max;
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_rotation_velocity_3d_curve(const Ref<Texture2D> &p_texture) {
|
||||
rotation_velocity_3d_curve = p_texture;
|
||||
Variant tex_rid = p_texture.is_valid() ? Variant(p_texture->get_rid()) : Variant();
|
||||
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->rotation_velocity_3d_curve, tex_rid);
|
||||
_queue_shader_change();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
Ref<Texture2D> ParticleProcessMaterial::get_rotation_velocity_3d_curve() const {
|
||||
return rotation_velocity_3d_curve;
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) {
|
||||
turbulence_enabled = p_turbulence_enabled;
|
||||
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_enabled, turbulence_enabled);
|
||||
@@ -2029,8 +2143,8 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
|
||||
if (emission_shape != EMISSION_SHAPE_BOX) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_point_texture" || p_property.name == "emission_color_texture") {
|
||||
if (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
||||
} else if ((p_property.name == "emission_point_texture" || p_property.name == "emission_color_texture")) {
|
||||
if ((emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_normal_texture") {
|
||||
@@ -2038,7 +2152,7 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_point_count") {
|
||||
if (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
||||
if ((emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name.begins_with("emission_ring_")) {
|
||||
@@ -2069,12 +2183,69 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
|
||||
if (collision_mode != COLLISION_RIGID) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "directional_velocity_min" || p_property.name == "directional_velocity_max") {
|
||||
} else if ((p_property.name == "directional_velocity_min" || p_property.name == "directional_velocity_max")) {
|
||||
if (!tex_parameters[PARAM_DIRECTIONAL_VELOCITY].is_valid()) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if (p_property.name == "scale_over_velocity_min" || p_property.name == "scale_over_velocity_max") {
|
||||
} else if ((p_property.name == "rotation_velocity_3d_min" || p_property.name == "rotation_velocity_3d_max" || p_property.name == "rotation_velocity_3d_curve")) {
|
||||
if (!using_rotation_velocity_3d) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if ((p_property.name == "scale_over_velocity_min" || p_property.name == "scale_over_velocity_max") && !tex_parameters[PARAM_SCALE_OVER_VELOCITY].is_valid()) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
|
||||
} else if (p_property.name == "emission_box_extents") {
|
||||
if (emission_shape != EMISSION_SHAPE_BOX) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_point_texture" || p_property.name == "emission_color_texture") {
|
||||
if (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_normal_texture") {
|
||||
if (emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "emission_point_count") {
|
||||
if (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name.begins_with("emission_ring_")) {
|
||||
if (emission_shape != EMISSION_SHAPE_RING) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "sub_emitter_frequency") {
|
||||
if (sub_emitter_mode != SUB_EMITTER_CONSTANT) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "sub_emitter_amount_at_end") {
|
||||
if (sub_emitter_mode != SUB_EMITTER_AT_END) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "sub_emitter_amount_at_collision") {
|
||||
if (sub_emitter_mode != SUB_EMITTER_AT_COLLISION) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "sub_emitter_amount_at_start") {
|
||||
if (sub_emitter_mode != SUB_EMITTER_AT_START) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "collision_friction") {
|
||||
if (collision_mode != COLLISION_RIGID) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "collision_bounce") {
|
||||
if (collision_mode != COLLISION_RIGID) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "directional_velocity_min" || p_property.name == "directional_velocity_max") {
|
||||
if (!tex_parameters[PARAM_DIRECTIONAL_VELOCITY].is_valid()) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
} else if (p_property.name == "scale_over_velocity_min" || p_property.name == "scale_over_velocity_max") {
|
||||
if (!tex_parameters[PARAM_SCALE_OVER_VELOCITY].is_valid()) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
@@ -2083,20 +2254,19 @@ void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
}
|
||||
} else if (p_property.usage & PROPERTY_USAGE_EDITOR && (p_property.name.ends_with("_min") || p_property.name.ends_with("_max")) &&
|
||||
!(p_property.name == "scale_3d_max" || p_property.name == "scale_3d_min") &&
|
||||
!(p_property.name == "rotation_3d_max" || p_property.name == "rotation_3d_min")) {
|
||||
!p_property.name.begins_with("rotation_velocity") &&
|
||||
!p_property.name.begins_with("scale_3d") &&
|
||||
!p_property.name.begins_with("rotation_3d")) {
|
||||
p_property.usage &= ~PROPERTY_USAGE_EDITOR;
|
||||
|
||||
} else if ((p_property.name == "scale_3d_min" || p_property.name == "scale_3d_max") && !use_scale_3d) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
} else if (p_property.name == "scale" && use_scale_3d) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
} else if ((p_property.name == "rotation_3d_max" || p_property.name == "rotation_3d_min") && (particle_flags[PARTICLE_FLAG_DISABLE_Z] || !use_rotation_3d)) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
}
|
||||
if ((p_property.name == "scale_3d_min" || p_property.name == "scale_3d_max") && !use_scale_3d) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
if (p_property.name == "scale" && use_scale_3d) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
if ((p_property.name == "rotation_3d_max" || p_property.name == "rotation_3d_min") && (particle_flags[PARTICLE_FLAG_DISABLE_Z] || !use_rotation_3d)) {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleProcessMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) {
|
||||
@@ -2368,6 +2538,15 @@ void ParticleProcessMaterial::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_collision_bounce", "bounce"), &ParticleProcessMaterial::set_collision_bounce);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_bounce"), &ParticleProcessMaterial::get_collision_bounce);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_using_rotation_velocity_3d", "use_rotation_velocity_3d"), &ParticleProcessMaterial::set_use_rotation_velocity_3d);
|
||||
ClassDB::bind_method(D_METHOD("is_using_rotation_velocity_3d"), &ParticleProcessMaterial::is_using_rotation_velocity_3d);
|
||||
ClassDB::bind_method(D_METHOD("set_rotation_velocity_3d_max", "rotation_velocity_3d_max"), &ParticleProcessMaterial::set_rotation_velocity_3d_max);
|
||||
ClassDB::bind_method(D_METHOD("get_rotation_velocity_3d_max"), &ParticleProcessMaterial::get_rotation_velocity_3d_max);
|
||||
ClassDB::bind_method(D_METHOD("set_rotation_velocity_3d_min", "rotation_velocity_3d_min"), &ParticleProcessMaterial::set_rotation_velocity_3d_min);
|
||||
ClassDB::bind_method(D_METHOD("get_rotation_velocity_3d_min"), &ParticleProcessMaterial::get_rotation_velocity_3d_min);
|
||||
ClassDB::bind_method(D_METHOD("set_rotation_velocity_3d_curve", "rotation_velocity_3d_curve"), &ParticleProcessMaterial::set_rotation_velocity_3d_curve);
|
||||
ClassDB::bind_method(D_METHOD("get_rotation_velocity_3d_curve"), &ParticleProcessMaterial::get_rotation_velocity_3d_curve);
|
||||
|
||||
#define ADD_MIN_MAX_PROPERTY(m_property, m_range, m_parameter_name) \
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::VECTOR2, m_property, PROPERTY_HINT_RANGE, m_range, PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_param", "get_param", m_parameter_name); \
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, m_property "_min", PROPERTY_HINT_RANGE, m_range), "set_param_min", "get_param_min", m_parameter_name); \
|
||||
@@ -2426,6 +2605,12 @@ void ParticleProcessMaterial::_bind_methods() {
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, CurveTexture::get_class_static()), "set_param_texture", "get_param_texture", PARAM_RADIAL_VELOCITY);
|
||||
ADD_SUBGROUP("Velocity Limit", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "velocity_limit_curve", PROPERTY_HINT_RESOURCE_TYPE, CurveTexture::get_class_static()), "set_velocity_limit_curve", "get_velocity_limit_curve");
|
||||
ADD_SUBGROUP("Rotation Velocity 3D", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_rotation_velocity_3d", PROPERTY_HINT_GROUP_ENABLE), "set_using_rotation_velocity_3d", "is_using_rotation_velocity_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_velocity_3d_min"), "set_rotation_velocity_3d_min", "get_rotation_velocity_3d_min");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_velocity_3d_max"), "set_rotation_velocity_3d_max", "get_rotation_velocity_3d_max");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "rotation_velocity_3d_curve", PROPERTY_HINT_RESOURCE_TYPE, CurveXYZTexture::get_class_static()), "set_rotation_velocity_3d_curve", "get_rotation_velocity_3d_curve");
|
||||
|
||||
ADD_GROUP("Accelerations", "");
|
||||
ADD_SUBGROUP("Gravity", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
|
||||
|
||||
@@ -130,6 +130,8 @@ private:
|
||||
uint64_t orbit_uses_curve_xyz : 1;
|
||||
uint64_t use_scale_3d : 1;
|
||||
uint64_t use_rotation_3d : 1;
|
||||
uint64_t use_rotation_velocity_3d : 1;
|
||||
uint64_t use_rotation_velocity_3d_curve : 1;
|
||||
|
||||
MaterialKey() {
|
||||
memset(this, 0, sizeof(MaterialKey));
|
||||
@@ -177,6 +179,11 @@ private:
|
||||
mk.orbit_uses_curve_xyz = texture ? 1 : 0;
|
||||
mk.use_scale_3d = use_scale_3d ? 1 : 0;
|
||||
mk.use_rotation_3d = use_rotation_3d ? 1 : 0;
|
||||
mk.use_rotation_velocity_3d = using_rotation_velocity_3d;
|
||||
if (using_rotation_velocity_3d) {
|
||||
texture = Object::cast_to<CurveXYZTexture>(rotation_velocity_3d_curve.ptr());
|
||||
mk.use_rotation_velocity_3d_curve = texture ? 1 : 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < PARAM_MAX; i++) {
|
||||
if (tex_parameters[i].is_valid()) {
|
||||
@@ -216,6 +223,7 @@ private:
|
||||
StringName directional_velocity_min;
|
||||
StringName scale_3d_min;
|
||||
StringName rotation_3d_min;
|
||||
StringName rotation_velocity_3d_min;
|
||||
|
||||
StringName initial_linear_velocity_max;
|
||||
StringName initial_angle_max;
|
||||
@@ -234,6 +242,7 @@ private:
|
||||
StringName directional_velocity_max;
|
||||
StringName scale_3d_max;
|
||||
StringName rotation_3d_max;
|
||||
StringName rotation_velocity_3d_max;
|
||||
|
||||
StringName angle_texture;
|
||||
StringName angular_velocity_texture;
|
||||
@@ -250,6 +259,7 @@ private:
|
||||
StringName anim_offset_texture;
|
||||
StringName velocity_limiter_texture;
|
||||
StringName directional_velocity_texture;
|
||||
StringName rotation_velocity_3d_curve;
|
||||
|
||||
StringName color;
|
||||
StringName color_ramp;
|
||||
@@ -361,6 +371,10 @@ private:
|
||||
Vector3 scale_3d_max;
|
||||
Vector3 rotation_3d_min;
|
||||
Vector3 rotation_3d_max;
|
||||
bool using_rotation_velocity_3d = false;
|
||||
Vector3 rotation_velocity_3d_min;
|
||||
Vector3 rotation_velocity_3d_max;
|
||||
Ref<Texture2D> rotation_velocity_3d_curve;
|
||||
|
||||
SubEmitterMode sub_emitter_mode;
|
||||
double sub_emitter_frequency = 0.0;
|
||||
@@ -492,6 +506,15 @@ public:
|
||||
void set_inherit_velocity_ratio(double p_ratio);
|
||||
double get_inherit_velocity_ratio();
|
||||
|
||||
void set_use_rotation_velocity_3d(bool p_use_rotation_velocity_3d);
|
||||
bool is_using_rotation_velocity_3d() const;
|
||||
void set_rotation_velocity_3d_min(const Vector3 &p_rotation_velocity_3d_min);
|
||||
Vector3 get_rotation_velocity_3d_min() const;
|
||||
void set_rotation_velocity_3d_max(const Vector3 &p_rotation_velocity_3d_max);
|
||||
Vector3 get_rotation_velocity_3d_max() const;
|
||||
void set_rotation_velocity_3d_curve(const Ref<Texture2D> &p_texture);
|
||||
Ref<Texture2D> get_rotation_velocity_3d_curve() const;
|
||||
|
||||
void set_attractor_interaction_enabled(bool p_enable);
|
||||
bool is_attractor_interaction_enabled() const;
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RSE::ParticlesTransformAlign p_transform_align) override {}
|
||||
virtual void particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_transform_align_channel_filter) override {}
|
||||
virtual void particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) override {}
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
|
||||
|
||||
@@ -65,14 +65,30 @@ layout(push_constant, std430) uniform Params {
|
||||
uint motion_vectors_current_offset;
|
||||
uint flags;
|
||||
|
||||
mat4 inv_emission_transform;
|
||||
float inv_emission_transform[12];
|
||||
|
||||
uint align_channel_filter;
|
||||
uint align_axis;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
}
|
||||
params;
|
||||
|
||||
#define TRANSFORM_ALIGN_DISABLED 0
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD 1
|
||||
#define TRANSFORM_ALIGN_Y_TO_VELOCITY 2
|
||||
#define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY 3
|
||||
#define ALIGN_DISABLED 0
|
||||
#define ALIGN_BILLBOARD 1
|
||||
#define ALIGN_Y_TO_VELOCITY 2
|
||||
#define ALIGN_Z_BILLBOARD_Y_TO_VELOCITY 3
|
||||
#define ALIGN_LOCAL_BILLBOARD 4
|
||||
|
||||
#define CHANNEL_FILTER_NONE 0
|
||||
#define CHANNEL_FILTER_X 1
|
||||
#define CHANNEL_FILTER_Y 2
|
||||
#define CHANNEL_FILTER_Z 3
|
||||
#define CHANNEL_FILTER_W 4
|
||||
|
||||
#define ALIGN_AXIS_X 0
|
||||
#define ALIGN_AXIS_Y 1
|
||||
#define ALIGN_AXIS_Z 2
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_FILL_SORT_BUFFER
|
||||
@@ -155,31 +171,89 @@ void main() {
|
||||
}
|
||||
|
||||
switch (params.align_mode) {
|
||||
case TRANSFORM_ALIGN_DISABLED: {
|
||||
case ALIGN_DISABLED: {
|
||||
} break; //nothing
|
||||
case TRANSFORM_ALIGN_Z_BILLBOARD: {
|
||||
mat3 local = mat3(normalize(cross(params.align_up, params.sort_direction)), params.align_up, params.sort_direction);
|
||||
case ALIGN_BILLBOARD: {
|
||||
float angle = 0.;
|
||||
switch (params.align_channel_filter) {
|
||||
case CHANNEL_FILTER_X: {
|
||||
angle = particles.data[particle].custom.x;
|
||||
} break;
|
||||
case CHANNEL_FILTER_Y: {
|
||||
angle = particles.data[particle].custom.y;
|
||||
} break;
|
||||
case CHANNEL_FILTER_Z: {
|
||||
angle = particles.data[particle].custom.z;
|
||||
} break;
|
||||
case CHANNEL_FILTER_W: {
|
||||
angle = particles.data[particle].custom.w;
|
||||
} break;
|
||||
}
|
||||
vec3 axis = normalize(params.sort_direction);
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float oc = 1.0 - c;
|
||||
mat3 rotated = mat3(
|
||||
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s,
|
||||
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s,
|
||||
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c);
|
||||
vec3 new_up = rotated * params.align_up;
|
||||
mat3 local = mat3(normalize(cross(new_up, params.sort_direction)), new_up, params.sort_direction);
|
||||
local = local * mat3(txform);
|
||||
txform[0].xyz = local[0];
|
||||
txform[1].xyz = local[1];
|
||||
txform[2].xyz = local[2];
|
||||
|
||||
} break;
|
||||
case TRANSFORM_ALIGN_Y_TO_VELOCITY: {
|
||||
case ALIGN_Y_TO_VELOCITY: {
|
||||
vec3 v = particles.data[particle].velocity;
|
||||
float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
|
||||
if (length(v) > 0.0) {
|
||||
txform[1].xyz = normalize(v);
|
||||
} else {
|
||||
txform[1].xyz = normalize(txform[1].xyz);
|
||||
}
|
||||
v = normalize(v);
|
||||
switch (params.align_axis) {
|
||||
case ALIGN_AXIS_X: {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
|
||||
txform[0].xyz = normalize(cross(txform[1].xyz, txform[2].xyz));
|
||||
txform[2].xyz = vec3(0.0, 0.0, 1.0) * s;
|
||||
txform[0].xyz *= s;
|
||||
txform[1].xyz *= s;
|
||||
txform[0].xyz = v;
|
||||
txform[1].xyz = normalize(cross(txform[2].xyz / len.z, txform[0].xyz));
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} break;
|
||||
case ALIGN_AXIS_Y: {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
|
||||
txform[0].xyz = normalize(cross(v, txform[2].xyz / len.z));
|
||||
txform[1].xyz = v;
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} break;
|
||||
case ALIGN_AXIS_Z: {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
|
||||
txform[0].xyz = normalize(cross(txform[1].xyz / len.y, v));
|
||||
txform[2].xyz = v;
|
||||
txform[1].xyz = normalize(cross(txform[2].xyz, txform[0].xyz));
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: {
|
||||
case ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: {
|
||||
vec3 v = particles.data[particle].velocity;
|
||||
vec3 sv = v - params.sort_direction * dot(params.sort_direction, v); //screen velocity
|
||||
|
||||
@@ -194,6 +268,39 @@ void main() {
|
||||
txform[2].xyz = params.sort_direction * length(txform[2]);
|
||||
|
||||
} break;
|
||||
case ALIGN_LOCAL_BILLBOARD: {
|
||||
switch (params.align_axis) {
|
||||
case ALIGN_AXIS_X: {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
|
||||
txform[0].xyz = normalize(txform[0].xyz);
|
||||
txform[1].xyz = normalize(cross(params.sort_direction, txform[0].xyz));
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} break;
|
||||
case ALIGN_AXIS_Y: {
|
||||
vec3 len = vec3(
|
||||
length(txform[0].xyz),
|
||||
length(txform[1].xyz),
|
||||
length(txform[2].xyz));
|
||||
|
||||
txform[1].xyz = normalize(txform[1].xyz);
|
||||
txform[0].xyz = normalize(cross(txform[1].xyz, params.sort_direction));
|
||||
txform[2].xyz = cross(txform[0].xyz, txform[1].xyz);
|
||||
|
||||
txform[0].xyz *= len.x;
|
||||
txform[1].xyz *= len.y;
|
||||
txform[2].xyz *= len.z;
|
||||
} break;
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
txform[3].xyz += particles.data[particle].velocity * params.frame_remainder;
|
||||
@@ -206,7 +313,13 @@ void main() {
|
||||
if (bool(params.flags & PARAMS_FLAG_COPY_MODE_2D)) {
|
||||
// In global mode, bring 2D particles to local coordinates
|
||||
// as they will be drawn with the node position as origin.
|
||||
txform = params.inv_emission_transform * txform;
|
||||
mat4 inv_emission_transform;
|
||||
inv_emission_transform[0] = vec4(params.inv_emission_transform[0], params.inv_emission_transform[1], params.inv_emission_transform[2], 0.0);
|
||||
inv_emission_transform[1] = vec4(params.inv_emission_transform[3], params.inv_emission_transform[4], params.inv_emission_transform[5], 0.0);
|
||||
inv_emission_transform[2] = vec4(params.inv_emission_transform[6], params.inv_emission_transform[7], params.inv_emission_transform[8], 0.0);
|
||||
inv_emission_transform[3] = vec4(params.inv_emission_transform[9], params.inv_emission_transform[10], params.inv_emission_transform[11], 1.0);
|
||||
inv_emission_transform = transpose(inv_emission_transform);
|
||||
txform = inv_emission_transform * txform;
|
||||
}
|
||||
} else {
|
||||
// Set scale to zero and translate to -INF so particle will be invisible
|
||||
|
||||
@@ -493,6 +493,20 @@ void ParticlesStorage::particles_set_transform_align(RID p_particles, RSE::Parti
|
||||
particles->transform_align = p_transform_align;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_transform_align_channel_filter) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
particles->transform_align_src = p_transform_align_channel_filter;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
particles->transform_align_axis = p_rotation_axis;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
@@ -1222,7 +1236,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
if (particles->draw_order != RSE::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY && particles->transform_align != RSE::PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1297,6 +1311,9 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
|
||||
copy_push_constant.align_up[2] = p_up_axis.z;
|
||||
|
||||
copy_push_constant.align_mode = particles->transform_align;
|
||||
copy_push_constant.align_src = particles->transform_align_src;
|
||||
copy_push_constant.align_axis = uint32_t(particles->transform_align_axis);
|
||||
copy_push_constant.pad2 = uint32_t(0);
|
||||
|
||||
if (do_sort) {
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
@@ -1621,7 +1638,18 @@ void ParticlesStorage::update_particles() {
|
||||
// So, we need to pass the inverse of the emission transform to bring the
|
||||
// particles to local coordinates before drawing.
|
||||
Transform3D inv = particles->emission_transform.affine_inverse();
|
||||
RendererRD::MaterialStorage::store_transform(inv, copy_push_constant.inv_emission_transform);
|
||||
copy_push_constant.inv_emission_transform[0] = inv.basis.rows[0][0];
|
||||
copy_push_constant.inv_emission_transform[1] = inv.basis.rows[1][0];
|
||||
copy_push_constant.inv_emission_transform[2] = inv.basis.rows[2][0];
|
||||
copy_push_constant.inv_emission_transform[3] = inv.basis.rows[0][1];
|
||||
copy_push_constant.inv_emission_transform[4] = inv.basis.rows[1][1];
|
||||
copy_push_constant.inv_emission_transform[5] = inv.basis.rows[2][1];
|
||||
copy_push_constant.inv_emission_transform[6] = inv.basis.rows[0][2];
|
||||
copy_push_constant.inv_emission_transform[7] = inv.basis.rows[1][2];
|
||||
copy_push_constant.inv_emission_transform[8] = inv.basis.rows[2][2];
|
||||
copy_push_constant.inv_emission_transform[9] = inv.origin.x;
|
||||
copy_push_constant.inv_emission_transform[10] = inv.origin.y;
|
||||
copy_push_constant.inv_emission_transform[11] = inv.origin.z;
|
||||
}
|
||||
|
||||
copy_push_constant.total_particles = total_amount;
|
||||
@@ -1630,6 +1658,8 @@ void ParticlesStorage::update_particles() {
|
||||
copy_push_constant.align_up[0] = 0;
|
||||
copy_push_constant.align_up[1] = 0;
|
||||
copy_push_constant.align_up[2] = 0;
|
||||
copy_push_constant.align_src = particles->transform_align_src;
|
||||
copy_push_constant.align_axis = uint32_t(particles->transform_align_axis);
|
||||
|
||||
if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
|
||||
copy_push_constant.trail_size = particles->trail_bind_poses.size();
|
||||
|
||||
@@ -183,7 +183,10 @@ private:
|
||||
|
||||
RID process_material;
|
||||
uint32_t frame_counter = 0;
|
||||
|
||||
RSE::ParticlesTransformAlign transform_align = RSE::PARTICLES_TRANSFORM_ALIGN_DISABLED;
|
||||
RSE::ParticlesTransformAlignCustomSrc transform_align_src = RSE::PARTICLES_ALIGN_CHANNEL_FILTER_X;
|
||||
RSE::ParticlesTransformAlignAxis transform_align_axis = RSE::ParticlesTransformAlignAxis::PARTICLES_ALIGN_AXIS_Y;
|
||||
|
||||
RSE::ParticlesDrawOrder draw_order = RSE::PARTICLES_DRAW_ORDER_INDEX;
|
||||
|
||||
@@ -317,7 +320,12 @@ private:
|
||||
uint32_t copy_mode_2d : 1;
|
||||
};
|
||||
|
||||
float inv_emission_transform[16];
|
||||
float inv_emission_transform[12];
|
||||
|
||||
uint32_t align_src;
|
||||
uint32_t align_axis;
|
||||
uint32_t pad1;
|
||||
uint32_t pad2;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -460,7 +468,11 @@ public:
|
||||
virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
|
||||
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RSE::ParticlesTransformAlign p_transform_align) override;
|
||||
virtual void particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_transform_align_channel_filter) override;
|
||||
virtual void particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) override;
|
||||
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
|
||||
|
||||
@@ -2724,6 +2724,8 @@ void RenderingServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("particles_set_fractional_delta", "particles", "enable"), &RenderingServer::particles_set_fractional_delta);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_collision_base_size", "particles", "size"), &RenderingServer::particles_set_collision_base_size);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_transform_align", "particles", "align"), &RenderingServer::particles_set_transform_align);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_transform_align_channel_filter", "particles", "channel_filter"), &RenderingServer::particles_set_transform_align_channel_filter);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_transform_align_axis", "particles", "p_rotation_axis"), &RenderingServer::particles_set_transform_align_axis);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_trails", "particles", "enable", "length_sec"), &RenderingServer::particles_set_trails);
|
||||
ClassDB::bind_method(D_METHOD("particles_set_trail_bind_poses", "particles", "bind_poses"), &RenderingServer::_particles_set_trail_bind_poses);
|
||||
|
||||
@@ -2747,6 +2749,16 @@ void RenderingServer::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD);
|
||||
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_CHANNEL_FILTER_DISABLED);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_CHANNEL_FILTER_X);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_CHANNEL_FILTER_Y);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_CHANNEL_FILTER_Z);
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_CHANNEL_FILTER_W);
|
||||
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_AXIS_X)
|
||||
BIND_ENUM_CONSTANT(RSE::PARTICLES_ALIGN_AXIS_Y)
|
||||
|
||||
BIND_CONSTANT(RSE::PARTICLES_EMIT_FLAG_POSITION);
|
||||
BIND_CONSTANT(RSE::PARTICLES_EMIT_FLAG_ROTATION_SCALE);
|
||||
|
||||
@@ -450,6 +450,8 @@ public:
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) = 0;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RSE::ParticlesTransformAlign p_transform_align) = 0;
|
||||
virtual void particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_transform_align_channel_filter) = 0;
|
||||
virtual void particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) = 0;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, float p_length_sec) = 0;
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
|
||||
@@ -1070,6 +1072,7 @@ private:
|
||||
};
|
||||
|
||||
// Make variant understand the enums.
|
||||
|
||||
VARIANT_ENUM_CAST_EXT(RSE::TextureType, RenderingServer::TextureType);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::TextureLayeredType, RenderingServer::TextureLayeredType);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::CubeMapLayer, RenderingServer::CubeMapLayer);
|
||||
@@ -1097,6 +1100,8 @@ VARIANT_ENUM_CAST_EXT(RSE::DecalTexture, RenderingServer::DecalTexture);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::DecalFilter, RenderingServer::DecalFilter);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesMode, RenderingServer::ParticlesMode);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesTransformAlign, RenderingServer::ParticlesTransformAlign);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesTransformAlignCustomSrc, RenderingServer::ParticlesTransformAlignCustomSrc);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesTransformAlignAxis, RenderingServer::ParticlesTransformAlignAxis);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesDrawOrder, RenderingServer::ParticlesDrawOrder);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesEmitFlags, RenderingServer::ParticlesEmitFlags);
|
||||
VARIANT_ENUM_CAST_EXT(RSE::ParticlesCollisionType, RenderingServer::ParticlesCollisionType);
|
||||
|
||||
@@ -639,6 +639,8 @@ public:
|
||||
FUNC2(particles_set_collision_base_size, RID, float)
|
||||
|
||||
FUNC2(particles_set_transform_align, RID, RSE::ParticlesTransformAlign)
|
||||
FUNC2(particles_set_transform_align_channel_filter, RID, RSE::ParticlesTransformAlignCustomSrc)
|
||||
FUNC2(particles_set_transform_align_axis, RID, RSE::ParticlesTransformAlignAxis)
|
||||
|
||||
FUNC2(particles_set_draw_order, RID, RSE::ParticlesDrawOrder)
|
||||
|
||||
|
||||
@@ -365,6 +365,7 @@ enum ParticlesTransformAlign {
|
||||
PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD,
|
||||
PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY,
|
||||
PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY,
|
||||
PARTICLES_TRANSFORM_ALIGN_LOCAL_BILLBOARD,
|
||||
};
|
||||
|
||||
enum ParticlesEmitFlags {
|
||||
@@ -382,6 +383,21 @@ enum ParticlesDrawOrder {
|
||||
PARTICLES_DRAW_ORDER_VIEW_DEPTH,
|
||||
};
|
||||
|
||||
enum ParticlesTransformAlignCustomSrc {
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_DISABLED,
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_X,
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_Y,
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_Z,
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_W,
|
||||
PARTICLES_ALIGN_CHANNEL_FILTER_MAX,
|
||||
};
|
||||
|
||||
enum ParticlesTransformAlignAxis {
|
||||
PARTICLES_ALIGN_AXIS_X,
|
||||
PARTICLES_ALIGN_AXIS_Y,
|
||||
PARTICLES_ALIGN_AXIS_MAX,
|
||||
};
|
||||
|
||||
/* PARTICLES COLLISION API */
|
||||
|
||||
enum ParticlesCollisionType {
|
||||
|
||||
@@ -76,6 +76,8 @@ public:
|
||||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RSE::ParticlesTransformAlign p_transform_align) = 0;
|
||||
virtual void particles_set_transform_align_channel_filter(RID p_particles, RSE::ParticlesTransformAlignCustomSrc p_channel_filter) = 0;
|
||||
virtual void particles_set_transform_align_axis(RID p_particles, RSE::ParticlesTransformAlignAxis p_rotation_axis) = 0;
|
||||
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user