Quellcode durchsuchen

Adding RelativeTransformSimulation.hx simulation shader to animate particle transform over time (also supports curves).

clementlandrin vor 2 Monaten
Ursprung
Commit
f152c0df14
1 geänderte Dateien mit 177 neuen und 0 gelöschten Zeilen
  1. 177 0
      hrt/prefab/fx/gpuemitter/RelativeTransformSimulation.hx

+ 177 - 0
hrt/prefab/fx/gpuemitter/RelativeTransformSimulation.hx

@@ -0,0 +1,177 @@
+package hrt.prefab.fx.gpuemitter;
+
+class RelativeTransformSimulationShader extends ComputeUtils {
+
+	override function onRemove(emitter : GPUEmitterObject) {
+		super.onRemove(emitter);
+
+		if ( curveTexture != null )
+			curveTexture.dispose();
+		curveTexture = null;
+	}
+
+	static var SRC = {
+
+		@const(511) var CURVE_MASK : Int;
+
+		@param var x : Float;
+		@param var y : Float;
+		@param var z : Float;
+
+		@param var scaleX : Float;
+		@param var scaleY : Float;
+		@param var scaleZ : Float;
+
+		@param var rotX : Float;
+		@param var rotY : Float;
+		@param var rotZ : Float;
+
+		@param var curveTexture : Sampler2D;
+
+		var life : Float;
+		var relativeTransform : Mat4;
+
+		function hasBit(n : Int) : Bool {
+			return (CURVE_MASK & (1 << n) ) != 0;
+		}
+
+		function getCurve(n : Int) : Float {
+			return curveTexture.getLod(vec2(life, (n + 0.5) / 9.0), 0.0).r;
+		}
+
+		function main() {
+			var translation = vec3(x,y,z);
+			var scale = vec3(scaleX, scaleY, scaleZ);
+			var rotation = vec3(rotX, rotY, rotZ);
+
+			if ( hasBit(0) )
+				translation.x = getCurve(0);
+			if ( hasBit(1) )
+				translation.y = getCurve(1);
+			if ( hasBit(2) )
+				translation.z = getCurve(2);
+
+			if ( hasBit(3) )
+				scale.x = getCurve(3);
+			if ( hasBit(4) )
+				scale.y = getCurve(4);
+			if ( hasBit(5) )
+				scale.z = getCurve(5);
+
+			if ( hasBit(6) )
+				rotation.x = getCurve(6);
+			if ( hasBit(7) )
+				rotation.y = getCurve(7);
+			if ( hasBit(8) )
+				rotation.z = getCurve(8);
+
+			// rotation not supported
+			var shaderTRS = scaleMatrix(scale) * translationMatrix(translation);
+			relativeTransform = relativeTransform * shaderTRS;
+		}
+	}
+}
+
+class RelativeTransformSimulation extends SimulationShader {
+
+	@:s var x : Float = 0.0;
+	@:s var y : Float = 0.0;
+	@:s var z : Float = 0.0;
+
+	@:s var scaleX : Float = 1.0;
+	@:s var scaleY : Float = 1.0;
+	@:s var scaleZ : Float = 1.0;
+
+	@:s var rotX : Float = 0.0;
+	@:s var rotY : Float = 0.0;
+	@:s var rotZ : Float = 0.0;
+
+	override function makeShader() {
+		return new RelativeTransformSimulationShader();
+	}
+
+	override function updateInstance(?propName) {
+		super.updateInstance(propName);
+
+		var s = Std.downcast(shader, RelativeTransformSimulationShader);
+		if ( s.curveTexture != null )
+			s.curveTexture.dispose();
+
+		s.x = x;
+		s.y = y;
+		s.z = z;
+
+		s.scaleX = scaleX;
+		s.scaleY = scaleY;
+		s.scaleZ = scaleZ;
+
+		s.rotX = rotX;
+		s.rotY = rotY;
+		s.rotZ = rotZ;
+
+		s.CURVE_MASK = 0;
+
+		var width = 256;
+		var height = 9;
+
+		s.curveTexture = new h3d.mat.Texture(width, height, null, R32F);
+
+		var curves = findAll(hrt.prefab.Curve);
+		if ( curves.length == 0 )
+			return;
+
+		var curveNames = ["x", "y", "z", "scaleX", "scaleY", "scaleZ", "rotX", "rotY", "rotZ"];
+
+
+		var pixels = hxd.Pixels.alloc(width, height, s.curveTexture.format);
+		for ( c in curves ) {
+			if ( !c.shouldBeInstanciated() )
+				continue;
+			for ( index => name in curveNames ) {
+				if ( c.name != name )
+					continue;
+				s.CURVE_MASK = s.CURVE_MASK | (1 << index);
+				for ( i in 0...width )
+					pixels.setPixelF(i, index, new h3d.Vector4(c.getVal(i / width)));
+			}
+		}
+
+		s.curveTexture.uploadPixels(pixels);
+	}
+
+	override function postMakeInstance() {
+		super.postMakeInstance();
+
+		updateInstance();
+	}
+
+	#if editor
+	override function edit( ctx : hide.prefab.EditContext ) {
+		ctx.properties.add(new hide.Element('
+			<div class="group" name="Simulation">
+				<dl>
+					<dt>X</dt><dd><input type="range" field="x"/></dd>
+					<dt>Y</dt><dd><input type="range" field="y"/></dd>
+					<dt>Z</dt><dd><input type="range" field="z"/></dd>
+					<dt>Scale X</dt><dd><input type="range" field="scaleX"/></dd>
+					<dt>Scale Y</dt><dd><input type="range" field="scaleY"/></dd>
+					<dt>Scale Z</dt><dd><input type="range" field="scaleZ"/></dd>
+					<dt>Rotation X</dt><dd><input type="range" field="rotX"/></dd>
+					<dt>Rotation Y</dt><dd><input type="range" field="rotY"/></dd>
+					<dt>Rotation Z</dt><dd><input type="range" field="rotZ"/></dd>
+				</dl>
+			</div>
+			'), this, function(pname) {
+				ctx.onChange(this, pname);
+		});
+	}
+
+	override function getHideProps() : hide.prefab.HideProps {
+		var p = super.getHideProps();
+		p.onChildUpdate = function(p : hrt.prefab.Prefab) updateInstance(p != null ? p.name : null);
+		return p;
+	}
+	#end
+
+	static var _ = Prefab.register("relativeTransformSimulation", RelativeTransformSimulation);
+}