ソースを参照

Particles + Instancing

Panagiotis Christopoulos Charitos 13 年 前
コミット
132cd5158c

+ 6 - 0
include/anki/resource/Material.h

@@ -88,6 +88,12 @@ public:
 	/// Get the name of all the shader program variables
 	const std::string& getName() const;
 
+	const ShaderProgramUniformVariable&
+		getAShaderProgramUniformVariable() const
+	{
+		return *oneSProgVar;
+	}
+
 	/// If false then it should be buildin
 	virtual Bool hasValue() const = 0;
 	/// @}

+ 4 - 4
include/anki/scene/ParticleEmitter.h

@@ -111,10 +111,10 @@ public:
 	/// Implements  Renderable::getMaterial
 	const Material& getRenderableMaterial() const;
 
-	/// Overrides Renderable::getRenderableInstancingTranslations
-	virtual const Vec3* getRenderableInstancingTranslations() const
+	/// Overrides Renderable::getRenderableInstancingTransformations
+	virtual const Transform* getRenderableInstancingWorldTransforms() const
 	{
-		return &instancintPositions[0];
+		return &instancingTransformations[0];
 	}
 
 	virtual U32 getRenderableInstancesCount() const
@@ -144,7 +144,7 @@ private:
 
 	U32 instancesCount; ///< AKA alive count
 
-	Vector<Vec3> instancintPositions;
+	Vector<Transform> instancingTransformations;
 
 	void init(const char* filename, Scene* scene);
 

+ 2 - 8
include/anki/scene/Renderable.h

@@ -21,9 +21,8 @@ enum BuildinMaterialVariableId
 	BMV_MODEL_VIEW_PROJECTION_MATRIX,
 	BMV_MODEL_VIEW_MATRIX,
 	BMV_NORMAL_MATRIX,
-	BMV_BLURRING,
-	BMV_INSTANCING_TRANSLATIONS,
 	BMV_INSTANCING_MODEL_VIEW_PROJECTION_MATRICES,
+	BMV_BLURRING,
 	BMV_COUNT
 };
 
@@ -83,11 +82,6 @@ public:
 	/// @name Instancing methods
 	/// @{
 
-	virtual const Vec3* getRenderableInstancingTranslations() const
-	{
-		return nullptr;
-	}
-
 	virtual const Transform* getRenderableInstancingWorldTransforms() const
 	{
 		return nullptr;
@@ -95,7 +89,7 @@ public:
 
 	virtual U32 getRenderableInstancesCount() const
 	{
-		return 0;
+		return 1;
 	}
 	/// @}
 

+ 2 - 0
shaders/MaterialFragmentCommon.glsl

@@ -0,0 +1,2 @@
+#pragma anki include "shaders/MaterialFragmentVariables.glsl"
+#pragma anki include "shaders/MaterialFragmentFunctions.glsl"

+ 25 - 15
src/gl/ShaderProgram.cpp

@@ -53,61 +53,61 @@ void ShaderProgramUniformVariable::set(const Vec2& x) const
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const F32 x[], uint size) const
+void ShaderProgramUniformVariable::set(const F32 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 	
 	glUniform1fv(getLocation(), size, x);
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Vec2 x[], uint size) const
+void ShaderProgramUniformVariable::set(const Vec2 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 
 	glUniform2fv(getLocation(), size, &(const_cast<Vec2&>(x[0]))[0]);
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Vec3 x[], uint size) const
+void ShaderProgramUniformVariable::set(const Vec3 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC3);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 
 	glUniform3fv(getLocation(), size, &(const_cast<Vec3&>(x[0]))[0]);
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Vec4 x[], uint size) const
+void ShaderProgramUniformVariable::set(const Vec4 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC4);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 	
 	glUniform4fv(getLocation(), size, &(const_cast<Vec4&>(x[0]))[0]);
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Mat3 x[], uint size) const
+void ShaderProgramUniformVariable::set(const Mat3 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT3);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 
 	glUniformMatrix3fv(getLocation(), size, true, &(x[0])[0]);
 }
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Mat4 x[], uint size) const
+void ShaderProgramUniformVariable::set(const Mat4 x[], U32 size) const
 {
 	doCommonSetCode();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT4);
-	ANKI_ASSERT(getSize() == size);
+	ANKI_ASSERT(size <= getSize());
 
 	glUniformMatrix4fv(getLocation(), size, true, &(x[0])[0]);
 }
@@ -647,10 +647,20 @@ void ShaderProgram::initUniAndAttribVars()
 		// overpopulate the uniforms vector and hash map. So, to solve this if 
 		// the uniform name has something like this "[N]" where N != 0 then 
 		// ignore the uniform and put it as array
-		if(strchr(&name_[0], '[') != nullptr 
-			&& strstr(&name_[0], "[0]") == nullptr)
+		if(strchr(&name_[0], '[') != nullptr)
 		{
-			continue;
+			// Found bracket
+
+			if(strstr(&name_[0], "[0]") == nullptr)
+			{
+				// Found something other than "[0]"
+				continue;
+			}
+			else
+			{
+				// Cut the bracket stuff
+				name_[length - 3] = '\0';
+			}
 		}
 
 		ShaderProgramUniformVariable& var = unis[unisCount++];

+ 1 - 1
src/physics/RigidBody.cpp

@@ -29,7 +29,7 @@ RigidBody::RigidBody(PhysWorld* masterContainer_, const Initializer& init,
 		localInertia = btVector3(0.0, 0.0, 0.0);
 	}
 
-	motionState = MotionState(init.startTrf, init.movable);
+	motionState = MotionState(init.startTrf, movable);
 
 	btRigidBody::btRigidBodyConstructionInfo cInfo(
 		init.mass, &motionState, init.shape, localInertia);

+ 1 - 1
src/renderer/Dbg.cpp

@@ -73,7 +73,7 @@ void Dbg::run()
 		sceneDrawer->draw(sector->getOctree());
 	}
 
-	/*scene.getPhysics().debugDraw();*/
+	scene.getPhysics().debugDraw();
 
 	drawer->flush();
 }

+ 30 - 21
src/renderer/Drawer.cpp

@@ -46,7 +46,6 @@ struct SetupMaterialVariableVisitor
 
 		Mat4 mMat = (rwtrf) ? Mat4(*rwtrf) : Mat4::getIdentity();
 		const Mat4& vpMat = fr->getViewProjectionMatrix();
-		Mat4 mvpMat = vpMat * mMat;
 
 		Mat4 mvMat;
 		Bool mvMatCalculated = false; // Opt
@@ -57,7 +56,10 @@ struct SetupMaterialVariableVisitor
 			uniSet(*uni, x);
 			break;
 		case BMV_MODEL_VIEW_PROJECTION_MATRIX:
-			uniSet(*uni, mvpMat);
+			{
+				Mat4 mvpMat = vpMat * mMat;
+				uniSet(*uni, mvpMat);
+			}
 			break;
 		case BMV_MODEL_VIEW_MATRIX:
 			if(!mvMatCalculated)
@@ -75,6 +77,24 @@ struct SetupMaterialVariableVisitor
 			}
 			uniSet(*uni, mvMat.getRotationPart());
 			break;
+		case BMV_INSTANCING_MODEL_VIEW_PROJECTION_MATRICES:
+			{
+				U32 instancesCount = renderable->getRenderableInstancesCount();
+
+				Array<Mat4, 64> mvps;
+				ANKI_ASSERT(mvps.getSize() >= instancesCount);
+				const Transform* trfs =
+					renderable->getRenderableInstancingWorldTransforms();
+				ANKI_ASSERT(trfs != nullptr);
+
+				for(U i = 0; i < instancesCount; i++)
+				{
+					mvps[i] = vpMat * Mat4(trfs[0]);
+				}
+
+				uni->set(&mvps[0], instancesCount);
+			}
+			break;
 		case BMV_BLURRING:
 			uniSet(*uni, 0.0);
 			break;
@@ -157,22 +177,6 @@ void RenderableDrawer::setupShaderProg(
 		renderable.getUbo().write(&vis.clientBlock[0]);
 		renderable.getUbo().setBinding(0);
 	}
-
-	// Write the instancing blocks
-#if 0
-	U32 instancesCount = renderable.getRenderableInstancesCount();
-	const Vec3* translations = renderable.getRenderableInstancingTranslations();
-	if(translations)
-	{
-		ShaderProgramUniformBlock& block = 
-			sprog.findUniformBlock("instancingTranslations");
-		ANKI_ASSERT(block.getBinding() == 1);
-
-		Ubo& ubo = renderable.getInstancingUbo();
-		ubo.write(translations, instancesCount * sizeof(Vec3), 0);
-		ubo.setBinding(1);
-	}
-#endif
 }
 
 //==============================================================================
@@ -183,6 +187,13 @@ void RenderableDrawer::render(const Frustumable& fr, U32 pass,
 		cam.getWorldTransform().getOrigin()).getLength();
 	uint lod = std::min(r.calculateLod(dist), mtl.getLevelsOfDetail() - 1);*/
 
+	U32 instancesCount = renderable.getRenderableInstancesCount();
+
+	if(instancesCount < 1)
+	{
+		return;
+	}
+
 	PassLevelKey key(pass, 0);
 
 	// Setup shader
@@ -196,9 +207,7 @@ void RenderableDrawer::render(const Frustumable& fr, U32 pass,
 	ANKI_ASSERT(vao.getAttachmentsCount() > 1);
 	vao.bind();
 
-	U32 instancesCount = renderable.getRenderableInstancesCount();
-
-	if(instancesCount == 0)
+	if(instancesCount == 1)
 	{
 		glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_SHORT, 0);
 	}

+ 2 - 2
src/resource/ParticleEmitterResource.cpp

@@ -54,10 +54,10 @@ void ParticleEmitterResource::load(const char* /*filename*/)
 	startingPos = Vec3(0.0, 1.0, 0.0);
 	startingPosDeviation = Vec3(0.0, 0.0, 0.0);
 	size = 0.5;
-	maxNumOfParticles = 50;
+	maxNumOfParticles = 16;
 	emissionPeriod = 1.0;
 	particlesPerEmittion = 1;
-	model.load("data/models/horse/horse.mdl");
+	model.load("data/particles/fire/fire.mdl");
 
 	// sanity checks
 	//

+ 16 - 7
src/scene/ParticleEmitter.cpp

@@ -144,30 +144,39 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	//
 	Vec3 aabbmin(std::numeric_limits<F32>::max());
 	Vec3 aabbmax(std::numeric_limits<F32>::min());
-	instancesCount = 0;
-	instancintPositions.clear();
+	instancingTransformations.clear();
 	for(Particle* p : particles)
 	{
 		// if its already dead so dont deactivate it again
 		if(!p->isDead() && p->getTimeOfDeath() < crntTime)
 		{
-			//cout << "Killing " << i << " " << p.timeOfDeath << endl;
 			p->setActivationState(DISABLE_SIMULATION);
 			p->setTimeOfDeath(-1.0);
-
+		}
+		else
+		{
 			const Vec3& origin = p->Movable::getWorldTransform().getOrigin();
+
 			for(U i = 0; i < 3; i++)
 			{
 				aabbmin[i] = std::min(aabbmin[i], origin[i]);
 				aabbmax[i] = std::max(aabbmax[i], origin[i]);
 			}
 
-			++instancesCount;
-			instancintPositions.push_back(origin);
+			instancingTransformations.push_back(
+				p->Movable::getWorldTransform());
 		}
 	}
 
-	aabb = Aabb(aabbmin, aabbmax);
+	instancesCount = instancingTransformations.size();
+	if(instancesCount != 0)
+	{
+		aabb = Aabb(aabbmin - size, aabbmax + size);
+	}
+	else
+	{
+		aabb = Aabb(Vec3(0.0), Vec3(0.01));
+	}
 	spatialMarkUpdated();
 
 	// pre calculate

+ 9 - 19
src/scene/Renderable.cpp

@@ -38,10 +38,8 @@ static Array<const char*, BMV_COUNT - 1> buildinNames = {{
 	"modelViewProjectionMat",
 	"modelViewMat",
 	"normalMat",
-	"blurring",
-	"instancingTranslations",
-	"instancingModelViewProjectionMatrices"
-}};
+	"instancingModelViewProjectionMatrices",
+	"blurring"}};
 
 //==============================================================================
 RenderableMaterialVariable::RenderableMaterialVariable(
@@ -104,24 +102,16 @@ void Renderable::init(PropertyMap& pmap)
 		ubo.create(block->getSize(), nullptr);
 	}
 
-	// Init the instancing UBO
-#if 0
-	const ShaderProgram* aprog = mtl.getShaderPrograms()[0].get();
+	// Instancing sanity checks
 	U32 instancesCount = getRenderableInstancesCount();
-	
-	const ShaderProrgamUniformBlock* block = 
-		aprog->tryFindUniformBlock("instancesTranslations");
-	if(block)
-	{
-		if(instancesCount < 1)
-		{
-			throw ANKI_EXCEPTION("The shader program implies multiple "
-				"instances but the object has zero");
-		}
+	const MaterialVariable* mv =
+		mtl.findVariableByName("instancingModelViewProjectionMatrices");
 
-		instancingUbo.create(instancesCount * sizeof(Vec3), nullptr);
+	if(mv && mv->getAShaderProgramUniformVariable().getSize() < instancesCount)
+	{
+		throw ANKI_EXCEPTION("The renderable needs more instances that the "
+			"shader program can handle");
 	}
-#endif
 }
 
 }  // end namespace anki

+ 7 - 0
testapp/Main.cpp

@@ -35,6 +35,7 @@
 #include "anki/core/Timestamp.h"
 #include "anki/core/NativeWindow.h"
 #include "anki/util/Functions.h"
+#include "anki/scene/ParticleEmitter.h"
 
 using namespace anki;
 
@@ -67,6 +68,7 @@ void initPhysics()
 
 	new RigidBody(&SceneSingleton::get().getPhysics(), init);
 
+#if 0
 	btCollisionShape* colShape = new btBoxShape(
 	    btVector3(1, 1, 1));
 
@@ -114,6 +116,7 @@ void initPhysics()
 			}
 		}
 	}
+#endif
 }
 
 //==============================================================================
@@ -244,6 +247,10 @@ void init()
 #endif
 
 	initPhysics();
+
+	ParticleEmitter* pe = new ParticleEmitter("todo", "pe", &scene,
+		Movable::MF_NONE, nullptr);
+	(void)pe;
 }
 
 //==============================================================================