Przeglądaj źródła

Add some funtionality on bone weights

Panagiotis Christopoulos Charitos 8 lat temu
rodzic
commit
3c7967c17a

+ 2 - 2
programs/LightShading.ankiprog

@@ -201,8 +201,8 @@ void main()
 	vec3 outC = diffCol * emission;
 
 	// Don't allow zero a2 because we may end up with division with zero
-	float a2 = roughness * 0.9 + 0.1;
-	a2 *= a2;
+	float a2 = roughness * 0.95 + 0.05;
+	a2 *= a2 * a2;
 
 	// Point lights
 	vec3 viewDir = normalize(-fragPos);

+ 2 - 2
sandbox/Main.cpp

@@ -65,8 +65,8 @@ Error MyApp::init(int argc, char* argv[])
 	ANKI_CHECK(resources.loadResource(argv[2], script));
 	ANKI_CHECK(getScriptManager().evalString(script->getSource()));
 
-	ANKI_CHECK(renderer.getOffscreenRenderer().getFinalComposite().loadColorGradingTexture(
-		"textures/color_gradient_luts/forge_lut.ankitex"));
+// ANKI_CHECK(renderer.getOffscreenRenderer().getFinalComposite().loadColorGradingTexture(
+//	"textures/color_gradient_luts/forge_lut.ankitex"));
 
 #if PLAYER
 	SceneGraph& scene = getSceneGraph();

+ 3 - 3
src/anki/renderer/DownscaleBlur.h

@@ -32,17 +32,17 @@ anki_internal:
 
 	U getPassWidth(U pass) const
 	{
-		return m_passes[min(pass, m_passes.getSize() - 1)].m_width;
+		return m_passes[min<U>(pass, m_passes.getSize() - 1)].m_width;
 	}
 
 	U getPassHeight(U pass) const
 	{
-		return m_passes[min(pass, m_passes.getSize() - 1)].m_height;
+		return m_passes[min<U>(pass, m_passes.getSize() - 1)].m_height;
 	}
 
 	TexturePtr getPassTexture(U pass) const
 	{
-		return m_passes[min(pass, m_passes.getSize() - 1)].m_rt;
+		return m_passes[min<U>(pass, m_passes.getSize() - 1)].m_rt;
 	}
 
 private:

+ 1 - 0
src/anki/renderer/Drawer.cpp

@@ -55,6 +55,7 @@ void RenderableDrawer::drawRange(Pass pass,
 	ctx.m_queueCtx.m_stagingGpuAllocator = &m_r->getStagingGpuMemoryManager();
 	ctx.m_queueCtx.m_commandBuffer = cmdb;
 	ctx.m_queueCtx.m_key = RenderingKey(pass, 0, 1);
+	ctx.m_queueCtx.m_debugDraw = false;
 
 	for(; begin != end; ++begin)
 	{

+ 1 - 0
src/anki/renderer/RenderQueue.h

@@ -31,6 +31,7 @@ public:
 	RenderingKey m_key;
 	CommandBufferPtr m_commandBuffer;
 	StagingGpuMemoryManager* m_stagingGpuAllocator ANKI_DBG_NULLIFY;
+	Bool m_debugDraw; ///< If true the drawcall should be drawing some kind of debug mesh.
 };
 
 /// Draw callback for the RenderableQueueElement.

+ 2 - 0
src/anki/resource/Mesh.cpp

@@ -84,6 +84,8 @@ Error Mesh::load(const ResourceFilename& filename, Bool async)
 	const MeshLoader::Header& header = loader.getHeader();
 	m_indicesCount = header.m_totalIndicesCount;
 
+	m_vertSize = loader.getVertexSize();
+
 	PtrSize vertexSize = loader.getVertexSize();
 	m_obb.setFromPointCloud(
 		loader.getVertexData(), header.m_totalVerticesCount, vertexSize, loader.getVertexDataSize());

+ 6 - 0
src/anki/resource/Mesh.h

@@ -83,6 +83,11 @@ public:
 		return m_indicesBuff;
 	}
 
+	U32 getVertexSize() const
+	{
+		return m_vertSize;
+	}
+
 	/// Helper function for correct loading
 	Bool isCompatible(const Mesh& other) const;
 
@@ -104,6 +109,7 @@ protected:
 	DynamicArray<SubMesh> m_subMeshes;
 	U32 m_indicesCount;
 	U32 m_vertsCount;
+	U32 m_vertSize;
 	Obb m_obb;
 	U8 m_texChannelsCount;
 	Bool8 m_weights;

+ 28 - 5
src/anki/resource/Model.cpp

@@ -47,33 +47,56 @@ void ModelPatch::getRenderingDataSub(
 		VertexBufferBinding& vertBuffBinding = inf.m_vertexBufferBindings[0];
 		vertBuffBinding.m_buffer = mesh.getVertexBuffer();
 		vertBuffBinding.m_offset = 0;
-		vertBuffBinding.m_stride = sizeof(Vec3) + sizeof(HVec2) + 2 * sizeof(U32);
+		vertBuffBinding.m_stride = mesh.getVertexSize();
 
 		inf.m_vertexAttributeCount = 4;
 		auto& attribs = inf.m_vertexAttributes;
 
+		U relativeOffset = 0;
+
 		attribs[0].m_bufferBinding = 0;
 		attribs[0].m_format = PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT);
-		attribs[0].m_relativeOffset = 0;
+		attribs[0].m_relativeOffset = relativeOffset;
+		relativeOffset += sizeof(Vec3);
 
 		attribs[1].m_bufferBinding = 0;
 		attribs[1].m_format = PixelFormat(ComponentFormat::R16G16, TransformFormat::FLOAT);
-		attribs[1].m_relativeOffset = sizeof(Vec3);
+		attribs[1].m_relativeOffset = relativeOffset;
+		relativeOffset += sizeof(U16) * 2;
 
 		if(key.m_pass == Pass::GB_FS)
 		{
 			attribs[2].m_bufferBinding = 0;
 			attribs[2].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
-			attribs[2].m_relativeOffset = sizeof(Vec3) + sizeof(U32);
+			attribs[2].m_relativeOffset = relativeOffset;
+			relativeOffset += sizeof(U32);
 
 			attribs[3].m_bufferBinding = 0;
 			attribs[3].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
-			attribs[3].m_relativeOffset = sizeof(Vec3) + sizeof(U32) * 2;
+			attribs[3].m_relativeOffset = relativeOffset;
+			relativeOffset += sizeof(U32);
 		}
 		else
 		{
 			inf.m_vertexAttributeCount = 1;
+
+			relativeOffset += sizeof(U32) * 2;
+		}
+
+		if(mesh.hasBoneWeights())
+		{
+			attribs[4].m_bufferBinding = 0;
+			attribs[4].m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
+			attribs[4].m_relativeOffset = relativeOffset;
+			relativeOffset += sizeof(U8) * 4;
+
+			attribs[5].m_bufferBinding = 0;
+			attribs[5].m_format = PixelFormat(ComponentFormat::R16G16B16A16, TransformFormat::UINT);
+			attribs[5].m_relativeOffset = relativeOffset;
+			relativeOffset += sizeof(U16) * 4;
 		}
+
+		ANKI_ASSERT(relativeOffset == mesh.getVertexSize());
 	}
 
 	// Index buff

+ 50 - 41
src/anki/scene/ModelNode.cpp

@@ -245,59 +245,68 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const void*>
 	ANKI_ASSERT(userData.getSize() > 0 && userData.getSize() <= MAX_INSTANCES);
 	ANKI_ASSERT(ctx.m_key.m_instanceCount == userData.getSize());
 
+	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+
 	const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
 	ANKI_ASSERT(self.isSinglePatch());
-	const ModelPatch* patch = self.m_model->getModelPatches()[0];
 
-	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
+	if(!ctx.m_debugDraw)
+	{
+		const ModelPatch* patch = self.m_model->getModelPatches()[0];
 
-	// That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw anywhere
-	ANKI_ASSERT(patch->getSubMeshesCount() == 0);
+		// That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw
+		// anywhere
+		ANKI_ASSERT(patch->getSubMeshesCount() == 0);
 
-	ModelRenderingInfo modelInf;
-	patch->getRenderingDataSub(ctx.m_key, WeakArray<U8>(), modelInf);
+		ModelRenderingInfo modelInf;
+		patch->getRenderingDataSub(ctx.m_key, WeakArray<U8>(), modelInf);
 
-	// Program
-	cmdb->bindShaderProgram(modelInf.m_program);
+		// Program
+		cmdb->bindShaderProgram(modelInf.m_program);
 
-	// Set attributes
-	for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
-	{
-		const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
-		cmdb->setVertexAttribute(i, attrib.m_bufferBinding, attrib.m_format, attrib.m_relativeOffset);
-	}
+		// Set attributes
+		for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
+		{
+			const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
+			cmdb->setVertexAttribute(i, attrib.m_bufferBinding, attrib.m_format, attrib.m_relativeOffset);
+		}
 
-	// Set vertex buffers
-	for(U i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
-	{
-		const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
-		cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
-	}
+		// Set vertex buffers
+		for(U i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
+		{
+			const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
+			cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
+		}
 
-	// Index buffer
-	cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
+		// Index buffer
+		cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
 
-	// Uniforms
-	Array<Mat4, MAX_INSTANCES> trfs;
-	trfs[0] = Mat4(self.getComponentAt<MoveComponent>(0).getWorldTransform());
-	for(U i = 1; i < userData.getSize(); ++i)
+		// Uniforms
+		Array<Mat4, MAX_INSTANCES> trfs;
+		trfs[0] = Mat4(self.getComponentAt<MoveComponent>(0).getWorldTransform());
+		for(U i = 1; i < userData.getSize(); ++i)
+		{
+			const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
+			trfs[i] = Mat4(self2.getComponentAt<MoveComponent>(0).getWorldTransform());
+		}
+
+		self.getComponentAt<RenderComponent>(3).allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
+			ctx,
+			WeakArray<const Mat4>(&trfs[0], userData.getSize()),
+			*ctx.m_stagingGpuAllocator);
+
+		// Draw
+		cmdb->drawElements(PrimitiveTopology::TRIANGLES,
+			modelInf.m_indicesCountArray[0],
+			userData.getSize(),
+			modelInf.m_indicesOffsetArray[0] / sizeof(U16),
+			0,
+			0);
+	}
+	else
 	{
-		const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
-		trfs[i] = Mat4(self2.getComponentAt<MoveComponent>(0).getWorldTransform());
+		ANKI_ASSERT(!"TODO");
 	}
-
-	self.getComponentAt<RenderComponent>(3).allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
-		ctx,
-		WeakArray<const Mat4>(&trfs[0], userData.getSize()),
-		*ctx.m_stagingGpuAllocator);
-
-	// Draw
-	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
-		modelInf.m_indicesCountArray[0],
-		userData.getSize(),
-		modelInf.m_indicesOffsetArray[0] / sizeof(U16),
-		0,
-		0);
 }
 
 } // end namespace anki

+ 70 - 5
tools/scene/ExporterMesh.cpp

@@ -87,6 +87,14 @@ struct Vertex
 	uint32_t m_tangent;
 };
 
+struct BoneVertex : Vertex
+{
+	uint8_t m_weights[4] = {0, 0, 0, 0};
+	uint16_t m_boneIndices[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
+};
+
+static_assert(sizeof(BoneVertex) == 9 * 4, "Wrong size");
+
 static uint16_t toF16(float f)
 {
 	union Val32
@@ -256,8 +264,53 @@ void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsi
 	header.m_uvsChannelCount = 1;
 	header.m_subMeshCount = 1;
 
+	const bool hasBoneWeights = mesh.mNumBones > 0;
+	if(hasBoneWeights)
+	{
+		header.m_boneIndicesFormat.m_components = ComponentFormat::R16G16B16A16;
+		header.m_boneIndicesFormat.m_transform = FormatTransform::UINT;
+
+		header.m_boneWeightsFormat.m_components = ComponentFormat::R8G8B8A8;
+		header.m_boneWeightsFormat.m_transform = FormatTransform::UNORM;
+	}
+
 	file.write(reinterpret_cast<char*>(&header), sizeof(header));
 
+	// Gather the bone weights
+	struct VertWeights
+	{
+		float m_weights[4];
+		uint32_t m_boneIndices[4];
+		uint32_t m_boneCount = 0;
+	};
+
+	std::vector<VertWeights> weights;
+
+	if(hasBoneWeights)
+	{
+		weights.resize(mesh.mNumVertices);
+
+		for(unsigned i = 0; i < mesh.mNumBones; ++i)
+		{
+			const aiBone& bone = *mesh.mBones[i];
+			for(unsigned j = 0; j < bone.mNumWeights; ++j)
+			{
+				const aiVertexWeight& aiWeight = bone.mWeights[j];
+				assert(aiWeight.mVertexId < weights.size());
+				VertWeights& vert = weights[aiWeight.mVertexId];
+
+				if(vert.m_boneCount == 4)
+				{
+					ERROR("Vertex has more than 4 bone weights");
+				}
+
+				vert.m_boneIndices[vert.m_boneCount] = i;
+				vert.m_weights[vert.m_boneCount] = aiWeight.mWeight;
+				++vert.m_boneCount;
+			}
+		}
+	}
+
 	// Write sub meshes
 	SubMesh smesh;
 	smesh.m_firstIndex = 0;
@@ -271,9 +324,8 @@ void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsi
 
 		if(face.mNumIndices != vertCountPerFace)
 		{
-			ERROR("For some reason assimp returned wrong number of verts "
-				  "for a face (face.mNumIndices=%d). Probably degenerates in "
-				  "input file",
+			ERROR("For some reason assimp returned wrong number of verts for a face (face.mNumIndices=%d). Probably"
+				  "degenerates in input file",
 				face.mNumIndices);
 		}
 
@@ -323,7 +375,7 @@ void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsi
 			b = toLefthanded * b;
 		}
 
-		Vertex vert;
+		BoneVertex vert;
 
 		// Position
 		vert.m_position[0] = pos[0];
@@ -342,6 +394,19 @@ void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsi
 		vert.m_tangent = toR10G10B10A2Sint(t[0], t[1], t[2], w);
 
 		// Write
-		file.write(reinterpret_cast<char*>(&vert), sizeof(vert));
+		if(hasBoneWeights)
+		{
+			for(unsigned j = 0; j < weights[i].m_boneCount; ++j)
+			{
+				vert.m_boneIndices[j] = weights[i].m_boneIndices[j];
+				vert.m_weights[j] = weights[i].m_weights[j] * 0xFF;
+			}
+
+			file.write(reinterpret_cast<char*>(&vert), sizeof(BoneVertex));
+		}
+		else
+		{
+			file.write(reinterpret_cast<char*>(&vert), sizeof(Vertex));
+		}
 	}
 }

+ 15 - 5
tools/scene/Main.cpp

@@ -11,10 +11,12 @@ static void parseCommandLineArgs(int argc, char** argv, Exporter& exporter)
 Options:
 -rpath <string>     : Replace all absolute paths of assets with that path
 -texrpath <string>  : Same as rpath but for textures
--progrpath <string> : Same as rpath but for shader programs
 -flipyz             : Flip y with z (For blender exports)
 )";
 
+	bool rpathFound = false;
+	bool texrpathFound = false;
+
 	// Parse config
 	if(argc < 3)
 	{
@@ -28,11 +30,15 @@ Options:
 	{
 		if(strcmp(argv[i], "-texrpath") == 0)
 		{
+			texrpathFound = true;
 			++i;
 
 			if(i < argc)
 			{
-				exporter.m_texrpath = argv[i] + std::string("/");
+				if(std::strlen(argv[i]) > 0)
+				{
+					exporter.m_texrpath = argv[i] + std::string("/");
+				}
 			}
 			else
 			{
@@ -41,11 +47,15 @@ Options:
 		}
 		else if(strcmp(argv[i], "-rpath") == 0)
 		{
+			rpathFound = true;
 			++i;
 
 			if(i < argc)
 			{
-				exporter.m_rpath = argv[i] + std::string("/");
+				if(std::strlen(argv[i]) > 0)
+				{
+					exporter.m_rpath = argv[i] + std::string("/");
+				}
 			}
 			else
 			{
@@ -62,12 +72,12 @@ Options:
 		}
 	}
 
-	if(exporter.m_rpath.empty())
+	if(!rpathFound)
 	{
 		exporter.m_rpath = exporter.m_outputDirectory;
 	}
 
-	if(exporter.m_texrpath.empty())
+	if(!texrpathFound)
 	{
 		exporter.m_texrpath = exporter.m_outputDirectory;
 	}