Просмотр исходного кода

Fixing code that triggers unwanted shadowpasses. Optimize a bit

Panagiotis Christopoulos Charitos 10 лет назад
Родитель
Сommit
97f199c473

+ 21 - 7
include/anki/scene/FrustumComponent.h

@@ -38,10 +38,12 @@ public:
 		TEST_LIGHT_COMPONENTS = 1 << 1,
 		TEST_LENS_FLARE_COMPONENTS = 1 << 2,
 		TEST_SHADOW_CASTERS = 1 << 3,
-		TEST_ALL = TEST_RENDER_COMPONENTS
-			| TEST_LIGHT_COMPONENTS
-			| TEST_LENS_FLARE_COMPONENTS
-			| TEST_SHADOW_CASTERS
+
+		ALL_TESTS =
+			VisibilityTestFlag::TEST_RENDER_COMPONENTS
+			| VisibilityTestFlag::TEST_LIGHT_COMPONENTS
+			| VisibilityTestFlag::TEST_LENS_FLARE_COMPONENTS
+			| VisibilityTestFlag::TEST_SHADOW_CASTERS
 	};
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VisibilityTestFlag, friend)
 
@@ -142,8 +144,20 @@ public:
 
 	void setEnabledVisibilityTests(VisibilityTestFlag bits)
 	{
-		m_flags.disableBits(VisibilityTestFlag::TEST_ALL);
+		m_flags.disableBits(VisibilityTestFlag::ALL_TESTS);
 		m_flags.enableBits(bits, true);
+
+#if ANKI_ASSERTS_ENABLED
+		if(m_flags.bitsEnabled(VisibilityTestFlag::TEST_RENDER_COMPONENTS)
+			|| m_flags.bitsEnabled(VisibilityTestFlag::TEST_SHADOW_CASTERS))
+		{
+			if(m_flags.bitsEnabled(VisibilityTestFlag::TEST_RENDER_COMPONENTS)
+				== m_flags.bitsEnabled(VisibilityTestFlag::TEST_SHADOW_CASTERS))
+			{
+				ANKI_ASSERT(0 && "Cannot have them both");
+			}
+		}
+#endif
 	}
 
 	Bool visibilityTestsEnabled(VisibilityTestFlag bits) const
@@ -153,7 +167,7 @@ public:
 
 	Bool anyVisibilityTestEnabled() const
 	{
-		return m_flags.anyBitsEnabled(VisibilityTestFlag::TEST_ALL);
+		return m_flags.anyBitsEnabled(VisibilityTestFlag::ALL_TESTS);
 	}
 
 	static Bool classof(const SceneComponent& c)
@@ -165,7 +179,7 @@ private:
 	enum Flags
 	{
 		SHAPE_MARKED_FOR_UPDATE = 1 << 4,
-		TRANSFORM_MARKED_FOR_UPDATE = 1 << 5
+		TRANSFORM_MARKED_FOR_UPDATE = 1 << 5,
 	};
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flags, friend)
 

+ 1 - 4
include/anki/scene/LightComponent.h

@@ -3,8 +3,7 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#ifndef ANKI_SCENE_LIGHT_COMPONENT_H
-#define ANKI_SCENE_LIGHT_COMPONENT_H
+#pragma once
 
 #include "anki/scene/SceneComponent.h"
 #include "anki/Math.h"
@@ -159,5 +158,3 @@ private:
 
 } // end namespace anki
 
-#endif
-

+ 12 - 0
include/anki/scene/Visibility.h

@@ -158,6 +158,16 @@ public:
 		moveBack(alloc, m_flares, m_flaresCount, x);
 	}
 
+	Timestamp getShapeUpdateTimestamp() const
+	{
+		return m_shapeUpdateTimestamp;
+	}
+
+	void setShapeUpdateTimestamp(Timestamp t)
+	{
+		m_shapeUpdateTimestamp = t;
+	}
+
 private:
 	Container m_renderables;
 	Container m_lights;
@@ -166,6 +176,8 @@ private:
 	U32 m_lightsCount = 0;
 	U32 m_flaresCount = 0;
 
+	Timestamp m_shapeUpdateTimestamp = 0;
+
 	void moveBack(SceneFrameAllocator<U8> alloc,
 		Container& c, U32& count, VisibleNode& x);
 };

+ 11 - 15
include/anki/util/Enum.h

@@ -3,8 +3,7 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#ifndef ANKI_UTIL_ENUM_H
-#define ANKI_UTIL_ENUM_H
+#pragma once
 
 #include "anki/Config.h"
 
@@ -21,38 +20,39 @@ struct EnumUnderlyingType
 
 /// Convert an enum to it's integer type.
 template<typename TEnum>
-inline typename EnumUnderlyingType<TEnum>::Type enumToType(TEnum e)
+constexpr inline typename EnumUnderlyingType<TEnum>::Type enumToType(TEnum e)
 {
 	return static_cast<typename EnumUnderlyingType<TEnum>::Type>(e);
 }
 
 #define _ANKI_ENUM_OPERATOR(enum_, qualifier_, operator_, selfOperator_) \
-	qualifier_ enum_ operator operator_ (enum_ a, enum_ b) \
+	constexpr qualifier_ enum_ operator operator_ ( \
+		const enum_ a, const enum_ b) \
 	{ \
 		using Int = EnumUnderlyingType<enum_>::Type; \
 		return static_cast<enum_>( \
 			static_cast<Int>(a) operator_ static_cast<Int>(b)); \
 	} \
-	qualifier_ enum_ operator operator_ ( \
-		enum_ a, EnumUnderlyingType<enum_>::Type b) \
+	constexpr qualifier_ enum_ operator operator_ ( \
+		const enum_ a, const EnumUnderlyingType<enum_>::Type b) \
 	{ \
 		using Int = EnumUnderlyingType<enum_>::Type; \
 		return static_cast<enum_>(static_cast<Int>(a) operator_ b); \
 	} \
-	qualifier_ enum_ operator operator_ ( \
-		EnumUnderlyingType<enum_>::Type a, enum_ b) \
+	constexpr qualifier_ enum_ operator operator_ ( \
+		const EnumUnderlyingType<enum_>::Type a, const enum_ b) \
 	{ \
 		using Int = EnumUnderlyingType<enum_>::Type; \
 		return static_cast<enum_>(a operator_ static_cast<Int>(b)); \
 	} \
-	qualifier_ enum_& operator selfOperator_ (enum_& a, enum_ b) \
+	qualifier_ enum_& operator selfOperator_ (enum_& a, const enum_ b) \
 	{ \
 		a = a operator_ b; \
 		return a; \
-	} \
+	}
 
 #define _ANKI_ENUM_UNARAY_OPERATOR(enum_, qualifier_, operator_) \
-	qualifier_ enum_ operator operator_ (enum_ a) \
+	constexpr qualifier_ enum_ operator operator_ (const enum_ a) \
 	{ \
 		using Int = EnumUnderlyingType<enum_>::Type; \
 		return static_cast<enum_>(operator_ static_cast<Int>(a)); \
@@ -71,7 +71,6 @@ inline typename EnumUnderlyingType<TEnum>::Type enumToType(TEnum e)
 		a = static_cast<enum_>(static_cast<Int>(a) - 1); \
 		return  a; \
 	}
-
 /// @}
 
 /// @addtogroup util_other
@@ -107,6 +106,3 @@ inline TEnum valueToEnum(typename EnumUnderlyingType<TEnum>::Type v)
 }
 /// @}
 
-#endif
-
-

+ 14 - 10
src/event/LightEvent.cpp

@@ -45,17 +45,21 @@ Error LightEvent::update(F32 prevUpdateTime, F32 crntTime)
 	F32 factor = sin(crntTime * freq * getPi<F32>()) / 2.0 + 0.5;
 	LightComponent& lightc = getSceneNode()->getComponent<LightComponent>();
 
-	switch(lightc.getLightType())
+	// Update radius
+	if(m_radiusMultiplier != 0.0)
 	{
-	case LightComponent::LightType::POINT:
-		lightc.setRadius(m_originalRadius + factor * m_radiusMultiplier);
-		break;
-	case LightComponent::LightType::SPOT:
-		ANKI_ASSERT("TODO");
-		break;
-	default:
-		ANKI_ASSERT(0);
-		break;
+		switch(lightc.getLightType())
+		{
+		case LightComponent::LightType::POINT:
+			lightc.setRadius(m_originalRadius + factor * m_radiusMultiplier);
+			break;
+		case LightComponent::LightType::SPOT:
+			ANKI_ASSERT("TODO");
+			break;
+		default:
+			ANKI_ASSERT(0);
+			break;
+		}
 	}
 
 	// Update the color and the lens flare's color if they are the same

+ 13 - 33
src/renderer/Sm.cpp

@@ -107,6 +107,12 @@ Error Sm::run(SArray<SceneNode*> spotShadowCasters,
 {
 	ANKI_ASSERT(m_enabled);
 
+	if(omniShadowCasters.getSize() > m_omnis.getSize()
+		|| spotShadowCasters.getSize() > m_spots.getSize())
+	{
+		ANKI_LOGW("Too many shadow casters");
+	}
+
 	// render all
 	for(SceneNode* node : spotShadowCasters)
 	{
@@ -165,50 +171,24 @@ void Sm::bestCandidate(SceneNode& light, TContainer& arr, TShadowmap*& out)
 //==============================================================================
 Bool Sm::skip(SceneNode& light, ShadowmapBase& sm)
 {
-	Timestamp lastUpdate = light.getComponent<MoveComponent>().getTimestamp();
+	MoveComponent* movc =
+		light.tryGetComponent<MoveComponent>();
+
+	Timestamp lastUpdate = movc->getTimestamp();
 
-	Bool shouldUpdate = false;
 	Error err = light.iterateComponentsOfType<FrustumComponent>(
 		[&](FrustumComponent& fr)
 	{
 		lastUpdate = max(lastUpdate, fr.getTimestamp());
-		VisibilityTestResults& vi = fr.getVisibilityTestResults();
 
-		auto it = vi.getRenderablesBegin();
-		auto end = vi.getRenderablesEnd();
-		for(; it != end; ++it)
-		{
-			SceneNode* node = it->m_node;
-
-			FrustumComponent* bfr = node->tryGetComponent<FrustumComponent>();
-			if(bfr)
-			{
-				lastUpdate = max(lastUpdate, bfr->getTimestamp());
-			}
-
-			MoveComponent* bmov = node->tryGetComponent<MoveComponent>();
-			if(bmov)
-			{
-				lastUpdate = max(lastUpdate, bmov->getTimestamp());
-			}
-
-			SpatialComponent* sp = node->tryGetComponent<SpatialComponent>();
-			if(sp)
-			{
-				lastUpdate = max(lastUpdate, sp->getTimestamp());
-			}
-
-			if(lastUpdate >= sm.m_timestamp)
-			{
-				shouldUpdate = true;
-				break;
-			}
-		}
+		VisibilityTestResults& vi = fr.getVisibilityTestResults();
+		lastUpdate = max(lastUpdate, vi.getShapeUpdateTimestamp());
 
 		return ErrorCode::NONE;
 	});
 	(void)err;
 
+	Bool shouldUpdate = lastUpdate >= sm.m_timestamp;
 	if(shouldUpdate)
 	{
 		sm.m_timestamp = getGlobalTimestamp();

+ 7 - 2
src/scene/Camera.cpp

@@ -89,8 +89,13 @@ Error Camera::create(const CString& name, Frustum* frustum)
 	addComponent(comp, true);
 
 	// Frustum component
-	comp = getSceneAllocator().newInstance<FrustumComponent>(this, frustum);
-	addComponent(comp, true);
+	FrustumComponent* frc =
+		getSceneAllocator().newInstance<FrustumComponent>(this, frustum);
+	frc->setEnabledVisibilityTests(
+		FrustumComponent::VisibilityTestFlag::TEST_RENDER_COMPONENTS
+		| FrustumComponent::VisibilityTestFlag::TEST_LIGHT_COMPONENTS
+		| FrustumComponent::VisibilityTestFlag::TEST_LENS_FLARE_COMPONENTS);
+	addComponent(frc, true);
 
 	// Feedback component #2
 	comp =

+ 1 - 1
src/scene/FrustumComponent.cpp

@@ -20,7 +20,7 @@ FrustumComponent::FrustumComponent(SceneNode* node, Frustum* frustum)
 	markShapeForUpdate();
 	markTransformForUpdate();
 
-	setEnabledVisibilityTests(VisibilityTestFlag::TEST_ALL);
+	setEnabledVisibilityTests(VisibilityTestFlag::TEST_NONE);
 }
 
 //==============================================================================

+ 4 - 0
src/scene/LightComponent.cpp

@@ -25,6 +25,10 @@ Error LightComponent::update(SceneNode&, F32, F32, Bool& updated)
 		updated = true;
 		m_dirty = false;
 	}
+	else
+	{
+		updated = false;
+	}
 
 	return ErrorCode::NONE;
 }

+ 41 - 0
src/scene/Visibility.cpp

@@ -9,6 +9,7 @@
 #include "anki/scene/FrustumComponent.h"
 #include "anki/scene/LensFlareComponent.h"
 #include "anki/scene/Light.h"
+#include "anki/scene/MoveComponent.h"
 #include "anki/renderer/MainRenderer.h"
 #include "anki/util/Logger.h"
 
@@ -59,6 +60,9 @@ public:
 	List<FrustumComponent*> m_frustumsList; ///< Frustums to test
 	SpinLock m_lock;
 
+	Timestamp m_timestamp = 0;
+	SpinLock m_timestampLock;
+
 	// Data per thread but that can be accessed by all threads
 	Array<VisibilityTestResults*, ThreadPool::MAX_THREADS> m_testResults;
 
@@ -97,6 +101,9 @@ public:
 			if(threadId == 0)
 			{
 				list.popFront(alloc);
+
+				// Set initial value of timestamp
+				m_shared->m_timestamp = 0;
 			}
 
 			m_shared->m_barrier.wait();
@@ -105,6 +112,33 @@ public:
 
 		return ErrorCode::NONE;
 	}
+
+	/// Update the timestamp if the node moved or changed its shape.
+	void updateTimestamp(const SceneNode& node)
+	{
+		Timestamp lastUpdate = 0;
+
+		const FrustumComponent* bfr = node.tryGetComponent<FrustumComponent>();
+		if(bfr)
+		{
+			lastUpdate = max(lastUpdate, bfr->getTimestamp());
+		}
+
+		const MoveComponent* bmov = node.tryGetComponent<MoveComponent>();
+		if(bmov)
+		{
+			lastUpdate = max(lastUpdate, bmov->getTimestamp());
+		}
+
+		const SpatialComponent* sp = node.tryGetComponent<SpatialComponent>();
+		if(sp)
+		{
+			lastUpdate = max(lastUpdate, sp->getTimestamp());
+		}
+
+		LockGuard<SpinLock> lock(m_shared->m_timestampLock);
+		m_shared->m_timestamp = max(m_shared->m_timestamp, lastUpdate);
+	}
 };
 
 //==============================================================================
@@ -272,6 +306,11 @@ void VisibilityTestTask::test(FrustumComponent& testedFrc,
 				(wantsShadowCasters && rc->getCastsShadow()))
 			{
 				visible->moveBackRenderable(alloc, visibleNode);
+
+				if(wantsShadowCasters)
+				{
+					updateTimestamp(node);
+				}
 			}
 		}
 
@@ -336,6 +375,8 @@ void VisibilityTestTask::combineTestResults(
 	// Allocate
 	VisibilityTestResults* visible = alloc.newInstance<VisibilityTestResults>();
 
+	visible->setShapeUpdateTimestamp(m_shared->m_timestamp);
+
 	visible->create(
 		alloc,
 		renderablesSize,