/// <summary> /// Generates instancing renderer data for a given GameObject, at the given LOD level. /// </summary> /// <param name="lod">Which LOD level to generate renderers in</param> /// <param name="gameObject">GameObject</param> /// <param name="settings">GPU Instancer settings to find appropriate shader for materials</param> /// <param name="includeChildren">if true, renderers for all found children of this gameObject will be created as well</param> private bool CreateRenderersFromGameObject(int lod, GameObject gameObject, GPUInstancerShaderBindings shaderBindings, bool createShadowMPB) { if (instanceLODs == null || instanceLODs.Count <= lod || instanceLODs[lod] == null) { Debug.LogError("Can't create renderer(s): Invalid LOD"); return(false); } if (!gameObject) { Debug.LogError("Can't create renderer(s): reference GameObject is null"); return(false); } List <MeshRenderer> meshRenderers = new List <MeshRenderer>(); GetMeshRenderersOfTransform(gameObject.transform, meshRenderers); if (meshRenderers == null || meshRenderers.Count == 0) { Debug.LogError("Can't create renderer(s): no MeshRenderers found in the reference GameObject <" + gameObject.name + "> or any of its children"); return(false); } foreach (MeshRenderer meshRenderer in meshRenderers) { if (meshRenderer.GetComponent <MeshFilter>() == null) { Debug.LogWarning("MeshRenderer with no MeshFilter found on GameObject <" + gameObject.name + "> (Child: <" + meshRenderer.gameObject + ">). Are you missing a component?"); continue; } List <Material> instanceMaterials = new List <Material>(); for (int m = 0; m < meshRenderer.sharedMaterials.Length; m++) { instanceMaterials.Add(shaderBindings.GetInstancedMaterial(meshRenderer.sharedMaterials[m])); } Matrix4x4 transformOffset = Matrix4x4.identity; Transform currentTransform = meshRenderer.gameObject.transform; while (currentTransform != gameObject.transform) { transformOffset = Matrix4x4.TRS(currentTransform.localPosition, currentTransform.localRotation, currentTransform.localScale) * transformOffset; currentTransform = currentTransform.parent; } MaterialPropertyBlock mpb = new MaterialPropertyBlock(); meshRenderer.GetPropertyBlock(mpb); MaterialPropertyBlock shadowMPB = null; if (createShadowMPB) { shadowMPB = new MaterialPropertyBlock(); meshRenderer.GetPropertyBlock(shadowMPB); } AddRenderer(lod, meshRenderer.GetComponent <MeshFilter>().sharedMesh, instanceMaterials, transformOffset, mpb, meshRenderer.shadowCastingMode != UnityEngine.Rendering.ShadowCastingMode.Off, meshRenderer.gameObject.layer, shadowMPB); } return(true); }
/// <summary> /// Generates all LOD and render data from the supplied Unity LODGroup. Deletes all existing LOD data. /// </summary> /// <param name="lodGroup">Unity LODGroup</param> /// <param name="settings">GPU Instancer settings to find appropriate shader for materials</param> private bool GenerateLODsFromLODGroup(LODGroup lodGroup, GPUInstancerShaderBindings shaderBindings, bool createShadowMPB) { if (instanceLODs == null) { instanceLODs = new List <GPUInstancerPrototypeLOD>(); } else { instanceLODs.Clear(); } for (int lod = 0; lod < lodGroup.GetLODs().Length; lod++) { bool hasBillboardRenderer = false; List <Renderer> lodRenderers = new List <Renderer>(); if (lodGroup.GetLODs()[lod].renderers != null) { foreach (Renderer renderer in lodGroup.GetLODs()[lod].renderers) { if (renderer != null && renderer is MeshRenderer && renderer.GetComponent <MeshFilter>() != null) { lodRenderers.Add(renderer); } else if (renderer != null && renderer is BillboardRenderer) { hasBillboardRenderer = true; } } } if (!lodRenderers.Any()) { if (!hasBillboardRenderer) { Debug.LogWarning("LODGroup has no mesh renderers. Prefab: " + lodGroup.gameObject.name + " LODIndex: " + lod); } continue; } AddLod(lodGroup.GetLODs()[lod].screenRelativeTransitionHeight); for (int r = 0; r < lodRenderers.Count; r++) { List <Material> instanceMaterials = new List <Material>(); for (int m = 0; m < lodRenderers[r].sharedMaterials.Length; m++) { instanceMaterials.Add(shaderBindings.GetInstancedMaterial(lodRenderers[r].sharedMaterials[m])); } Matrix4x4 transformOffset = Matrix4x4.identity; Transform currentTransform = lodRenderers[r].gameObject.transform; while (currentTransform != lodGroup.gameObject.transform) { transformOffset = Matrix4x4.TRS(currentTransform.localPosition, currentTransform.localRotation, currentTransform.localScale) * transformOffset; currentTransform = currentTransform.parent; } MaterialPropertyBlock mpb = new MaterialPropertyBlock(); lodRenderers[r].GetPropertyBlock(mpb); MaterialPropertyBlock shadowMPB = null; if (createShadowMPB) { shadowMPB = new MaterialPropertyBlock(); lodRenderers[r].GetPropertyBlock(shadowMPB); } AddRenderer(lod, lodRenderers[r].GetComponent <MeshFilter>().sharedMesh, instanceMaterials, transformOffset, mpb, lodRenderers[r].shadowCastingMode != UnityEngine.Rendering.ShadowCastingMode.Off, lodRenderers[r].gameObject.layer, shadowMPB); } } return(true); }