Browse Source

Add a height cutoff for fog

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
b322b5579b

+ 73 - 31
AnKi/Importer/GltfImporter.cpp

@@ -135,6 +135,19 @@ static ANKI_USE_RESULT Error getNodeTransform(const cgltf_node& node, Transform&
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
+static Bool stringsExist(const HashMapAuto<CString, StringAuto>& map, const std::initializer_list<CString>& list)
+{
+	for(CString item : list)
+	{
+		if(map.find(item) != map.getEnd())
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
 const char* GltfImporter::XML_HEADER = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
 const char* GltfImporter::XML_HEADER = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
 
 
 GltfImporter::GltfImporter(GenericMemoryPoolAllocator<U8> alloc)
 GltfImporter::GltfImporter(GenericMemoryPoolAllocator<U8> alloc)
@@ -456,51 +469,80 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 		}
 		}
-		else if((it = extras.find("skybox_solid_color")) != extras.getEnd())
+		else if(stringsExist(extras, {"skybox_solid_color", "skybox_image", "fog_min_density", "fog_max_density",
+									  "fog_height_of_min_density", "fog_height_of_max_density"}))
 		{
 		{
-			StringListAuto tokens(m_alloc);
-			tokens.splitString(*it, ' ');
-			if(tokens.getSize() != 3)
-			{
-				ANKI_IMPORTER_LOGE("Error parsing \"skybox_solid_color\" of node %s", getNodeName(node).cstr());
-				return Error::USER_DATA;
-			}
+			// Atmosphere
 
 
-			U count = 0;
-			Vec3 solidColor(0.0f);
-			for(auto& it : tokens)
+			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newSkyboxNode(\"%s\")\n", getNodeName(node).cstr()));
+			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getSkyboxComponent()\n"));
+
+			if((it = extras.find("skybox_solid_color")) != extras.getEnd())
 			{
 			{
-				F32 f;
-				const Error err = it.toNumber(f);
-				if(err)
+				StringListAuto tokens(m_alloc);
+				tokens.splitString(*it, ' ');
+				if(tokens.getSize() != 3)
 				{
 				{
 					ANKI_IMPORTER_LOGE("Error parsing \"skybox_solid_color\" of node %s", getNodeName(node).cstr());
 					ANKI_IMPORTER_LOGE("Error parsing \"skybox_solid_color\" of node %s", getNodeName(node).cstr());
 					return Error::USER_DATA;
 					return Error::USER_DATA;
 				}
 				}
 
 
-				solidColor[count++] = f;
+				U count = 0;
+				Vec3 solidColor(0.0f);
+				for(auto& it : tokens)
+				{
+					F32 f;
+					const Error err = it.toNumber(f);
+					if(err)
+					{
+						ANKI_IMPORTER_LOGE("Error parsing \"skybox_solid_color\" of node %s", getNodeName(node).cstr());
+						return Error::USER_DATA;
+					}
+
+					solidColor[count++] = f;
+				}
+
+				ANKI_CHECK(m_sceneFile.writeText("comp:setSolidColor(Vec3.new(%f, %f, %f))\n", solidColor.x(),
+												 solidColor.y(), solidColor.z()));
+			}
+			else if((it = extras.find("skybox_image")) != extras.getEnd())
+			{
+				ANKI_CHECK(m_sceneFile.writeText("comp:setImage(\"%s\")\n", it->cstr()));
 			}
 			}
 
 
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newSkyboxNode(\"%s\")\n", getNodeName(node).cstr()));
-			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getSkyboxComponent()\n"));
-			ANKI_CHECK(m_sceneFile.writeText("comp:setSolidColor(Vec3.new(%f, %f, %f))\n", solidColor.x(),
-											 solidColor.y(), solidColor.z()));
+			if((it = extras.find("fog_min_density")) != extras.getEnd())
+			{
+				F32 val;
+				ANKI_CHECK(it->toNumber(val));
+				ANKI_CHECK(m_sceneFile.writeText("comp:setMinFogDensity(\"%f\")\n", val));
+			}
 
 
-			Transform localTrf;
-			ANKI_CHECK(getNodeTransform(node, localTrf));
-			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
-		}
-		else if((it = extras.find("skybox_image")) != extras.getEnd())
-		{
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newSkyboxNode(\"%s\")\n", getNodeName(node).cstr()));
-			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getSkyboxComponent()\n"));
-			ANKI_CHECK(m_sceneFile.writeText("comp:setImage(\"%s\")\n", it->cstr()));
+			if((it = extras.find("fog_max_density")) != extras.getEnd())
+			{
+				F32 val;
+				ANKI_CHECK(it->toNumber(val));
+				ANKI_CHECK(m_sceneFile.writeText("comp:setMaxFogDensity(\"%f\")\n", val));
+			}
+
+			if((it = extras.find("fog_height_of_min_density")) != extras.getEnd())
+			{
+				F32 val;
+				ANKI_CHECK(it->toNumber(val));
+				ANKI_CHECK(m_sceneFile.writeText("comp:setHeightOfMinFogDensity(\"%f\")\n", val));
+			}
+
+			if((it = extras.find("fog_height_of_max_density")) != extras.getEnd())
+			{
+				F32 val;
+				ANKI_CHECK(it->toNumber(val));
+				ANKI_CHECK(m_sceneFile.writeText("comp:setHeightOfMaxFogDensity(\"%f\")\n", val));
+			}
 
 
 			Transform localTrf;
 			Transform localTrf;
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 		}
 		}
-		else if((it = extras.find("collision")) != extras.getEnd() && *it == "true")
+		else if((it = extras.find("collision")) != extras.getEnd() && (*it == "true" || *it == "1"))
 		{
 		{
 			ANKI_CHECK(
 			ANKI_CHECK(
 				m_sceneFile.writeText("\nnode = scene:newStaticCollisionNode(\"%s\")\n", getNodeName(node).cstr()));
 				m_sceneFile.writeText("\nnode = scene:newStaticCollisionNode(\"%s\")\n", getNodeName(node).cstr()));
@@ -513,7 +555,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 		}
 		}
-		else if((it = extras.find("reflection_probe")) != extras.getEnd() && *it == "true")
+		else if((it = extras.find("reflection_probe")) != extras.getEnd() && (*it == "true" || *it == "1"))
 		{
 		{
 			Vec3 tsl;
 			Vec3 tsl;
 			Mat3 rot;
 			Mat3 rot;
@@ -572,7 +614,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 		}
 		}
-		else if((it = extras.find("decal")) != extras.getEnd() && *it == "true")
+		else if((it = extras.find("decal")) != extras.getEnd() && (*it == "true" || *it == "1"))
 		{
 		{
 			StringAuto diffuseAtlas(m_alloc);
 			StringAuto diffuseAtlas(m_alloc);
 			if((it = extras.find("decal_diffuse_atlas")) != extras.getEnd())
 			if((it = extras.find("decal_diffuse_atlas")) != extras.getEnd())

+ 12 - 0
AnKi/Renderer/RenderQueue.h

@@ -377,6 +377,18 @@ class SkyboxQueueElement final
 public:
 public:
 	const TextureView* m_skyboxTexture;
 	const TextureView* m_skyboxTexture;
 	Vec3 m_solidColor;
 	Vec3 m_solidColor;
+
+	class
+	{
+	public:
+		F32 m_minDensity;
+		F32 m_maxDensity;
+		F32 m_heightOfMinDensity; ///< The height (meters) where fog density is max.
+		F32 m_heightOfMaxDensity; ///< The height (meters) where fog density is the min value.
+		F32 m_scatteringCoeff;
+		F32 m_absorptionCoeff;
+		Vec3 m_diffuseColor;
+	} m_fog;
 };
 };
 
 
 static_assert(std::is_trivially_destructible<SkyboxQueueElement>::value == true, "Should be trivially destructible");
 static_assert(std::is_trivially_destructible<SkyboxQueueElement>::value == true, "Should be trivially destructible");

+ 8 - 7
AnKi/Renderer/VolumetricFog.cpp

@@ -72,20 +72,21 @@ void VolumetricFog::populateRenderGraph(RenderingContext& ctx)
 
 
 		rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, TextureSubresourceInfo());
 		rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, TextureSubresourceInfo());
 
 
-		struct PushConsts
+		class PushConsts
 		{
 		{
+		public:
+			Vec3 m_fogDiffuse;
 			F32 m_fogScatteringCoeff;
 			F32 m_fogScatteringCoeff;
 			F32 m_fogAbsorptionCoeff;
 			F32 m_fogAbsorptionCoeff;
-			F32 m_density;
 			F32 m_near;
 			F32 m_near;
-			Vec3 m_fogDiffuse;
 			F32 m_far;
 			F32 m_far;
+			F32 m_padding;
 		} regs;
 		} regs;
 
 
-		regs.m_fogScatteringCoeff = m_fogScatteringCoeff;
-		regs.m_fogAbsorptionCoeff = m_fogAbsorptionCoeff;
-		regs.m_density = m_fogDensity;
-		regs.m_fogDiffuse = m_fogDiffuseColor;
+		const SkyboxQueueElement& el = ctx.m_renderQueue->m_skybox;
+		regs.m_fogDiffuse = el.m_fog.m_diffuseColor;
+		regs.m_fogScatteringCoeff = el.m_fog.m_scatteringCoeff;
+		regs.m_fogAbsorptionCoeff = el.m_fog.m_absorptionCoeff;
 		regs.m_near = ctx.m_renderQueue->m_cameraNear;
 		regs.m_near = ctx.m_renderQueue->m_cameraNear;
 		regs.m_far = ctx.m_renderQueue->m_cameraFar;
 		regs.m_far = ctx.m_renderQueue->m_cameraFar;
 
 

+ 0 - 25
AnKi/Renderer/VolumetricFog.h

@@ -27,26 +27,6 @@ public:
 
 
 	ANKI_USE_RESULT Error init();
 	ANKI_USE_RESULT Error init();
 
 
-	void setFogParticleColor(const Vec3& col)
-	{
-		m_fogDiffuseColor = col;
-	}
-
-	const Vec3& getFogParticleColor() const
-	{
-		return m_fogDiffuseColor;
-	}
-
-	void setParticleDensity(F32 d)
-	{
-		m_fogDensity = d;
-	}
-
-	F32 getParticleDensity() const
-	{
-		return m_fogDensity;
-	}
-
 	/// Populate the rendergraph.
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 	void populateRenderGraph(RenderingContext& ctx);
 
 
@@ -77,11 +57,6 @@ private:
 	Array<U32, 2> m_workgroupSize = {};
 	Array<U32, 2> m_workgroupSize = {};
 	Array<U32, 3> m_volumeSize;
 	Array<U32, 3> m_volumeSize;
 
 
-	Vec3 m_fogDiffuseColor = Vec3(1.0f);
-	F32 m_fogDensity = 0.9f;
-	F32 m_fogScatteringCoeff = 0.01f;
-	F32 m_fogAbsorptionCoeff = 0.02f;
-
 	class
 	class
 	{
 	{
 	public:
 	public:

+ 25 - 0
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -127,6 +127,31 @@ void VolumetricLightingAccumulation::run(const RenderingContext& ctx, RenderPass
 	bindUniforms(cmdb, 0, 11, rsrc.m_fogDensityVolumesToken);
 	bindUniforms(cmdb, 0, 11, rsrc.m_fogDensityVolumesToken);
 	bindStorage(cmdb, 0, 12, rsrc.m_clustersToken);
 	bindStorage(cmdb, 0, 12, rsrc.m_clustersToken);
 
 
+	class FogUniforms
+	{
+	public:
+		F32 m_densityAtMinHeight;
+		F32 m_densityAtMaxHeight;
+		F32 m_minHeight;
+		F32 m_oneOverMaxMinusMinHeight; // 1 / (maxHeight / minHeight)
+	} unis;
+	const SkyboxQueueElement& queueEl = ctx.m_renderQueue->m_skybox;
+	if(queueEl.m_fog.m_heightOfMaxDensity > queueEl.m_fog.m_heightOfMinDensity)
+	{
+		unis.m_minHeight = queueEl.m_fog.m_heightOfMinDensity;
+		unis.m_oneOverMaxMinusMinHeight = 1.0f / (queueEl.m_fog.m_heightOfMaxDensity - unis.m_minHeight + EPSILON);
+		unis.m_densityAtMinHeight = queueEl.m_fog.m_minDensity;
+		unis.m_densityAtMaxHeight = queueEl.m_fog.m_maxDensity;
+	}
+	else
+	{
+		unis.m_minHeight = queueEl.m_fog.m_heightOfMaxDensity;
+		unis.m_oneOverMaxMinusMinHeight = 1.0f / (queueEl.m_fog.m_heightOfMinDensity - unis.m_minHeight + EPSILON);
+		unis.m_densityAtMinHeight = queueEl.m_fog.m_maxDensity;
+		unis.m_densityAtMaxHeight = queueEl.m_fog.m_minDensity;
+	}
+	cmdb->setPushConstants(&unis, sizeof(unis));
+
 	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_workgroupSize[2], m_volumeSize[0],
 	dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_workgroupSize[2], m_volumeSize[0],
 					  m_volumeSize[1], m_volumeSize[2]);
 					  m_volumeSize[1], m_volumeSize[2]);
 }
 }

+ 8 - 0
AnKi/Scene/Components/SkyboxComponent.cpp

@@ -48,6 +48,14 @@ void SkyboxComponent::setupSkyboxQueueElement(SkyboxQueueElement& queueElement)
 		queueElement.m_skyboxTexture = nullptr;
 		queueElement.m_skyboxTexture = nullptr;
 		queueElement.m_solidColor = m_color;
 		queueElement.m_solidColor = m_color;
 	}
 	}
+
+	queueElement.m_fog.m_minDensity = m_fog.m_minDensity;
+	queueElement.m_fog.m_maxDensity = m_fog.m_maxDensity;
+	queueElement.m_fog.m_heightOfMinDensity = m_fog.m_heightOfMinDensity;
+	queueElement.m_fog.m_heightOfMaxDensity = m_fog.m_heightOfMaxDensity;
+	queueElement.m_fog.m_scatteringCoeff = m_fog.m_scatteringCoeff;
+	queueElement.m_fog.m_absorptionCoeff = m_fog.m_absorptionCoeff;
+	queueElement.m_fog.m_diffuseColor = m_fog.m_diffuseColor;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 85 - 0
AnKi/Scene/Components/SkyboxComponent.h

@@ -42,6 +42,78 @@ public:
 
 
 	void setImage(CString filename);
 	void setImage(CString filename);
 
 
+	void setMinFogDensity(F32 density)
+	{
+		m_fog.m_minDensity = clamp(0.0f, 100.0f, density);
+	}
+
+	F32 getMinFogDensity() const
+	{
+		return m_fog.m_minDensity;
+	}
+
+	void setMaxFogDensity(F32 density)
+	{
+		m_fog.m_maxDensity = clamp(0.0f, 100.0f, density);
+	}
+
+	F32 getMaxFogDensity() const
+	{
+		return m_fog.m_maxDensity;
+	}
+
+	/// The height (units) where fog density is getMinFogDensity().
+	void setHeightOfMinFogDensity(F32 height)
+	{
+		m_fog.m_heightOfMinDensity = height;
+	}
+
+	F32 getHeightOfMinFogDensity() const
+	{
+		return m_fog.m_heightOfMinDensity;
+	}
+
+	/// The height (units) where fog density is getMaxFogDensity().
+	void setHeightOfMaxFogDensity(F32 height)
+	{
+		m_fog.m_heightOfMaxDensity = height;
+	}
+
+	F32 getHeightOfMaxFogDensity() const
+	{
+		return m_fog.m_heightOfMaxDensity;
+	}
+
+	void setFogScatteringCoefficient(F32 coeff)
+	{
+		m_fog.m_scatteringCoeff = coeff;
+	}
+
+	F32 getFogScatteringCoefficient() const
+	{
+		return m_fog.m_scatteringCoeff;
+	}
+
+	void setFogAbsorptionCoefficient(F32 coeff)
+	{
+		m_fog.m_absorptionCoeff = coeff;
+	}
+
+	F32 getFogAbsorptionCoefficient() const
+	{
+		return m_fog.m_absorptionCoeff;
+	}
+
+	void setFogDiffuseColor(const Vec3& color)
+	{
+		m_fog.m_diffuseColor = color;
+	}
+
+	const Vec3& getFogDiffuseColor() const
+	{
+		return m_fog.m_diffuseColor;
+	}
+
 	void setupSkyboxQueueElement(SkyboxQueueElement& queueElement) const;
 	void setupSkyboxQueueElement(SkyboxQueueElement& queueElement) const;
 
 
 private:
 private:
@@ -49,6 +121,19 @@ private:
 	SkyboxType m_type = SkyboxType::SOLID_COLOR;
 	SkyboxType m_type = SkyboxType::SOLID_COLOR;
 	Vec3 m_color = Vec3(0.0f, 0.0f, 0.5f);
 	Vec3 m_color = Vec3(0.0f, 0.0f, 0.5f);
 	ImageResourcePtr m_image;
 	ImageResourcePtr m_image;
+
+	// Fog
+	class
+	{
+	public:
+		F32 m_minDensity = 0.0f;
+		F32 m_maxDensity = 0.9f;
+		F32 m_heightOfMinDensity = 20.0f; ///< The height (meters) where fog density is max.
+		F32 m_heightOfMaxDensity = 0.0f; ///< The height (meters) where fog density is the min value.
+		F32 m_scatteringCoeff = 0.01f;
+		F32 m_absorptionCoeff = 0.02f;
+		Vec3 m_diffuseColor = Vec3(1.0f);
+	} m_fog;
 };
 };
 /// @}
 /// @}
 
 

+ 237 - 38
AnKi/Script/Scene.cpp

@@ -62,7 +62,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArraySceneNodePtr = {
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArraySceneNodePtr = {
-	5809609439055747671, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
+	8814433783201007862, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -188,7 +188,7 @@ static inline void wrapWeakArraySceneNodePtr(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArrayBodyComponentPtr = {
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArrayBodyComponentPtr = {
-	-1302287398877025658, "WeakArrayBodyComponentPtr",
+	4134408123720650344, "WeakArrayBodyComponentPtr",
 	LuaUserData::computeSizeForGarbageCollected<WeakArrayBodyComponentPtr>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<WeakArrayBodyComponentPtr>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -313,7 +313,7 @@ static inline void wrapWeakArrayBodyComponentPtr(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {-5580144793264375722, "MoveComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {-2782483694839231720, "MoveComponent",
 														LuaUserData::computeSizeForGarbageCollected<MoveComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<MoveComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -735,7 +735,7 @@ static inline void wrapMoveComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {4175312591147666241, "LightComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {-264261612992291842, "LightComponent",
 														 LuaUserData::computeSizeForGarbageCollected<LightComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<LightComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -1335,7 +1335,7 @@ static inline void wrapLightComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {5797483157062716608, "DecalComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {-6101197258688216989, "DecalComponent",
 														 LuaUserData::computeSizeForGarbageCollected<DecalComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<DecalComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -1548,7 +1548,7 @@ static inline void wrapDecalComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLensFlareComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoLensFlareComponent = {
-	8291782139168759161, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
+	6339963378570005601, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -1729,7 +1729,7 @@ static inline void wrapLensFlareComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoBodyComponent = {-1677508886981088311, "BodyComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoBodyComponent = {-7895721206334327065, "BodyComponent",
 														LuaUserData::computeSizeForGarbageCollected<BodyComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<BodyComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -1911,7 +1911,7 @@ static inline void wrapBodyComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerComponent = {
-	-9171498885335792114, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
+	-2949486936283864894, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -2084,7 +2084,7 @@ static inline void wrapTriggerComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityComponent = {
-	5928776937533851267, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
+	-8499827988833337284, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2300,7 +2300,7 @@ static inline void wrapFogDensityComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFrustumComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoFrustumComponent = {
-	8015481865942255503, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
+	9147516887634331682, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -2486,7 +2486,7 @@ static inline void wrapFrustumComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
-	-3844726379578612797, "GlobalIlluminationProbeComponent",
+	-4624100876972454463, "GlobalIlluminationProbeComponent",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2748,7 +2748,7 @@ static inline void wrapGlobalIlluminationProbeComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeComponent = {
-	6046202958999409161, "ReflectionProbeComponent",
+	-4409109585695554536, "ReflectionProbeComponent",
 	LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2870,7 +2870,7 @@ static inline void wrapReflectionProbeComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterComponent = {
-	-8328014367866362919, "ParticleEmitterComponent",
+	-1840330071892320119, "ParticleEmitterComponent",
 	LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2947,7 +2947,7 @@ static inline void wrapParticleEmitterComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterComponent = {
-	3218466719653579577, "GpuParticleEmitterComponent",
+	-3165492497720485956, "GpuParticleEmitterComponent",
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -3023,7 +3023,7 @@ static inline void wrapGpuParticleEmitterComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoModelComponent = {-2378722133865985395, "ModelComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoModelComponent = {-8496169455932140599, "ModelComponent",
 														 LuaUserData::computeSizeForGarbageCollected<ModelComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<ModelComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -3099,7 +3099,7 @@ static inline void wrapModelComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoSkinComponent = {-521841775230543159, "SkinComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoSkinComponent = {2682686981618364073, "SkinComponent",
 														LuaUserData::computeSizeForGarbageCollected<SkinComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<SkinComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -3176,7 +3176,7 @@ static inline void wrapSkinComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxComponent = {
-	-2277626995161381444, "SkyboxComponent", LuaUserData::computeSizeForGarbageCollected<SkyboxComponent>(), nullptr,
+	-2964944961812371060, "SkyboxComponent", LuaUserData::computeSizeForGarbageCollected<SkyboxComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -3286,17 +3286,217 @@ static int wrapSkyboxComponentsetImage(lua_State* l)
 	return 0;
 	return 0;
 }
 }
 
 
+/// Pre-wrap method SkyboxComponent::setMinFogDensity.
+static inline int pwrapSkyboxComponentsetMinFogDensity(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 2)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSkyboxComponent, ud))
+	{
+		return -1;
+	}
+
+	SkyboxComponent* self = ud->getData<SkyboxComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	self->setMinFogDensity(arg0);
+
+	return 0;
+}
+
+/// Wrap method SkyboxComponent::setMinFogDensity.
+static int wrapSkyboxComponentsetMinFogDensity(lua_State* l)
+{
+	int res = pwrapSkyboxComponentsetMinFogDensity(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method SkyboxComponent::setMaxFogDensity.
+static inline int pwrapSkyboxComponentsetMaxFogDensity(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 2)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSkyboxComponent, ud))
+	{
+		return -1;
+	}
+
+	SkyboxComponent* self = ud->getData<SkyboxComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	self->setMaxFogDensity(arg0);
+
+	return 0;
+}
+
+/// Wrap method SkyboxComponent::setMaxFogDensity.
+static int wrapSkyboxComponentsetMaxFogDensity(lua_State* l)
+{
+	int res = pwrapSkyboxComponentsetMaxFogDensity(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method SkyboxComponent::setHeightOfMinFogDensity.
+static inline int pwrapSkyboxComponentsetHeightOfMinFogDensity(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 2)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSkyboxComponent, ud))
+	{
+		return -1;
+	}
+
+	SkyboxComponent* self = ud->getData<SkyboxComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	self->setHeightOfMinFogDensity(arg0);
+
+	return 0;
+}
+
+/// Wrap method SkyboxComponent::setHeightOfMinFogDensity.
+static int wrapSkyboxComponentsetHeightOfMinFogDensity(lua_State* l)
+{
+	int res = pwrapSkyboxComponentsetHeightOfMinFogDensity(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method SkyboxComponent::setHeightOfMaxFogDensity.
+static inline int pwrapSkyboxComponentsetHeightOfMaxFogDensity(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 2)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSkyboxComponent, ud))
+	{
+		return -1;
+	}
+
+	SkyboxComponent* self = ud->getData<SkyboxComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	self->setHeightOfMaxFogDensity(arg0);
+
+	return 0;
+}
+
+/// Wrap method SkyboxComponent::setHeightOfMaxFogDensity.
+static int wrapSkyboxComponentsetHeightOfMaxFogDensity(lua_State* l)
+{
+	int res = pwrapSkyboxComponentsetHeightOfMaxFogDensity(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 /// Wrap class SkyboxComponent.
 /// Wrap class SkyboxComponent.
 static inline void wrapSkyboxComponent(lua_State* l)
 static inline void wrapSkyboxComponent(lua_State* l)
 {
 {
 	LuaBinder::createClass(l, &luaUserDataTypeInfoSkyboxComponent);
 	LuaBinder::createClass(l, &luaUserDataTypeInfoSkyboxComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "setSolidColor", wrapSkyboxComponentsetSolidColor);
 	LuaBinder::pushLuaCFuncMethod(l, "setSolidColor", wrapSkyboxComponentsetSolidColor);
 	LuaBinder::pushLuaCFuncMethod(l, "setImage", wrapSkyboxComponentsetImage);
 	LuaBinder::pushLuaCFuncMethod(l, "setImage", wrapSkyboxComponentsetImage);
+	LuaBinder::pushLuaCFuncMethod(l, "setMinFogDensity", wrapSkyboxComponentsetMinFogDensity);
+	LuaBinder::pushLuaCFuncMethod(l, "setMaxFogDensity", wrapSkyboxComponentsetMaxFogDensity);
+	LuaBinder::pushLuaCFuncMethod(l, "setHeightOfMinFogDensity", wrapSkyboxComponentsetHeightOfMinFogDensity);
+	LuaBinder::pushLuaCFuncMethod(l, "setHeightOfMaxFogDensity", wrapSkyboxComponentsetHeightOfMaxFogDensity);
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
-	-2144620823698428177, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
+	-5400401657999711208, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneNode>()
@@ -4295,7 +4495,7 @@ static inline void wrapSceneNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoModelNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoModelNode = {
-	1774496801925125084, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
+	8662759923963606691, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ModelNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ModelNode>()
@@ -4361,7 +4561,7 @@ static inline void wrapModelNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoPerspectiveCameraNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoPerspectiveCameraNode = {
-	7105894622742243507, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
+	8909199665941427003, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4427,7 +4627,7 @@ static inline void wrapPerspectiveCameraNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {4218115462400439550, "PointLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {-2447480660720507473, "PointLightNode",
 														 LuaUserData::computeSizeForGarbageCollected<PointLightNode>(),
 														 LuaUserData::computeSizeForGarbageCollected<PointLightNode>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -4494,7 +4694,7 @@ static inline void wrapPointLightNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {-2091793083632766288, "SpotLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {6726145533735581976, "SpotLightNode",
 														LuaUserData::computeSizeForGarbageCollected<SpotLightNode>(),
 														LuaUserData::computeSizeForGarbageCollected<SpotLightNode>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -4562,7 +4762,7 @@ static inline void wrapSpotLightNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDirectionalLightNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoDirectionalLightNode = {
-	-6501285280031403439, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
+	2895977680019784023, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4629,7 +4829,7 @@ static inline void wrapDirectionalLightNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoStaticCollisionNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoStaticCollisionNode = {
-	-7265536825047312096, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
+	-2251427408983804610, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4696,7 +4896,7 @@ static inline void wrapStaticCollisionNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterNode = {
-	2973919878633574234, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
+	5897893899886372328, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4763,7 +4963,7 @@ static inline void wrapParticleEmitterNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterNode = {
-	6956159109755782816, "GpuParticleEmitterNode",
+	-3241600850163286281, "GpuParticleEmitterNode",
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterNode>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4830,7 +5030,7 @@ static inline void wrapGpuParticleEmitterNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeNode = {
-	419937439133921472, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
+	-8557166066628998745, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4897,7 +5097,7 @@ static inline void wrapReflectionProbeNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDecalNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoDecalNode = {
-	3441301994380797745, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
+	-1932303121881080630, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalNode>()
@@ -4963,7 +5163,7 @@ static inline void wrapDecalNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerNode = {
-	6802202778981369878, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
+	2440876625659171023, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<TriggerNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<TriggerNode>()
@@ -5028,7 +5228,7 @@ static inline void wrapTriggerNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {-386589015556072926, "FogDensityNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {218112438823942081, "FogDensityNode",
 														 LuaUserData::computeSizeForGarbageCollected<FogDensityNode>(),
 														 LuaUserData::computeSizeForGarbageCollected<FogDensityNode>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -5096,7 +5296,7 @@ static inline void wrapFogDensityNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {
-	1732740056305938491, "GlobalIlluminationProbeNode",
+	818943944104314135, "GlobalIlluminationProbeNode",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -5163,7 +5363,7 @@ static inline void wrapGlobalIlluminationProbeNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxNode = {
-	-2304987273644644341, "SkyboxNode", LuaUserData::computeSizeForGarbageCollected<SkyboxNode>(), nullptr, nullptr};
+	-626365928506700221, "SkyboxNode", LuaUserData::computeSizeForGarbageCollected<SkyboxNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SkyboxNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SkyboxNode>()
@@ -5229,7 +5429,7 @@ static inline void wrapSkyboxNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
-	8108006252110358060, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
+	-6920547741977779572, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneGraph>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneGraph>()
@@ -6116,7 +6316,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {273791316102449211, "Event",
+LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {4084280106248842326, "Event",
 												LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr, nullptr};
 												LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -6185,7 +6385,7 @@ static inline void wrapEvent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLightEvent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoLightEvent = {
-	1694734869694099565, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
+	-4403989328470667375, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightEvent>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightEvent>()
@@ -6309,9 +6509,8 @@ static inline void wrapLightEvent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {-5376406320197242602, "EventManager",
-													   LuaUserData::computeSizeForGarbageCollected<EventManager>(),
-													   nullptr, nullptr};
+LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {
+	3843303004909953115, "EventManager", LuaUserData::computeSizeForGarbageCollected<EventManager>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<EventManager>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<EventManager>()

+ 20 - 0
AnKi/Script/Scene.xml

@@ -403,6 +403,26 @@ using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 						<arg>CString</arg>
 						<arg>CString</arg>
 					</args>
 					</args>
 				</method>
 				</method>
+				<method name="setMinFogDensity">
+					<args>
+						<arg>F32</arg>
+					</args>
+				</method>
+				<method name="setMaxFogDensity">
+					<args>
+						<arg>F32</arg>
+					</args>
+				</method>
+				<method name="setHeightOfMinFogDensity">
+					<args>
+						<arg>F32</arg>
+					</args>
+				</method>
+				<method name="setHeightOfMaxFogDensity">
+					<args>
+						<arg>F32</arg>
+					</args>
+				</method>
 			</methods>
 			</methods>
 		</class>
 		</class>
 
 

+ 17 - 13
AnKi/Shaders/VolumetricFogAccumulation.ankiprog

@@ -19,14 +19,19 @@ layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 1) uniform ANKI_RP texture3D u_lightVolume;
 layout(set = 0, binding = 1) uniform ANKI_RP texture3D u_lightVolume;
 layout(set = 0, binding = 2) writeonly uniform ANKI_RP image3D u_fogVolume;
 layout(set = 0, binding = 2) writeonly uniform ANKI_RP image3D u_fogVolume;
 
 
-layout(push_constant, std430) uniform b_pc
+struct Uniforms
 {
 {
-	ANKI_RP F32 u_fogScatteringCoeff;
-	ANKI_RP F32 u_fogAbsorptionCoeff;
-	ANKI_RP F32 u_density;
-	ANKI_RP F32 u_near;
-	ANKI_RP Vec3 u_fogDiffuse;
-	ANKI_RP F32 u_far;
+	ANKI_RP Vec3 m_fogDiffuse;
+	ANKI_RP F32 m_fogScatteringCoeff;
+	ANKI_RP F32 m_fogAbsorptionCoeff;
+	ANKI_RP F32 m_near;
+	ANKI_RP F32 m_far;
+	F32 m_padding;
+};
+
+layout(push_constant, scalar) uniform b_pc
+{
+	Uniforms u_unis;
 };
 };
 
 
 void main()
 void main()
@@ -50,8 +55,8 @@ void main()
 		const ANKI_RP F32 linearDepthFar = (fi + 1.0) * linearDepthFraction;
 		const ANKI_RP F32 linearDepthFar = (fi + 1.0) * linearDepthFraction;
 
 
 		// Compute the min and max Z in view space if this cluster fragment
 		// Compute the min and max Z in view space if this cluster fragment
-		const ANKI_RP F32 zVSpaceNear = -linearDepthNear * (u_far - u_near) + u_near;
-		const ANKI_RP F32 zVSpaceFar = -linearDepthFar * (u_far - u_near) + u_near;
+		const ANKI_RP F32 zVSpaceNear = -linearDepthNear * (u_unis.m_far - u_unis.m_near) + u_unis.m_near;
+		const ANKI_RP F32 zVSpaceFar = -linearDepthFar * (u_unis.m_far - u_unis.m_near) + u_unis.m_near;
 
 
 		// Compute the thikness of this fragment
 		// Compute the thikness of this fragment
 		const ANKI_RP F32 layerThinkness = abs(zVSpaceNear - zVSpaceFar);
 		const ANKI_RP F32 layerThinkness = abs(zVSpaceNear - zVSpaceFar);
@@ -59,12 +64,11 @@ void main()
 		// Read the light value and the fog density from the fog volumes
 		// Read the light value and the fog density from the fog volumes
 		const ANKI_RP F32 w = (fi + 0.5) / F32(VOLUME_SIZE.z);
 		const ANKI_RP F32 w = (fi + 0.5) / F32(VOLUME_SIZE.z);
 		ANKI_RP Vec4 lightAndFogDensity = textureLod(u_lightVolume, u_linearAnyClampSampler, Vec3(uv, w), 0.0);
 		ANKI_RP Vec4 lightAndFogDensity = textureLod(u_lightVolume, u_linearAnyClampSampler, Vec3(uv, w), 0.0);
-		lightAndFogDensity.xyz *= u_fogDiffuse / PI;
-		lightAndFogDensity.w += u_density; // Apply the default density
+		lightAndFogDensity.xyz *= u_unis.m_fogDiffuse / PI;
 
 
 		// Scattering & absorption
 		// Scattering & absorption
-		const ANKI_RP F32 scattering = lightAndFogDensity.w * u_fogScatteringCoeff * layerThinkness;
-		const ANKI_RP F32 absorption = lightAndFogDensity.w * u_fogAbsorptionCoeff * layerThinkness;
+		const ANKI_RP F32 scattering = lightAndFogDensity.w * u_unis.m_fogScatteringCoeff * layerThinkness;
+		const ANKI_RP F32 absorption = lightAndFogDensity.w * u_unis.m_fogAbsorptionCoeff * layerThinkness;
 
 
 		// Integrate
 		// Integrate
 		const ANKI_RP Vec4 colorAndDensityBack = Vec4(lightAndFogDensity.xyz * scattering, scattering + absorption);
 		const ANKI_RP Vec4 colorAndDensityBack = Vec4(lightAndFogDensity.xyz * scattering, scattering + absorption);

+ 17 - 0
AnKi/Shaders/VolumetricLightingAccumulation.ankiprog

@@ -34,6 +34,19 @@ layout(set = 0, binding = 4) uniform texture3D u_prevVolume;
 #define CLUSTERED_SHADING_CLUSTERS_BINDING 12
 #define CLUSTERED_SHADING_CLUSTERS_BINDING 12
 #include <AnKi/Shaders/ClusteredShadingCommon.glsl>
 #include <AnKi/Shaders/ClusteredShadingCommon.glsl>
 
 
+struct FogUniforms
+{
+	ANKI_RP F32 m_densityAtMinHeight;
+	ANKI_RP F32 m_densityAtMaxHeight;
+	F32 m_minHeight;
+	F32 m_oneOverMaxMinusMinHeight; // 1 / (maxHeight / minHeight)
+};
+
+layout(push_constant, scalar) uniform b_pc
+{
+	FogUniforms u_fogUnis;
+};
+
 Vec3 g_globalInvocationID = Vec3(gl_GlobalInvocationID);
 Vec3 g_globalInvocationID = Vec3(gl_GlobalInvocationID);
 
 
 Vec3 readRand()
 Vec3 readRand()
@@ -216,6 +229,10 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 	// Fog density
 	// Fog density
 	F32 fogDensity = 0.0;
 	F32 fogDensity = 0.0;
 	{
 	{
+		// Calculate the constant density
+		const F32 fogFactor = saturate((worldPos.y - u_fogUnis.m_minHeight) * u_fogUnis.m_oneOverMaxMinusMinHeight);
+		fogDensity = mix(u_fogUnis.m_densityAtMinHeight, u_fogUnis.m_densityAtMaxHeight, fogFactor);
+
 		ANKI_LOOP while(cluster.m_fogDensityVolumesMask != 0u)
 		ANKI_LOOP while(cluster.m_fogDensityVolumesMask != 0u)
 		{
 		{
 			const U32 idx = U32(findLSB2(cluster.m_fogDensityVolumesMask));
 			const U32 idx = U32(findLSB2(cluster.m_fogDensityVolumesMask));

+ 0 - 3
Samples/Common/SampleApp.cpp

@@ -35,9 +35,6 @@ Error SampleApp::init(int argc, char** argv, CString sampleName)
 	ANKI_CHECK(m_config.setFromCommandLineArguments(argc - 1, argv + 1));
 	ANKI_CHECK(m_config.setFromCommandLineArguments(argc - 1, argv + 1));
 	ANKI_CHECK(App::init(&m_config, allocAligned, nullptr));
 	ANKI_CHECK(App::init(&m_config, allocAligned, nullptr));
 
 
-	// Some renderer stuff
-	getMainRenderer().getOffscreenRenderer().getVolumetricFog().setFogParticleColor(Vec3(1.0f, 0.9f, 0.9f));
-
 	ANKI_CHECK(sampleExtraInit());
 	ANKI_CHECK(sampleExtraInit());
 
 
 	return Error::NONE;
 	return Error::NONE;

+ 12 - 10
Samples/PhysicsPlayground/Assets/Scene.lua

@@ -307,16 +307,6 @@ comp = node2:getSceneNodeBase():getBodyComponent()
 comp:loadMeshResource("Assets/Suzanne.ankimesh")
 comp:loadMeshResource("Assets/Suzanne.ankimesh")
 comp:setWorldTransform(trf)
 comp:setWorldTransform(trf)
 
 
-node = scene:newModelNode("Cube.001")
-node:getSceneNodeBase():getModelComponent():loadModelResource("Assets/walls_sky.ankimdl")
-trf = Transform.new()
-trf:setOrigin(Vec4.new(0.000000, 9.109353, 0.000000, 0))
-rot = Mat3x4.new()
-rot:setAll(1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000)
-trf:setRotation(rot)
-trf:setScale(10.000000)
-node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)
-
 node = scene:newModelNode("Cube")
 node = scene:newModelNode("Cube")
 node:getSceneNodeBase():getModelComponent():loadModelResource("Assets/floor_walls.ankimdl")
 node:getSceneNodeBase():getModelComponent():loadModelResource("Assets/floor_walls.ankimdl")
 trf = Transform.new()
 trf = Transform.new()
@@ -726,3 +716,15 @@ rot:setAll(1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000,
 trf:setRotation(rot)
 trf:setRotation(rot)
 trf:setScale(1.000000)
 trf:setScale(1.000000)
 node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)
 node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)
+
+node = scene:newSkyboxNode("Skybox")
+comp = node:getSceneNodeBase():getSkyboxComponent()
+comp:setImage("EngineAssets/DefaultSkybox.ankitex")
+comp:setMaxFogDensity("0.100000")
+trf = Transform.new()
+trf:setOrigin(Vec4.new(-3.710423, 69.685875, 0.000000, 0))
+rot = Mat3x4.new()
+rot:setAll(1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000)
+trf:setRotation(rot)
+trf:setScale(1.000000)
+node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)

BIN
Samples/PhysicsPlayground/Assets/Unbacked/PhysicsPlayground.blend


+ 0 - 3
Samples/SkeletalAnimation/Main.cpp

@@ -31,9 +31,6 @@ public:
 			.getFirstComponentOfType<SkinComponent>()
 			.getFirstComponentOfType<SkinComponent>()
 			.playAnimation(0, m_floatAnim, animInfo);
 			.playAnimation(0, m_floatAnim, animInfo);
 
 
-		getMainRenderer().getOffscreenRenderer().getVolumetricFog().setFogParticleColor(Vec3(1.0f, 0.9f, 0.9f));
-		getMainRenderer().getOffscreenRenderer().getVolumetricFog().setParticleDensity(2.0f);
-
 		getConfig().setRBloomThreshold(5.0f);
 		getConfig().setRBloomThreshold(5.0f);
 		return Error::NONE;
 		return Error::NONE;
 	}
 	}

+ 3 - 0
Samples/Sponza/Assets/Scene.lua

@@ -5,6 +5,9 @@ local events = getEventManager()
 node = scene:newSkyboxNode("Cube.017")
 node = scene:newSkyboxNode("Cube.017")
 comp = node:getSceneNodeBase():getSkyboxComponent()
 comp = node:getSceneNodeBase():getSkyboxComponent()
 comp:setImage("EngineAssets/DefaultSkybox.ankitex")
 comp:setImage("EngineAssets/DefaultSkybox.ankitex")
+comp:setMinFogDensity("0.000000")
+comp:setMaxFogDensity("0.900000")
+comp:setHeightOfMaxFogDensity("10.000000")
 trf = Transform.new()
 trf = Transform.new()
 trf:setOrigin(Vec4.new(0.000000, 23.077700, 25.287918, 0))
 trf:setOrigin(Vec4.new(0.000000, 23.077700, 25.287918, 0))
 rot = Mat3x4.new()
 rot = Mat3x4.new()

+ 0 - 2
Samples/Sponza/Main.cpp

@@ -17,8 +17,6 @@ public:
 		ANKI_CHECK(getResourceManager().loadResource("Assets/Scene.lua", script));
 		ANKI_CHECK(getResourceManager().loadResource("Assets/Scene.lua", script));
 		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
 		ANKI_CHECK(getScriptManager().evalString(script->getSource()));
 
 
-		getMainRenderer().getOffscreenRenderer().getVolumetricFog().setFogParticleColor(Vec3(1.0f, 0.9f, 0.9f));
-		getMainRenderer().getOffscreenRenderer().getVolumetricFog().setParticleDensity(2.0f);
 		return Error::NONE;
 		return Error::NONE;
 	}
 	}
 };
 };

+ 0 - 4
Sandbox/Main.cpp

@@ -41,12 +41,8 @@ Error MyApp::init(int argc, char* argv[])
 	ANKI_CHECK(App::init(&m_config, allocAligned, nullptr));
 	ANKI_CHECK(App::init(&m_config, allocAligned, nullptr));
 
 
 	// Other init
 	// Other init
-	Renderer& renderer = getMainRenderer().getOffscreenRenderer();
 	ResourceManager& resources = getResourceManager();
 	ResourceManager& resources = getResourceManager();
 
 
-	renderer.getVolumetricFog().setFogParticleColor(Vec3(1.0f, 0.9f, 0.9f));
-	renderer.getVolumetricFog().setParticleDensity(1.0f);
-
 	if(getenv("PROFILE"))
 	if(getenv("PROFILE"))
 	{
 	{
 		m_profile = true;
 		m_profile = true;