using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif [ExecuteInEditMode] public class BakedVolumetricArea : MonoBehaviour { [SerializeField, Tooltip("Texel density per meter. Controls the resolution of the baked texture.")] public float TexelDensity = 5; // [SerializeField, Tooltip("Texel density ratio scaler. Multiples Texel density per dimension")] Vector3 TexelRatio = new Vector3(1,1,1); [SerializeField] public Vector3 BoxScale = new Vector3(10,5,10); [SerializeField] public Texture3D bakedTexture; [SerializeField] public Vector3Int NormalizedTexelDensity; //exposed to see target resolution [HideInInspector,SerializeField] public Vector3 NormalizedScale; [HideInInspector,SerializeField] public Vector3 Corner; private void OnEnable() { VolumetricRegisters.RegisterVolumetricArea(this); } private void OnDisable() { VolumetricRegisters.UnregisterVolumetricArea(this); #if UNITY_EDITOR DisableDebugMesh(); #endif } private void OnDestroy() { VolumetricRegisters.UnregisterVolumetricArea(this); #if UNITY_EDITOR DisableDebugMesh(); #endif } private void OnValidate() { //Check to see if the same and change if different Vector3 tempscale = Vector3.Scale(gameObject.transform.localScale, BoxScale); if (NormalizedScale != tempscale) NormalizedScale = tempscale; Vector3 UnclampedResolution = Vector3.Scale(NormalizedScale, new Vector3(TexelDensity, TexelDensity, TexelDensity)) ; float Maxres = Mathf.Max(UnclampedResolution.x, UnclampedResolution.y, UnclampedResolution.z); float rescaler = Mathf.Min(1, 4096 / Maxres); // Debug.Log("Clamped resolution to " + Mathf.RoundToInt(UnclampedResolution.x * rescaler)); Vector3Int tempTexelDensity = new Vector3Int { x = ((Mathf.RoundToInt(UnclampedResolution.x * rescaler) + 3) / 4 ) * 4, y = ((Mathf.RoundToInt(UnclampedResolution.y * rescaler) + 3) / 4 ) * 4, z = ((Mathf.RoundToInt(UnclampedResolution.z * rescaler) + 3) / 4 ) * 4, }; //if (tempTexelDensity.x > 8096 || tempTexelDensity.y > 8096 || tempTexelDensity.z > 8096) //{ //} // if (NormalizedTexelDensity != tempTexelDensity) NormalizedTexelDensity = tempTexelDensity; Corner = transform.position - (NormalizedScale * 0.5f); } #if UNITY_EDITOR private void Awake() { if (UnityEditor.EditorApplication.isPlaying) DisableDebugMesh(); } private void OnDrawGizmos() { //if (!UnityEditor.Selection.Contains(gameObject)) DisableDebugMesh(); Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.5f); Gizmos.matrix = Matrix4x4.TRS(gameObject.transform.position, Quaternion.identity, NormalizedScale); Gizmos.DrawWireCube(Vector3.zero, Vector3.one); //Gizmos.DrawWireCube(new Vector3( // (0.0f /TexelDensity.x) - (TexelDensity.x * 0.5f), // (0.0f /TexelDensity.y) - (TexelDensity.y * 0.5f), // (0.0f /TexelDensity.z) - (TexelDensity.x * 0.5f)) , new Vector3(1 / TexelDensity.x, 1 / TexelDensity.y, 1 / TexelDensity.z) ); } private void OnDrawGizmosSelected() { /* if (DEBUG) { if (UnityEditor.Selection.Contains(gameObject)) { EnableDebugMesh(); } else { DisableDebugMesh(); } } else if (DebugCube != null) { DisableDebugMesh(); } */ OnValidate(); // Gizmos.DrawWireSphere(transform.position - (NormalizedScale* 0.5f), .5f); Gizmos.color = new Color(0.5f,0.5f,0.5f,0.25f); Gizmos.matrix = Matrix4x4.TRS(gameObject.transform.position, Quaternion.identity, NormalizedScale); if (!DEBUG) Gizmos.DrawCube(Vector3.zero, Vector3.one); Gizmos.color = Color.white; Gizmos.DrawWireCube(Vector3.zero, Vector3.one); // Gizmos.DrawWireSphere(Corner, 0.5f); } [HideInInspector] public bool DEBUG; [HideInInspector] public static bool VisStateGlobal; [SerializeField,HideInInspector] GameObject DebugCube; [SerializeField,HideInInspector] Material mat; [HideInInspector,SerializeField] public bool MarkDebugCubeForDelete; private bool VisStateLocal; public void EnableDebugMesh() { if (bakedTexture == null || DebugCube != null || UnityEditor.EditorApplication.isPlaying) return; MarkDebugCubeForDelete = false; DebugCube = GameObject.CreatePrimitive(PrimitiveType.Cube); DebugCube.transform.parent = gameObject.transform; DebugCube.transform.localPosition = Vector3.zero; DebugCube.transform.localScale = BoxScale; DebugCube.transform.rotation = Quaternion.identity; DestroyImmediate(DebugCube.GetComponent()); Renderer rnd = DebugCube.GetComponent(); mat = new Material(Shader.Find("hidden/VolumetricPreview")); mat.SetTexture("_Volume", bakedTexture); mat.renderQueue = 3000; rnd.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off; rnd.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; rnd.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; rnd.material = mat; DebugCube.hideFlags = HideFlags.HideAndDontSave; } public void DisableDebugMesh() { if (DebugCube == null) return; MarkDebugCubeForDelete = true; //DestroyImmediate(DebugCube); //DestroyImmediate(mat); } public void RefreshDebugMesh() { DisableDebugMesh(); EnableDebugMesh(); } [ExecuteInEditMode] void LateUpdate() { if (VisStateLocal != VisStateGlobal) { VisStateLocal = VisStateGlobal; if (VisStateGlobal) { EnableDebugMesh(); } else { DisableDebugMesh(); } } if (MarkDebugCubeForDelete && DebugCube != null) { MarkDebugCubeForDelete = false; DestroyImmediate(DebugCube); DestroyImmediate(mat); } } [MenuItem("GameObject/Light/Baked Volumetric Area", false, 10)] static void CreateBakedVolumetricArea(MenuCommand menuCommand) { // Create a custom game object GameObject go = new GameObject("Baked Volumetric Area"); // Ensure it gets reparented if this was a context click (otherwise does nothing) GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject); // Register the creation in the undo system go.AddComponent(); Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); Selection.activeObject = go; } #endif }