InstanceData CreateInstanceData(int packageCount) { InstanceData data = new InstanceData(); data.worldMatrix = new List <Matrix4x4[]> [packageCount]; data.frameIndex = new List <float[]> [packageCount]; data.preFrameIndex = new List <float[]> [packageCount]; data.transitionProgress = new List <float[]> [packageCount]; for (int i = 0; i != packageCount; ++i) { data.worldMatrix[i] = new List <Matrix4x4[]>(); data.frameIndex[i] = new List <float[]>(); data.preFrameIndex[i] = new List <float[]>(); data.transitionProgress[i] = new List <float[]>(); } return(data); }
private VertexCache CreateVertexCache(string prefabName, int renderName, int alias, Mesh mesh) { VertexCache vertexCache = new VertexCache(); int cacheName = renderName + alias; vertexCachePool[cacheName] = vertexCache; vertexCache.nameCode = cacheName; vertexCache.mesh = mesh; vertexCache.boneTextureIndex = FindTexture_internal(prefabName); vertexCache.weight = new Vector4[mesh.vertexCount]; vertexCache.boneIndex = new Vector4[mesh.vertexCount]; int packageCount = GetPackageCount(vertexCache); InstanceData data = null; int instanceName = prefabName.GetHashCode() + alias; if (!instanceDataPool.TryGetValue(instanceName, out data)) { data = CreateInstanceData(packageCount); instanceDataPool.Add(instanceName, data); } vertexCache.instanceBlockList = new Dictionary <int, MaterialBlock>(); return(vertexCache); }
public InstancingPackage CreatePackage(InstanceData data, Mesh mesh, Material[] originalMaterial, int animationIndex) { InstancingPackage package = new InstancingPackage(); package.material = new Material[mesh.subMeshCount]; package.subMeshCount = mesh.subMeshCount; package.size = 1; for (int i = 0; i != mesh.subMeshCount; ++i) { package.material[i] = new Material(originalMaterial[i]); #if UNITY_5_6_OR_NEWER package.material[i].enableInstancing = UseInstancing; #endif if (UseInstancing) { package.material[i].EnableKeyword("INSTANCING_ON"); } else { package.material[i].DisableKeyword("INSTANCING_ON"); } package.propertyBlock = new MaterialPropertyBlock(); package.material[i].EnableKeyword("USE_CONSTANT_BUFFER"); package.material[i].DisableKeyword("USE_COMPUTE_BUFFER"); } Matrix4x4[] mat = new Matrix4x4[instancingPackageSize]; float[] frameIndex = new float[instancingPackageSize]; float[] preFrameIndex = new float[instancingPackageSize]; float[] transitionProgress = new float[instancingPackageSize]; data.worldMatrix[animationIndex].Add(mat); data.frameIndex[animationIndex].Add(frameIndex); data.preFrameIndex[animationIndex].Add(preFrameIndex); data.transitionProgress[animationIndex].Add(transitionProgress); return(package); }
private void Render() { foreach (var obj in vertexCachePool) { VertexCache vertexCache = obj.Value; foreach (var block in vertexCache.instanceBlockList) { List <InstancingPackage>[] packageList = block.Value.packageList; for (int k = 0; k != packageList.Length; ++k) { for (int i = 0; i != packageList[k].Count; ++i) { InstancingPackage package = packageList[k][i]; if (package.instancingCount == 0) { continue; } for (int j = 0; j != package.subMeshCount; ++j) { InstanceData data = block.Value.instanceData; if (useInstancing) { #if UNITY_EDITOR PreparePackageMaterial(package, vertexCache, k); #endif package.propertyBlock.SetFloatArray("frameIndex", data.frameIndex[k][i]); package.propertyBlock.SetFloatArray("preFrameIndex", data.preFrameIndex[k][i]); package.propertyBlock.SetFloatArray("transitionProgress", data.transitionProgress[k][i]); Graphics.DrawMeshInstanced(vertexCache.mesh, j, package.material[j], data.worldMatrix[k][i], package.instancingCount, package.propertyBlock, vertexCache.shadowcastingMode, vertexCache.receiveShadow, vertexCache.layer); } else { package.material[j].SetFloat("frameIndex", data.frameIndex[k][i][0]); package.material[j].SetFloat("preFrameIndex", data.preFrameIndex[k][i][0]); package.material[j].SetFloat("transitionProgress", data.transitionProgress[k][i][0]); Graphics.DrawMesh(vertexCache.mesh, data.worldMatrix[k][i][0], package.material[j], 0, null, j); } } package.instancingCount = 0; } block.Value.runtimePackageIndex[k] = 0; } } // if (obj.Value.instancingData == null) // continue; // vertexCache.bufInstance.SetData(obj.Value.instancingData); // // for (int i = 0; i != vertexCache.subMeshCount; ++i) // { // Material material = vertexCache.instanceMaterial[i]; // material.SetBuffer("buf_InstanceMatrices", vertexCache.bufInstance); // vertexCache.args[i][1] = (uint)vertexCache.currentInstancingIndex; // vertexCache.bufArgs[i].SetData(vertexCache.args[i]); // // Graphics.DrawMeshInstancedIndirect(vertexCache.mesh, // i, // vertexCache.instanceMaterial[i], // new Bounds(Vector3.zero, new Vector3(10000.0f, 10000.0f, 10000.0f)), // vertexCache.bufArgs[i]); // } // vertexCache.currentInstancingIndex = 0; } }
void ApplyBoneMatrix() { Vector3 cameraPosition = cameraTransform.position; for (int i = 0; i != aniInstancingList.Count; ++i) { AnimationInstancing instance = aniInstancingList[i]; if (!instance.IsPlaying()) { continue; } if (instance.aniIndex < 0 && instance.parentInstance == null) { continue; } if (instance.applyRootMotion) { ApplyRootMotion(instance); } instance.UpdateAnimation(); instance.boundingSpere.position = instance.worldTransform.position; boundingSphere[i] = instance.boundingSpere; if (!instance.visible) { continue; } instance.UpdateLod(cameraPosition); AnimationInstancing.LodInfo lod = instance.lodInfo[instance.lodLevel]; int aniTextureIndex = -1; if (instance.parentInstance != null) { aniTextureIndex = instance.parentInstance.aniTextureIndex; } else { aniTextureIndex = instance.aniTextureIndex; } Matrix4x4 worldMat = instance.worldTransform.localToWorldMatrix; for (int j = 0; j != lod.vertexCacheList.Length; ++j) { VertexCache cache = lod.vertexCacheList[j]; MaterialBlock block = lod.materialBlockList[j]; Debug.Assert(block != null); int packageIndex = block.runtimePackageIndex[aniTextureIndex]; Debug.Assert(packageIndex < block.packageList[aniTextureIndex].Count); InstancingPackage package = block.packageList[aniTextureIndex][packageIndex]; if (package.instancingCount + 1 > instancingPackageSize) { ++block.runtimePackageIndex[aniTextureIndex]; packageIndex = block.runtimePackageIndex[aniTextureIndex]; if (packageIndex >= block.packageList[aniTextureIndex].Count) { InstancingPackage newPackage = CreatePackage(block.instanceData, cache.mesh, cache.materials, aniTextureIndex); block.packageList[aniTextureIndex].Add(newPackage); PreparePackageMaterial(newPackage, cache, aniTextureIndex); newPackage.instancingCount = 1; } block.packageList[aniTextureIndex][packageIndex].instancingCount = 1; } else { ++package.instancingCount; } { VertexCache vertexCache = cache; InstanceData data = block.instanceData; int index = block.runtimePackageIndex[aniTextureIndex]; InstancingPackage pkg = block.packageList[aniTextureIndex][index]; int count = pkg.instancingCount - 1; if (count >= 0) { Matrix4x4[] arrayMat = data.worldMatrix[aniTextureIndex][index]; arrayMat[count].m00 = worldMat.m00; arrayMat[count].m01 = worldMat.m01; arrayMat[count].m02 = worldMat.m02; arrayMat[count].m03 = worldMat.m03; arrayMat[count].m10 = worldMat.m10; arrayMat[count].m11 = worldMat.m11; arrayMat[count].m12 = worldMat.m12; arrayMat[count].m13 = worldMat.m13; arrayMat[count].m20 = worldMat.m20; arrayMat[count].m21 = worldMat.m21; arrayMat[count].m22 = worldMat.m22; arrayMat[count].m23 = worldMat.m23; arrayMat[count].m30 = worldMat.m30; arrayMat[count].m31 = worldMat.m31; arrayMat[count].m32 = worldMat.m32; arrayMat[count].m33 = worldMat.m33; float frameIndex = 0, preFrameIndex = -1, transition = 0f; if (instance.parentInstance != null) { frameIndex = instance.parentInstance.aniInfo[instance.parentInstance.aniIndex].animationIndex + instance.parentInstance.curFrame; if (instance.parentInstance.preAniIndex >= 0) { preFrameIndex = instance.parentInstance.aniInfo[instance.parentInstance.preAniIndex].animationIndex + instance.parentInstance.preAniFrame; } transition = instance.parentInstance.transitionProgress; } else { frameIndex = instance.aniInfo[instance.aniIndex].animationIndex + instance.curFrame; if (instance.preAniIndex >= 0) { preFrameIndex = instance.aniInfo[instance.preAniIndex].animationIndex + instance.preAniFrame; } transition = instance.transitionProgress; } data.frameIndex[aniTextureIndex][index][count] = frameIndex; data.preFrameIndex[aniTextureIndex][index][count] = preFrameIndex; data.transitionProgress[aniTextureIndex][index][count] = transition; } } } } }