瀏覽代碼

Update Emitter, allow shader and ParticleLit prefab as children
Add Particle Lit Prefab et particleForward shader

ShiroSmith 4 年之前
父節點
當前提交
c1fe67685b
共有 3 個文件被更改,包括 165 次插入1 次删除
  1. 17 1
      hrt/prefab/fx/Emitter.hx
  2. 81 0
      hrt/prefab/pbr/ParticleLit.hx
  3. 67 0
      hrt/shader/ParticleForward.hx

+ 17 - 1
hrt/prefab/fx/Emitter.hx

@@ -1057,8 +1057,24 @@ class Emitter extends Object3D {
 	}
 
 	override function make(ctx: Context) {
+		if( ctx == null ) {
+			ctx = new Context();
+			ctx.init();
+		}
+
+		ctx = makeInstance(ctx);
+
 		// Don't make children, which are used to setup particles
-		return makeInstance(ctx);
+		for( c in children ) {
+			var shader = Std.downcast(c, hrt.prefab.Shader);
+			if( shader != null )
+				shader.make(ctx);
+			var lit = Std.downcast(c, hrt.prefab.pbr.ParticleLit);
+			if( lit != null )
+				lit.make(ctx);
+		}
+
+		return ctx;
 	}
 
 	static inline function randProp(name: String) {

+ 81 - 0
hrt/prefab/pbr/ParticleLit.hx

@@ -0,0 +1,81 @@
+package hrt.prefab.pbr;
+
+import hrt.shader.ParticleForward;
+
+class ParticleLit extends Prefab {
+
+	public var vertexShader : Bool = true;
+
+	public function new(?parent) {
+		super(parent);
+		type = "particleLit";
+	}
+
+	override function load( obj : Dynamic ) {
+		super.load(obj);
+		if( obj.vertexShader != null ) vertexShader = obj.vertexShader;
+	}
+
+	override function save() {
+		var obj : Dynamic = super.save();
+		obj.vertexShader = vertexShader;
+		return obj;
+	}
+
+	override function makeInstance( ctx : Context ):Context {
+		ctx = ctx.clone(this);
+		refreshShaders(ctx);
+		updateInstance(ctx);
+		return ctx;
+	}
+
+	function refreshShaders( ctx : Context ) {
+
+		var pf = new ParticleForward();
+		var o = ctx.local3d;
+
+		for( m in o.getMaterials() ) {
+			if( m.mainPass.name != "forward" )
+				continue;
+			m.mainPass.removeShader(m.mainPass.getShader(ParticleForward));
+			m.mainPass.addShader(pf);
+			pf.VERTEX = vertexShader;
+		}
+		
+	}
+
+	override function updateInstance( ctx : Context, ?propName : String ) {
+		for( m in ctx.local3d.getMaterials() ) {
+			var pf = m.mainPass.getShader(ParticleForward);
+			if( pf != null ) {
+				pf.VERTEX = vertexShader;
+			}
+		}
+	}
+
+	#if editor
+	override function getHideProps() : HideProps {
+		return { 	icon : "cube", 
+					name : "ParticleLit",
+					allowParent : function(p) return true  };
+	}
+
+	override function edit( ctx : EditContext ) {
+		super.edit(ctx);
+
+		var props = new hide.Element('
+			<div class="group" name="Particle Lit">
+				<dl>
+					<dt>Vertex Shader</dt><dd><input type="checkbox" field="vertexShader"/></dd>
+				</dl>
+			</div>
+		');
+
+		ctx.properties.add(props, this, function(pname) {
+			ctx.onChange(this, pname);
+		});
+	}
+	#end
+
+	static var _ = Library.register("particleLit", ParticleLit);
+}

+ 67 - 0
hrt/shader/ParticleForward.hx

@@ -0,0 +1,67 @@
+package hrt.shader;
+
+class ParticleForward extends h3d.shader.pbr.DefaultForward implements h3d.scene.MeshBatch.MeshBatchAccess {
+
+	public var perInstance : Bool = false;
+
+	static var SRC = {
+
+		@const var VERTEX : Bool = true;
+		var lighting : Vec3;
+
+		function indirectLighting() : Vec3 {
+			var rotatedNormal = rotateNormal(transformedNormal);
+			var diffuse = irrDiffuse.get(rotatedNormal).rgb;
+			var indirect = diffuse * irrPower;
+			return indirect;
+		}
+		
+		function directLighting( lightColor : Vec3, lightDirection : Vec3) : Vec3 {
+			var result = vec3(0);
+			var NdL = clamp(transformedNormal.dot(lightDirection), 0.0, 1.0);
+			result = lightColor * NdL;
+			return result;
+		}
+
+		function evaluateLighting() : Vec3 {
+			var lightAccumulation = vec3(0);
+
+			// Dir Light
+			for( l in 0 ... dirLightCount )
+				lightAccumulation += evaluateDirLight(l);
+			// Point Light
+			for( l in 0 ... pointLightCount )
+				lightAccumulation += evaluatePointLight(l);
+			// Spot Light
+			for( l in 0 ... spotLightCount )
+				lightAccumulation += evaluateSpotLight(l);
+
+			// Indirect only support the main env from the scene at the moment
+			if( USE_INDIRECT > 0.0)
+				lightAccumulation += indirectLighting();
+
+			return lightAccumulation;
+		}
+
+		function init() {
+			view = (cameraPosition - transformedPosition).normalize();
+			NdV = transformedNormal.dot(view).max(0.);
+		}
+
+		function vertex() {
+			if( VERTEX ) {
+				init();
+				lighting = evaluateLighting();
+			}
+		}
+
+		function fragment() {
+			if( !VERTEX ) {
+				init();
+				lighting = evaluateLighting();
+			}
+			output.color.rgb *= lighting / PI;
+		}
+
+	}
+}