Prechádzať zdrojové kódy

Add new bloom effect

ShiroSmith 6 rokov pred
rodič
commit
3fcffe5fb1
1 zmenil súbory, kde vykonal 202 pridanie a 0 odobranie
  1. 202 0
      hrt/prefab/rfx/TemporalBloom.hx

+ 202 - 0
hrt/prefab/rfx/TemporalBloom.hx

@@ -0,0 +1,202 @@
+package hrt.prefab.rfx;
+
+import hxsl.Eval;
+import h3d.pass.Copy;
+
+class Temporal extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@param var cur : Sampler2D;
+		@param var prev : Sampler2D;
+		@param var prevCamMat : Mat4;
+		@param var cameraInverseViewProj : Mat4;
+		@ignore @param var depthMap : Channel;
+		@param var strength : Float;
+
+		function getPixelPosition() : Vec3 {
+			var depth = depthMap.get(calculatedUV);
+			var temp = vec4(uvToScreen(calculatedUV), depthMap.get(calculatedUV), 1) * cameraInverseViewProj;
+			var originWS = temp.xyz / temp.w;
+			return originWS;
+		}
+
+		function fragment() {
+			var pixelPos = getPixelPosition();
+			var prevPos =  vec4(pixelPos, 1.0) * prevCamMat;
+			prevPos.xyz /= prevPos.w;
+			var prevUV = screenToUv(prevPos.xy);
+			var curVal = cur.get(calculatedUV).rgb;
+			var prevVal = prev.get(prevUV).rgb;
+			pixelColor.rgb = mix(curVal, prevVal, strength);
+		}
+	};
+}
+
+class DualFilterDown extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@param var source : Sampler2D;
+		@param var halfPixel : Vec2;
+
+		function fragment() {
+			var sum = vec3(0,0,0);
+			sum += texture(source, calculatedUV).rgb * 4.0;
+			sum += texture(source, calculatedUV + halfPixel.xy).rgb;
+			sum += texture(source, calculatedUV - halfPixel.xy).rgb;
+			sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb;
+			sum += texture(source, calculatedUV - vec2(halfPixel.x, -halfPixel.y)).rgb;
+			pixelColor.rgb = sum / 8.0;
+		}
+	};
+}
+
+class DualFilterUp extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@param var source : Sampler2D;
+		@param var halfPixel : Vec2;
+		
+		function fragment() {
+			var sum = vec3(0,0,0);
+			sum += texture(source, calculatedUV + vec2(-halfPixel.x * 2.0, 0.0)).rgb;
+			sum += texture(source, calculatedUV + vec2(-halfPixel.x, halfPixel.y)).rgb * 2.0;
+			sum += texture(source, calculatedUV + vec2(0.0, halfPixel.y * 2.0)).rgb;
+			sum += texture(source, calculatedUV + vec2(halfPixel.x, halfPixel.y)).rgb * 2.0;
+			sum += texture(source, calculatedUV + vec2(halfPixel.x * 2.0, 0.0)).rgb;
+			sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb * 2.0;
+			sum += texture(source, calculatedUV + vec2(0.0, -halfPixel.y * 2.0)).rgb;
+			sum += texture(source, calculatedUV + vec2(-halfPixel.x, -halfPixel.y)).rgb * 2.0;
+			pixelColor.rgb = sum / 12.0;
+		}
+	};
+}
+
+class Threshold extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@param var hdr : Sampler2D;
+		@param var threshold : Float;
+        @param var intensity : Float;
+
+		function fragment() {
+			pixelColor = hdr.get(calculatedUV);
+			pixelColor.rgb = max(pixelColor.rgb - threshold, vec3(0)) * intensity;
+		}
+	};
+}
+
+typedef TemporalBloomProps = {
+	var size : Float;
+	var downScaleCount : Int;
+	var threshold : Float;
+    var intensity : Float;
+	var useTemporalFilter : Bool;
+	var temporalStrength : Float;
+}
+
+class TemporalBloom extends RendererFX {
+
+	var thresholdPass = new h3d.pass.ScreenFx(new Threshold());
+	var temporalPass = new h3d.pass.ScreenFx(new Temporal());
+	var downScale = new h3d.pass.ScreenFx(new DualFilterDown());
+	var upScale = new h3d.pass.ScreenFx(new DualFilterUp());
+
+	var prevResult : h3d.mat.Texture;
+	var prevCamMat : h3d.Matrix;
+
+	public function new(?parent) {
+		super(parent);
+		props = ({
+			size : 0.5,
+			downScaleCount : 5,
+			threshold : 0.5,
+            intensity : 1.0,
+			useTemporalFilter : true,
+			temporalStrength : 0
+		} : TemporalBloomProps);
+		prevCamMat = new h3d.Matrix();
+		prevCamMat.identity();
+	}
+
+	override function apply(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
+		if( step == BeforeTonemapping ) {
+			var pb : TemporalBloomProps = props;
+			var ctx = r.ctx;
+
+			var source = r.allocTarget("source", false, pb.size, RGBA16F);
+			ctx.engine.pushTarget(source);
+			thresholdPass.shader.hdr = ctx.getGlobal("hdr");
+			thresholdPass.shader.threshold = pb.threshold;
+            thresholdPass.shader.intensity= pb.intensity;
+			thresholdPass.render();
+			ctx.engine.popTarget();
+
+			var curSize = pb.size ;
+			var curTarget : h3d.mat.Texture = source;
+			for( i in 0 ... pb.downScaleCount ) {
+				curSize *= 0.5;
+				var prevTarget = curTarget;
+				curTarget = r.allocTarget("dso_"+i, false, curSize, RGBA16F);
+				ctx.engine.pushTarget(curTarget);
+				downScale.shader.source = prevTarget;
+				downScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height);
+				downScale.render();
+				ctx.engine.popTarget();
+			}
+			for( i in 0 ... pb.downScaleCount ) {
+				curSize *= 1.5;
+				var prevTarget = curTarget;
+				curTarget = r.allocTarget("uso_"+i, false, curSize, RGBA16F);
+				ctx.engine.pushTarget(curTarget);
+				upScale.shader.source = prevTarget;
+				upScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height);
+				upScale.render();
+				ctx.engine.popTarget();
+			}
+
+			if( pb.useTemporalFilter ) {
+				var finalTarget = r.allocTarget("tpf", false, curSize, RGBA16F);
+				prevResult = r.allocTarget("pr", false, curSize, RGBA16F);
+				ctx.engine.pushTarget(finalTarget);
+				var depth : hxsl.ChannelTexture = ctx.getGlobal("depthMap");
+				temporalPass.shader.depthMapChannel = depth.channel;
+				temporalPass.shader.depthMap = depth.texture;
+				temporalPass.shader.cur = curTarget;
+				temporalPass.shader.prev = prevResult;
+				temporalPass.shader.prevCamMat.load(prevCamMat);
+				temporalPass.shader.cameraInverseViewProj.load(ctx.camera.getInverseViewProj());
+				temporalPass.shader.strength = pb.temporalStrength;
+				temporalPass.render();
+				ctx.engine.popTarget();
+
+				Copy.run(finalTarget, prevResult);
+				ctx.setGlobal("bloom", finalTarget);
+				prevCamMat.load(ctx.camera.m);
+			}
+			else
+				ctx.setGlobal("bloom", curTarget);
+		}
+	}
+
+	#if editor
+	override function edit( ctx : hide.prefab.EditContext ) {
+		ctx.properties.add(new hide.Element('
+			<dl>
+			<dt>Threshold</dt><dd><input type="range" min="0" max="1" field="threshold"/></dd>
+            <dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
+			<dt>Size</dt><dd><input type="range" min="0" max="1" field="size"/></dd>
+			<dt>DownScale Count</dt><dd><input type="range" min="1" max="5" field="downScaleCount" step="1"/></dd>
+			<dt>Use Temporal Filter</dt><dd><input type="checkbox" field="useTemporalFilter"/></dd>
+			<dt>Temporal Strength</dt><dd><input type="range" min="0" max="1" field="temporalStrength"/></dd>
+			</dl>
+		'),props);
+	}
+	#end
+
+	static var _ = Library.register("rfx.temporalbloom", TemporalBloom);
+
+}