Browse Source

Port the physics sample to the new material

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
b60f66c490

BIN
samples/physics_playground/assets/Icosphere.ankimesh


BIN
samples/physics_playground/assets/Suzanne.ankimesh


+ 10 - 16
samples/physics_playground/assets/dynamic-material.ankimtl

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ExporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.glslp">
+<material shaderProgram="shaders/GBufferGeneric.ankiprog">
 
-	<mutators>
+	<mutation>
 		<mutator name="DIFFUSE_TEX" value="0"/>
 		<mutator name="SPECULAR_TEX" value="0"/>
 		<mutator name="ROUGHNESS_TEX" value="0"/>
@@ -10,22 +10,16 @@
 		<mutator name="NORMAL_TEX" value="0"/>
 		<mutator name="PARALLAX" value="0"/>
 		<mutator name="EMISSIVE_TEX" value="0"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
-		
+		<input shaderVar="m_diffColor" value="0.078310 0.218610 0.640000"/>
+		<input shaderVar="m_specColor" value="0.400000 0.400000 0.400000"/>
+		<input shaderVar="m_roughness" value="0.000000" />
+		<input shaderVar="m_metallic" value="1.000000"/>
+
+		<input shaderVar="m_emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderVar="m_subsurface" value="0.000000"/>
 
-		<input shaderInput="diffColor" value="0.078310 0.218610 0.640000"/>
-		<input shaderInput="specColor" value="0.400000 0.400000 0.400000"/>
-		<input shaderInput="roughness" value="0.000000" />
-		<input shaderInput="metallic" value="1.000000"/>
-		
-		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
-		<input shaderInput="subsurface" value="0.000000"/>
-		
 	</inputs>
 </material>

+ 9 - 13
samples/physics_playground/assets/dynamic.ankimtl

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ImporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.glslp">
-	<mutators>
+<material shaderProgram="shaders/GBufferGeneric.ankiprog">
+	<mutation>
 		<mutator name="DIFFUSE_TEX" value="0"/>
 		<mutator name="SPECULAR_TEX" value="0"/>
 		<mutator name="ROUGHNESS_TEX" value="0"/>
@@ -9,22 +9,18 @@
 		<mutator name="NORMAL_TEX" value="0"/>
 		<mutator name="PARALLAX" value="0"/>
 		<mutator name="EMISSIVE_TEX" value="0"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
 		
 
-		<input shaderInput="diffColor" value="0.097887 0.273263 0.800000"/>
-		<input shaderInput="specColor" value="0.040000 0.040000 0.040000"/>
-		<input shaderInput="roughness" value="0.000000" />
-		<input shaderInput="metallic" value="0.609091" />
+		<input shaderVar="m_diffColor" value="0.097887 0.273263 0.800000"/>
+		<input shaderVar="m_specColor" value="0.040000 0.040000 0.040000"/>
+		<input shaderVar="m_roughness" value="0.000000"/>
+		<input shaderVar="m_metallic" value="0.609091"/>
 		
-		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
-		<input shaderInput="subsurface" value="0.000000"/>
+		<input shaderVar="m_emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderVar="m_subsurface" value="0.000000"/>
 		
 	</inputs>
 </material>

BIN
samples/physics_playground/assets/floor.ankimesh


+ 7 - 7
samples/physics_playground/assets/gpu_sparks.ankimtl

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<material shaderProgram="shaders/GpuParticles.glslp" shadow="0">
+<material shaderProgram="shaders/GBufferGpuParticles.ankiprog" shadow="0">
 	<inputs>
-		<input shaderInput="diffColor" value="1.0 0.1 0.1"/>
-		<input shaderInput="specColor" value="0.04 0.04 0.04"/>
-		<input shaderInput="roughness" value="9.0"/>
-		<input shaderInput="metallic" value="0.0"/>
-		<input shaderInput="initialEmission" value="1024 1024 1024"/>
-		<input shaderInput="finalEmission" value="10 10 10"/>
+		<input shaderVar="m_diffColor" value="1.0 0.1 0.1"/>
+		<input shaderVar="m_specColor" value="0.04 0.04 0.04"/>
+		<input shaderVar="m_roughness" value="9.0"/>
+		<input shaderVar="m_metallic" value="0.0"/>
+		<input shaderVar="m_initialEmission" value="1024 1024 1024"/>
+		<input shaderVar="m_finalEmission" value="10 10 10"/>
 	</inputs>
 </material>
 

+ 9 - 13
samples/physics_playground/assets/sky.ankimtl

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ImporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.glslp">
-	<mutators>
+<material shaderProgram="shaders/GBufferGeneric.ankiprog">
+	<mutation>
 		<mutator name="DIFFUSE_TEX" value="0"/>
 		<mutator name="SPECULAR_TEX" value="0"/>
 		<mutator name="ROUGHNESS_TEX" value="0"/>
@@ -9,22 +9,18 @@
 		<mutator name="NORMAL_TEX" value="0"/>
 		<mutator name="PARALLAX" value="0"/>
 		<mutator name="EMISSIVE_TEX" value="0"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
 		
 
-		<input shaderInput="diffColor" value="0.015215 0.459168 0.800000"/>
-		<input shaderInput="specColor" value="0.040000 0.040000 0.040000"/>
-		<input shaderInput="roughness" value="0.500000" />
-		<input shaderInput="metallic" value="0.000000" />
+		<input shaderVar="m_diffColor" value="0.015215 0.459168 0.800000"/>
+		<input shaderVar="m_specColor" value="0.040000 0.040000 0.040000"/>
+		<input shaderVar="m_roughness" value="0.500000"/>
+		<input shaderVar="m_metallic" value="0.000000"/>
 		
-		<input shaderInput="emission" value="0.110506 0.266543 1.000000"/>
-		<input shaderInput="subsurface" value="0.000000"/>
+		<input shaderVar="m_emission" value="0.110506 0.266543 1.000000"/>
+		<input shaderVar="m_subsurface" value="0.000000"/>
 		
 	</inputs>
 </material>

+ 6 - 10
samples/physics_playground/assets/smoke.ankimtl

@@ -1,18 +1,14 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<material shaderProgram="shaders/ForwardShadingParticles.glslp" forwardShading="1" shadow="0">
-	<mutators>
+<material shaderProgram="shaders/ForwardShadingParticles.ankiprog" forwardShading="1" shadow="0">
+	<mutation>
 		<mutator name="ANIMATED_TEXTURE" value="0"/>
 		<mutator name="LIGHT" value="1"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="cameraRotMat" builtin="CAMERA_ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
-
-		<input shaderInput="diffuseMap" value="assets/smoke.ankitex"/>
-		<input shaderInput="colorScale" value="1.0 1.0 1.0 1.0"/>
-		<input shaderInput="colorBias" value="0 0 0 0"/>
+		<input shaderVar="u_diffuseMap" value="assets/smoke.ankitex"/>
+		<input shaderVar="m_colorScale" value="1.0 1.0 1.0 1.0"/>
+		<input shaderVar="m_colorBias" value="0 0 0 0"/>
 	</inputs>
 </material>
 

BIN
samples/physics_playground/assets/wall.ankimesh


+ 10 - 14
samples/physics_playground/assets/walls.001.ankimtl

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ImporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.glslp">
-	<mutators>
+<material shaderProgram="shaders/GBufferGeneric.ankiprog">
+	<mutation>
 		<mutator name="DIFFUSE_TEX" value="1"/>
 		<mutator name="SPECULAR_TEX" value="0"/>
 		<mutator name="ROUGHNESS_TEX" value="1"/>
@@ -9,22 +9,18 @@
 		<mutator name="NORMAL_TEX" value="1"/>
 		<mutator name="PARALLAX" value="0"/>
 		<mutator name="EMISSIVE_TEX" value="0"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
 		
 
-		<input shaderInput="diffTex" value="assets/Stone_Wall_007_COLOR.ankitex"/>
-		<input shaderInput="specColor" value="0.040000 0.040000 0.040000"/>
-		<input shaderInput="roughnessTex" value="assets/Stone_Wall_007_ROUGH.ankitex"/>
-		<input shaderInput="metallic" value="0.000000" />
-		<input shaderInput="normalTex" value="assets/Stone_Wall_007_NORM.ankitex"/>
-		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
-		<input shaderInput="subsurface" value="0.000000"/>
+		<input shaderVar="u_diffTex" value="assets/Stone_Wall_007_COLOR.ankitex"/>
+		<input shaderVar="m_specColor" value="0.040000 0.040000 0.040000"/>
+		<input shaderVar="u_roughnessTex" value="assets/Stone_Wall_007_ROUGH.ankitex"/>
+		<input shaderVar="m_metallic" value="0.000000"/>
+		<input shaderVar="u_normalTex" value="assets/Stone_Wall_007_NORM.ankitex"/>
+		<input shaderVar="m_emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderVar="m_subsurface" value="0.000000"/>
 		
 	</inputs>
 </material>

BIN
samples/physics_playground/assets/walls.ankimesh


+ 10 - 14
samples/physics_playground/assets/walls.ankimtl

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!-- This file is auto generated by ImporterMaterial.cpp -->
-<material shaderProgram="shaders/GBufferGeneric.glslp">
-	<mutators>
+<material shaderProgram="shaders/GBufferGeneric.ankiprog">
+	<mutation>
 		<mutator name="DIFFUSE_TEX" value="1"/>
 		<mutator name="SPECULAR_TEX" value="0"/>
 		<mutator name="ROUGHNESS_TEX" value="1"/>
@@ -9,22 +9,18 @@
 		<mutator name="NORMAL_TEX" value="1"/>
 		<mutator name="PARALLAX" value="0"/>
 		<mutator name="EMISSIVE_TEX" value="0"/>
-	</mutators>
+	</mutation>
 
 	<inputs>
-		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
-		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
-		<input shaderInput="globalSampler" builtin="GLOBAL_SAMPLER"/>
 		
 
-		<input shaderInput="diffTex" value="assets/Asphalt_004_COLOR.ankitex"/>
-		<input shaderInput="specColor" value="0.040000 0.040000 0.040000"/>
-		<input shaderInput="roughnessTex" value="assets/Asphalt_004_ROUGH.ankitex"/>
-		<input shaderInput="metallic" value="0.000000" />
-		<input shaderInput="normalTex" value="assets/Asphalt_004_NRM.ankitex"/>
-		<input shaderInput="emission" value="0.000000 0.000000 0.000000"/>
-		<input shaderInput="subsurface" value="0.000000"/>
+		<input shaderVar="u_diffTex" value="assets/Asphalt_004_COLOR.ankitex"/>
+		<input shaderVar="m_specColor" value="0.040000 0.040000 0.040000"/>
+		<input shaderVar="u_roughnessTex" value="assets/Asphalt_004_ROUGH.ankitex"/>
+		<input shaderVar="m_metallic" value="0.000000"/>
+		<input shaderVar="u_normalTex" value="assets/Asphalt_004_NRM.ankitex"/>
+		<input shaderVar="m_emission" value="0.000000 0.000000 0.000000"/>
+		<input shaderVar="m_subsurface" value="0.000000"/>
 		
 	</inputs>
 </material>

+ 11 - 5
shaders/ForwardShadingGpuParticles.ankiprog → shaders/GBufferGpuParticles.ankiprog

@@ -3,13 +3,14 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki mutator ANKI_PASS 0 2 3
+#pragma anki mutator ANKI_VELOCITY 0 1
+
 #include <shaders/glsl_cpp_common/GpuParticles.h>
 
 struct PerDraw
 {
 	Mat4 m_ankiMvp;
-	Vec3 m_minusCameraZ;
-	U32 m_particleCount;
 	Vec3 m_diffColor;
 	F32 m_roughness;
 	Vec3 m_specColor;
@@ -18,16 +19,21 @@ struct PerDraw
 	Vec3 m_finalEmission;
 };
 
-layout(set = 1, binding = 0, std140, row_major) uniform b_ankiMaterial
+layout(set = 0, binding = 0, std140, row_major) uniform b_ankiMaterial
 {
 	PerDraw u_ankiPerDraw;
 };
 
-layout(set = 0, binding = 0) buffer ssbo_
+layout(set = 0, binding = 1) buffer b_particles
 {
 	GpuParticle u_particles[];
 };
 
+layout(set = 0, binding = 2) uniform b_extra
+{
+	Vec3 u_minusCameraZ;
+};
+
 #pragma anki start vert
 
 #include <shaders/Common.glsl>
@@ -70,7 +76,7 @@ void main()
 {
 	GbufferInfo g;
 	g.m_diffuse = u_ankiPerDraw.m_diffColor;
-	g.m_normal = u_ankiPerDraw.m_minusCameraZ;
+	g.m_normal = u_minusCameraZ;
 	g.m_specular = u_ankiPerDraw.m_specColor;
 	g.m_roughness = u_ankiPerDraw.m_roughness;
 	g.m_subsurface = 0.0;

+ 24 - 7
src/anki/importer/GltfImporter.cpp

@@ -161,6 +161,7 @@ Error GltfImporter::init(CString inputFname,
 	Bool optimizeMeshes,
 	F32 lodFactor,
 	U32 lodCount,
+	F32 lightIntensityScale,
 	U32 threadCount)
 {
 	m_inputFname.create(inputFname);
@@ -169,6 +170,8 @@ Error GltfImporter::init(CString inputFname,
 	m_texrpath.create(texrpath);
 	m_optimizeMeshes = optimizeMeshes;
 
+	m_lightIntensityScale = clamp(lightIntensityScale, 0.1f, 1.0f);
+
 	m_lodCount = clamp(lodCount, 1u, 3u);
 	m_lodFactor = clamp(lodFactor, 0.0f, 1.0f);
 	if(m_lodFactor * F32(m_lodCount - 1) > 0.7f)
@@ -646,6 +649,7 @@ Error GltfImporter::visitNode(
 
 				// LOD 0
 				Error err = self.m_importer->writeMesh(*self.m_mesh, CString(), 1.0f);
+				U32 maxLod = 0;
 
 				// LOD 1
 				if(!err && self.m_lodCount > 1)
@@ -653,6 +657,7 @@ Error GltfImporter::visitNode(
 					StringAuto name(self.m_importer->m_alloc);
 					name.sprintf("%s_lod1", self.m_mesh->name);
 					err = self.m_importer->writeMesh(*self.m_mesh, name, 1.0f - self.m_lodFactor);
+					maxLod = 1;
 				}
 
 				// LOD 2
@@ -661,6 +666,7 @@ Error GltfImporter::visitNode(
 					StringAuto name(self.m_importer->m_alloc);
 					name.sprintf("%s_lod2", self.m_mesh->name);
 					err = self.m_importer->writeMesh(*self.m_mesh, name, 1.0f - self.m_lodFactor * 2.0f);
+					maxLod = 2;
 				}
 
 				if(!err)
@@ -680,7 +686,7 @@ Error GltfImporter::visitNode(
 
 				if(!err && self.m_selfCollision)
 				{
-					err = self.m_importer->writeCollisionMesh(*self.m_mesh);
+					err = self.m_importer->writeCollisionMesh(*self.m_mesh, maxLod);
 				}
 
 				if(err)
@@ -1037,7 +1043,7 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 	return Error::NONE;
 }
 
-Error GltfImporter::writeCollisionMesh(const cgltf_mesh& mesh)
+Error GltfImporter::writeCollisionMesh(const cgltf_mesh& mesh, U32 maxLod)
 {
 	StringAuto fname(m_alloc);
 	fname.sprintf("%s%s.ankicl", m_outDir.cstr(), mesh.name);
@@ -1049,10 +1055,21 @@ Error GltfImporter::writeCollisionMesh(const cgltf_mesh& mesh)
 
 	ANKI_CHECK(file.writeText("%s\n", XML_HEADER));
 
-	ANKI_CHECK(file.writeText("<collisionShape>\n\t<type>staticMesh</type>\n\t<value>"
-							  "%s%s_lod2.ankimesh</value>\n</collisionShape>\n",
-		m_rpath.cstr(),
-		mesh.name));
+	if(maxLod == 0)
+	{
+		ANKI_CHECK(file.writeText("<collisionShape>\n\t<type>staticMesh</type>\n\t<value>"
+								  "%s%s.ankimesh</value>\n</collisionShape>\n",
+			m_rpath.cstr(),
+			mesh.name));
+	}
+	else
+	{
+		ANKI_CHECK(file.writeText("<collisionShape>\n\t<type>staticMesh</type>\n\t<value>"
+								  "%s%s_lod%u.ankimesh</value>\n</collisionShape>\n",
+			m_rpath.cstr(),
+			mesh.name,
+			maxLod));
+	}
 
 	return Error::NONE;
 }
@@ -1088,7 +1105,7 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 
 	Vec3 color(light.color[0], light.color[1], light.color[2]);
 	color *= light.intensity;
-	color /= 100.0f; // Blender changed something
+	color *= m_lightIntensityScale;
 	ANKI_CHECK(
 		m_sceneFile.writeText("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
 

+ 4 - 2
src/anki/importer/GltfImporter.h

@@ -37,7 +37,8 @@ public:
 		Bool optimizeMeshes,
 		F32 lodFactor,
 		U32 lodCount,
-		U32 threadCount = MAX_U32);
+		F32 lightIntensityScale,
+		U32 threadCount);
 
 	ANKI_USE_RESULT Error writeAll();
 
@@ -75,6 +76,7 @@ private:
 
 	F32 m_lodFactor = 1.0f;
 	U32 m_lodCount = 1;
+	F32 m_lightIntensityScale = 1.0f;
 	Bool m_optimizeMeshes = false;
 
 	// Misc
@@ -100,7 +102,7 @@ private:
 	ANKI_USE_RESULT Error writeModel(const cgltf_mesh& mesh, CString skinName);
 	ANKI_USE_RESULT Error writeAnimation(const cgltf_animation& anim);
 	ANKI_USE_RESULT Error writeSkeleton(const cgltf_skin& skin);
-	ANKI_USE_RESULT Error writeCollisionMesh(const cgltf_mesh& mesh);
+	ANKI_USE_RESULT Error writeCollisionMesh(const cgltf_mesh& mesh, U32 maxLod);
 
 	// Scene
 	ANKI_USE_RESULT Error writeTransform(const Transform& trf);

+ 13 - 3
src/anki/resource/MaterialResource2.cpp

@@ -160,6 +160,9 @@ Error MaterialResource2::load(const ResourceFilename& filename, Bool async)
 		ANKI_CHECK(parseMutators(mutatorsEl));
 	}
 
+	// The rest of the mutators
+	ANKI_CHECK(findBuiltinMutators());
+
 	// <inputs>
 	ANKI_CHECK(rootEl.getChildElementOptional("inputs", el));
 	if(el)
@@ -243,9 +246,12 @@ Error MaterialResource2::parseMutators(XmlElement mutatorsEl)
 
 	ANKI_ASSERT(mutatorCount == m_nonBuiltinsMutation.getSize());
 
-	//
-	// Find the builtin mutators
-	//
+	return Error::NONE;
+}
+
+Error MaterialResource2::findBuiltinMutators()
+{
+	// INSTANCE_COUNT
 	U builtinMutatorCount = 0;
 
 	m_builtinMutators[BuiltinMutatorId2::INSTANCE_COUNT] =
@@ -273,6 +279,7 @@ Error MaterialResource2::parseMutators(XmlElement mutatorsEl)
 		++builtinMutatorCount;
 	}
 
+	// PASS
 	m_builtinMutators[BuiltinMutatorId2::PASS] = m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId2::PASS]);
 	if(m_builtinMutators[BuiltinMutatorId2::PASS] && m_forwardShading)
 	{
@@ -322,6 +329,7 @@ Error MaterialResource2::parseMutators(XmlElement mutatorsEl)
 		return Error::USER_DATA;
 	}
 
+	// LOD
 	m_builtinMutators[BuiltinMutatorId2::LOD] = m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId2::LOD]);
 	if(m_builtinMutators[BuiltinMutatorId2::LOD])
 	{
@@ -347,6 +355,7 @@ Error MaterialResource2::parseMutators(XmlElement mutatorsEl)
 		++builtinMutatorCount;
 	}
 
+	// BONES
 	m_builtinMutators[BuiltinMutatorId2::BONES] =
 		m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId2::BONES]);
 	if(m_builtinMutators[BuiltinMutatorId2::BONES])
@@ -395,6 +404,7 @@ Error MaterialResource2::parseMutators(XmlElement mutatorsEl)
 		}
 	}
 
+	// VELOCITY
 	m_builtinMutators[BuiltinMutatorId2::VELOCITY] =
 		m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId2::VELOCITY]);
 	if(m_builtinMutators[BuiltinMutatorId2::VELOCITY])

+ 1 - 0
src/anki/resource/MaterialResource2.h

@@ -384,6 +384,7 @@ private:
 	ANKI_USE_RESULT Error parseInputs(XmlElement inputsEl, Bool async);
 
 	ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl);
+	ANKI_USE_RESULT Error findBuiltinMutators();
 
 	static U32 getInstanceGroupIdx(U32 instanceCount);
 

+ 3 - 4
src/anki/resource/ParticleEmitterResource.cpp

@@ -141,11 +141,10 @@ Error ParticleEmitterResource::readVar(
 	return Error::NONE;
 }
 
-void ParticleEmitterResource::getRenderingInfo(U32 lod, ShaderProgramPtr& prog) const
+void ParticleEmitterResource::getRenderingInfo(const RenderingKey& key_, ShaderProgramPtr& prog) const
 {
-	lod = min<U32>(lod, m_lodCount - 1);
-
-	RenderingKey key(Pass::FS, U8(lod), 1, false, false);
+	RenderingKey key = key_;
+	key.setLod(min<U32>(key.getLod(), m_lodCount - 1));
 	const MaterialVariant2& variant = m_material->getOrCreateVariant(key);
 	prog = variant.getShaderProgram();
 }

+ 1 - 1
src/anki/resource/ParticleEmitterResource.h

@@ -111,7 +111,7 @@ public:
 	}
 
 	/// Get program for rendering.
-	void getRenderingInfo(U32 lod, ShaderProgramPtr& prog) const;
+	void getRenderingInfo(const RenderingKey& key, ShaderProgramPtr& prog) const;
 
 	/// Load it
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);

+ 1 - 0
src/anki/resource/ShaderProgramResource2.h

@@ -282,6 +282,7 @@ inline ShaderProgramResourceVariantInitInfo2& ShaderProgramResourceVariantInitIn
 {
 	const ShaderProgramResourceMutator2* m = m_ptr->tryFindMutator(name);
 	ANKI_ASSERT(m);
+	ANKI_ASSERT(m->valueExists(t));
 	const PtrSize mutatorIdx = m - m_ptr->getMutators().getBegin();
 	m_mutation[mutatorIdx] = t;
 	m_setMutators.set(mutatorIdx);

+ 15 - 14
src/anki/scene/GpuParticleEmitterNode.cpp

@@ -216,23 +216,24 @@ void GpuParticleEmitterNode::draw(RenderQueueDrawContext& ctx) const
 	{
 		// Program
 		ShaderProgramPtr prog;
-		m_emitterRsrc->getRenderingInfo(ctx.m_key.getLod(), prog);
+		m_emitterRsrc->getRenderingInfo(ctx.m_key, prog);
 		cmdb->bindShaderProgram(prog);
 
 		// Resources
-		cmdb->bindStorageBuffer(0, 0, m_particlesBuff, 0, MAX_PTR_SIZE);
-
-		struct PC
-		{
-			Mat4 m_mvp;
-			Vec3 m_minusCameraZ;
-			U32 m_particleCount;
-		} pc;
-
-		pc.m_mvp = ctx.m_viewProjectionMatrix;
-		pc.m_minusCameraZ = ctx.m_cameraTransform.getColumn(2).xyz();
-		pc.m_particleCount = m_particleCount;
-		cmdb->setPushConstants(&pc, sizeof(pc));
+		static const Mat4 identity = Mat4::getIdentity();
+		static_cast<const MaterialRenderComponent&>(getComponent<RenderComponent>())
+			.allocateAndSetupUniforms(ctx,
+				ConstWeakArray<Mat4>(&identity, 1),
+				ConstWeakArray<Mat4>(&identity, 1),
+				*ctx.m_stagingGpuAllocator);
+
+		cmdb->bindStorageBuffer(0, 1, m_particlesBuff, 0, MAX_PTR_SIZE);
+
+		StagingGpuMemoryToken token;
+		Vec4* extraUniforms = static_cast<Vec4*>(
+			ctx.m_stagingGpuAllocator->allocateFrame(sizeof(Vec4), StagingGpuMemoryType::UNIFORM, token));
+		*extraUniforms = ctx.m_cameraTransform.getColumn(2);
+		cmdb->bindUniformBuffer(0, 2, token.m_buffer, token.m_offset, token.m_range);
 
 		// Draw
 		cmdb->setLineWidth(8.0f);

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

@@ -172,8 +172,7 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 
 		// Uniforms
 		static_cast<const MaterialRenderComponent&>(getComponent<RenderComponent>())
-			.allocateAndSetupUniforms(patch.getMaterial()->getDescriptorSetIndex(),
-				ctx,
+			.allocateAndSetupUniforms(ctx,
 				ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
 				ConstWeakArray<Mat4>(&prevTrfs[0], userData.getSize()),
 				*ctx.m_stagingGpuAllocator);

+ 2 - 6
src/anki/scene/ParticleEmitterNode.cpp

@@ -308,7 +308,7 @@ void ParticleEmitterNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArr
 
 		// Program
 		ShaderProgramPtr prog;
-		self.m_particleEmitterResource->getRenderingInfo(ctx.m_key.getLod(), prog);
+		self.m_particleEmitterResource->getRenderingInfo(ctx.m_key, prog);
 		cmdb->bindShaderProgram(prog);
 
 		// Vertex attribs
@@ -322,11 +322,7 @@ void ParticleEmitterNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArr
 		// Uniforms
 		Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
 		static_cast<const MaterialRenderComponent&>(self.getComponent<RenderComponent>())
-			.allocateAndSetupUniforms(self.m_particleEmitterResource->getMaterial()->getDescriptorSetIndex(),
-				ctx,
-				trf,
-				trf,
-				*ctx.m_stagingGpuAllocator);
+			.allocateAndSetupUniforms(ctx, trf, trf, *ctx.m_stagingGpuAllocator);
 
 		// Draw
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);

+ 2 - 2
src/anki/scene/components/RenderComponent.cpp

@@ -37,8 +37,7 @@ MaterialRenderComponent::~MaterialRenderComponent()
 	m_vars.destroy(m_node->getAllocator());
 }
 
-void MaterialRenderComponent::allocateAndSetupUniforms(U32 set,
-	const RenderQueueDrawContext& ctx,
+void MaterialRenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
 	ConstWeakArray<Mat4> transforms,
 	ConstWeakArray<Mat4> prevTransforms,
 	StagingGpuMemoryManager& alloc) const
@@ -47,6 +46,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U32 set,
 	ANKI_ASSERT(prevTransforms.getSize() == transforms.getSize());
 
 	const MaterialVariant2& variant = m_mtl->getOrCreateVariant(ctx.m_key);
+	const U32 set = m_mtl->getDescriptorSetIndex();
 
 	// Allocate uniform memory
 	StagingGpuMemoryToken token;

+ 1 - 2
src/anki/scene/components/RenderComponent.h

@@ -159,8 +159,7 @@ public:
 		return err;
 	}
 
-	void allocateAndSetupUniforms(U32 set,
-		const RenderQueueDrawContext& ctx,
+	void allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
 		ConstWeakArray<Mat4> transforms,
 		ConstWeakArray<Mat4> prevTransforms,
 		StagingGpuMemoryManager& alloc) const;

+ 15 - 0
tools/gltf_importer/Main.cpp

@@ -29,6 +29,7 @@ public:
 	U32 m_threadCount = MAX_U32;
 	U32 m_lodCount = 1;
 	F32 m_lodFactor = 0.25f;
+	F32 m_lightIntensityScale = 1.0f;
 };
 
 static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
@@ -145,6 +146,19 @@ static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
 				return Error::USER_DATA;
 			}
 		}
+		else if(strcmp(argv[i], "-light-scale") == 0)
+		{
+			++i;
+
+			if(i < argc)
+			{
+				ANKI_CHECK(CString(argv[i]).toNumber(info.m_lightIntensityScale));
+			}
+			else
+			{
+				return Error::USER_DATA;
+			}
+		}
 		else
 		{
 			return Error::USER_DATA;
@@ -182,6 +196,7 @@ int main(int argc, char** argv)
 		   info.m_optimizeMeshes,
 		   info.m_lodFactor,
 		   info.m_lodCount,
+		   info.m_lightIntensityScale,
 		   info.m_threadCount))
 	{
 		return 1;