Quellcode durchsuchen

Making the rendering of multimeshes more elegant. Need to sort them as well

Panagiotis Christopoulos Charitos vor 12 Jahren
Ursprung
Commit
f93304d6b0

+ 6 - 2
include/anki/renderer/Drawer.h

@@ -32,8 +32,12 @@ public:
 	void prepareDraw()
 	{}
 
-	void render(SceneNode& frsn,
-		RenderingStage stage, U32 pass, SceneNode& renderableSceneNode);
+	void render(
+		SceneNode& frsn,
+		RenderingStage stage, 
+		U32 pass, 
+		SceneNode& renderableSceneNode,
+		U64 subSpatialsMask);
 
 private:
 	Renderer* r;

+ 1 - 28
include/anki/scene/Renderable.h

@@ -195,44 +195,17 @@ public:
 		return getRenderableModelPatchBase().getSubMeshesCount();
 	}
 
-	/// Set the visibility mask of submeshes. This is called on visibility tests
-	void setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask);
-
-	/// Get the mask to render only the needed submeshess. Called on rendering
-	U64 getVisibleSubMeshesMask(const SceneNode& frustumable) const;
-
 	/// Reset on frame start
 	void resetFrame()
-	{
-		perframe = nullptr;
-	}
+	{}
 
 protected:
 	/// The derived class needs to call that
 	void init(PropertyMap& pmap);
 
 private:
-	struct FrustumableMaskPair
-	{
-		const SceneNode* frustumable;
-		U64 mask;
-	};
-
-	/// Per frame data
-	struct PerFrame
-	{
-		PerFrame(const SceneAllocator<U8>& frameAlloc)
-			: pairs(frameAlloc)
-		{
-			pairs.reserve(3);
-		}
-
-		SceneFrameVector<FrustumableMaskPair> pairs;
-	};
-
 	RenderableVariables vars;
 	Ubo ubo;
-	PerFrame* perframe;
 	std::mutex mtx;
 };
 /// @}

+ 38 - 10
include/anki/scene/Visibility.h

@@ -32,10 +32,33 @@ enum VisibleBy
 	VB_LIGHT = 1 << 1
 };
 
+/// Visible node pointer with some more info
+struct VisibleNode
+{
+	SceneNode* node;
+	U64 subSpatialsMask; ///< The mask of the subspatials
+
+	VisibleNode()
+		: node(nullptr), subSpatialsMask(0)
+	{}
+
+	VisibleNode(SceneNode* node_, U64 subSpatialsMask_)
+		: node(node_), subSpatialsMask(subSpatialsMask_)
+	{
+		ANKI_ASSERT(node);
+	}
+
+	VisibleNode(const VisibleNode& other)
+		: node(other.node), subSpatialsMask(other.subSpatialsMask)
+	{
+		ANKI_ASSERT(node);
+	}
+};
+
 /// Its actually a container for visible entities. It should be per frame
 struct VisibilityTestResults
 {
-	typedef SceneFrameVector<SceneNode*> Container;
+	typedef SceneFrameVector<VisibleNode> Container;
 
 	Container renderables;
 	Container lights;
@@ -79,14 +102,17 @@ struct DistanceSortFunctor
 {
 	Vec3 origin;
 
-	Bool operator()(SceneNode* a, SceneNode* b)
+	Bool operator()(const VisibleNode& a, const VisibleNode& b)
 	{
-		ANKI_ASSERT(a->getSpatial() != nullptr && b->getSpatial() != nullptr);
+		ANKI_ASSERT(a.node && b.node);
+
+		ANKI_ASSERT(a.node->getSpatial() != nullptr 
+			&& b.node->getSpatial() != nullptr);
 
 		F32 dist0 = origin.getDistanceSquared(
-			a->getSpatial()->getSpatialOrigin());
+			a.node->getSpatial()->getSpatialOrigin());
 		F32 dist1 = origin.getDistanceSquared(
-			b->getSpatial()->getSpatialOrigin());
+			b.node->getSpatial()->getSpatialOrigin());
 
 		return dist0 < dist1;
 	}
@@ -95,13 +121,15 @@ struct DistanceSortFunctor
 /// Sort renderable scene nodes on material
 struct MaterialSortFunctor
 {
-	Bool operator()(SceneNode* a, SceneNode* b)
+	Bool operator()(const VisibleNode& a, const VisibleNode& b)
 	{
-		ANKI_ASSERT(a->getRenderable() != nullptr 
-			&& b->getRenderable() != nullptr);
+		ANKI_ASSERT(a.node && b.node);
+
+		ANKI_ASSERT(a.node->getRenderable() != nullptr 
+			&& b.node->getRenderable() != nullptr);
 
-		return a->getRenderable()->getRenderableMaterial()
-			< b->getRenderable()->getRenderableMaterial();
+		return a.node->getRenderable()->getRenderableMaterial()
+			< b.node->getRenderable()->getRenderableMaterial();
 	}
 };
 

+ 1 - 1
src/renderer/Bs.cpp

@@ -31,7 +31,7 @@ void Bs::run()
 		++it)
 	{
 		drawer.render(scene.getActiveCamera(), RenderableDrawer::RS_BLEND,
-			0, *(*it));
+			0, *(*it).node, (*it).subSpatialsMask);
 	}
 
 	GlStateSingleton::get().setDepthMaskEnabled(true);

+ 4 - 6
src/renderer/Drawer.cpp

@@ -224,7 +224,7 @@ void RenderableDrawer::setupShaderProg(const PassLevelKey& key_,
 
 //==============================================================================
 void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
-	U32 pass, SceneNode& rsn)
+	U32 pass, SceneNode& rsn, U64 subSpatialsMask)
 {
 	ANKI_ASSERT(frsn.getFrustumable());
 	Frustumable& fr = *frsn.getFrustumable();
@@ -284,18 +284,16 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 
 	U32 primCount = 1;
 
-	if(renderable->getSubMeshesCount() == 0)
+	if(subSpatialsMask == 0)
 	{
 		renderable->getRenderableModelPatchBase().getRenderingData(
 			key, vao, prog, indicesCountArray[0]);
 	}
 	else
 	{
-		U64 mask = renderable->getVisibleSubMeshesMask(frsn);
-
 		renderable->getRenderableModelPatchBase().getRenderingDataSub(
-			key, mask, vao, prog, indicesCountArray, indicesOffsetArray,
-			primCount);
+			key, subSpatialsMask, vao, prog, indicesCountArray, 
+			indicesOffsetArray, primCount);
 	}
 
 	// Setup shader

+ 1 - 1
src/renderer/Ez.cpp

@@ -35,7 +35,7 @@ void Ez::run()
 		it != vi.getRenderablesEnd() && count < maxObjectsToDraw; ++it)
 	{
 		r->getSceneDrawer().render(cam, RenderableDrawer::RS_MATERIAL,
-			0, *(*it));
+			0, *(*it).node, (*it).subSpatialsMask);
 		++count;
 	}
 

+ 2 - 2
src/renderer/Is.cpp

@@ -175,7 +175,7 @@ struct WriteLightsJob: ThreadJob
 		// Run all lights
 		for(U64 i = start; i < end; i++)
 		{
-			const SceneNode* snode = *(lightsBegin + i);
+			const SceneNode* snode = (*(lightsBegin + i)).node;
 			const Light* light = snode->getLight();
 			ANKI_ASSERT(light);
 
@@ -602,7 +602,7 @@ void Is::lightPass()
 
 	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
 	{
-		Light* light = (*it)->getLight();
+		Light* light = (*it).node->getLight();
 		ANKI_ASSERT(light);
 		switch(light->getLightType())
 		{

+ 2 - 1
src/renderer/Ms.cpp

@@ -79,7 +79,8 @@ void Ms::run()
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{
 		r->getSceneDrawer().render(r->getSceneGraph().getActiveCamera(),
-			RenderableDrawer::RS_MATERIAL, 0, *(*it));
+			RenderableDrawer::RS_MATERIAL, 0, *(*it).node, 
+			(*it).subSpatialsMask);
 	}
 
 	// restore depth

+ 2 - 2
src/renderer/Sm.cpp

@@ -164,7 +164,7 @@ Sm::Shadowmap* Sm::doLight(Light& light)
 
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{
-		SceneNode* node = *it;
+		SceneNode* node = (*it).node;
 		Frustumable* bfr = node->getFrustumable();
 		Movable* bmov = node->getMovable();
 		Spatial* sp = node->getSpatial();
@@ -207,7 +207,7 @@ Sm::Shadowmap* Sm::doLight(Light& light)
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{
 		r->getSceneDrawer().render(light, RenderableDrawer::RS_MATERIAL,
-			1, *(*it));
+			1, *(*it).node, (*it).subSpatialsMask);
 	}
 
 	return &sm;

+ 2 - 2
src/scene/Octree.cpp

@@ -318,14 +318,14 @@ void Octree::doVisibilityTestsInternal(SceneNode& fsn,
 				if(!((test & VT_ONLY_SHADOW_CASTERS) == true
 					&& !r->getRenderableMaterial().getShadow()))
 				{
-					visible.renderables.push_back(sn);
+					//visible.renderables.push_back(VisibleNode(sn, 0));
 				}
 			}
 
 			Light* l = sn->getLight();
 			if(l != nullptr && (test & VT_LIGHTS))
 			{
-				visible.lights.push_back(sn);
+				//visible.lights.push_back(VisibleNode(sn, 0));
 			}
 		}
 	}

+ 0 - 36
src/scene/Renderable.cpp

@@ -133,40 +133,4 @@ void Renderable::init(PropertyMap& pmap)
 	}
 }
 
-//==============================================================================
-void Renderable::setVisibleSubMeshesMask(const SceneNode* frustumable, U64 mask)
-{
-	ANKI_ASSERT(frustumable && mask != 0);
-	mtx.lock();
-
-	if(ANKI_UNLIKELY(perframe == nullptr))
-	{
-		perframe = ANKI_NEW(PerFrame, frustumable->getSceneFrameAllocator(),
-			frustumable->getSceneFrameAllocator());
-	}
-
-	perframe->pairs.push_back(FrustumableMaskPair{frustumable, mask});
-
-	mtx.unlock();
-}
-
-//==============================================================================
-U64 Renderable::getVisibleSubMeshesMask(const SceneNode& frustumable) const
-{
-	ANKI_ASSERT(perframe);
-
-	SceneFrameVector<FrustumableMaskPair>::const_iterator it =
-		perframe->pairs.begin();
-	for(; it != perframe->pairs.end(); it++)
-	{
-		if(it->frustumable == &frustumable)
-		{
-			return it->mask;
-		}
-	}
-
-	ANKI_ASSERT(0 && "Shouldn't have come to this");
-	return 0;
-}
-
 }  // end namespace anki

+ 6 - 6
src/scene/Sector.cpp

@@ -333,7 +333,7 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 		for(VisibilityTestResults& testResult : testResults)
 		{
 			// First the renderables
-			for(SceneNode* renderable : testResult.renderables)
+			for(VisibleNode& renderable : testResult.renderables)
 			{
 				/*XXX if(r->getTiler().test2(
 					renderable->getSpatial()->getOptimalCollisionShape()))*/
@@ -343,7 +343,7 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 			}
 
 			// Then the lights
-			for(SceneNode* light : testResult.lights)
+			for(VisibleNode& light : testResult.lights)
 			{
 				/*XXX if(r->doVisibilityTests(
 					light->getSpatial()->getOptimalCollisionShape()))*/
@@ -387,16 +387,16 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 	// Continue by testing the lights
 	//
 
-	for(SceneNode* lsn : visible->lights)
+	for(VisibleNode& lsn : visible->lights)
 	{
-		Light* l = lsn->getLight();
+		Light* l = lsn.node->getLight();
 		ANKI_ASSERT(l != nullptr);
 
 		if(l->getShadowEnabled())
 		{
-			ANKI_ASSERT(lsn->getFrustumable() != nullptr);
+			ANKI_ASSERT(lsn.node->getFrustumable() != nullptr);
 
-			doVisibilityTestsInternal(*lsn,
+			doVisibilityTestsInternal(*lsn.node,
 				(VisibilityTest)(VT_RENDERABLES | VT_ONLY_SHADOW_CASTERS),
 				nullptr, VB_LIGHT);
 		}

+ 10 - 21
src/scene/Visibility.cpp

@@ -69,6 +69,7 @@ struct VisibilityTestJob: ThreadJob
 
 			if(ANKI_UNLIKELY(i > 0 && subSpatialsMask == 0))
 			{
+				// The camera is looking something in between all submeshes
 				continue;
 			}
 
@@ -76,21 +77,15 @@ struct VisibilityTestJob: ThreadJob
 			Renderable* r = node->getRenderable();
 			if(r)
 			{
-				visible->renderables.push_back(node);
-
-				// Inform the renderable for the mask
-				if(subSpatialsMask)
-				{
-					ANKI_ASSERT(r->getSubMeshesCount() > 0);
-					r->setVisibleSubMeshesMask(frustumableSn, subSpatialsMask);
-				}
+				visible->renderables.push_back(
+					VisibleNode(node, subSpatialsMask));
 			}
 			else
 			{
 				Light* l = node->getLight();
 				if(l)
 				{
-					visible->lights.push_back(node);
+					visible->lights.push_back(VisibleNode(node, 0));
 
 					if(l->getShadowEnabled() && fr)
 					{
@@ -167,14 +162,8 @@ struct VisibilityTestJob: ThreadJob
 			Renderable* r = node->getRenderable();
 			if(r)
 			{
-				lvisible->renderables.push_back(node);
-
-				// Inform the renderable for the mask
-				if(subSpatialsMask)
-				{
-					ANKI_ASSERT(r->getSubMeshesCount() > 0);
-					r->setVisibleSubMeshesMask(&lightSn, subSpatialsMask);
-				}
+				lvisible->renderables.push_back(
+					VisibleNode(node, subSpatialsMask));
 			}
 		}
 	}
@@ -226,8 +215,8 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 		renderablesSize, 
 		lightsSize);
 
-	visible->renderables.resize(renderablesSize, nullptr);
-	visible->lights.resize(lightsSize, nullptr);
+	visible->renderables.resize(renderablesSize);
+	visible->lights.resize(lightsSize);
 
 	// Append thread results
 	renderablesSize = 0;
@@ -238,13 +227,13 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 
 		memcpy(&visible->renderables[renderablesSize],
 			&from.renderables[0],
-			sizeof(SceneNode*) * from.renderables.size());
+			sizeof(VisibleNode) * from.renderables.size());
 
 		renderablesSize += from.renderables.size();
 
 		memcpy(&visible->lights[lightsSize],
 			&from.lights[0],
-			sizeof(SceneNode*) * from.lights.size());
+			sizeof(VisibleNode) * from.lights.size());
 
 		lightsSize += from.lights.size();
 	}

+ 0 - 2
tools/2anki/Main.cpp

@@ -51,8 +51,6 @@ std::string replaceAllString(const std::string& str, const std::string& from,
 //==============================================================================
 std::string getFilename(const std::string& path)
 {
-	assert(path);
-
 	std::string out;
 
 	const size_t last = path.find_last_of("/");