public static GPUInstancerShaderBindings GetDefaultGPUInstancerShaderBindings() { GPUInstancerShaderBindings shaderBindings = Resources.Load <GPUInstancerShaderBindings>(GPUInstancerConstants.SETTINGS_PATH + GPUInstancerConstants.SHADER_BINDINGS_DEFAULT_NAME); if (shaderBindings == null) { shaderBindings = ScriptableObject.CreateInstance <GPUInstancerShaderBindings>(); shaderBindings.ResetShaderInstances(); #if UNITY_EDITOR if (!Application.isPlaying) { if (!System.IO.Directory.Exists(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.RESOURCES_PATH + GPUInstancerConstants.SETTINGS_PATH)) { System.IO.Directory.CreateDirectory(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.RESOURCES_PATH + GPUInstancerConstants.SETTINGS_PATH); } AssetDatabase.CreateAsset(shaderBindings, GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.RESOURCES_PATH + GPUInstancerConstants.SETTINGS_PATH + GPUInstancerConstants.SHADER_BINDINGS_DEFAULT_NAME + ".asset"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } #endif } return(shaderBindings); }
public virtual void SetDefaultGPUInstancerShaderBindings() { if (shaderBindings == null) { #if UNITY_EDITOR if (!Application.isPlaying) { Undo.RecordObject(this, "GPUInstancerShaderBindings instance generated"); } #endif shaderBindings = GetDefaultGPUInstancerShaderBindings(); } }
public static void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype, UnityAction <string> DrawHelpText, Object component, UnityAction OnEditorDataChanged, GPUInstancerShaderBindings shaderBindings, GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings) { GPUInstancerTreePrototype treePrototype = (GPUInstancerTreePrototype)selectedPrototype; EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_treeSettings, GPUInstancerEditorConstants.Styles.boldLabel); treePrototype.isApplyRotation = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useRandomTreeTotation, treePrototype.isApplyRotation); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useRandomTreeTotation); EditorGUILayout.EndVertical(); }
/// <summary> /// Generates instancing renderer data for a given GameObject, at the first LOD level. /// </summary> /// <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> public bool CreateRenderersFromGameObject(GPUInstancerPrototype prototype, GPUInstancerShaderBindings shaderBindings) { if (prototype.prefabObject == null) { return(false); } if (prototype.prefabObject.GetComponent <LODGroup>() != null) { return(GenerateLODsFromLODGroup(prototype.prefabObject.GetComponent <LODGroup>(), shaderBindings, prototype.isShadowCasting)); } else { if (instanceLODs == null || instanceLODs.Count == 0) { AddLod(); } return(CreateRenderersFromGameObject(0, prototype.prefabObject, shaderBindings, prototype.isShadowCasting)); } }
/// <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); }
public static void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype, UnityAction <string> DrawHelpText, UnityEngine.Object component, UnityAction OnEditorDataChanged, GPUInstancerShaderBindings shaderBindings, GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings, int detailLayer) { GPUInstancerDetailPrototype prototype = (GPUInstancerDetailPrototype)selectedPrototype; EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_detailProperties, GPUInstancerEditorConstants.Styles.boldLabel); EditorGUI.BeginChangeCheck(); prototype.detailDensity = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_detailDensity, prototype.detailDensity, 0.0f, terrainSettings.detailDensity); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailDensity); prototype.detailScale = EditorGUILayout.Vector4Field(GPUInstancerEditorConstants.TEXT_detailScale, prototype.detailScale); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailScale); prototype.noiseSpread = EditorGUILayout.FloatField(GPUInstancerEditorConstants.TEXT_noiseSpread, prototype.noiseSpread); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_noiseSpread); prototype.useCustomHealthyDryNoiseTexture = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomHealthyDryNoiseTexture, prototype.useCustomHealthyDryNoiseTexture); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomHealthyDryNoiseTexture); if (prototype.useCustomHealthyDryNoiseTexture) { prototype.healthyDryNoiseTexture = (Texture2D)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_healthyDryNoiseTexture, prototype.healthyDryNoiseTexture, typeof(Texture2D), false); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_healthyDryNoiseTexture); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(component, "Editor data changed."); if (OnEditorDataChanged != null) { OnEditorDataChanged(); } EditorUtility.SetDirty(prototype); } EditorGUI.BeginChangeCheck(); if (!prototype.usePrototypeMesh) { prototype.useCustomMaterialForTextureDetail = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomMaterialForTextureDetail, prototype.useCustomMaterialForTextureDetail); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomMaterialForTextureDetail); if (prototype.useCustomMaterialForTextureDetail) { prototype.textureDetailCustomMaterial = (Material)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_textureDetailCustomMaterial, prototype.textureDetailCustomMaterial, typeof(Material), false); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_textureDetailCustomMaterial); prototype.isBillboard = false; } else { prototype.textureDetailCustomMaterial = null; } } EditorGUILayout.EndVertical(); if (!prototype.usePrototypeMesh && !prototype.isBillboard) { EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_crossQuads, GPUInstancerEditorConstants.Styles.boldLabel); prototype.useCrossQuads = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_crossQuads, prototype.useCrossQuads); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_crossQuads); if (prototype.useCrossQuads) { prototype.quadCount = EditorGUILayout.IntSlider(GPUInstancerEditorConstants.TEXT_quadCount, prototype.quadCount, 2, 4); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_quadCount); if (!prototype.useCustomMaterialForTextureDetail) { prototype.billboardDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_billboardDistance, prototype.billboardDistance, 0.5f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistance); prototype.billboardDistanceDebug = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardDistanceDebug, prototype.billboardDistanceDebug); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistanceDebug); if (prototype.billboardDistanceDebug) { prototype.billboardDistanceDebugColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_billboardDistanceDebugColor, prototype.billboardDistanceDebugColor); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistanceDebugColor); } prototype.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_CQBillboardFaceCamPos, prototype.billboardFaceCamPos); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_CQBillboardFaceCamPos); } } else { prototype.quadCount = 1; } EditorGUILayout.EndVertical(); } else { prototype.useCrossQuads = false; } if (EditorGUI.EndChangeCheck()) { if (!prototype.usePrototypeMesh && prototype.useCustomMaterialForTextureDetail && prototype.textureDetailCustomMaterial != null) { if (!shaderBindings.IsShadersInstancedVersionExists(prototype.textureDetailCustomMaterial.shader.name)) { Shader instancedShader; if (GPUInstancerUtility.IsShaderInstanced(prototype.textureDetailCustomMaterial.shader)) { instancedShader = prototype.textureDetailCustomMaterial.shader; } else { instancedShader = GPUInstancerUtility.CreateInstancedShader(prototype.textureDetailCustomMaterial.shader, shaderBindings); } if (instancedShader != null) { shaderBindings.AddShaderInstance(prototype.textureDetailCustomMaterial.shader.name, instancedShader); } else { Debug.LogWarning("Can not create instanced version for shader: " + prototype.textureDetailCustomMaterial.shader.name + ". Standard Shader will be used instead."); } } } EditorUtility.SetDirty(prototype); } if (!prototype.usePrototypeMesh && !prototype.useCustomMaterialForTextureDetail) { EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_foliageShaderProperties, GPUInstancerEditorConstants.Styles.boldLabel); EditorGUI.BeginChangeCheck(); prototype.isBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isBillboard, prototype.isBillboard); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isBillboard); if (prototype.isBillboard) { prototype.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardFaceCamPos, prototype.billboardFaceCamPos); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFaceCamPos); } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(prototype); if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances) { GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer); } } EditorGUI.BeginChangeCheck(); prototype.detailHealthyColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_detailHealthyColor, prototype.detailHealthyColor); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailHealthyColor); prototype.detailDryColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_detailDryColor, prototype.detailDryColor); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailDryColor); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(component, "Editor data changed."); if (OnEditorDataChanged != null) { OnEditorDataChanged(); } if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances) { GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer); } EditorUtility.SetDirty(prototype); } EditorGUI.BeginChangeCheck(); prototype.ambientOcclusion = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_ambientOcclusion, prototype.ambientOcclusion, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_ambientOcclusion); prototype.gradientPower = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_gradientPower, prototype.gradientPower, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_gradientPower); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_windSettings, GPUInstancerEditorConstants.Styles.boldLabel); prototype.windIdleSway = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windIdleSway, prototype.windIdleSway, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windIdleSway); prototype.windWavesOn = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_windWavesOn, prototype.windWavesOn); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWavesOn); if (prototype.windWavesOn) { prototype.windWaveTintColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_windWaveTintColor, prototype.windWaveTintColor); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveTintColor); prototype.windWaveSize = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveSize, prototype.windWaveSize, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveSize); prototype.windWaveTint = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveTint, prototype.windWaveTint, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveTint); prototype.windWaveSway = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveSway, prototype.windWaveSway, 0f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveSway); } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(prototype); if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances) { GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer); } } EditorGUILayout.EndVertical(); } }
public virtual void DrawGPUInstancerPrototypeBillboardSettings(GPUInstancerPrototype selectedPrototype, GPUInstancerShaderBindings shaderBindings, GPUInstancerBillboardAtlasBindings billboardAtlasBindings) { if (selectedPrototype.isBillboardDisabled || (selectedPrototype is GPUInstancerDetailPrototype && !((GPUInstancerDetailPrototype)selectedPrototype).usePrototypeMesh)) { if (selectedPrototype.useGeneratedBillboard) { selectedPrototype.useGeneratedBillboard = false; } if (selectedPrototype.billboard != null) { selectedPrototype.billboard = null; } return; } if (Event.current.type == EventType.Repaint && !selectedPrototype.checkedForBillboardExtentions) { selectedPrototype.checkedForBillboardExtentions = true; if (CheckForBillboardExtentions(selectedPrototype, billboardAtlasBindings)) { return; } } EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_billboardSettings, GPUInstancerEditorConstants.Styles.boldLabel); selectedPrototype.useGeneratedBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useGeneratedBillboard, selectedPrototype.useGeneratedBillboard); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useGeneratedBillboard); if (selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard == null) { selectedPrototype.billboard = new GPUInstancerBillboard(); } else if (!selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard != null) { if (selectedPrototype.billboard.albedoAtlasTexture != null) { billboardAtlasBindings.DeleteBillboardTextures(selectedPrototype); } if (!selectedPrototype.billboard.useCustomBillboard) { selectedPrototype.billboard = null; } } if (selectedPrototype.useGeneratedBillboard) { if (selectedPrototype.treeType != GPUInstancerTreeType.SpeedTree && selectedPrototype.treeType != GPUInstancerTreeType.TreeCreatorTree && selectedPrototype.treeType != GPUInstancerTreeType.SoftOcclusionTree && !selectedPrototype.billboard.useCustomBillboard) { EditorGUILayout.HelpBox(GPUInstancerEditorConstants.HELPTEXT_unsupportedBillboardWarning, MessageType.Warning); } bool previousUseCustomBillboard = selectedPrototype.billboard.useCustomBillboard; selectedPrototype.billboard.useCustomBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomBillboard, selectedPrototype.billboard.useCustomBillboard); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomBillboard); if (selectedPrototype.billboard.useCustomBillboard) { selectedPrototype.billboard.customBillboardMesh = (Mesh)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_customBillboardMesh, selectedPrototype.billboard.customBillboardMesh, typeof(Mesh), false); selectedPrototype.billboard.customBillboardMaterial = (Material)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_customBillboardMaterial, selectedPrototype.billboard.customBillboardMaterial, typeof(Material), false); selectedPrototype.billboard.isBillboardShadowCasting = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isBillboardShadowCasting, selectedPrototype.billboard.isBillboardShadowCasting); if (!previousUseCustomBillboard && selectedPrototype.billboard.albedoAtlasTexture != null) { billboardAtlasBindings.DeleteBillboardTextures(selectedPrototype); } if (shaderBindings != null && selectedPrototype.billboard.customBillboardMaterial != null) { if (!shaderBindings.IsShadersInstancedVersionExists(selectedPrototype.billboard.customBillboardMaterial.shader.name)) { Shader instancedShader = GPUInstancerUtility.CreateInstancedShader(selectedPrototype.billboard.customBillboardMaterial.shader, shaderBindings); if (instancedShader != null) { shaderBindings.AddShaderInstance(selectedPrototype.billboard.customBillboardMaterial.shader.name, instancedShader); } } } } else { if (selectedPrototype.billboard.customBillboardInLODGroup) { selectedPrototype.billboard.customBillboardInLODGroup = false; } selectedPrototype.billboard.billboardQuality = (BillboardQuality)EditorGUILayout.Popup(GPUInstancerEditorConstants.TEXT_billboardQuality, (int)selectedPrototype.billboard.billboardQuality, GPUInstancerEditorConstants.TEXT_BillboardQualityOptions); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardQuality); switch (selectedPrototype.billboard.billboardQuality) { case BillboardQuality.Low: selectedPrototype.billboard.atlasResolution = 1024; break; case BillboardQuality.Mid: selectedPrototype.billboard.atlasResolution = 2048; break; case BillboardQuality.High: selectedPrototype.billboard.atlasResolution = 4096; break; case BillboardQuality.VeryHigh: selectedPrototype.billboard.atlasResolution = 8192; break; } selectedPrototype.billboard.frameCount = EditorGUILayout.IntSlider(GPUInstancerEditorConstants.TEXT_billboardFrameCount, selectedPrototype.billboard.frameCount, 8, 32); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFrameCount); selectedPrototype.billboard.frameCount = Mathf.NextPowerOfTwo(selectedPrototype.billboard.frameCount); selectedPrototype.billboard.billboardBrightness = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_billboardBrightness, selectedPrototype.billboard.billboardBrightness, 0.0f, 1.0f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardBrightness); selectedPrototype.billboard.isOverridingOriginalCutoff = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_overrideOriginalCutoff, selectedPrototype.billboard.isOverridingOriginalCutoff); if (selectedPrototype.billboard.isOverridingOriginalCutoff) { selectedPrototype.billboard.cutoffOverride = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_overrideCutoffAmount, selectedPrototype.billboard.cutoffOverride, 0.01f, 1.0f); } else { selectedPrototype.billboard.cutoffOverride = -1f; } DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_overrideOriginalCutoff); } if (!selectedPrototype.billboard.customBillboardInLODGroup) { bool hasLODGroup = selectedPrototype.prefabObject.GetComponent <LODGroup>() != null; bool speedTreeBillboard = selectedPrototype.treeType == GPUInstancerTreeType.SpeedTree && hasLODGroup && selectedPrototype.prefabObject.GetComponentInChildren <BillboardRenderer>() != null; if (hasLODGroup && !speedTreeBillboard) { selectedPrototype.billboard.replaceLODCullWithBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_replaceLODCull, selectedPrototype.billboard.replaceLODCullWithBillboard); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_replaceLODCull); } if ((!hasLODGroup || !selectedPrototype.billboard.replaceLODCullWithBillboard) && !speedTreeBillboard) { selectedPrototype.billboard.billboardDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_generatedBillboardDistance, selectedPrototype.billboard.billboardDistance, 0.01f, 1f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_generatedBillboardDistance); } } if (!selectedPrototype.billboard.useCustomBillboard) { selectedPrototype.billboard.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardFaceCamPos, selectedPrototype.billboard.billboardFaceCamPos); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFaceCamPos); if (selectedPrototype.billboard.albedoAtlasTexture == null) { GPUInstancerUtility.AssignBillboardBinding(selectedPrototype, billboardAtlasBindings); } EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_billboardAlbedo, selectedPrototype.billboard.albedoAtlasTexture, typeof(GameObject), false); EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_billboardNormal, selectedPrototype.billboard.normalAtlasTexture, typeof(GameObject), false); EditorGUI.EndDisabledGroup(); } GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); if (!selectedPrototype.billboard.useCustomBillboard) { GPUInstancerEditorConstants.DrawColoredButton(selectedPrototype.billboard.albedoAtlasTexture == null ? GPUInstancerEditorConstants.Contents.generateBillboard : GPUInstancerEditorConstants.Contents.regenerateBillboard, GPUInstancerEditorConstants.Colors.green, Color.white, FontStyle.Bold, Rect.zero, () => { GPUInstancerUtility.GeneratePrototypeBillboard(selectedPrototype, billboardAtlasBindings, selectedPrototype.billboard.albedoAtlasTexture != null); }); } if ((!selectedPrototype.billboard.useCustomBillboard && selectedPrototype.billboard.albedoAtlasTexture != null) || (selectedPrototype.billboard.useCustomBillboard && selectedPrototype.billboard.customBillboardMesh != null && selectedPrototype.billboard.customBillboardMaterial != null)) { GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.showBillboard, GPUInstancerEditorConstants.Colors.lightBlue, Color.white, FontStyle.Bold, Rect.zero, () => { GPUInstancerUtility.ShowBillboardQuad(selectedPrototype, Vector3.zero); }); } EditorGUILayout.EndHorizontal(); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_regenerateBillboard); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_showBillboard); } if (selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard != null && selectedPrototype.billboard.useCustomBillboard && GPUInstancerDefines.billboardExtentions != null && GPUInstancerDefines.billboardExtentions.Count > 0) { GUILayout.Space(10); EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel("External Billboard Generators", GPUInstancerEditorConstants.Styles.boldLabel); GUILayout.Space(5); foreach (Extention.GPUInstancerBillboardExtention billboardExtention in GPUInstancerDefines.billboardExtentions) { try { EditorGUILayout.BeginHorizontal(); GUILayout.Label(billboardExtention.GetTitle(), GPUInstancerEditorConstants.Styles.label); GPUInstancerEditorConstants.DrawColoredButton(new GUIContent(billboardExtention.GetButtonText()), GPUInstancerEditorConstants.Colors.green, Color.white, FontStyle.Bold, Rect.zero, () => { _redirectObject = billboardExtention.GenerateBillboard(selectedPrototype.prefabObject); selectedPrototype.checkedForBillboardExtentions = false; }); EditorGUILayout.EndHorizontal(); GUILayout.Space(5); } catch (System.Exception e) { EditorUtility.ClearProgressBar(); Debug.LogError("Error generating billboard: " + e.Message + " StackTrace:" + e.StackTrace); } } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); }
public virtual void DrawGPUInstancerPrototypeBox(GPUInstancerPrototype selectedPrototype, bool isFrustumCulling, bool isOcclusionCulling, GPUInstancerShaderBindings shaderBindings, GPUInstancerBillboardAtlasBindings billboardAtlasBindings) { if (selectedPrototype == null) { return; } EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); // title Rect foldoutRect = GUILayoutUtility.GetRect(0, 20, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false)); foldoutRect.x += 12; showPrototypeBox = EditorGUI.Foldout(foldoutRect, showPrototypeBox, selectedPrototype.ToString(), true, GPUInstancerEditorConstants.Styles.foldout); if (!showPrototypeBox) { EditorGUILayout.EndVertical(); return; } if (!string.IsNullOrEmpty(selectedPrototype.warningText)) { EditorGUILayout.HelpBox(selectedPrototype.warningText, MessageType.Error); if (selectedPrototype.warningText.StartsWith("Can not create instanced version for shader")) { GPUInstancerEditorConstants.DrawColoredButton(new GUIContent("Go to Unity Archive"), GPUInstancerEditorConstants.Colors.lightred, Color.white, FontStyle.Bold, Rect.zero, () => { Application.OpenURL("https://unity3d.com/get-unity/download/archive"); }); GUILayout.Space(10); } } EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_prefabObject, selectedPrototype.prefabObject, typeof(GameObject), false); EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_prototypeSO, selectedPrototype, typeof(GPUInstancerPrototype), false); EditorGUI.EndDisabledGroup(); EditorGUI.BeginChangeCheck(); #region Shadows EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_shadows, GPUInstancerEditorConstants.Styles.boldLabel); EditorGUI.BeginDisabledGroup(Application.isPlaying); selectedPrototype.isShadowCasting = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isShadowCasting, selectedPrototype.isShadowCasting); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isShadowCasting); EditorGUI.EndDisabledGroup(); if (selectedPrototype.isShadowCasting) { if (selectedPrototype is GPUInstancerPrefabPrototype) { EditorGUI.BeginDisabledGroup(Application.isPlaying); selectedPrototype.useOriginalShaderForShadow = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useOriginalShaderForShadow, selectedPrototype.useOriginalShaderForShadow); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useOriginalShaderForShadow); EditorGUI.EndDisabledGroup(); } if (!(selectedPrototype is GPUInstancerDetailPrototype)) { selectedPrototype.useCustomShadowDistance = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomShadowDistance, selectedPrototype.useCustomShadowDistance); if (selectedPrototype.useCustomShadowDistance) { selectedPrototype.shadowDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_shadowDistance, selectedPrototype.shadowDistance, 0.0f, QualitySettings.shadowDistance); } DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomShadowDistance); if (selectedPrototype.prefabObject != null && selectedPrototype.prefabObject.GetComponent <LODGroup>() != null) { LODGroup lodGroup = selectedPrototype.prefabObject.GetComponent <LODGroup>(); List <GUIContent> optionsList = GPUInstancerEditorConstants.Contents.LODs.GetRange(0, lodGroup.lodCount); optionsList.Add(GPUInstancerEditorConstants.Contents.LODs[8]); GUIContent[] options = optionsList.ToArray(); int index = 0; for (int i = 0; i < lodGroup.lodCount; i++) { index = i * 4; if (i >= 4) { index = (i - 4) * 4 + 1; } selectedPrototype.shadowLODMap[index] = EditorGUILayout.Popup(GPUInstancerEditorConstants.Contents.shadowLODs[i], selectedPrototype.shadowLODMap[index], options); } } selectedPrototype.cullShadows = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_cullShadows, selectedPrototype.cullShadows); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_cullShadows); } } EditorGUILayout.EndVertical(); #endregion Shadows #region Culling EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_culling, GPUInstancerEditorConstants.Styles.boldLabel); selectedPrototype.maxDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_maxDistance, selectedPrototype.maxDistance, 0.0f, GetMaxDistance(selectedPrototype)); DrawHelpText(selectedPrototype is GPUInstancerDetailPrototype ? GPUInstancerEditorConstants.HELPTEXT_maxDistanceDetail : GPUInstancerEditorConstants.HELPTEXT_maxDistance); if (isFrustumCulling) { selectedPrototype.isFrustumCulling = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isFrustumCulling, selectedPrototype.isFrustumCulling); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isFrustumCulling); selectedPrototype.frustumOffset = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_frustumOffset, selectedPrototype.frustumOffset, 0.0f, 0.5f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_frustumOffset); } if (isOcclusionCulling) { selectedPrototype.isOcclusionCulling = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isOcclusionCulling, selectedPrototype.isOcclusionCulling); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isOcclusionCulling); } if (isFrustumCulling || isOcclusionCulling) { selectedPrototype.minCullingDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_minCullingDistance, selectedPrototype.minCullingDistance, 0, 100); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_minCullingDistance); } EditorGUILayout.EndVertical(); #endregion Culling #region LOD if (selectedPrototype.prefabObject != null && (selectedPrototype.prefabObject.GetComponent <LODGroup>() != null || selectedPrototype.useGeneratedBillboard)) { EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_LOD, GPUInstancerEditorConstants.Styles.boldLabel); EditorGUI.BeginDisabledGroup(Application.isPlaying); selectedPrototype.isLODCrossFade = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isLODCrossFade, selectedPrototype.isLODCrossFade); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isLODCrossFade); if (selectedPrototype.isLODCrossFade) { selectedPrototype.isLODCrossFadeAnimate = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isLODCrossFadeAnimate, selectedPrototype.isLODCrossFadeAnimate); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isLODCrossFadeAnimate); if (!selectedPrototype.isLODCrossFadeAnimate) { selectedPrototype.lodFadeTransitionWidth = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_lodFadeTransitionWidth, selectedPrototype.lodFadeTransitionWidth, 0.0f, 1.0f); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_lodFadeTransitionWidth); } } selectedPrototype.lodBiasAdjustment = EditorGUILayout.FloatField(GPUInstancerEditorConstants.TEXT_lodBiasAdjustment, selectedPrototype.lodBiasAdjustment); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_lodBiasAdjustment); EditorGUI.EndDisabledGroup(); EditorGUILayout.EndVertical(); } #endregion LOD EditorGUI.BeginDisabledGroup(Application.isPlaying); DrawGPUInstancerPrototypeInfo(selectedPrototype); DrawGPUInstancerPrototypeBillboardSettings(selectedPrototype, shaderBindings, billboardAtlasBindings); DrawGPUInstancerPrototypeActions(); DrawGPUInstancerPrototypeAdvancedActions(); if (EditorGUI.EndChangeCheck() && selectedPrototype != null) { EditorUtility.SetDirty(selectedPrototype); } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndVertical(); }