美文网首页
Unity3d之 SkinnedMeshRenderer 渲染U

Unity3d之 SkinnedMeshRenderer 渲染U

作者: 会打马赛克的小老弟 | 来源:发表于2019-11-27 19:26 被阅读0次

很多时候美术在出一个特效的时候往往会用到MeshRenderer以及本文主角SkinnedMeshRenderer(蒙皮渲染组件),那么在UGUI上由于没有深度概念(其实是有,但这里我们姑且认为没有,因为我不可能也不想去调整他的排序层或者渲染层。)

那这个时候怎么办?因为mesh的的渲染永远都是最早的,UI没法遮挡,最后想了一个折中方案,那就是把Mesh渲染到UI上,大家应该都知道UGUI的渲染依靠网格,那么我们把模型的mesh填充进去就可以了(这个很简单,这里不做阐述了)。

那么问题又来了!正常的MeshRenderer是可以正常填充,SkinnedMeshRenderer也可以填充,但是!!如果SkinnedMeshRenderer用到了骨骼动画,怎么办??因为它的动画是基于骨骼,不是基于网格点,所以在我们的网格点不变化的情况下 SkinnedMeshRenderer 渲染出来的永远是静态的。

下面进入代码模式。(首先你要会怎么把网格填充到UGUI上,如果对 OnPopulateMesh ,SetMaterialDirty等等这些函数不清楚的话,建议先忽略本文)

m_SkinnedMesh.GetUVs(0, Uvs);

m_SkinnedMesh.GetVertices(Vertices);

m_SkinnedMesh.GetColors(Colors);

m_SkinnedMesh.GetTriangles(Triangles, 0);

m_SkinnedMesh.GetBindposes(bindposesMatrix4x4);

m_SkinnedMesh.GetBoneWeights(boneWeights);

bones = this.skinnedMeshRenderer.bones;

上述代码片段是我们需要的一下数据,可以从mesh网格中获取,里面包含骨骼的权重以及Matrix的矩阵信息,还有骨骼,对应的权重信息和顶点数相同,矩阵信息与骨骼数量相同.

//遍历顶点数,LBS蒙皮算法

for (int i = 0; i < Vertices.Count; i++){

                                BoneWeight boneWeight = boneWeights[i];

                                Vector3 point = Vertices[i];

                                Transform trans0 = bones[boneWeight.boneIndex0];

                                Transform trans1 = bones[boneWeight.boneIndex1];

                                Transform trans2 = bones[boneWeight.boneIndex2];

                                Transform trans3 = bones[boneWeight.boneIndex3];

                                Matrix4x4 tempMat0 = trans0.localToWorldMatrix * bindposesMatrix4x4[boneWeight.boneIndex0];

                                Matrix4x4 tempMat1 = trans1.localToWorldMatrix * bindposesMatrix4x4[boneWeight.boneIndex1];

                                Matrix4x4 tempMat2 = trans2.localToWorldMatrix * bindposesMatrix4x4[boneWeight.boneIndex2];

                                Matrix4x4 tempMat3 = trans3.localToWorldMatrix * bindposesMatrix4x4[boneWeight.boneIndex3];

                                Vector3 temp = tempMat0.MultiplyPoint(point) * boneWeight.weight0 +

                                              tempMat1.MultiplyPoint(point) * boneWeight.weight1 +

                                              tempMat2.MultiplyPoint(point) * boneWeight.weight2 +

                                              tempMat3.MultiplyPoint(point) * boneWeight.weight3;

                                Vertices[i] = this.skinnedMeshRenderer.worldToLocalMatrix.MultiplyPoint(temp);

                                vh.AddVert(Vertices[i], Color.white, Uvs[i]);

}

//填充三角面

for (int i = 0; i < Triangles.Count; i++)

                {

                    try

                    {

                        vh.AddTriangle(Triangles[i], Triangles[i + 1], Triangles[i + 2]);

                        i += 2;

                    }

                    catch (System.Exception ex)

                    {

                        Debug.LogError(ex.Message);

                    }

                }

换句大白话来说就是透过骨骼的偏移来改变顶点信息。

注意!!!前方高能警告!!!

此方式的渲染会很大提高CPU的计算量,一个mesh我本地计算预计是增加4ms左右,但是这样可以使用UGUI批处理合批(记得把 SkinnedMeshRenderer 的mesh去掉,不然UGUI渲染一份,SkinnedMeshRenderer渲染一份,多余垃圾)

大家根据自己的项目来使用,毕竟这样就可以不用给UGUI造轮子(如果不渲染到UGUI上,那么就得需要自己管理整个UI层的 (SortingOrder || SortingLayer),反正笔者是不想管理这些东西,希望UIElements能够早点出来,也希望Unity轮子已经造好,毕竟作者懒。

相关文章

网友评论

      本文标题:Unity3d之 SkinnedMeshRenderer 渲染U

      本文链接:https://www.haomeiwen.com/subject/eaunvctx.html