Sfoglia il codice sorgente

Add probe support, refacto some code in renderer
LUT for environment is now static

ShiroSmith 4 anni fa
parent
commit
515185d29c

+ 4 - 0
h3d/scene/CameraController.hx

@@ -229,6 +229,10 @@ class CameraController extends h3d.scene.Object {
 
 	override function sync(ctx:RenderContext) {
 
+		// Disable Camera Sync during bake
+		if( ctx.scene.renderer.renderMode == LightProbe )
+			return;
+
 		if( !ctx.visibleFlag && !alwaysSync ) {
 			super.sync(ctx);
 			return;

+ 53 - 15
h3d/scene/pbr/Environment.hx

@@ -38,7 +38,6 @@ class IrradBase extends h3d.shader.ScreenShader {
 
 }
 
-
 class IrradShader extends IrradBase {
 
 	static var SRC = {
@@ -152,7 +151,7 @@ class IrradLut extends IrradBase {
 	}
 }
 
-class IrradEquiProj extends h3d.shader.ScreenShader {
+class PanoramaToCube extends h3d.shader.ScreenShader {
 
 	static var SRC = {
 
@@ -173,20 +172,48 @@ class IrradEquiProj extends h3d.shader.ScreenShader {
 		}
 
 	};
+}
+
+class CubeToPanorama extends h3d.shader.ScreenShader {
+
+	static var SRC = {
 
+		@param var source : SamplerCube;
+
+		function fragment() {
+			var PI = 3.1415926;
+			var fovX = PI * 2;
+			var fovY = PI;
+			var hOffset = (2.0 * PI - fovX) * 0.5;
+			var vOffset = (PI - fovY) * 0.5;
+			var hAngle = hOffset + calculatedUV.x * fovX;
+			var vAngle = vOffset + calculatedUV.y * fovY;
+			var n = vec3(0);
+			n.x = sin(vAngle) * sin(hAngle);
+			n.y = cos(vAngle);
+			n.z = sin(vAngle) * cos(hAngle);
+			n = n.normalize();
+			pixelColor = vec4(source.get(n).rgb, 1.0);
+			pixelColor = vec4(1,0,0,1);
+		}
+
+	};
 }
 
-class Environment  {
+class Environment {
 
 	public var sampleBits : Int;
 	public var diffSize : Int;
 	public var specSize : Int;
 	public var specLevels : Int;
-
 	public var ignoredSpecLevels : Int = 1;
 
+	// 2D Texture - Panoramic
 	public var source : h3d.mat.Texture;
+
+	// Cube Texture - Source converted
 	public var env : h3d.mat.Texture;
+
 	public var lut : h3d.mat.Texture;
 	public var diffuse : h3d.mat.Texture;
 	public var specular : h3d.mat.Texture;
@@ -205,8 +232,26 @@ class Environment  {
 		this.diffSize = diffSize;
 		this.specSize = specSize;
 		this.sampleBits = sampleBits;
+		this.lut = getDefaultLUT();
 	}
 
+	public static function getDefaultLUT() {
+		var engine = h3d.Engine.getCurrent();
+		var t : h3d.mat.Texture = @:privateAccess engine.resCache.get(Environment);
+		if( t != null )
+			return t;
+		t = new h3d.mat.Texture(128, 128, [Target], RGBA32F);
+		computeIrradLut(t);
+		@:privateAccess engine.resCache.set(Environment, t);
+
+		function computeLut() {
+			t = new h3d.mat.Texture(128, 128, [Target], RGBA32F);
+			computeIrradLut(t);
+		}
+		t.realloc = computeLut;
+
+		return t;
+	}
 
 	function equiToCube() {
 		if( source.flags.has(Loading) )
@@ -218,7 +263,7 @@ class Environment  {
 				throw "Unrecognized environment map format";
 			if(env == null)
 				env = new h3d.mat.Texture(source.height, source.height, [Cube, Target]);
-			var pass = new h3d.pass.ScreenFx(new IrradEquiProj());
+			var pass = new h3d.pass.ScreenFx(new PanoramaToCube());
 			var engine = h3d.Engine.getCurrent();
 			pass.shader.texture = source;
 			for( i in 0...6 ) {
@@ -237,17 +282,11 @@ class Environment  {
 
 	public function dispose() {
 		if( env != null ) env.dispose();
-		if( lut != null ) lut.dispose();
 		if( diffuse != null ) diffuse.dispose();
 		if( specular != null ) specular.dispose();
 	}
 
 	function createTextures() {
-		if( lut == null ) {
-			lut = new h3d.mat.Texture(128, 128, [Target], RGBA32F);
-			lut.setName("irradLut");
-			lut.preventAutoDispose();
-		}
 		if( diffuse == null ) {
 			diffuse = new h3d.mat.Texture(diffSize, diffSize, [Cube, Target], RGBA32F);
 			diffuse.setName("irradDiffuse");
@@ -263,7 +302,6 @@ class Environment  {
 
 	public function compute() {
 		createTextures();
-		computeIrradLut();
 		computeIrradiance();
 	}
 
@@ -290,12 +328,12 @@ class Environment  {
 		});
 	}
 
-	function computeIrradLut() {
+	static function computeIrradLut( t : h3d.mat.Texture ) {
 		var screen = new h3d.pass.ScreenFx(new IrradLut());
-		screen.shader.samplesBits = sampleBits;
+		screen.shader.samplesBits = 12;
 
 		var engine = h3d.Engine.getCurrent();
-		engine.pushTarget(lut);
+		engine.pushTarget(t);
 		screen.render();
 		engine.popTarget();
 		screen.dispose();

+ 46 - 14
h3d/scene/pbr/Renderer.hx

@@ -193,7 +193,7 @@ class Renderer extends h3d.scene.Renderer {
 	function lighting() {
 
 		begin(Shadows);
-		var ls = hxd.impl.Api.downcast(getLightSystem(), LightSystem);
+		var ls = hxd.impl.Api.downcast(getLightSystem(), h3d.scene.pbr.LightSystem);
 		var count = ctx.engine.drawCalls;
 		if( ls != null ) drawShadows(ls);
 		if( ctx.lightSystem != null ) ctx.lightSystem.drawPasses = ctx.engine.drawCalls - count;
@@ -221,9 +221,15 @@ class Renderer extends h3d.scene.Renderer {
 		pbrProps.isScreen = false;
 		draw(pbrLightPass.name);
 
-		if( renderMode == LightProbe ) {
+		if( !renderLightProbes() && env != null ) {
+			mark("Indirect Lighting");
 			pbrProps.isScreen = true;
+			pbrIndirect.drawIndirectDiffuse = true;
+			pbrIndirect.drawIndirectSpecular = true;
 			pbrOut.render();
+		}
+
+		if( renderMode == LightProbe ) {
 			resetTarget();
 			copy(textures.hdr, null);
 			// no warnings
@@ -232,15 +238,39 @@ class Renderer extends h3d.scene.Renderer {
 			return;
 		}
 
-		// Indirect Lighting - Diffuse and Specular
- 		if( env != null ) {
+		end();
+	}
+
+	function renderLightProbes() {
+		var probePass = get("lightProbe");
+		if( probePass.isEmpty() )
+			return false;
+		function probeSort( passes : h3d.pass.PassList ) {
+			// Priority of the probe stored in _44 of AbsPos
+			passes.sort( (po1, po2) -> return Std.int(po1.obj.getAbsPos()._44 - po2.obj.getAbsPos()._44) );
+		}
+
+		// Probe Rendering & Blending
+		var probeOutput = allocTarget("probeOutput", true, 1.0, RGBA16F);
+		ctx.engine.pushTarget(probeOutput);
+		clear(0);
+
+		// Default Env & SkyBox
+		if( env != null ) {
 			mark("Indirect Lighting");
 			pbrProps.isScreen = true;
 			pbrIndirect.drawIndirectDiffuse = true;
 			pbrIndirect.drawIndirectSpecular = true;
 			pbrOut.render();
 		}
-		end();
+
+		// Light Probe with Alpha Blend
+		pbrProps.isScreen = false;
+		renderPass(defaultPass, get("lightProbe"), probeSort);
+		ctx.engine.popTarget();
+
+		h3d.pass.Copy.run(probeOutput, textures.hdr, Add);
+		return true;
 	}
 
 	function drawShadows( ls : LightSystem ) {
@@ -354,12 +384,13 @@ class Renderer extends h3d.scene.Renderer {
 			pbrIndirect.irrSpecular = env.specular;
 			pbrIndirect.irrSpecularLevels = env.specLevels;
 			pbrIndirect.cameraInvViewProj.load(ctx.camera.getInverseViewProj());
+			pbrIndirect.skyScale = 1.0;
 
 			pbrDirect.doDiscard = false;
 			switch( renderMode ) {
 			case Default:
 				pbrIndirect.drawIndirectDiffuse = true;
-				pbrIndirect.drawIndirectSpecular= true;
+				pbrIndirect.drawIndirectSpecular = true;
 				pbrIndirect.showSky = skyMode != Hide;
 				pbrIndirect.skyColor = false;
 				pbrIndirect.skyMap = switch( skyMode ) {
@@ -370,11 +401,9 @@ class Renderer extends h3d.scene.Renderer {
 					pbrIndirect.gammaCorrect = true;
 					env.env;
 				case Specular:
-					pbrIndirect.skyScale = 1.0;
 					pbrIndirect.gammaCorrect = false;
 					env.specular;
 				case Irrad:
-					pbrIndirect.skyScale = 1.0;
 					pbrIndirect.gammaCorrect = false;
 					env.diffuse;
 				case Background:
@@ -383,18 +412,21 @@ class Renderer extends h3d.scene.Renderer {
 					pbrIndirect.gammaCorrect = true;
 					null;
 				};
-
-				if( pbrIndirect.skyMap == null && pbrIndirect.showSky && !pbrIndirect.skyColor )
-					pbrIndirect.showSky = false;
-
 			case LightProbe:
 				pbrIndirect.drawIndirectDiffuse = false;
 				pbrIndirect.drawIndirectSpecular = false;
 				pbrIndirect.showSky = true;
-				pbrIndirect.skyColor = false;
 				pbrIndirect.skyMap = env.env;
+				pbrIndirect.gammaCorrect = false;			
 			}
-			pbrDirect.doDiscard = true;
+
+			if( pbrIndirect.skyMap == null && pbrIndirect.showSky && !pbrIndirect.skyColor )
+				pbrIndirect.showSky = false;
+
+		}
+		else {
+			pbrIndirect.drawIndirectDiffuse = false;
+			pbrIndirect.drawIndirectSpecular = false;
 		}
 
 		tonemap.shader.mode = switch( toneMode ) {

+ 13 - 8
h3d/shader/pbr/Lighting.hx

@@ -4,26 +4,31 @@ class Indirect extends PropsDefinition {
 
 	static var SRC = {
 
+		// Flags
+		@const var drawIndirectDiffuse : Bool;
+		@const var drawIndirectSpecular : Bool;
+		@const var showSky : Bool;
+		@const var skyColor : Bool;
+
+		// Indirect Params
 		@param var irrLut : Sampler2D;
 		@param var irrDiffuse : SamplerCube;
 		@param var irrSpecular : SamplerCube;
 		@param var irrSpecularLevels : Float;
 		@param var irrPower : Float;
-
 		@param var rot : Float;
 
-		@const var showSky : Bool;
-		@const var skyColor : Bool;
-		@param var skyColorValue : Vec3;
-
-		@const var drawIndirectDiffuse : Bool;
-		@const var drawIndirectSpecular : Bool;
+		// Sky Params
 		@param var skyMap : SamplerCube;
 		@param var skyThreshold : Float;
 		@param var skyScale : Float;
 		@const var gammaCorrect : Bool;
 		@param var cameraInvViewProj : Mat4;
+		@param var skyColorValue : Vec3;
+
+		// Emissive Blend
 		@param var emissivePower : Float;
+
 		var calculatedUV : Vec2;
 
 		function fragment() {
@@ -37,7 +42,7 @@ class Indirect extends PropsDefinition {
 					if( skyColor )
 						color = skyColorValue;
 					else {
-						normal = (vec3( uvToScreen(calculatedUV) * 5. /*?*/ , 1. ) * cameraInvViewProj.mat3x4()).normalize();
+						normal = (vec3( uvToScreen(calculatedUV), 1. ) * cameraInvViewProj.mat3x4()).normalize();
 						var rotatedNormal = vec3(normal.x * c - normal.y * s, normal.x * s + normal.y * c, normal.z);
 						color = skyMap.get(rotatedNormal).rgb;
 						color.rgb *= mix(1.0, skyScale, (max( max(color.r, max(color.g, color.b)) - skyThreshold, 0) / max(0.001, (1.0 - skyThreshold))));