public static Texture2D GenerateBillboardNormalTexture(GameObject prefab, BillboardQuality billboardQuality, LODLevel billboardSourceLODLevel, Quaternion rotationOffset, string overrideBillboardAtlasNormalShader, bool recalculateNormals, float normalBlendFactor, bool flipBackNormals) { Shader normalShader = BillboardShaderDetector.GetNormalBillboardAtlasShader(prefab); if (overrideBillboardAtlasNormalShader != "") { normalShader = Shader.Find(overrideBillboardAtlasNormalShader); } if (flipBackNormals) { Shader.SetGlobalInt("_FlipBackNormals", 1); } else { Shader.SetGlobalInt("_FlipBackNormals", 0); } Material minPostfilter = (Material)Resources.Load("MinPostFilter/MinPostFilter", typeof(Material)); Texture2D texture = GenerateBillboardNew(prefab, GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityColumnCount(billboardQuality), GetBillboardQualityRowCount(billboardQuality), normalShader, new Color(0.5f, 0.5f, 1, 0), minPostfilter, billboardSourceLODLevel, rotationOffset, false, recalculateNormals, normalBlendFactor); Shader.SetGlobalInt("_FlipBackNormals", 0); return(texture); }
public static Texture2D GenerateBillboardTexture(GameObject prefab, BillboardQuality billboardQuality, LODLevel billboardSourceLODLevel, VegetationShaderType vegetationShaderType, Quaternion rotationOffset, Color backgroundColor, string overrideBillboardAtlasShader, bool recalculateNormals, float normalBlendFactor) { Shader diffuseShader = BillboardShaderDetector.GetDiffuceBillboardAtlasShader(prefab); if (overrideBillboardAtlasShader != "") { diffuseShader = Shader.Find(overrideBillboardAtlasShader); } //if (vegetationShaderType == VegetationShaderType.Speedtree) //{ // diffuseShader = Shader.Find("AwesomeTechnologies/Billboards/RenderDiffuseAtlas"); //} //else //{ // diffuseShader = Shader.Find("AwesomeTechnologies/Billboards/RenderDiffuseAtlasBright"); //} Material minPostfilter = (Material)Resources.Load("MinPostFilter/MinPostFilter", typeof(Material)); Texture2D texture = GenerateBillboardNew(prefab, GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityColumnCount(billboardQuality), GetBillboardQualityRowCount(billboardQuality), diffuseShader, backgroundColor, minPostfilter, billboardSourceLODLevel, rotationOffset, false, recalculateNormals, normalBlendFactor); return(texture); }
public LODParent(int lodCount) { lodLevels = new LODLevel[lodCount]; for (int i = 0; i < lodLevels.Length; i++) { lodLevels[i] = new LODLevel(); } }
void AddObjectInternal(MeshCombiner meshCombiner, CachedGameObject cachedGO, Vector3 position, int lodParentIndex, int lodLevel, bool isChangeMode) { if (level == maxLevels) { MaxCell thisCell = (MaxCell)this; if (thisCell.lodParents == null) { thisCell.lodParents = new LODParent[10]; } if (thisCell.lodParents[lodParentIndex] == null) { thisCell.lodParents[lodParentIndex] = new LODParent(lodParentIndex + 1); } LODParent lodParent = thisCell.lodParents[lodParentIndex]; LODLevel lod = lodParent.lodLevels[lodLevel]; lod.cachedGOs.Add(cachedGO); if (isChangeMode) { if (SortObject(meshCombiner, lod, cachedGO)) { if (!thisCell.hasChanged) { thisCell.hasChanged = true; if (meshCombiner.changedCells == null) { meshCombiner.changedCells = new List <MaxCell>(); } meshCombiner.changedCells.Add(thisCell); } if (!lodParent.hasChanged) { lodParent.hasChanged = true; thisCell.changedLodParents.Add(lodParent); } } } lod.objectCount++; lod.vertCount += cachedGO.mesh.vertexCount; return; } else { bool maxCellCreated; int index = AddCell <Cell, MaxCell>(ref cells, position, out maxCellCreated); if (maxCellCreated) { MaxCell.maxCellCount++; } cells[index].AddObjectInternal(meshCombiner, cachedGO, position, lodParentIndex, lodLevel, isChangeMode); } }
public static Texture2D GenerateBillboardAOTexture(GameObject prefab, BillboardQuality billboardQuality, LODLevel billboardSourceLODLevel, Quaternion rotationOffset, bool recalculateNormals, float normalBlendFactor) { Shader normalShader = Shader.Find("AwesomeTechnologies/Billboards/AOBackground"); Material minPostfilter = (Material)Resources.Load("MinPostFilter/MinPostFilter", typeof(Material)); Texture2D texture = GenerateBillboardNew(prefab, GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityTileWidth(billboardQuality), GetBillboardQualityColumnCount(billboardQuality), GetBillboardQualityRowCount(billboardQuality), normalShader, new Color(0.5f, 0.5f, 1, 0), minPostfilter, billboardSourceLODLevel, rotationOffset, true, recalculateNormals, normalBlendFactor); return(texture); }
public static Quaternion GetMeshRotation(GameObject go, LODLevel lodLevel) { GameObject meshGameObject = SelectMeshObject(go, lodLevel); if (meshGameObject) { return(Quaternion.Inverse(Quaternion.identity) * meshGameObject.transform.rotation); } else { return(Quaternion.identity); } }
public bool SortObject(MeshCombiner meshCombiner, LODLevel lod, CachedGameObject cachedGO, bool isChangeMode = false) { if (cachedGO.mr == null) { return(false); } if (lod.meshObjectsHolders == null) { lod.meshObjectsHolders = new List <MeshObjectsHolder>(); } Material[] mats = cachedGO.mr.sharedMaterials; // TODO check submeshes and material int length = Mathf.Min(cachedGO.mesh.subMeshCount, mats.Length); for (int l = 0; l < length; l++) { Material mat = mats[l]; if (mat == null) { continue; } bool shadowCastingModeTwoSided = (cachedGO.mr.shadowCastingMode == UnityEngine.Rendering.ShadowCastingMode.TwoSided); int lightmapIndex = meshCombiner.validCopyBakedLighting ? cachedGO.mr.lightmapIndex : -1; int index = lod.GetSortMeshIndex(mat, shadowCastingModeTwoSided, lightmapIndex); MeshObjectsHolder meshObjectHolder; if (index == -1) { meshObjectHolder = new MeshObjectsHolder(cachedGO, mat, l, shadowCastingModeTwoSided, lightmapIndex); lod.meshObjectsHolders.Add(meshObjectHolder); } else { meshObjectHolder = lod.meshObjectsHolders[index]; meshObjectHolder.meshObjects.Add(new MeshObject(cachedGO, l)); } if (isChangeMode && !meshObjectHolder.hasChanged) { meshObjectHolder.hasChanged = true; lod.changedMeshObjectsHolders.Add(meshObjectHolder); } } return(true); }
private static Mesh GetVegetationMesh(GameObject rootVegetationModel, LODLevel lodLevel) { GameObject selectedVegetationModel = MeshUtils.SelectMeshObject(rootVegetationModel, lodLevel); MeshFilter vegetationMeshFilter = selectedVegetationModel.GetComponentInChildren <MeshFilter>(); if (vegetationMeshFilter.sharedMesh) { return(vegetationMeshFilter.sharedMesh); } else { return(new Mesh()); } }
public void AssignLODGroup(MeshCombiner meshCombiner) { LOD[] lods = new LOD[lodLevels.Length]; int lodGroupParentIndex = lods.Length - 1; for (int i = 0; i < lodLevels.Length; i++) { LODLevel lodLevel = lodLevels[i]; // Debug.Log(i + " " + lodLevel.newMeshRenderers.Count); lods[i] = new LOD(meshCombiner.lodGroupsSettings[lodGroupParentIndex].lodSettings[i].screenRelativeTransitionHeight, lodLevel.newMeshRenderers.ToArray()); } lodGroup.SetLODs(lods); lodGroup.size = meshCombiner.cellSize; }
public void SortObjects(MeshCombiner meshCombiner) { if (level == maxLevels) { MaxCell thisCell = (MaxCell)this; LODParent[] lodParents = thisCell.lodParents; for (int i = 0; i < lodParents.Length; i++) { LODParent lodParent = lodParents[i]; if (lodParent == null) { continue; } for (int j = 0; j < lodParent.lodLevels.Length; j++) { LODLevel lod = lodParent.lodLevels[j]; if (lod == null || lod.cachedGOs.Count == 0) { return; } for (int k = 0; k < lod.cachedGOs.Count; ++k) { CachedGameObject cachedGO = lod.cachedGOs.items[k]; if (!SortObject(meshCombiner, lod, cachedGO)) { lod.cachedGOs.RemoveAt(k--); } } } } } else { for (int i = 0; i < 8; ++i) { if (cellsUsed[i]) { cells[i].SortObjects(meshCombiner); } } } }
static GameObject SelectNormalMesh(GameObject go, LODLevel lodLevel) { LODGroup lodGroup = go.GetComponentInChildren <LODGroup>(); if (lodGroup) { LOD[] lods = lodGroup.GetLODs(); int lodIndex = (int)lodLevel; lodIndex = Mathf.Clamp(lodIndex, 0, lods.Length - 1); LOD lod = lods[lodIndex]; if (lod.renderers.Length > 0) { if (lod.renderers[0].gameObject.GetComponent <BillboardRenderer>()) { if (lodIndex > 0) { lod = lods[lodIndex - 1]; } else { return(null); } } } return(lod.renderers.Length > 0 ? lod.renderers[0].gameObject : null); } else { var meshRenderer = go.GetComponent <MeshRenderer>(); if (meshRenderer) { return(meshRenderer.gameObject); } meshRenderer = go.GetComponentInChildren <MeshRenderer>(); if (meshRenderer) { return(meshRenderer.gameObject); } return(null); } }
public LOD(BinaryReader reader) { Type = (LODLevel)reader.ReadUInt32(); MaxEdgeLength = reader.ReadSingle(); GroupCount = reader.ReadUInt32(); PositionsPointer = reader.ReadUInt32(); //if (Context.Current.Game == Context.NextGenGame.DromeRacers) RenderGroupsPointer = reader.ReadUInt32(); if (PositionsPointer > 0) { Positions = new Vector3[GroupCount]; for (int i = 0; i < GroupCount; i++) { Positions[i] = reader.ReadVector3(); } } for (int i = 0; i < GroupCount; i++) { RenderGroups.Add(new RenderGroup(reader, true)); } }
LODLevel EnableLODRenderers( LODLevel newLevel ) { LODLevel retLevel = newLevel; currentRenderer = null; for ( int i = 0; i < (int)LODLevel.LODCulled; i++ ) { if ( i == (int)newLevel ) { if ( _renderers[i] != null ) { _renderers[i].enabled = true; currentRenderer = _renderers[i]; if ( level == newLevel && !_renderers[i].isVisible ) { retLevel = LODLevel.LODCulled; } } } else { if ( _renderers[i] != null ) { _renderers[i].enabled = false; } } } return retLevel; }
public void CombineMeshes(MeshCombiner meshCombiner, int lodParentIndex) { if (level == maxLevels) { MaxCell thisCell = (MaxCell)this; LODParent lodParent = thisCell.lodParents[lodParentIndex]; if (lodParent == null) { return; } CombineMode combineMode = meshCombiner.combineMode; if (combineMode != CombineMode.DynamicObjects) { lodParent.cellGO = new GameObject(meshCombiner.combineMode == CombineMode.StaticObjects ? "Cell " + bounds.center : "Combined Objects"); lodParent.cellT = lodParent.cellGO.transform; lodParent.cellT.position = bounds.center; lodParent.cellT.parent = meshCombiner.lodParentHolders[lodParentIndex].t; } if (lodParentIndex > 0) { lodParent.lodGroup = lodParent.cellGO.AddComponent <LODGroup>(); lodParent.lodGroup.localReferencePoint = lodParent.cellT.position = bounds.center; } LODLevel[] lods = lodParent.lodLevels; for (int i = 0; i < lods.Length; i++) { LODLevel lod = lodParent.lodLevels[i]; if (lod == null || lod.meshObjectsHoldersLookup == null) { return; } GameObject lodGO; Transform lodT = null; if (lodParentIndex > 0) { lodGO = new GameObject("LOD" + i); lodT = lodGO.transform; lodT.parent = lodParent.cellT; } foreach (MeshObjectsHolder sortedMeshes in lod.meshObjectsHoldersLookup.Values) { sortedMeshes.lodParent = lodParent; sortedMeshes.lodLevel = i; Vector3 position = (combineMode == CombineMode.DynamicObjects ? sortedMeshes.meshObjects.items[0].cachedGO.rootT.position : bounds.center); MeshCombineJobManager.instance.AddJob(meshCombiner, sortedMeshes, lodParentIndex > 0 ? lodT : lodParent.cellT, position); } } } else { for (int i = 0; i < 8; ++i) { if (cellsUsed[i]) { cells[i].CombineMeshes(meshCombiner, lodParentIndex); } } } }
public bool SortObject(MeshCombiner meshCombiner, LODLevel lod, CachedGameObject cachedGO, bool isChangeMode = false) { if (cachedGO.mr == null) { return(false); } if (lod.meshObjectsHoldersLookup == null) { lod.meshObjectsHoldersLookup = new Dictionary <CombineCondition, MeshObjectsHolder>(); } CombineConditionSettings combineConditions = meshCombiner.combineConditionSettings; Material[] mats = cachedGO.mr.sharedMaterials; // TODO check submeshes and material int length = Mathf.Min(cachedGO.mesh.subMeshCount, mats.Length); int rootInstanceId = -1; if (meshCombiner.combineMode == CombineMode.DynamicObjects) { rootInstanceId = cachedGO.rootInstanceId; if (rootInstanceId == -1) { cachedGO.GetRoot(); rootInstanceId = cachedGO.rootInstanceId; } } for (int l = 0; l < length; l++) { Material mat; if (combineConditions.sameMaterial) { mat = mats[l]; if (mat == null) { continue; } } else { mat = combineConditions.material; } CombineCondition combineCondition = new CombineCondition(); combineCondition.ReadFromGameObject(rootInstanceId, combineConditions, meshCombiner.copyBakedLighting && meshCombiner.validCopyBakedLighting, cachedGO.go, cachedGO.t, cachedGO.mr, mat); MeshObjectsHolder meshObjectHolder; if (!lod.meshObjectsHoldersLookup.TryGetValue(combineCondition, out meshObjectHolder)) { meshCombiner.foundCombineConditions.combineConditions.Add(combineCondition); meshObjectHolder = new MeshObjectsHolder(ref combineCondition, mat); lod.meshObjectsHoldersLookup.Add(combineCondition, meshObjectHolder); } meshObjectHolder.meshObjects.Add(new MeshObject(cachedGO, l)); if (isChangeMode && !meshObjectHolder.hasChanged) { meshObjectHolder.hasChanged = true; lod.changedMeshObjectsHolders.Add(meshObjectHolder); } } return(true); }
public void CombineMeshes(MeshCombiner meshCombiner, int lodParentIndex) { if (level == maxLevels) { MaxCell thisCell = (MaxCell)this; LODParent lodParent = thisCell.lodParents[lodParentIndex]; if (lodParent == null) { return; } lodParent.cellGO = new GameObject(meshCombiner.useCells ? "Cell " + bounds.center : "Combined Objects"); lodParent.cellT = lodParent.cellGO.transform; lodParent.cellT.position = bounds.center; lodParent.cellT.parent = meshCombiner.lodParentHolders[lodParentIndex].t; if (lodParentIndex > 0) { lodParent.lodGroup = lodParent.cellGO.AddComponent <LODGroup>(); lodParent.lodGroup.localReferencePoint = lodParent.cellT.position = bounds.center; } LODLevel[] lods = lodParent.lodLevels; for (int i = 0; i < lods.Length; i++) { LODLevel lod = lodParent.lodLevels[i]; if (lod == null || lod.meshObjectsHolders == null) { return; } GameObject lodGO; Transform lodT = null; if (lodParentIndex > 0) { lodGO = new GameObject("LOD" + i); lodT = lodGO.transform; lodT.parent = lodParent.cellT; } for (int k = 0; k < lod.meshObjectsHolders.Count; ++k) { MeshObjectsHolder sortedMeshes = lod.meshObjectsHolders[k]; sortedMeshes.lodParent = lodParent; sortedMeshes.lodLevel = i; MeshCombineJobManager.instance.AddJob(meshCombiner, sortedMeshes, lodParentIndex > 0 ? lodT : lodParent.cellT, bounds.center); } } } else { for (int i = 0; i < 8; ++i) { if (cellsUsed[i]) { cells[i].CombineMeshes(meshCombiner, lodParentIndex); } } } }
public static GameObject SelectMeshObject(GameObject go, LODLevel lodLevel) { return(SelectNormalMesh(go, lodLevel)); }
public static Texture2D GenerateBillboardNew(GameObject prefab, int width, int height, int gridSizeX, int gridSizeY, Shader replacementShader, Color backgroundColor, Material minPostfilter, LODLevel billboardSourceLODLevel, Quaternion rotationOffset, bool generateAo, bool recalculateNormals, float normalBlendFactor) { #if UNITY_EDITOR bool fog = RenderSettings.fog; Unsupported.SetRenderSettingsUseFogNoDirty(false); #endif Vector3 renderPosition = new Vector3(0, 0, 0); const int invisibleLayer = 31; // used for instance and camera cull // atlas size var w = width * gridSizeX; var h = height * gridSizeY; var result = new Texture2D(w, h); var frameBuffer = new RenderTexture(width, height, 24); var filteredFrameBuffer = new RenderTexture(width, height, 24); var camGo = new GameObject("TempCamera"); var cam = camGo.AddComponent <Camera>(); //if (generateAo) //{ // ScreenSpaceAmbientOcclusion ao = camGo.AddComponent<ScreenSpaceAmbientOcclusion>(); // ao.m_Radius = 0.874f; // ao.m_SampleCount = ScreenSpaceAmbientOcclusion.SSAOSamples.High; // ao.m_OcclusionIntensity = 4; // ao.m_Blur = 4; // ao.m_Downsampling = 6; // ao.m_OcclusionAttenuation = 2; // ao.m_MinZ = 0.0001f; //} cam.clearFlags = CameraClearFlags.Color; backgroundColor.a = 0; cam.backgroundColor = backgroundColor; cam.renderingPath = RenderingPath.Forward; if (replacementShader != null) { cam.SetReplacementShader(replacementShader, ""); } //cam.renderingPath = RenderingPath.DeferredShading; //cam.gameObject.AddComponent<ReadSpecularOcclusion>(); var go = Instantiate(prefab, renderPosition, rotationOffset); if (recalculateNormals) { RecalculateMeshNormals(go, normalBlendFactor); } go.hideFlags = HideFlags.DontSave; LODGroup lodGroup = go.GetComponent <LODGroup>(); if (lodGroup) { if (lodGroup.fadeMode == LODFadeMode.SpeedTree) { lodGroup.ForceLOD((int)billboardSourceLODLevel); } } //MeshFilter meshFilter = go.GetComponent<MeshFilter>(); //RecalculateMeshNormals(meshFilter.mesh,0); var children = go.GetComponentsInChildren <Transform>(); foreach (var t in children) { t.gameObject.layer = invisibleLayer; } var bounds = CalculateBounds(go); float yOffset = FindLowestMeshYposition(go); cam.cullingMask = 1 << invisibleLayer; cam.orthographic = true; //var boundsSize = Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z) * 2; var boundsSize = Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z); cam.orthographicSize = boundsSize; cam.nearClipPlane = -boundsSize * 2; cam.farClipPlane = boundsSize * 2; //cam.renderingPath = RenderingPath.DeferredShading; //float aspect = (float) width/(float)height; //float orthographicSize = boundsSize; //cam.projectionMatrix = Matrix4x4.Ortho(-orthographicSize * aspect, orthographicSize * aspect, -orthographicSize, orthographicSize, 0, cam.farClipPlane); cam.targetTexture = frameBuffer; cam.transform.position = renderPosition + new Vector3(0, bounds.extents.y - yOffset / 2, 0); // + yOffset/2 var xAngleStep = 360f / gridSizeY / 4; var yAngleStep = 360f / gridSizeX; minPostfilter.SetInt("_UseGammaCorrection", 0); #if UNITY_EDITOR #if UNITY_2018_1_OR_NEWER #else if (PlayerSettings.colorSpace == ColorSpace.Linear) { minPostfilter.SetInt("_UseGammaCorrection", 1); } #endif #endif for (int i = 0; i < gridSizeX; i++) { for (int j = 0; j < gridSizeY; j++) { cam.transform.rotation = Quaternion.AngleAxis(yAngleStep * i, Vector3.up) * Quaternion.AngleAxis(xAngleStep * j, Vector3.right); cam.Render(); RenderTexture.active = filteredFrameBuffer; Graphics.Blit(frameBuffer, minPostfilter); result.ReadPixels(new Rect(0, 0, frameBuffer.width, frameBuffer.height), i * width, j * height); RenderTexture.active = null; } } DestroyImmediate(go); DestroyImmediate(camGo); result.Apply(); #if UNITY_EDITOR Unsupported.SetRenderSettingsUseFogNoDirty(fog); #endif return(result); }