/// <summary> /// 通过 id 获取 GPURendererRes /// </summary> /// <param name="id">SkinnedMeshRenderer.sharedMesh.GetInstanceID()</param> /// <returns></returns> public GPURendererRes GetDataByID(int id) { GPURendererRes data = null; _dic.TryGetValue(id, out data); return(data); }
public void AddMeshRenderer(GPURendererRes res) { GPUSkinnedMeshRenderer renderer = new GPUSkinnedMeshRenderer(); renderer.Init(this, res); _GPUMeshRenderers.Add(renderer); }
public void Init(BakedGPUAnimation animation, GPURendererRes res) { _bakedAnimation = animation; _rendererRes = res; _skinningData = animation.skinningData; _pixelPerFrame = _skinningData.boneInfos.Length * 3; GameObject go = animation.gameObject; Transform t = go.transform; t.localPosition = Vector3.zero; t.localRotation = Quaternion.identity; _meshRenderer = go.GetOrAddComponent <MeshRenderer>(); _meshFilter = go.GetOrAddComponent <MeshFilter>(); _meshFilter.sharedMesh = res.mesh; _rendererParamDirty = true; _runningBakedAnimData = new RunningBakedAnimData(); _meshRenderer.additionalVertexStreams = _rendererRes.additionalMesh; _meshRenderer.sharedMaterial = _rendererRes.bakedGPUMaterial; _AnimParamId = Shader.PropertyToID("_AnimParam"); _mbp = new MaterialPropertyBlock(); _meshRenderer.SetPropertyBlock(_mbp); }
public void AddMeshRenderer(GPURendererRes res) { BakedGPUSkinnedMeshRenderer bsmr = new BakedGPUSkinnedMeshRenderer(); bsmr.Init(this, res); _bakedRenderers.Add(bsmr); }
public void Add(int id, GPURendererRes data) { if (_dic.ContainsKey(id)) { Debug.LogErrorFormat("AdditionalMeshCache already contains key {0}", id); return; } _dic.Add(id, data); }
private void CreateBakedTexture2D(GPURendererRes res) { Texture2D tex = new Texture2D(res.skinningData.width, res.skinningData.height, TextureFormat.RGBAHalf, false, true); tex.name = string.Format("BakedAnimTexture_{0}", res.skinningData.name); tex.filterMode = FilterMode.Point; tex.LoadRawTextureData(res.skinningData.bakedBoneDatas); tex.Apply(false, true); tex.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor; res.bakedAnimTex = tex; }
/// <summary> /// 创建 GPUSkin 所需的 Mesh, 强制每个顶点只有两根骨骼 /// /// 由于 Unity 没有开放 BLENDINDICES 和 BLENDWEIGHT 语义,我们又不想修改资源内的原始mesh,只能自己创建一个 mesh 来存储, /// 缺点就是每个顶点多出了 4 * 4 个字节的体积, 假设每个模型 4000 个顶点,共缓存了 30 套模型,那么将多出 /// 16 * 4000 * 30 = 1920000 = 1.83MB, 可以接受 /// </summary> /// <param name="smr"></param> /// <returns></returns> private void CreateSkinMesh(SkinnedMeshRenderer smr, GPURendererRes res) { int[] boneIdxMap = GPUAnimUtils.CalcBoneIdxMap(smr, res.skinningData); Mesh smrMesh = smr.sharedMesh; Mesh addMesh = new Mesh(); BoneWeight[] oriBoneWeights = smrMesh.boneWeights; int weightCount = oriBoneWeights.Length; List <Vector4> boneIndices = new List <Vector4>(weightCount); List <Vector4> boneWeights = new List <Vector4>(weightCount); for (int i = 0; i < weightCount; i++) { BoneWeight weight = oriBoneWeights[i]; Vector4 indices = new Vector4(); indices.x = boneIdxMap[weight.boneIndex0]; // 骨骼索引重新映射下 indices.y = boneIdxMap[weight.boneIndex1]; indices.z = boneIdxMap[weight.boneIndex2]; indices.w = boneIdxMap[weight.boneIndex3]; boneIndices.Add(indices); Vector4 weights = new Vector4(); weights.x = weight.weight0; weights.y = weight.weight1; weights.z = weight.weight2; weights.w = weight.weight3; boneWeights.Add(weights); //float sum = weight.weight0 + weight.weight1; //blendWeights[i].x = weight.weight0 / sum; //blendWeights[i].y = weight.weight1 /sum; } addMesh.vertices = smrMesh.vertices; // 由于 Unity 有判断要求其它 channel 长度必须与 vertices 相等,这个内存只能浪费掉了 addMesh.SetUVs(2, boneIndices); addMesh.SetUVs(3, boneWeights); //addMesh.uv3 = blendIndices; //addMesh.uv4 = blendWeights; addMesh.UploadMeshData(true); // warning!, DeviceLost 时可能无法恢复数据 res.additionalMesh = addMesh; }
/// <summary> /// 获取或者创建 Res /// </summary> /// <param name="smr"></param> /// <param name="skinningData"></param> /// <returns></returns> public GPURendererRes GetOrCreateRes(SkinnedMeshRenderer smr, SkinningData skinningData) { int id = smr.sharedMesh.GetInstanceID(); GPURendererRes ret = null; if (_dic.TryGetValue(id, out ret)) { return(ret); } ret = new GPURendererRes(); ret.skinningData = skinningData; ret.mesh = smr.sharedMesh; CreateSkinMesh(smr, ret); CreateBakedTexture2D(ret); CreateMaterial(smr, ret); _dic.Add(id, ret); return(ret); }
private void CreateMaterial(SkinnedMeshRenderer smr, GPURendererRes res) { Texture2D animTex = res.bakedAnimTex; Material srcMat = smr.sharedMaterial; Material bakedGPUMaterial = new Material(Shader.Find("GPUSkinning/BakedGPUSkinning")); bakedGPUMaterial.SetTexture("_MainTex", srcMat.mainTexture); bakedGPUMaterial.SetTexture("_BakedAnimTex", animTex); bakedGPUMaterial.SetVector("_BakedAnimTexWH", new Vector4(res.skinningData.width, res.skinningData.height, 0, 0)); bakedGPUMaterial.enableInstancing = true; Material GPUMaterial = new Material(Shader.Find("GPUSkinning/GPUSkinning")); GPUMaterial.SetTexture("_MainTex", srcMat.mainTexture); GPUMaterial.enableInstancing = true; res.bakedGPUMaterial = bakedGPUMaterial; res.GPUMaterial = GPUMaterial; }
private Vector4[] _matrixPalette; // _boneIdxMap.Length * 3 public void Init(GPUAnimation gpuAnim, GPURendererRes res) { _gpuAnimation = gpuAnim; _res = res; _matrixPalette = new Vector4[_boneIdxMap.Length * 3]; }
/// <summary> /// 将除 mesh 节点,挂点(将其提到最顶级),rootMotion 之外的所有节点移除 /// </summary> private void ProcessNode() { _rootMotionNode = transform.Find(Consts.ROOT_MOTION_NAME); List <Transform> allChildren = new List <Transform>(); GPUAnimUtils.GetAllChildren(transform, allChildren); List <SkinnedMeshRenderer> smrs = new List <SkinnedMeshRenderer>(); foreach (var node in allChildren) { if (node == transform) { continue; } SkinnedMeshRenderer smr = node.GetComponent <SkinnedMeshRenderer>(); if (smr != null) { /* * 调试代码,发布时把 if 去掉 * (挂载的这个武器并不能使用模型的 Animation, 并且其 Bone 数量也为0,因此应该是用 MeshRenderer 而不是 SkinnedMeshRenderer) */ if (node.name != "right_weapon") { // 某些 smr 不位于模型直接子节点,将其提升以避免被移除掉(显示不会受到影响) if (node.parent != transform) { node.parent = transform; } smrs.Add(smr); continue; } } if (node == _rootMotionNode) { continue; } bool isJoint = false; //foreach (var name in skinningData.jointNames) //{ // if (name == node.name) // { // node.parent = transform; // isJoint = true; // break; // } //} if (!isJoint) { // 不要使用 DestroyImmediate, 否则循环中的其它元素可能无法访问并且下面的 bsmr.Init 无法获取到 bones Destroy(node.gameObject); } } // 原始的 SkinnedMeshRenderer 都创建对应的两种 Renderer foreach (var smr in smrs) { GPURendererRes res = GPUSkinRuntimeResMgr.Instance.GetOrCreateRes(smr, skinningData); _bakedGPUAnimation.AddMeshRenderer(res); _GPUAnimation.AddMeshRenderer(res); DestroyImmediate(smr); } Animation oriAnimation = gameObject.GetComponent <Animation>(); if (oriAnimation != null) { DestroyImmediate(oriAnimation); } // 初始化绑点 //_jointTrans = new Transform[skinningData.jointNames.Length]; //for (int i = 0; i < _jointTrans.Length; i++) //{ // Transform t = transform.Find(skinningData.jointNames[i]); // if (t == null) // { // Debug.LogErrorFormat("can not find join {0}", skinningData.jointNames[i]); // return; // } // _jointTrans[i] = t; //} _bakedGPUAnimation.SetJointTransforms(_jointTrans); _GPUAnimation.SetJointTransforms(_jointTrans); }