Browse Source

Some refactoring

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
84aae87e5b

+ 13 - 5
shaders/LightShading.glslp

@@ -147,13 +147,21 @@ void main()
 
 
 	// Dir light
 	// Dir light
 	Vec3 viewDir = normalize(u_cameraPos - worldPos);
 	Vec3 viewDir = normalize(u_cameraPos - worldPos);
-	if(u_dirLight.m_cascadeCount > 0u)
+	if(u_dirLight.m_active != 0u)
 	{
 	{
-		F32 linearDepth = linearizeDepth(depth, u_near, u_far);
-		F32 cascadeCountf = F32(u_dirLight.m_cascadeCount);
-		U32 cascadeIdx = min(U32(linearDepth * cascadeCountf), u_dirLight.m_cascadeCount - 1u);
+		F32 shadowFactor;
+		if(u_dirLight.m_cascadeCount > 0)
+		{
+			F32 linearDepth = linearizeDepth(depth, u_near, u_far);
+			F32 cascadeCountf = F32(u_dirLight.m_cascadeCount);
+			U32 cascadeIdx = min(U32(linearDepth * cascadeCountf), u_dirLight.m_cascadeCount - 1u);
 
 
-		F32 shadowFactor = computeShadowFactorDirLight(u_dirLight, cascadeIdx, worldPos, u_shadowTex);
+			shadowFactor = computeShadowFactorDirLight(u_dirLight, cascadeIdx, worldPos, u_shadowTex);
+		}
+		else
+		{
+			shadowFactor = 1.0;
+		}
 
 
 		Vec3 l = u_dirLight.m_dir;
 		Vec3 l = u_dirLight.m_dir;
 
 

+ 8 - 8
shaders/VolumetricLightingAccumulation.glslp

@@ -107,19 +107,19 @@ Vec4 accumulateLightsAndFog(U32 clusterIdx, Vec3 worldPos, F32 linearDepth)
 	U32 idxOffset = u_clusters[clusterIdx];
 	U32 idxOffset = u_clusters[clusterIdx];
 
 
 	// Dir light
 	// Dir light
-	if(u_dirLight.m_cascadeCount > 0u)
+	if(u_dirLight.m_active != 0u)
 	{
 	{
-		F32 cascadeCountf = F32(u_dirLight.m_cascadeCount);
-		U32 cascadeIdx = min(U32(linearDepth * cascadeCountf), u_dirLight.m_cascadeCount - 1u);
+		F32 factor = phaseFunction(viewDir, u_dirLight.m_dir, PHASE_FUNCTION_ANISOTROPY);
 
 
 #if ENABLE_SHADOWS
 #if ENABLE_SHADOWS
-		F32 factor = computeShadowFactorDirLight(u_dirLight, cascadeIdx, worldPos, u_shadowTex);
-#else
-		F32 factor = 1.0;
+		if(u_dirLight.m_cascadeCount > 0u)
+		{
+			F32 cascadeCountf = F32(u_dirLight.m_cascadeCount);
+			U32 cascadeIdx = min(U32(linearDepth * cascadeCountf), u_dirLight.m_cascadeCount - 1u);
+			factor *= computeShadowFactorDirLight(u_dirLight, cascadeIdx, worldPos, u_shadowTex);
+		}
 #endif
 #endif
 
 
-		factor *= phaseFunction(viewDir, u_dirLight.m_dir, PHASE_FUNCTION_ANISOTROPY);
-
 		color += u_dirLight.m_diffuseColor * factor;
 		color += u_dirLight.m_diffuseColor * factor;
 	}
 	}
 
 

+ 2 - 2
shaders/glsl_cpp_common/ClusteredShading.h

@@ -60,9 +60,9 @@ ANKI_SHADER_STATIC_ASSERT(sizeof(SpotLight) == SIZEOF_SPOT_LIGHT)
 struct DirectionalLight
 struct DirectionalLight
 {
 {
 	Vec3 m_diffuseColor;
 	Vec3 m_diffuseColor;
-	U32 m_cascadeCount; // If it's zero then it's not active
+	U32 m_cascadeCount; // If it's zero then it doesn't case shadow
 	Vec3 m_dir;
 	Vec3 m_dir;
-	U32 m_padding;
+	U32 m_active;
 	Mat4 m_textureMatrices[MAX_SHADOW_CASCADES];
 	Mat4 m_textureMatrices[MAX_SHADOW_CASCADES];
 };
 };
 const U32 SIZEOF_DIR_LIGHT = 2 * SIZEOF_VEC4 + MAX_SHADOW_CASCADES * SIZEOF_MAT4;
 const U32 SIZEOF_DIR_LIGHT = 2 * SIZEOF_VEC4 + MAX_SHADOW_CASCADES * SIZEOF_MAT4;

+ 2 - 2
src/anki/renderer/RenderQueue.h

@@ -128,10 +128,10 @@ public:
 	Array<RenderQueue*, MAX_SHADOW_CASCADES> m_shadowRenderQueues;
 	Array<RenderQueue*, MAX_SHADOW_CASCADES> m_shadowRenderQueues;
 	const void* m_userData;
 	const void* m_userData;
 	RenderQueueDrawCallback m_drawCallback;
 	RenderQueueDrawCallback m_drawCallback;
-	U64 m_uuid;
+	U64 m_uuid; ///< Zero means that there is no dir light
 	Vec3 m_diffuseColor;
 	Vec3 m_diffuseColor;
 	Vec3 m_direction;
 	Vec3 m_direction;
-	U8 m_shadowCascadeCount;
+	U8 m_shadowCascadeCount; ///< Zero means that it doesn't case any shadows
 
 
 	DirectionalLightQueueElement()
 	DirectionalLightQueueElement()
 	{
 	{

+ 3 - 2
src/anki/renderer/Renderer.cpp

@@ -567,7 +567,7 @@ void Renderer::updateLightShadingUniforms(RenderingContext& ctx) const
 		ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 		ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 
 
 	// Directional light
 	// Directional light
-	if(ctx.m_renderQueue->m_directionalLight.m_shadowCascadeCount > 0)
+	if(ctx.m_renderQueue->m_directionalLight.m_uuid != 0)
 	{
 	{
 		DirectionalLight& out = blk->m_dirLight;
 		DirectionalLight& out = blk->m_dirLight;
 		const DirectionalLightQueueElement& in = ctx.m_renderQueue->m_directionalLight;
 		const DirectionalLightQueueElement& in = ctx.m_renderQueue->m_directionalLight;
@@ -575,6 +575,7 @@ void Renderer::updateLightShadingUniforms(RenderingContext& ctx) const
 		out.m_diffuseColor = in.m_diffuseColor;
 		out.m_diffuseColor = in.m_diffuseColor;
 		out.m_cascadeCount = in.m_shadowCascadeCount;
 		out.m_cascadeCount = in.m_shadowCascadeCount;
 		out.m_dir = in.m_direction;
 		out.m_dir = in.m_direction;
+		out.m_active = 1;
 
 
 		for(U cascade = 0; cascade < in.m_shadowCascadeCount; ++cascade)
 		for(U cascade = 0; cascade < in.m_shadowCascadeCount; ++cascade)
 		{
 		{
@@ -583,7 +584,7 @@ void Renderer::updateLightShadingUniforms(RenderingContext& ctx) const
 	}
 	}
 	else
 	else
 	{
 	{
-		blk->m_dirLight.m_cascadeCount = 0;
+		blk->m_dirLight.m_active = 0;
 	}
 	}
 }
 }
 
 

+ 55 - 29
src/anki/renderer/ShadowMapping.cpp

@@ -518,46 +518,72 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 		Array<U32, MAX_SHADOW_CASCADES> lods;
 		Array<U32, MAX_SHADOW_CASCADES> lods;
 		Array<Bool, MAX_SHADOW_CASCADES> blurEsms;
 		Array<Bool, MAX_SHADOW_CASCADES> blurEsms;
 
 
+		U activeCascades = 0;
+
 		for(U cascade = 0; cascade < light.m_shadowCascadeCount; ++cascade)
 		for(U cascade = 0; cascade < light.m_shadowCascadeCount; ++cascade)
 		{
 		{
 			ANKI_ASSERT(light.m_shadowRenderQueues[cascade]);
 			ANKI_ASSERT(light.m_shadowRenderQueues[cascade]);
-			timestamps[cascade] = m_r->getGlobalTimestamp(); // This light is always updated
-			cascadeIndices[cascade] = cascade;
-			drawcallCounts[cascade] = 1; // Doesn't matter
+			if(light.m_shadowRenderQueues[cascade]->m_renderables.getSize() > 0)
+			{
+				// Cascade with drawcalls, will need tiles
+
+				timestamps[activeCascades] = m_r->getGlobalTimestamp(); // This light is always updated
+				cascadeIndices[activeCascades] = cascade;
+				drawcallCounts[activeCascades] = 1; // Doesn't matter
 
 
-			// Change the quality per cascade
-			blurEsms[cascade] = (cascade <= 1);
-			lods[cascade] = (cascade <= 1) ? (m_lodCount - 1) : (lods[0] - 1);
+				// Change the quality per cascade
+				blurEsms[activeCascades] = (cascade <= 1);
+				lods[activeCascades] = (cascade <= 1) ? (m_lodCount - 1) : (lods[0] - 1);
+
+				++activeCascades;
+			}
 		}
 		}
 
 
-		const Bool allocationFailed = allocateTilesAndScratchTiles(light.m_uuid,
-										  light.m_shadowCascadeCount,
-										  &timestamps[0],
-										  &cascadeIndices[0],
-										  &drawcallCounts[0],
-										  &lods[0],
-										  &esmViewports[0],
-										  &scratchViewports[0],
-										  &subResults[0])
-									  == TileAllocatorResult::ALLOCATION_FAILED;
+		const Bool allocationFailed = activeCascades == 0
+									  || allocateTilesAndScratchTiles(light.m_uuid,
+											 activeCascades,
+											 &timestamps[0],
+											 &cascadeIndices[0],
+											 &drawcallCounts[0],
+											 &lods[0],
+											 &esmViewports[0],
+											 &scratchViewports[0],
+											 &subResults[0])
+											 == TileAllocatorResult::ALLOCATION_FAILED;
 
 
 		if(!allocationFailed)
 		if(!allocationFailed)
 		{
 		{
+			activeCascades = 0;
+
 			for(U cascade = 0; cascade < light.m_shadowCascadeCount; ++cascade)
 			for(U cascade = 0; cascade < light.m_shadowCascadeCount; ++cascade)
 			{
 			{
-				// Update the texture matrix to point to the correct region in the atlas
-				light.m_textureMatrices[cascade] =
-					createSpotLightTextureMatrix(esmViewports[cascade]) * light.m_textureMatrices[cascade];
-
-				// Push work
-				newScratchAndEsmResloveRenderWorkItems(esmViewports[cascade],
-					scratchViewports[cascade],
-					blurEsms[cascade],
-					false,
-					light.m_shadowRenderQueues[cascade],
-					lightsToRender,
-					esmWorkItems,
-					drawcallCount);
+				if(light.m_shadowRenderQueues[cascade]->m_renderables.getSize() > 0)
+				{
+					// Cascade with drawcalls, push some work for it
+
+					// Update the texture matrix to point to the correct region in the atlas
+					light.m_textureMatrices[cascade] =
+						createSpotLightTextureMatrix(esmViewports[activeCascades]) * light.m_textureMatrices[cascade];
+
+					// Push work
+					newScratchAndEsmResloveRenderWorkItems(esmViewports[activeCascades],
+						scratchViewports[activeCascades],
+						blurEsms[activeCascades],
+						false,
+						light.m_shadowRenderQueues[cascade],
+						lightsToRender,
+						esmWorkItems,
+						drawcallCount);
+
+					++activeCascades;
+				}
+				else
+				{
+					// Empty cascade, point it to the empty tile
+
+					light.m_textureMatrices[cascade] =
+						createSpotLightTextureMatrix(emptyTileViewport) * light.m_textureMatrices[cascade];
+				}
 			}
 			}
 		}
 		}
 		else
 		else

+ 2 - 1
src/anki/scene/CameraNode.cpp

@@ -79,7 +79,8 @@ Error CameraNode::init(Frustum* frustum)
 		| FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS
 		| FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS
 		| FrustumComponentVisibilityTestFlag::REFLECTION_PROBES | FrustumComponentVisibilityTestFlag::REFLECTION_PROXIES
 		| FrustumComponentVisibilityTestFlag::REFLECTION_PROBES | FrustumComponentVisibilityTestFlag::REFLECTION_PROXIES
 		| FrustumComponentVisibilityTestFlag::OCCLUDERS | FrustumComponentVisibilityTestFlag::DECALS
 		| FrustumComponentVisibilityTestFlag::OCCLUDERS | FrustumComponentVisibilityTestFlag::DECALS
-		| FrustumComponentVisibilityTestFlag::FOG_DENSITY_COMPONENTS | FrustumComponentVisibilityTestFlag::EARLY_Z);
+		| FrustumComponentVisibilityTestFlag::FOG_DENSITY_COMPONENTS | FrustumComponentVisibilityTestFlag::EARLY_Z
+		| FrustumComponentVisibilityTestFlag::ALL_SHADOWS_ENABLED);
 
 
 	// Feedback component #2
 	// Feedback component #2
 	newComponent<FrustumFeedbackComponent>();
 	newComponent<FrustumFeedbackComponent>();

+ 36 - 37
src/anki/scene/Visibility.cpp

@@ -242,45 +242,24 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 		Bool wantNode = false;
 		Bool wantNode = false;
 
 
 		const RenderComponent* rc = nullptr;
 		const RenderComponent* rc = nullptr;
-		if(wantsRenderComponents && (rc = node.tryGetComponent<RenderComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsRenderComponents && (rc = node.tryGetComponent<RenderComponent>());
 
 
-		if(wantsShadowCasters && (rc = node.tryGetComponent<RenderComponent>()) && rc->getCastsShadow())
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsShadowCasters && (rc = node.tryGetComponent<RenderComponent>()) && rc->getCastsShadow();
 
 
 		const LightComponent* lc = nullptr;
 		const LightComponent* lc = nullptr;
-		if(wantsLightComponents && (lc = node.tryGetComponent<LightComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsLightComponents && (lc = node.tryGetComponent<LightComponent>());
 
 
 		const LensFlareComponent* lfc = nullptr;
 		const LensFlareComponent* lfc = nullptr;
-		if(wantsFlareComponents && (lfc = node.tryGetComponent<LensFlareComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsFlareComponents && (lfc = node.tryGetComponent<LensFlareComponent>());
 
 
 		const ReflectionProbeComponent* reflc = nullptr;
 		const ReflectionProbeComponent* reflc = nullptr;
-		if(wantsReflectionProbes && (reflc = node.tryGetComponent<ReflectionProbeComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsReflectionProbes && (reflc = node.tryGetComponent<ReflectionProbeComponent>());
 
 
 		DecalComponent* decalc = nullptr;
 		DecalComponent* decalc = nullptr;
-		if(wantsDecals && (decalc = node.tryGetComponent<DecalComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsDecals && (decalc = node.tryGetComponent<DecalComponent>());
 
 
 		const FogDensityComponent* fogc = nullptr;
 		const FogDensityComponent* fogc = nullptr;
-		if(wantsFogDensityComponents && (fogc = node.tryGetComponent<FogDensityComponent>()))
-		{
-			wantNode = true;
-		}
+		wantNode |= wantsFogDensityComponents && (fogc = node.tryGetComponent<FogDensityComponent>());
 
 
 		if(ANKI_UNLIKELY(!wantNode))
 		if(ANKI_UNLIKELY(!wantNode))
 		{
 		{
@@ -369,7 +348,9 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 				PointLightQueueElement* el = result.m_pointLights.newElement(alloc);
 				PointLightQueueElement* el = result.m_pointLights.newElement(alloc);
 				lc->setupPointLightQueueElement(*el);
 				lc->setupPointLightQueueElement(*el);
 
 
-				if(lc->getShadowEnabled())
+				if(lc->getShadowEnabled()
+					&& testedFrc.visibilityTestsEnabled(
+						   FrustumComponentVisibilityTestFlag::POINT_LIGHT_SHADOWS_ENABLED))
 				{
 				{
 					RenderQueue* a = alloc.newArray<RenderQueue>(6);
 					RenderQueue* a = alloc.newArray<RenderQueue>(6);
 					nextQueues = WeakArray<RenderQueue>(a, 6);
 					nextQueues = WeakArray<RenderQueue>(a, 6);
@@ -396,7 +377,8 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 				SpotLightQueueElement* el = result.m_spotLights.newElement(alloc);
 				SpotLightQueueElement* el = result.m_spotLights.newElement(alloc);
 				lc->setupSpotLightQueueElement(*el);
 				lc->setupSpotLightQueueElement(*el);
 
 
-				if(lc->getShadowEnabled())
+				if(lc->getShadowEnabled()
+					&& testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::SPOT_LIGHT_SHADOWS_ENABLED))
 				{
 				{
 					RenderQueue* a = alloc.newInstance<RenderQueue>();
 					RenderQueue* a = alloc.newInstance<RenderQueue>();
 					nextQueues = WeakArray<RenderQueue>(a, 1);
 					nextQueues = WeakArray<RenderQueue>(a, 1);
@@ -416,16 +398,31 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			{
 			{
 				ANKI_ASSERT(lc->getShadowEnabled() == true && "Only with shadow for now");
 				ANKI_ASSERT(lc->getShadowEnabled() == true && "Only with shadow for now");
 
 
-				const U cascadeCount = lc->getShadowCascadeCount();
-				ANKI_ASSERT(cascadeCount > 0 && cascadeCount <= MAX_SHADOW_CASCADES);
+				U cascadeCount;
+				if(testedFrc.visibilityTestsEnabled(
+					   FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE))
+				{
+					cascadeCount = 1;
+				}
+				else if(testedFrc.visibilityTestsEnabled(
+							FrustumComponentVisibilityTestFlag::DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES))
+				{
+					cascadeCount = MAX_SHADOW_CASCADES;
+				}
+				else
+				{
+					cascadeCount = 0;
+				}
+				ANKI_ASSERT(cascadeCount <= MAX_SHADOW_CASCADES);
 
 
 				WeakArray<OrthographicFrustum> cascadeFrustums(
 				WeakArray<OrthographicFrustum> cascadeFrustums(
-					alloc.newArray<OrthographicFrustum>(cascadeCount), cascadeCount);
+					(cascadeCount) ? alloc.newArray<OrthographicFrustum>(cascadeCount) : nullptr, cascadeCount);
 
 
 				lc->setupDirectionalLightQueueElement(
 				lc->setupDirectionalLightQueueElement(
 					testedFrc.getFrustum(), result.m_directionalLight, cascadeFrustums);
 					testedFrc.getFrustum(), result.m_directionalLight, cascadeFrustums);
 
 
-				nextQueues = WeakArray<RenderQueue>(alloc.newArray<RenderQueue>(cascadeCount), cascadeCount);
+				nextQueues = WeakArray<RenderQueue>(
+					(cascadeCount) ? alloc.newArray<RenderQueue>(cascadeCount) : nullptr, cascadeCount);
 				for(U i = 0; i < cascadeCount; ++i)
 				for(U i = 0; i < cascadeCount; ++i)
 				{
 				{
 					result.m_directionalLight.m_shadowRenderQueues[i] = &nextQueues[i];
 					result.m_directionalLight.m_shadowRenderQueues[i] = &nextQueues[i];
@@ -437,8 +434,10 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 				result.m_directionalLight.m_uuid = testedNode.getUuid();
 				result.m_directionalLight.m_uuid = testedNode.getUuid();
 
 
 				// Create some dummy frustum components and manually update them
 				// Create some dummy frustum components and manually update them
-				FrustumComponent* cascadeFrustumComponents = reinterpret_cast<FrustumComponent*>(
-					alloc.allocate(cascadeCount * sizeof(FrustumComponent), alignof(FrustumComponent)));
+				FrustumComponent* cascadeFrustumComponents =
+					(cascadeCount) ? reinterpret_cast<FrustumComponent*>(alloc.allocate(
+										 cascadeCount * sizeof(FrustumComponent), alignof(FrustumComponent)))
+								   : nullptr;
 				for(U i = 0; i < cascadeCount; ++i)
 				for(U i = 0; i < cascadeCount; ++i)
 				{
 				{
 					::new(&cascadeFrustumComponents[i]) FrustumComponent(&node, &cascadeFrustums[i]);
 					::new(&cascadeFrustumComponents[i]) FrustumComponent(&node, &cascadeFrustums[i]);
@@ -590,7 +589,7 @@ void CombineResultsTask::combine()
 
 
 	for(U i = 0; i < threadCount; ++i)
 	for(U i = 0; i < threadCount; ++i)
 	{
 	{
-		if(m_frcCtx->m_queueViews[i].m_directionalLight.m_shadowCascadeCount > 0)
+		if(m_frcCtx->m_queueViews[i].m_directionalLight.m_uuid != 0)
 		{
 		{
 			results.m_directionalLight = m_frcCtx->m_queueViews[i].m_directionalLight;
 			results.m_directionalLight = m_frcCtx->m_queueViews[i].m_directionalLight;
 		}
 		}

+ 25 - 15
src/anki/scene/components/FrustumComponent.h

@@ -25,16 +25,26 @@ enum class FrustumComponentVisibilityTestFlag : U16
 	RENDER_COMPONENTS = 1 << 0,
 	RENDER_COMPONENTS = 1 << 0,
 	LIGHT_COMPONENTS = 1 << 1,
 	LIGHT_COMPONENTS = 1 << 1,
 	LENS_FLARE_COMPONENTS = 1 << 2,
 	LENS_FLARE_COMPONENTS = 1 << 2,
-	SHADOW_CASTERS = 1 << 3,
-	REFLECTION_PROBES = 1 << 4,
-	REFLECTION_PROXIES = 1 << 5,
-	OCCLUDERS = 1 << 6,
-	DECALS = 1 << 7,
-	FOG_DENSITY_COMPONENTS = 1 << 8,
-	EARLY_Z = 1 << 9,
-
-	ALL_TESTS = RENDER_COMPONENTS | LIGHT_COMPONENTS | LENS_FLARE_COMPONENTS | SHADOW_CASTERS | REFLECTION_PROBES
-				| REFLECTION_PROXIES | DECALS | FOG_DENSITY_COMPONENTS | EARLY_Z
+	SHADOW_CASTERS = 1 << 3, ///< Render components that cast shadow
+	POINT_LIGHT_SHADOWS_ENABLED = 1 << 4,
+	SPOT_LIGHT_SHADOWS_ENABLED = 1 << 5,
+	DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES = 1 << 6,
+	DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE = 1 << 7,
+	REFLECTION_PROBES = 1 << 8,
+	REFLECTION_PROXIES = 1 << 9,
+	OCCLUDERS = 1 << 10,
+	DECALS = 1 << 11,
+	FOG_DENSITY_COMPONENTS = 1 << 12,
+	EARLY_Z = 1 << 13,
+
+	LAST = EARLY_Z,
+
+	ALL = RENDER_COMPONENTS | LIGHT_COMPONENTS | LENS_FLARE_COMPONENTS | SHADOW_CASTERS | POINT_LIGHT_SHADOWS_ENABLED
+		  | SPOT_LIGHT_SHADOWS_ENABLED | DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES | DIRECTIONAL_LIGHT_SHADOWS_1_CASCADE
+		  | REFLECTION_PROBES | REFLECTION_PROXIES | OCCLUDERS | DECALS | FOG_DENSITY_COMPONENTS | EARLY_Z,
+
+	ALL_SHADOWS_ENABLED =
+		POINT_LIGHT_SHADOWS_ENABLED | SPOT_LIGHT_SHADOWS_ENABLED | DIRECTIONAL_LIGHT_SHADOWS_ALL_CASCADES
 };
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(FrustumComponentVisibilityTestFlag, inline)
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(FrustumComponentVisibilityTestFlag, inline)
 
 
@@ -132,7 +142,7 @@ public:
 
 
 	void setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag bits)
 	void setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag bits)
 	{
 	{
-		m_flags.unset(FrustumComponentVisibilityTestFlag::ALL_TESTS);
+		m_flags.unset(FrustumComponentVisibilityTestFlag::ALL);
 		m_flags.set(bits, true);
 		m_flags.set(bits, true);
 
 
 #if ANKI_ASSERTS_ENABLED
 #if ANKI_ASSERTS_ENABLED
@@ -155,7 +165,7 @@ public:
 
 
 	Bool anyVisibilityTestEnabled() const
 	Bool anyVisibilityTestEnabled() const
 	{
 	{
-		return m_flags.getAny(FrustumComponentVisibilityTestFlag::ALL_TESTS);
+		return m_flags.getAny(FrustumComponentVisibilityTestFlag::ALL);
 	}
 	}
 
 
 	/// The type is FillCoverageBufferCallback.
 	/// The type is FillCoverageBufferCallback.
@@ -182,10 +192,10 @@ public:
 	}
 	}
 
 
 private:
 private:
-	enum Flags
+	enum Flags : U16
 	{
 	{
-		SHAPE_MARKED_FOR_UPDATE = 1 << 10,
-		TRANSFORM_MARKED_FOR_UPDATE = 1 << 12,
+		SHAPE_MARKED_FOR_UPDATE = static_cast<U16>(FrustumComponentVisibilityTestFlag::LAST) << 1,
+		TRANSFORM_MARKED_FOR_UPDATE = static_cast<U16>(FrustumComponentVisibilityTestFlag::LAST) << 2,
 	};
 	};
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flags, friend)
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flags, friend)
 
 

+ 16 - 8
src/anki/scene/components/LightComponent.cpp

@@ -32,7 +32,7 @@ LightComponent::LightComponent(LightComponentType type, U64 uuid)
 		m_spot.m_textureMat = Mat4::getIdentity();
 		m_spot.m_textureMat = Mat4::getIdentity();
 		break;
 		break;
 	case LightComponentType::DIRECTIONAL:
 	case LightComponentType::DIRECTIONAL:
-		m_dir.m_cascadeCount = MAX_SHADOW_CASCADES;
+		m_dir.m_sceneAabbMaxZLightSpace = MIN_F32;
 		break;
 		break;
 	default:
 	default:
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
@@ -99,15 +99,23 @@ void LightComponent::setupDirectionalLightQueueElement(
 	const Frustum& frustum, DirectionalLightQueueElement& el, WeakArray<OrthographicFrustum> cascadeFrustums) const
 	const Frustum& frustum, DirectionalLightQueueElement& el, WeakArray<OrthographicFrustum> cascadeFrustums) const
 {
 {
 	ANKI_ASSERT(m_type == LightComponentType::DIRECTIONAL);
 	ANKI_ASSERT(m_type == LightComponentType::DIRECTIONAL);
+	ANKI_ASSERT(cascadeFrustums.getSize() <= MAX_SHADOW_CASCADES);
+
+	const U shadowCascadeCount = cascadeFrustums.getSize();
 
 
 	el.m_userData = this;
 	el.m_userData = this;
 	el.m_drawCallback = derectionalLightDebugDrawCallback;
 	el.m_drawCallback = derectionalLightDebugDrawCallback;
 	el.m_uuid = m_uuid;
 	el.m_uuid = m_uuid;
 	el.m_diffuseColor = m_diffColor.xyz();
 	el.m_diffuseColor = m_diffColor.xyz();
 	el.m_direction = m_trf.getRotation().getZAxis().xyz();
 	el.m_direction = m_trf.getRotation().getZAxis().xyz();
-	el.m_shadowCascadeCount = m_dir.m_cascadeCount;
+	el.m_shadowCascadeCount = shadowCascadeCount;
+
+	// Compute the texture matrices
+	if(shadowCascadeCount == 0)
+	{
+		return;
+	}
 
 
-	// Compute sub frustum edges
 	const Mat4 lightTrf(m_trf);
 	const Mat4 lightTrf(m_trf);
 	const Mat4 lightViewMat(lightTrf.getInverse());
 	const Mat4 lightViewMat(lightTrf.getInverse());
 	if(frustum.getType() == FrustumType::PERSPECTIVE)
 	if(frustum.getType() == FrustumType::PERSPECTIVE)
@@ -120,12 +128,12 @@ void LightComponent::setupDirectionalLightQueueElement(
 
 
 		// Gather the edges
 		// Gather the edges
 		Array<Vec4, (MAX_SHADOW_CASCADES + 1) * 4> edgesLocalSpaceStorage;
 		Array<Vec4, (MAX_SHADOW_CASCADES + 1) * 4> edgesLocalSpaceStorage;
-		WeakArray<Vec4> edgesLocalSpace(&edgesLocalSpaceStorage[0], (m_dir.m_cascadeCount + 1) * 4);
+		WeakArray<Vec4> edgesLocalSpace(&edgesLocalSpaceStorage[0], (shadowCascadeCount + 1) * 4);
 		edgesLocalSpace[0] = edgesLocalSpace[1] = edgesLocalSpace[2] = edgesLocalSpace[3] =
 		edgesLocalSpace[0] = edgesLocalSpace[1] = edgesLocalSpace[2] = edgesLocalSpace[3] =
 			Vec4(0.0f, 0.0f, 0.0f, 1.0f); // Eye
 			Vec4(0.0f, 0.0f, 0.0f, 1.0f); // Eye
-		for(U i = 0; i < m_dir.m_cascadeCount; ++i)
+		for(U i = 0; i < shadowCascadeCount; ++i)
 		{
 		{
-			const F32 cascadeFarNearDist = far / F32(m_dir.m_cascadeCount);
+			const F32 cascadeFarNearDist = far / F32(shadowCascadeCount);
 			const F32 cascadeFar = F32(i + 1) * cascadeFarNearDist;
 			const F32 cascadeFar = F32(i + 1) * cascadeFarNearDist;
 
 
 			const F32 x = cascadeFar * tan(fovY / 2.0f) * fovX / fovY;
 			const F32 x = cascadeFar * tan(fovY / 2.0f) * fovX / fovY;
@@ -150,7 +158,7 @@ void LightComponent::setupDirectionalLightQueueElement(
 
 
 		// Compute the min max per cascade
 		// Compute the min max per cascade
 		Array2d<Vec3, MAX_SHADOW_CASCADES, 2> minMaxes;
 		Array2d<Vec3, MAX_SHADOW_CASCADES, 2> minMaxes;
-		for(U i = 0; i < m_dir.m_cascadeCount; ++i)
+		for(U i = 0; i < shadowCascadeCount; ++i)
 		{
 		{
 			Vec3 aabbMin(MAX_F32);
 			Vec3 aabbMin(MAX_F32);
 			Vec3 aabbMax(MIN_F32);
 			Vec3 aabbMax(MIN_F32);
@@ -177,7 +185,7 @@ void LightComponent::setupDirectionalLightQueueElement(
 		}
 		}
 
 
 		// Compute the view and projection matrices per cascade
 		// Compute the view and projection matrices per cascade
-		for(U i = 0; i < m_dir.m_cascadeCount; ++i)
+		for(U i = 0; i < shadowCascadeCount; ++i)
 		{
 		{
 			const Vec3& min = minMaxes[i][0];
 			const Vec3& min = minMaxes[i][0];
 			const Vec3& max = minMaxes[i][1];
 			const Vec3& max = minMaxes[i][1];

+ 1 - 8
src/anki/scene/components/LightComponent.h

@@ -122,12 +122,6 @@ public:
 		m_flags.set(SHADOW, x);
 		m_flags.set(SHADOW, x);
 	}
 	}
 
 
-	U32 getShadowCascadeCount() const
-	{
-		ANKI_ASSERT(m_type == LightComponentType::DIRECTIONAL);
-		return m_dir.m_cascadeCount;
-	}
-
 	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 
 	void setupPointLightQueueElement(PointLightQueueElement& el) const
 	void setupPointLightQueueElement(PointLightQueueElement& el) const
@@ -158,7 +152,7 @@ public:
 	/// Setup a directional queue element.
 	/// Setup a directional queue element.
 	/// @param[in] frustum The frustum that is looking that directional light. Used to calculate the cascades.
 	/// @param[in] frustum The frustum that is looking that directional light. Used to calculate the cascades.
 	/// @param[out] el The queue element to fill out.
 	/// @param[out] el The queue element to fill out.
-	/// @param[out] cascadeFrustums Fill those frustums as well.
+	/// @param[out] cascadeFrustums Fill those frustums as well. The size of this array is the count of the cascades.
 	void setupDirectionalLightQueueElement(
 	void setupDirectionalLightQueueElement(
 		const Frustum& frustum, DirectionalLightQueueElement& el, WeakArray<OrthographicFrustum> cascadeFrustums) const;
 		const Frustum& frustum, DirectionalLightQueueElement& el, WeakArray<OrthographicFrustum> cascadeFrustums) const;
 
 
@@ -184,7 +178,6 @@ private:
 
 
 	struct Dir
 	struct Dir
 	{
 	{
-		U32 m_cascadeCount;
 		F32 m_sceneAabbMaxZLightSpace;
 		F32 m_sceneAabbMaxZLightSpace;
 	};
 	};