@@ -545,6 +545,7 @@ impl Module {
545545 impl_module_binary ! ( uniform, UniformRand ) ;
546546 impl_module_binary ! ( normal, NormalRand ) ;
547547 impl_module_binary ! ( vec2, Vec2 ) ;
548+ impl_module_binary ! ( vec4_xyz_w, Vec4XyzW ) ;
548549
549550 /// Build a ternary expression and append it to the module.
550551 ///
@@ -581,7 +582,9 @@ impl Module {
581582 }
582583
583584 impl_module_ternary ! ( mix, Mix ) ;
585+ impl_module_ternary ! ( clamp, Clamp ) ;
584586 impl_module_ternary ! ( smoothstep, SmoothStep ) ;
587+ impl_module_ternary ! ( vec3, Vec3 ) ;
585588
586589 /// Build a cast expression and append it to the module.
587590 ///
@@ -2187,6 +2190,17 @@ pub enum TernaryOperator {
21872190 /// (1 - t) + y * t`.
21882191 Mix ,
21892192
2193+ /// Clamp operator.
2194+ ///
2195+ /// Returns the first argument clamped to the range defined by the second
2196+ /// and third arguments. If the operands are vectors, they must be of
2197+ /// the same rank, and the result is a vector of that rank
2198+ /// and same element scalar type.
2199+ ///
2200+ /// The expression `clamp(x, low, high)` is equivalent to `min(max(x, low),
2201+ /// high)`.
2202+ Clamp ,
2203+
21902204 /// Smooth stepping operator.
21912205 ///
21922206 /// Returns the smooth Hermitian interpolation between the first and second
@@ -2212,6 +2226,7 @@ impl ToWgslString for TernaryOperator {
22122226 fn to_wgsl_string ( & self ) -> String {
22132227 match * self {
22142228 TernaryOperator :: Mix => "mix" . to_string ( ) ,
2229+ TernaryOperator :: Clamp => "clamp" . to_string ( ) ,
22152230 TernaryOperator :: SmoothStep => "smoothstep" . to_string ( ) ,
22162231 TernaryOperator :: Vec3 => "vec3" . to_string ( ) ,
22172232 }
@@ -3600,6 +3615,35 @@ impl WriterExpr {
36003615 self . binary_op ( other, BinaryOperator :: Mul )
36013616 }
36023617
3618+ /// Apply the logical operator "normal" to this expression and another
3619+ /// expression.
3620+ ///
3621+ /// This is a binary operator, which applies component-wise to vector
3622+ /// operand expressions. That is, for vectors, this produces a vector of
3623+ /// random values where each component is normally distributed with a mean
3624+ /// of the corresponding component of the first operand and a standard
3625+ /// deviation of the corresponding component of the second operand.
3626+ ///
3627+ /// # Example
3628+ ///
3629+ /// ```
3630+ /// # use bevy_hanabi::*;
3631+ /// # use bevy::math::Vec3;
3632+ /// # let mut w = ExprWriter::new();
3633+ /// // A literal expression `x = vec3<f32>(3., -2., 7.);`.
3634+ /// let x = w.lit(Vec3::new(3., -2., 7.));
3635+ ///
3636+ /// // Another literal expression `y = vec3<f32>(1., 5., 7.);`.
3637+ /// let y = w.lit(Vec3::new(1., 5., 7.));
3638+ ///
3639+ /// // A random variable normally distributed in [1:3]x[-2:5]x[7:7].
3640+ /// let z = x.normal(y);
3641+ /// ```
3642+ #[ inline]
3643+ pub fn normal ( self , other : Self ) -> Self {
3644+ self . binary_op ( other, BinaryOperator :: NormalRand )
3645+ }
3646+
36033647 /// Calculate the remainder of the division of the current expression by
36043648 /// another expression.
36053649 ///
@@ -3712,35 +3756,6 @@ impl WriterExpr {
37123756 self . binary_op ( other, BinaryOperator :: UniformRand )
37133757 }
37143758
3715- /// Apply the logical operator "normal" to this expression and another
3716- /// expression.
3717- ///
3718- /// This is a binary operator, which applies component-wise to vector
3719- /// operand expressions. That is, for vectors, this produces a vector of
3720- /// random values where each component is normally distributed with a mean
3721- /// of the corresponding component of the first operand and a standard
3722- /// deviation of the corresponding component of the second operand.
3723- ///
3724- /// # Example
3725- ///
3726- /// ```
3727- /// # use bevy_hanabi::*;
3728- /// # use bevy::math::Vec3;
3729- /// # let mut w = ExprWriter::new();
3730- /// // A literal expression `x = vec3<f32>(3., -2., 7.);`.
3731- /// let x = w.lit(Vec3::new(3., -2., 7.));
3732- ///
3733- /// // Another literal expression `y = vec3<f32>(1., 5., 7.);`.
3734- /// let y = w.lit(Vec3::new(1., 5., 7.));
3735- ///
3736- /// // A random variable normally distributed in [1:3]x[-2:5]x[7:7].
3737- /// let z = x.normal(y);
3738- /// ```
3739- #[ inline]
3740- pub fn normal ( self , other : Self ) -> Self {
3741- self . binary_op ( other, BinaryOperator :: NormalRand )
3742- }
3743-
37443759 fn ternary_op ( self , second : Self , third : Self , op : TernaryOperator ) -> Self {
37453760 assert_eq ! ( self . module, second. module) ;
37463761 assert_eq ! ( self . module, third. module) ;
@@ -3788,6 +3803,34 @@ impl WriterExpr {
37883803 self . ternary_op ( other, fraction, TernaryOperator :: Mix )
37893804 }
37903805
3806+ /// Clamp an expression between the bounds defined by two other expressions.
3807+ ///
3808+ /// This is a ternary operator, which applies component-wise to vector
3809+ /// operand expressions.
3810+ ///
3811+ /// # Example
3812+ ///
3813+ /// ```
3814+ /// # use bevy_hanabi::*;
3815+ /// # use bevy::math::Vec2;
3816+ /// # let mut w = ExprWriter::new();
3817+ /// // A literal expression `x = vec2<f32>(1., -2.);`.
3818+ /// let x = w.lit(Vec2::new(1., -2.));
3819+ ///
3820+ /// // A literal expression `lo = vec2<f32>(3., -3.);`.
3821+ /// let lo = w.lit(Vec2::new(3., -3.));
3822+ ///
3823+ /// // A literal expression `hi = vec2<f32>(5., 1.);`.
3824+ /// let hi = w.lit(Vec2::new(5., 1.));
3825+ ///
3826+ /// // Clamp x in [lo:hi]
3827+ /// let z = x.clamp(lo, hi); // == vec2<f32>(3., -2.)
3828+ /// ```
3829+ #[ inline]
3830+ pub fn clamp ( self , lo : Self , hi : Self ) -> Self {
3831+ self . ternary_op ( lo, hi, TernaryOperator :: Clamp )
3832+ }
3833+
37913834 /// Calculate the smooth Hermite interpolation in \[0:1\] of the current
37923835 /// value taken between the given bounds.
37933836 ///
@@ -4326,6 +4369,7 @@ mod tests {
43264369
43274370 let x = m. attr ( Attribute :: POSITION ) ;
43284371 let y = m. lit ( Vec3 :: ONE ) ;
4372+ let z = m. lit ( 1.45 ) ;
43294373
43304374 let atan2 = m. atan2 ( x, y) ;
43314375 let cross = m. cross ( x, y) ;
@@ -4334,6 +4378,7 @@ mod tests {
43344378 let min = m. min ( x, y) ;
43354379 let max = m. max ( x, y) ;
43364380 let step = m. step ( x, y) ;
4381+ let vec4_xyz_w = m. vec4_xyz_w ( x, z) ;
43374382
43384383 let property_layout = PropertyLayout :: default ( ) ;
43394384 let particle_layout = ParticleLayout :: default ( ) ;
@@ -4361,6 +4406,17 @@ mod tests {
43614406 )
43624407 ) ;
43634408 }
4409+
4410+ {
4411+ let expr = ctx. eval ( & m, vec4_xyz_w) ;
4412+ assert ! ( expr. is_ok( ) ) ;
4413+ let expr = expr. unwrap ( ) ;
4414+ let z = ctx. eval ( & m, z) . unwrap ( ) ;
4415+ assert_eq ! (
4416+ expr,
4417+ format!( "vec4(particle.{}, {})" , Attribute :: POSITION . name( ) , z)
4418+ ) ;
4419+ }
43644420 }
43654421
43664422 #[ test]
@@ -4369,17 +4425,26 @@ mod tests {
43694425
43704426 let x = m. attr ( Attribute :: POSITION ) ;
43714427 let y = m. lit ( Vec3 :: ONE ) ;
4428+ let z = m. lit ( Vec3 :: splat ( 2. ) ) ;
43724429 let t = m. lit ( 0.3 ) ;
4430+ let a = m. lit ( -4.2 ) ;
4431+ let b = m. lit ( 53.09 ) ;
43734432
43744433 let mix = m. mix ( x, y, t) ;
4434+ let clamp = m. clamp ( x, y, z) ;
43754435 let smoothstep = m. smoothstep ( x, y, x) ;
4436+ let vecthree = m. vec3 ( a, b, t) ;
43764437
43774438 let property_layout = PropertyLayout :: default ( ) ;
43784439 let particle_layout = ParticleLayout :: default ( ) ;
43794440 let mut ctx =
43804441 ShaderWriter :: new ( ModifierContext :: Update , & property_layout, & particle_layout) ;
43814442
4382- for ( expr, op, third) in [ ( mix, "mix" , t) , ( smoothstep, "smoothstep" , x) ] {
4443+ for ( expr, op, third) in [
4444+ ( mix, "mix" , t) ,
4445+ ( clamp, "clamp" , z) ,
4446+ ( smoothstep, "smoothstep" , x) ,
4447+ ] {
43834448 let expr = ctx. eval ( & m, expr) ;
43844449 assert ! ( expr. is_ok( ) ) ;
43854450 let expr = expr. unwrap ( ) ;
@@ -4394,6 +4459,16 @@ mod tests {
43944459 )
43954460 ) ;
43964461 }
4462+
4463+ {
4464+ let expr = ctx. eval ( & m, vecthree) ;
4465+ assert ! ( expr. is_ok( ) ) ;
4466+ let expr = expr. unwrap ( ) ;
4467+ let a = ctx. eval ( & m, a) . unwrap ( ) ;
4468+ let b = ctx. eval ( & m, b) . unwrap ( ) ;
4469+ let t = ctx. eval ( & m, t) . unwrap ( ) ;
4470+ assert_eq ! ( expr, format!( "vec3({}, {}, {})" , a, b, t) ) ;
4471+ }
43974472 }
43984473
43994474 #[ test]
0 commit comments