Panagiotis Christopoulos Charitos 6 年 前
コミット
30ee7c8a30

+ 2 - 0
src/anki/Scene.h

@@ -21,6 +21,7 @@
 #include <anki/scene/PhysicsDebugNode.h>
 #include <anki/scene/TriggerNode.h>
 #include <anki/scene/FogDensityNode.h>
+#include <anki/scene/GlobalIlluminationProbeNode.h>
 
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/RenderComponent.h>
@@ -38,6 +39,7 @@
 #include <anki/scene/components/JointComponent.h>
 #include <anki/scene/components/TriggerComponent.h>
 #include <anki/scene/components/FogDensityComponent.h>
+#include <anki/scene/components/GlobalIlluminationProbeComponent.h>
 
 #include <anki/scene/events/EventManager.h>
 #include <anki/scene/events/Event.h>

+ 1 - 1
src/anki/renderer/ForwardShading.cpp

@@ -32,7 +32,7 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 	const U threadId = rgraphCtx.m_currentSecondLevelCommandBufferIndex;
 	const U threadCount = rgraphCtx.m_secondLevelCommandBufferCount;
 	const U problemSize = ctx.m_renderQueue->m_forwardShadingRenderables.getSize();
-	PtrSize start, end;
+	U start, end;
 	splitThreadedProblem(threadId, threadCount, problemSize, start, end);
 
 	if(start != end)

+ 0 - 1
src/anki/resource/AnimationResource.cpp

@@ -27,7 +27,6 @@ AnimationResource::~AnimationResource()
 Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 {
 	XmlElement el;
-	I64 tmp;
 	Second ftmp;
 
 	m_startTime = MAX_SECOND;

+ 27 - 0
src/anki/scene/GlobalIlluminationProbeNode.cpp

@@ -0,0 +1,27 @@
+// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/scene/GlobalIlluminationProbeNode.h>
+
+namespace anki
+{
+
+GlobalIlluminationProbeNode::~GlobalIlluminationProbeNode()
+{
+}
+
+Error GlobalIlluminationProbeNode::init()
+{
+	// TODO
+	return Error::NONE;
+}
+
+Error GlobalIlluminationProbeNode::frameUpdate(Second prevUpdateTime, Second crntTime)
+{
+	// TODO
+	return Error::NONE;
+}
+
+} // end namespace anki

+ 42 - 0
src/anki/scene/GlobalIlluminationProbeNode.h

@@ -0,0 +1,42 @@
+// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/scene/SceneNode.h>
+#include <anki/collision/Aabb.h>
+
+namespace anki
+{
+
+/// @addtogroup scene
+/// @{
+
+/// Probe used in global illumination.
+class GlobalIlluminationProbeNode : public SceneNode
+{
+public:
+	GlobalIlluminationProbeNode(SceneGraph* scene, CString name)
+		: SceneNode(scene, name)
+	{
+	}
+
+	~GlobalIlluminationProbeNode();
+
+	ANKI_USE_RESULT Error init();
+
+	ANKI_USE_RESULT Error frameUpdate(Second prevUpdateTime, Second crntTime) override;
+
+private:
+	class MoveFeedbackComponent;
+
+	Array<Transform, 6> m_cubeFaceTransforms;
+	Aabb m_spatialAabb;
+
+	void onMoveUpdate(MoveComponent& move);
+};
+/// @}
+
+} // end namespace anki

+ 0 - 2
src/anki/scene/ReflectionProbeNode.h

@@ -6,9 +6,7 @@
 #pragma once
 
 #include <anki/scene/SceneNode.h>
-#include <anki/collision/Sphere.h>
 #include <anki/collision/Aabb.h>
-#include <anki/Gr.h>
 
 namespace anki
 {

+ 64 - 9
src/anki/scene/components/GlobalIlluminationProbeComponent.h

@@ -14,7 +14,7 @@ namespace anki
 /// @addtogroup scene
 /// @{
 
-/// Reflection probe component.
+/// Global illumination probe component. It's an axis aligned box divided into cells.
 class GlobalIlluminationProbeComponent : public SceneComponent
 {
 public:
@@ -24,12 +24,31 @@ public:
 		: SceneComponent(CLASS_TYPE)
 		, m_uuid(uuid)
 	{
+		ANKI_ASSERT(uuid > 0);
 	}
 
+	/// Set the bounding box in world coordinates.
 	void setBoundingBox(const Vec4& min, const Vec4& max)
 	{
+		ANKI_ASSERT(min < max);
 		m_aabbMin = min.xyz();
 		m_aabbMax = max.xyz();
+		updateMembers();
+		m_dirty = true;
+	}
+
+	/// Set the cell size in meters.
+	void setCellSize(F32 cellSize)
+	{
+		ANKI_ASSERT(cellSize > 0.0f);
+		m_cellSize = cellSize;
+		updateMembers();
+		m_dirty = true;
+	}
+
+	F32 getCellSize() const
+	{
+		return m_cellSize;
 	}
 
 	Vec4 getAlignedBoundingBoxMin() const
@@ -56,30 +75,66 @@ public:
 		return m_renderPosition.xyz0();
 	}
 
-	void setupGlobalIlluminationProbeQueueElement(GlobalIlluminationProbeQueueElement& el) const
+	void setupGlobalIlluminationProbeQueueElement(GlobalIlluminationProbeQueueElement& el)
 	{
-		ANKI_ASSERT(m_aabbMin < m_aabbMax);
-		// TODO
+		el.m_uuid = m_uuid;
+		el.m_feedbackCallback = giProbeQueueElementFeedbackCallback;
+		el.m_userData = this;
+		el.m_renderQueues = {};
+		el.m_aabbMin = m_aabbMin;
+		el.m_aabbMax = m_aabbMax;
+		el.m_cellCounts = m_cellCounts;
+		el.m_totalCellCount = m_cellCounts.x() * m_cellCounts.y() * m_cellCounts.z();
+		ANKI_DEBUG_CODE(el.m_cacheEntryIndex = MAX_U32);
+	}
+
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
+	{
+		updated = m_dirty;
+		m_dirty = false;
+		return Error::NONE;
 	}
 
 private:
 	U64 m_uuid;
-	Vec3 m_aabbMin = Vec3(+1.0f);
-	Vec3 m_aabbMax = Vec3(-1.0f);
+	Vec3 m_aabbMin = Vec3(-1.0f);
+	Vec3 m_aabbMax = Vec3(+1.0f);
 	Vec3 m_renderPosition = Vec3(0.0f);
-	F32 m_cellSize = 1.0f;
+	F32 m_cellSize = 1.0f; ///< Cell size in meters.
+	UVec3 m_cellCounts = UVec3(2u);
 	Bool m_markedForRendering = false;
+	Bool m_dirty = true;
 
-	static void reflectionProbeQueueElementFeedbackCallback(Bool fillRenderQueuesOnNextFrame, void* userData)
+	static void giProbeQueueElementFeedbackCallback(
+		Bool fillRenderQueuesOnNextFrame, void* userData, const Vec4& eyeWorldPosition)
 	{
 		ANKI_ASSERT(userData);
-		static_cast<GlobalIlluminationProbeComponent*>(userData)->m_markedForRendering = fillRenderQueuesOnNextFrame;
+		GlobalIlluminationProbeComponent& self = *static_cast<GlobalIlluminationProbeComponent*>(userData);
+		ANKI_ASSERT(eyeWorldPosition.xyz() > self.m_aabbMin && eyeWorldPosition.xyz() < self.m_aabbMax);
+		self.m_markedForRendering = fillRenderQueuesOnNextFrame;
+		self.m_renderPosition = eyeWorldPosition.xyz();
 	}
 
 	static void debugDrawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData)
 	{
 		// TODO
 	}
+
+	/// Recalc come values.
+	void updateMembers()
+	{
+		for(U i = 0; i < 3; ++i)
+		{
+			// Align the box
+			alignRoundDown(m_cellSize, m_aabbMin[i]);
+			alignRoundUp(m_cellSize, m_aabbMax[i]);
+			ANKI_ASSERT(m_aabbMax[i] > m_aabbMin[i]);
+
+			// Compute the counts
+			const F32 epsilon = m_cellSize / 100.0f;
+			m_cellCounts[i] = U32((m_aabbMax[i] - m_aabbMin[i] + epsilon) / m_cellSize);
+		}
+	}
 };
 /// @}
 

+ 475 - 0
src/anki/script/Scene.cpp

@@ -1948,6 +1948,289 @@ static inline void wrapFrustumComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
+LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {-8635406553972724905,
+	"GlobalIlluminationProbeComponent",
+	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(),
+	nullptr,
+	nullptr};
+
+template<>
+const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<GlobalIlluminationProbeComponent>()
+{
+	return luaUserDataTypeInfoGlobalIlluminationProbeComponent;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeComponent::setBoundingBox.
+static inline int pwrapGlobalIlluminationProbeComponentsetBoundingBox(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 3)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoGlobalIlluminationProbeComponent, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeComponent* self = ud->getData<GlobalIlluminationProbeComponent>();
+
+	// Pop arguments
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 2, luaUserDataTypeInfoVec4, ud)))
+	{
+		return -1;
+	}
+
+	Vec4* iarg0 = ud->getData<Vec4>();
+	const Vec4& arg0(*iarg0);
+
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 3, luaUserDataTypeInfoVec4, ud)))
+	{
+		return -1;
+	}
+
+	Vec4* iarg1 = ud->getData<Vec4>();
+	const Vec4& arg1(*iarg1);
+
+	// Call the method
+	self->setBoundingBox(arg0, arg1);
+
+	return 0;
+}
+
+/// Wrap method GlobalIlluminationProbeComponent::setBoundingBox.
+static int wrapGlobalIlluminationProbeComponentsetBoundingBox(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeComponentsetBoundingBox(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeComponent::getAlignedBoundingBoxMin.
+static inline int pwrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMin(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoGlobalIlluminationProbeComponent, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeComponent* self = ud->getData<GlobalIlluminationProbeComponent>();
+
+	// Call the method
+	Vec4 ret = self->getAlignedBoundingBoxMin();
+
+	// Push return value
+	size = LuaUserData::computeSizeForGarbageCollected<Vec4>();
+	voidp = lua_newuserdata(l, size);
+	luaL_setmetatable(l, "Vec4");
+	ud = static_cast<LuaUserData*>(voidp);
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	ud->initGarbageCollected(&luaUserDataTypeInfoVec4);
+	::new(ud->getData<Vec4>()) Vec4(std::move(ret));
+
+	return 1;
+}
+
+/// Wrap method GlobalIlluminationProbeComponent::getAlignedBoundingBoxMin.
+static int wrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMin(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMin(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeComponent::getAlignedBoundingBoxMax.
+static inline int pwrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMax(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoGlobalIlluminationProbeComponent, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeComponent* self = ud->getData<GlobalIlluminationProbeComponent>();
+
+	// Call the method
+	Vec4 ret = self->getAlignedBoundingBoxMax();
+
+	// Push return value
+	size = LuaUserData::computeSizeForGarbageCollected<Vec4>();
+	voidp = lua_newuserdata(l, size);
+	luaL_setmetatable(l, "Vec4");
+	ud = static_cast<LuaUserData*>(voidp);
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	ud->initGarbageCollected(&luaUserDataTypeInfoVec4);
+	::new(ud->getData<Vec4>()) Vec4(std::move(ret));
+
+	return 1;
+}
+
+/// Wrap method GlobalIlluminationProbeComponent::getAlignedBoundingBoxMax.
+static int wrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMax(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMax(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeComponent::setCellSize.
+static inline int pwrapGlobalIlluminationProbeComponentsetCellSize(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, luaUserDataTypeInfoGlobalIlluminationProbeComponent, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeComponent* self = ud->getData<GlobalIlluminationProbeComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	self->setCellSize(arg0);
+
+	return 0;
+}
+
+/// Wrap method GlobalIlluminationProbeComponent::setCellSize.
+static int wrapGlobalIlluminationProbeComponentsetCellSize(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeComponentsetCellSize(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeComponent::getCellSize.
+static inline int pwrapGlobalIlluminationProbeComponentgetCellSize(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoGlobalIlluminationProbeComponent, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeComponent* self = ud->getData<GlobalIlluminationProbeComponent>();
+
+	// Call the method
+	F32 ret = self->getCellSize();
+
+	// Push return value
+	lua_pushnumber(l, ret);
+
+	return 1;
+}
+
+/// Wrap method GlobalIlluminationProbeComponent::getCellSize.
+static int wrapGlobalIlluminationProbeComponentgetCellSize(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeComponentgetCellSize(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Wrap class GlobalIlluminationProbeComponent.
+static inline void wrapGlobalIlluminationProbeComponent(lua_State* l)
+{
+	LuaBinder::createClass(l, &luaUserDataTypeInfoGlobalIlluminationProbeComponent);
+	LuaBinder::pushLuaCFuncMethod(l, "setBoundingBox", wrapGlobalIlluminationProbeComponentsetBoundingBox);
+	LuaBinder::pushLuaCFuncMethod(
+		l, "getAlignedBoundingBoxMin", wrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMin);
+	LuaBinder::pushLuaCFuncMethod(
+		l, "getAlignedBoundingBoxMax", wrapGlobalIlluminationProbeComponentgetAlignedBoundingBoxMax);
+	LuaBinder::pushLuaCFuncMethod(l, "setCellSize", wrapGlobalIlluminationProbeComponentsetCellSize);
+	LuaBinder::pushLuaCFuncMethod(l, "getCellSize", wrapGlobalIlluminationProbeComponentgetCellSize);
+	lua_settop(l, 0);
+}
+
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
 	-2220074417980276571, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
 
@@ -2481,6 +2764,62 @@ static int wrapSceneNodegetFrustumComponent(lua_State* l)
 	return 0;
 }
 
+/// Pre-wrap method SceneNode::tryGetComponent<GlobalIlluminationProbeComponent>.
+static inline int pwrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSceneNode, ud))
+	{
+		return -1;
+	}
+
+	SceneNode* self = ud->getData<SceneNode>();
+
+	// Call the method
+	GlobalIlluminationProbeComponent* ret = self->tryGetComponent<GlobalIlluminationProbeComponent>();
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "GlobalIlluminationProbeComponent");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent;
+	ud->initPointed(
+		&luaUserDataTypeInfoGlobalIlluminationProbeComponent, const_cast<GlobalIlluminationProbeComponent*>(ret));
+
+	return 1;
+}
+
+/// Wrap method SceneNode::tryGetComponent<GlobalIlluminationProbeComponent>.
+static int wrapSceneNodegetGlobalIlluminationProbeComponent(lua_State* l)
+{
+	int res = pwrapSceneNodegetGlobalIlluminationProbeComponent(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 /// Wrap class SceneNode.
 static inline void wrapSceneNode(lua_State* l)
 {
@@ -2495,6 +2834,8 @@ static inline void wrapSceneNode(lua_State* l)
 	LuaBinder::pushLuaCFuncMethod(l, "getTriggerComponent", wrapSceneNodegetTriggerComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getFogDensityComponent", wrapSceneNodegetFogDensityComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getFrustumComponent", wrapSceneNodegetFrustumComponent);
+	LuaBinder::pushLuaCFuncMethod(
+		l, "getGlobalIlluminationProbeComponent", wrapSceneNodegetGlobalIlluminationProbeComponent);
 	lua_settop(l, 0);
 }
 
@@ -3376,6 +3717,75 @@ static inline void wrapFogDensityNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
+LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {7117765190519964845,
+	"GlobalIlluminationProbeNode",
+	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(),
+	nullptr,
+	nullptr};
+
+template<>
+const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<GlobalIlluminationProbeNode>()
+{
+	return luaUserDataTypeInfoGlobalIlluminationProbeNode;
+}
+
+/// Pre-wrap method GlobalIlluminationProbeNode::getSceneNodeBase.
+static inline int pwrapGlobalIlluminationProbeNodegetSceneNodeBase(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoGlobalIlluminationProbeNode, ud))
+	{
+		return -1;
+	}
+
+	GlobalIlluminationProbeNode* self = ud->getData<GlobalIlluminationProbeNode>();
+
+	// Call the method
+	SceneNode& ret = *self;
+
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "SceneNode");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode;
+	ud->initPointed(&luaUserDataTypeInfoSceneNode, const_cast<SceneNode*>(&ret));
+
+	return 1;
+}
+
+/// Wrap method GlobalIlluminationProbeNode::getSceneNodeBase.
+static int wrapGlobalIlluminationProbeNodegetSceneNodeBase(lua_State* l)
+{
+	int res = pwrapGlobalIlluminationProbeNodegetSceneNodeBase(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Wrap class GlobalIlluminationProbeNode.
+static inline void wrapGlobalIlluminationProbeNode(lua_State* l)
+{
+	LuaBinder::createClass(l, &luaUserDataTypeInfoGlobalIlluminationProbeNode);
+	LuaBinder::pushLuaCFuncMethod(l, "getSceneNodeBase", wrapGlobalIlluminationProbeNodegetSceneNodeBase);
+	lua_settop(l, 0);
+}
+
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
 	-7754439619132389154, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
 
@@ -4124,6 +4534,68 @@ static int wrapSceneGraphnewTriggerNode(lua_State* l)
 	return 0;
 }
 
+/// Pre-wrap method SceneGraph::newGlobalIlluminationProbeNode.
+static inline int pwrapSceneGraphnewGlobalIlluminationProbeNode(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, luaUserDataTypeInfoSceneGraph, ud))
+	{
+		return -1;
+	}
+
+	SceneGraph* self = ud->getData<SceneGraph>();
+
+	// Pop arguments
+	const char* arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkString(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	GlobalIlluminationProbeNode* ret = newSceneNode<GlobalIlluminationProbeNode>(self, arg0);
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "GlobalIlluminationProbeNode");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode;
+	ud->initPointed(&luaUserDataTypeInfoGlobalIlluminationProbeNode, const_cast<GlobalIlluminationProbeNode*>(ret));
+
+	return 1;
+}
+
+/// Wrap method SceneGraph::newGlobalIlluminationProbeNode.
+static int wrapSceneGraphnewGlobalIlluminationProbeNode(lua_State* l)
+{
+	int res = pwrapSceneGraphnewGlobalIlluminationProbeNode(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 /// Pre-wrap method SceneGraph::setActiveCameraNode.
 static inline int pwrapSceneGraphsetActiveCameraNode(lua_State* l)
 {
@@ -4191,6 +4663,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	LuaBinder::pushLuaCFuncMethod(l, "newOccluderNode", wrapSceneGraphnewOccluderNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newDecalNode", wrapSceneGraphnewDecalNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newTriggerNode", wrapSceneGraphnewTriggerNode);
+	LuaBinder::pushLuaCFuncMethod(l, "newGlobalIlluminationProbeNode", wrapSceneGraphnewGlobalIlluminationProbeNode);
 	LuaBinder::pushLuaCFuncMethod(l, "setActiveCameraNode", wrapSceneGraphsetActiveCameraNode);
 	lua_settop(l, 0);
 }
@@ -4590,6 +5063,7 @@ void wrapModuleScene(lua_State* l)
 	wrapTriggerComponent(l);
 	wrapFogDensityComponent(l);
 	wrapFrustumComponent(l);
+	wrapGlobalIlluminationProbeComponent(l);
 	wrapSceneNode(l);
 	wrapModelNode(l);
 	wrapPerspectiveCameraNode(l);
@@ -4603,6 +5077,7 @@ void wrapModuleScene(lua_State* l)
 	wrapDecalNode(l);
 	wrapTriggerNode(l);
 	wrapFogDensityNode(l);
+	wrapGlobalIlluminationProbeNode(l);
 	wrapSceneGraph(l);
 	wrapEvent(l);
 	wrapLightEvent(l);

+ 49 - 0
src/anki/script/Scene.xml

@@ -114,6 +114,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
 		<class name="LightComponent">
 			<methods>
 				<method name="setDiffuseColor">
@@ -166,6 +167,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
 		<class name="DecalComponent">
 			<methods>
 				<method name="setDiffuseDecal">
@@ -193,6 +195,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
 		<class name="LensFlareComponent">
 			<methods>
 				<method name="setFirstFlareSize">
@@ -207,6 +210,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
 		<class name="TriggerComponent">
 			<methods>
 				<method name="getContactSceneNodes">
@@ -214,6 +218,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
 		<class name="FogDensityComponent">
 			<methods>
 				<method name="setAabb">
@@ -236,6 +241,8 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 					<return>F32</return>
 				</method>
 			</methods>
+		</class>
+
 		<class name="FrustumComponent">
 			<methods>
 				<method name="setPerspective">
@@ -248,6 +255,30 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+
+		<class name="GlobalIlluminationProbeComponent">
+			<methods>
+				<method name="setBoundingBox">
+					<args>
+						<arg>const Vec4&amp;</arg>
+						<arg>const Vec4&amp;</arg>
+					</args>
+				</method>
+				<method name="getAlignedBoundingBoxMin">
+					<return>Vec4</return>
+				</method>
+				<method name="getAlignedBoundingBoxMax">
+					<return>Vec4</return>
+				</method>
+				<method name="setCellSize">
+					<args>
+						<arg>F32</arg>
+					</args>
+				</method>
+				<method name="getCellSize">
+					<return>F32</return>
+				</method>
+			</methods>
 		</class>
 
 		<!-- Nodes -->
@@ -283,6 +314,9 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				<method name="tryGetComponent&lt;FrustumComponent&gt;" alias="getFrustumComponent">
 					<return>FrustumComponent*</return>
 				</method>
+				<method name="tryGetComponent&lt;GlobalIlluminationProbeComponent&gt;" alias="getGlobalIlluminationProbeComponent">
+					<return>GlobalIlluminationProbeComponent*</return>
+				</method>
 			</methods>
 		</class>
 		<class name="ModelNode">
@@ -387,6 +421,14 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
+		<class name="GlobalIlluminationProbeNode">
+			<methods>
+				<method name="getSceneNodeBase">
+					<overrideCall>SceneNode&amp; ret = *self;</overrideCall>
+					<return>SceneNode&amp;</return>
+				</method>
+			</methods>
+		</class>
 		<class name="SceneGraph">
 			<methods>
 				<method name="newPerspectiveCameraNode">
@@ -474,6 +516,13 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 					</args>
 					<return>TriggerNode*</return>
 				</method>
+				<method name="newGlobalIlluminationProbeNode">
+					<overrideCall><![CDATA[GlobalIlluminationProbeNode* ret = newSceneNode<GlobalIlluminationProbeNode>(self, arg0);]]></overrideCall>
+					<args>
+						<arg>const CString&amp;</arg>
+					</args>
+					<return>GlobalIlluminationProbeNode*</return>
+				</method>
 				<method name="setActiveCameraNode">
 					<args>
 						<arg>SceneNode*</arg>