Panagiotis Christopoulos Charitos пре 13 година
родитељ
комит
193ac0ee8d

+ 1 - 1
include/anki/renderer/Drawer.h

@@ -32,7 +32,7 @@ public:
 	void prepareDraw()
 	{}
 
-	void render(Frustumable& fr,
+	void render(SceneNode& frsn,
 		RenderingStage stage, U32 pass, SceneNode& renderableSceneNode);
 
 private:

+ 2 - 1
include/anki/resource/Model.h

@@ -66,7 +66,8 @@ public:
 	/// Get information for multiDraw rendering
 	void getRenderingDataSub(const PassLevelKey& key, U64 subMeshesMask,
 		const Vao*& vao, const ShaderProgram*& prog,
-		U32* indicesCountArray, U32* indicesOffsetArray, U32& primcount) const;
+		U32* indicesCountArray, void** indicesOffsetArray, 
+		U32& primcount) const;
 
 protected:
 	struct

+ 40 - 5
include/anki/scene/Spatial.h

@@ -32,17 +32,25 @@ public:
 		SF_VISIBLE_CAMERA = 1 << 1,
 		SF_VISIBLE_LIGHT = 1 << 2,
 		/// Visible or not. The visibility tester sets it
-		SF_VISIBLE_ANY = SF_VISIBLE_CAMERA | SF_VISIBLE_LIGHT
+		SF_VISIBLE_ANY = SF_VISIBLE_CAMERA | SF_VISIBLE_LIGHT,
+
+		/// This is used for example in lights. If the light does not collide 
+		/// with any surface then it shouldn't be visible and be processed 
+		/// further. This flag is being used to check if we should test agains
+		/// near plane when using the tiler for visibility tests.
+		SF_FULLY_TRANSPARENT = 1 << 3
 	};
 
 	/// Pass the collision shape here so we can avoid the virtuals
-	Spatial(const CollisionShape* cs)
+	Spatial(const CollisionShape* cs, const SceneAllocator<U8>& alloc,
+		U32 flags = SF_NONE)
+		: spatialProtected(cs, alloc)
 	{
-		spatialProtected.spatialCs = cs;
+		enableFlags(flags);
 	}
 
 	// Remove from current OctreeNode
-	~Spatial();
+	virtual ~Spatial();
 
 	/// @name Accessors
 	/// @{
@@ -90,6 +98,27 @@ public:
 	{
 		return octreeNode;
 	}
+
+	SceneVector<Spatial*>::iterator getSubSpatialsBegin()
+	{
+		return spatialProtected.subSpatials.begin();
+	}
+	SceneVector<Spatial*>::const_iterator getSubSpatialsBegin() const
+	{
+		return spatialProtected.subSpatials.begin();
+	}
+	SceneVector<Spatial*>::iterator getSubSpatialsEnd()
+	{
+		return spatialProtected.subSpatials.end();
+	}
+	SceneVector<Spatial*>::const_iterator getSubSpatialsEnd() const
+	{
+		return spatialProtected.subSpatials.end();
+	}
+	PtrSize getSubSpatialsCount() const
+	{
+		return spatialProtected.subSpatials.size();
+	}
 	/// @}
 
 	/// The derived class has to manually set when the collision shape got
@@ -102,9 +131,15 @@ public:
 	}
 
 protected:
-	struct
+	struct SpatialProtected
 	{
+		SpatialProtected(const CollisionShape* spatialCs_, 
+			const SceneAllocator<U8>& alloc)
+			: spatialCs(spatialCs_), subSpatials(alloc)
+		{}
+
 		const CollisionShape* spatialCs = nullptr;
+		SceneVector<Spatial*> subSpatials;
 	} spatialProtected;
 
 private:

+ 2 - 4
include/anki/scene/StaticGeometryNode.h

@@ -12,13 +12,12 @@ namespace anki {
 /// @{
 
 /// Part of the static geometry. Used only for visibility tests
-class StaticGeometrySpatialNode: public SceneNode, public Spatial
+class StaticGeometrySpatial: public Spatial
 {
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	StaticGeometrySpatialNode(const Obb& obb,
-		const char* name, SceneGraph* scene); // Scene
+	StaticGeometrySpatial(const Obb& obb, const SceneAllocator<U8>& alloc);
 	/// @}
 };
 
@@ -53,7 +52,6 @@ public:
 
 private:
 	const ModelPatchBase* modelPatch;
-	SceneVector<StaticGeometrySpatialNode*> spatials;
 };
 
 /// Static geometry scene node

+ 3 - 3
include/anki/util/Memory.h

@@ -62,6 +62,9 @@ public:
 	void reset();
 
 private:
+	/// Alignment of allocations
+	U32 alignmentBytes;
+
 	/// Pre-allocated memory chunk
 	U8* memory = nullptr;
 
@@ -71,9 +74,6 @@ private:
 	/// Points to the memory and more specifically to the top of the stack
 	std::atomic<U8*> top = {nullptr};
 
-	/// Alignment of allocations
-	U32 alignmentBits;
-
 	/// Calculate tha aligned size of an allocation
 	PtrSize calcAlignSize(PtrSize size) const;
 };

+ 40 - 6
src/renderer/Drawer.cpp

@@ -211,9 +211,11 @@ void RenderableDrawer::setupShaderProg(const PassLevelKey& key_,
 }
 
 //==============================================================================
-void RenderableDrawer::render(Frustumable& fr, RenderingStage stage,
+void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	U32 pass, SceneNode& rsn)
 {
+	ANKI_ASSERT(frsn.getFrustumable());
+	Frustumable& fr = *frsn.getFrustumable();
 	Renderable* renderable = rsn.getRenderable();
 	ANKI_ASSERT(renderable);
 
@@ -261,10 +263,23 @@ void RenderableDrawer::render(Frustumable& fr, RenderingStage stage,
 	// Get rendering useful stuff
 	const ShaderProgram* prog;
 	const Vao* vao;
-	U32 indicesCount;
+	U32 indicesCountArray[64];
+	void* indicesOffsetArray[64];
+	U32 primCount = 1;
 
-	renderable->getRenderableModelPatchBase().getRenderingData(
-		key, vao, prog, indicesCount);
+	if(renderable->getSubMeshesCount() == 0)
+	{
+		renderable->getRenderableModelPatchBase().getRenderingData(
+			key, vao, prog, indicesCountArray[0]);
+	}
+	else
+	{
+		U64 mask = renderable->getVisibleSubMeshsMask(frsn);
+
+		renderable->getRenderableModelPatchBase().getRenderingDataSub(
+			key, mask, vao, prog, indicesCountArray, indicesOffsetArray,
+			primCount);
+	}
 
 	// Setup shader
 	setupShaderProg(key, fr, *prog, *renderable);
@@ -275,12 +290,31 @@ void RenderableDrawer::render(Frustumable& fr, RenderingStage stage,
 
 	if(instancesCount == 1)
 	{
-		glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, 0);
+		if(primCount == 1)
+		{
+			glDrawElements(
+				GL_TRIANGLES, 
+				indicesCountArray[0], 
+				GL_UNSIGNED_SHORT, 
+				0);
+		}
+		else
+		{
+			glMultiDrawElements(GL_TRIANGLES, 
+				(GLsizei*)indicesCountArray, 
+				GL_UNSIGNED_SHORT, 
+				(const void**)indicesOffsetArray, 
+				primCount);
+		}
 	}
 	else
 	{
 		glDrawElementsInstanced(
-			GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, 0, instancesCount);
+			GL_TRIANGLES, 
+			indicesCountArray[0], 
+			GL_UNSIGNED_SHORT, 
+			0, 
+			instancesCount);
 	}
 }
 

+ 1 - 1
src/renderer/Sm.cpp

@@ -205,7 +205,7 @@ Sm::Shadowmap* Sm::doLight(Light& light)
 
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{
-		r->getSceneDrawer().render(*fr, RenderableDrawer::RS_MATERIAL,
+		r->getSceneDrawer().render(light, RenderableDrawer::RS_MATERIAL,
 			1, *(*it));
 	}
 

+ 14 - 2
src/resource/Model.cpp

@@ -109,7 +109,7 @@ void ModelPatchBase::getRenderingData(const PassLevelKey& key, const Vao*& vao,
 //==============================================================================
 void ModelPatchBase::getRenderingDataSub(const PassLevelKey& key,
 	U64 subMeshesMask, const Vao*& vao, const ShaderProgram*& prog,
-	U32* indicesCountArray, U32* indicesOffsetArray, U32& primcount) const
+	U32* indicesCountArray, void** indicesOffsetArray, U32& primcount) const
 {
 	const U meshLods = getMeshesCount();
 	ANKI_ASSERT(meshLods > 0);
@@ -144,11 +144,23 @@ void ModelPatchBase::getRenderingDataSub(const PassLevelKey& key,
 	{
 		if(subMeshesMask & (1 << i))
 		{
+			U32 tmp;
 			indicesCountArray[primcount] =
-				meshBase.getIndicesCountSub(i, indicesOffsetArray[primcount]);
+				meshBase.getIndicesCountSub(i, tmp);
+
+			indicesOffsetArray[primcount] = 
+				reinterpret_cast<void*>((PtrSize)tmp);
 			++primcount;
 		}
 	}
+
+	// If all submeshes are covered by the mask then return the super mesh
+	if(primcount == subMeshesCount)
+	{
+		indicesCountArray[0] = meshBase.getIndicesCount();
+		indicesOffsetArray[0] = 0;
+		primcount = 1;
+	}
 }
 
 //==============================================================================

+ 1 - 1
src/scene/Camera.cpp

@@ -13,7 +13,7 @@ Camera::Camera(CameraType type_,
 	Frustum* frustum) // Spatial & Frustumable
 	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
-		Spatial(frustum),
+		Spatial(frustum, getSceneAllocator()),
 		Frustumable(frustum),
 		type(type_)
 {

+ 2 - 2
src/scene/Light.cpp

@@ -11,9 +11,9 @@ Light::Light(LightType t, // Light
 	const char* name, SceneGraph* scene, // Scene
 	U32 movableFlags, Movable* movParent, // Movable
 	CollisionShape* cs) // Spatial
-	: SceneNode(name, scene),
+	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
-		Spatial(cs),
+		Spatial(cs, getSceneAllocator()),
 		type(t)
 {
 	sceneNodeProtected.movable = this;

+ 2 - 1
src/scene/ModelNode.cpp

@@ -15,7 +15,8 @@ ModelPatchNode::ModelPatchNode(const ModelPatchBase *modelPatch_,
 	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		Renderable(getSceneAllocator()),
-		Spatial(&obb), modelPatch(modelPatch_)
+		Spatial(&obb, getSceneAllocator()), 
+		modelPatch(modelPatch_)
 {
 	sceneNodeProtected.movable = this;
 	sceneNodeProtected.renderable = this;

+ 1 - 1
src/scene/ParticleEmitter.cpp

@@ -228,7 +228,7 @@ ParticleEmitter::ParticleEmitter(
 	// Movable
 	U32 movableFlags, Movable* movParent)
 	:	SceneNode(name, scene),
-		Spatial(&aabb),
+		Spatial(&aabb, getSceneAllocator()),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		Renderable(getSceneAllocator()),
 		particles(getSceneAllocator())

+ 1 - 1
src/scene/SkinNode.cpp

@@ -132,7 +132,7 @@ SkinPatchNode::SkinPatchNode(const ModelPatchBase* modelPatch_,
 	: 	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		Renderable(getSceneAllocator()),
-		Spatial(spatialCs)
+		Spatial(spatialCs, getSceneAllocator())
 {
 	sceneNodeProtected.movable = this;
 	sceneNodeProtected.renderable = this;

+ 13 - 17
src/scene/StaticGeometryNode.cpp

@@ -4,16 +4,14 @@
 namespace anki {
 
 //==============================================================================
-// StaticGeometrySpatialNode                                                   =
+// StaticGeometrySpatial                                                       =
 //==============================================================================
 
 //==============================================================================
-StaticGeometrySpatialNode::StaticGeometrySpatialNode(const Obb& obb,
-	const char* name, SceneGraph* scene)
-	: SceneNode(name, scene), Spatial(&obb)
-{
-	sceneNodeProtected.spatial = this;
-}
+StaticGeometrySpatial::StaticGeometrySpatial(const Obb& obb,
+	const SceneAllocator<U8>& alloc)
+	: Spatial(&obb, alloc)
+{}
 
 //==============================================================================
 // StaticGeometryPatchNode                                                     =
@@ -23,7 +21,7 @@ StaticGeometrySpatialNode::StaticGeometrySpatialNode(const Obb& obb,
 StaticGeometryPatchNode::StaticGeometryPatchNode(
 	const ModelPatchBase* modelPatch_, const char* name, SceneGraph* scene)
 	:	SceneNode(name, scene),
-		Spatial(&modelPatch->getBoundingShape()),
+		Spatial(&modelPatch->getBoundingShape(), getSceneAllocator()),
 		Renderable(getSceneAllocator()),
 		modelPatch(modelPatch_)
 {
@@ -36,17 +34,15 @@ StaticGeometryPatchNode::StaticGeometryPatchNode(
 	// For all submeshes create a StaticGeometrySp[atialNode
 	if(modelPatch->getSubMeshesCount() > 1)
 	{
-		spatials.reserve(modelPatch->getSubMeshesCount());
+		spatialProtected.subSpatials.resize(modelPatch->getSubMeshesCount());
 
 		for(U i = 0; i < modelPatch->getSubMeshesCount(); i++)
 		{
-			std::string aName = name + std::to_string(i);
-
-			StaticGeometrySpatialNode* node =
-				ANKI_NEW(StaticGeometrySpatialNode, getSceneAllocator(),
-				modelPatch->getBoundingShapeSub(i), aName.c_str(), scene);
+			StaticGeometrySpatial* spatial =
+				ANKI_NEW(StaticGeometrySpatial, getSceneAllocator(),
+				modelPatch->getBoundingShapeSub(i), getSceneAllocator());
 
-			spatials.push_back(node);
+			spatialProtected.subSpatials[i] = spatial;
 		}
 	}
 }
@@ -54,9 +50,9 @@ StaticGeometryPatchNode::StaticGeometryPatchNode(
 //==============================================================================
 StaticGeometryPatchNode::~StaticGeometryPatchNode()
 {
-	for(StaticGeometrySpatialNode* node : spatials)
+	for(Spatial* spatial : spatialProtected.subSpatials)
 	{
-		ANKI_DELETE(node, getSceneAllocator());
+		ANKI_DELETE(spatial, getSceneAllocator());
 	}
 }
 

+ 23 - 0
src/scene/Visibility.cpp

@@ -47,6 +47,22 @@ struct VisibilityTestJob: ThreadJob
 				continue;
 			}
 
+			// Hierarchical spatial => check subspatials
+			U64 subSpatialsMask = 0;
+			for(auto it = sp->getSubSpatialsEnd() - 1; 
+				it >= sp->getSubSpatialsBegin(); --it)
+			{
+				Spatial* subsp = *it;
+
+				subSpatialsMask <<= 1;
+	
+				if(frustumable->insideFrustum(*subsp))
+				{
+					subSpatialsMask |= 1; 
+				}
+			}
+
+			// renderable
 			Renderable* r = node->getRenderable();
 			if(r)
 			{
@@ -56,6 +72,13 @@ struct VisibilityTestJob: ThreadJob
 					continue;
 				}
 				visible->renderables.push_back(node);
+
+				// Inform the renderable for the mask
+				if(subSpatialsMask)
+				{
+					ANKI_ASSERT(r->getSubMeshesCount() > 0);
+					r->setVisibleSubMeshesMask(node, subSpatialsMask);
+				}
 			}
 			else
 			{

+ 4 - 4
src/util/Memory.cpp

@@ -14,8 +14,8 @@ struct MemoryBlockHeader
 };
 
 //==============================================================================
-StackMemoryPool::StackMemoryPool(PtrSize size_, U32 alignmentBits_)
-	: memsize(size_), alignmentBits(alignmentBits_)
+StackMemoryPool::StackMemoryPool(PtrSize size, U32 alignmentBits)
+	: alignmentBytes(alignmentBits / 8), memsize(calcAlignSize(size))
 {
 	ANKI_ASSERT(memsize > 0);
 	memory = (U8*)::malloc(memsize);
@@ -50,7 +50,7 @@ StackMemoryPool& StackMemoryPool::operator=(StackMemoryPool&& other)
 	memory = other.memory;
 	memsize = other.memsize;
 	top.store(other.top.load());
-	alignmentBits = other.alignmentBits;
+	alignmentBytes = other.alignmentBytes;
 
 	other.memory = nullptr;
 	other.memsize = 0;
@@ -142,7 +142,7 @@ void StackMemoryPool::reset()
 //==============================================================================
 PtrSize StackMemoryPool::calcAlignSize(PtrSize size) const
 {
-	return size + (size % (alignmentBits / 8));
+	return size + alignmentBytes - (size % alignmentBytes);
 }
 
 } // end namespace anki