// -------------------------------------------------- // BAKE #if UNITY_EDITOR private IEnumerator BakePortalData() { // Generate Portal data m_Completion = 0.0f; m_BakeTime = 0.0f; m_BakeStartTime = Time.realtimeSinceStartup; m_BakeState = BakeState.Occluders; var occluders = PortalPrepareUtil.GetOccluderData(); m_BakeState = BakeState.Volumes; var volumes = PortalPrepareUtil.GetVolumeData(m_VolumeMode, m_Subdivisions); m_BakeState = BakeState.Visibility; List <VisbilityData> visibilityTable = null; yield return(EditorCoroutines.StartCoroutine(GenerateVisibilityTable(occluders, volumes, value => visibilityTable = value), this)); // Serialize m_PortalData = new SerializablePortalData() { occluders = occluders, volumes = volumes, visibilityTable = visibilityTable }; // Finalize m_BakeState = BakeState.Active; m_Completion = 1.0f; m_BakeTime = Time.realtimeSinceStartup - m_BakeStartTime; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
public void OnClickBake() { var passedRenderers = new List <MeshRenderer>(); var rays = new List <RayDebug>(); m_Completion = 0.0f; m_BakeState = BakeState.Volumes; var staticRenderers = PortalPrepareUtil.GetStaticOccludeeRenderers(); m_SerializableVolumes = PortalPrepareUtil.GetVolumeData(VolumeMode.Auto, 0); m_BakeState = BakeState.Visibility; var rayCount = PortalVisibilityUtil.CalculateRayCount(m_RayDensity, m_SerializableVolumes[0].scaleWS); for (int r = 0; r < rayCount; r++) { var rayPosition = PortalVisibilityUtil.GetRandomPointWithinVolume(m_SerializableVolumes[0]); var rayDirection = PortalVisibilityUtil.RandomSphericalDistributionVector(); rays.Add(new RayDebug(rayPosition, rayDirection)); foreach (MeshRenderer renderer in staticRenderers) { if (PortalVisibilityUtil.CheckAABBIntersection(rayPosition, rayDirection, renderer.bounds)) { passedRenderers.AddIfUnique(renderer); } } } m_PassedRenderers = passedRenderers.ToArray(); m_Rays = rays.ToArray(); m_BakeState = BakeState.Active; m_Completion = 1.0f; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
public void OnClickCancel() { EditorCoroutines.StopAllCoroutines(this); ClearOccluderData(); ClearVolumeData(); m_BakeState = BakeState.Empty; m_Completion = 0; }
public void OnClickCancel() { m_SerializableOccluders = null; m_BakeState = BakeState.Empty; m_Completion = 0.0f; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
public void OnClickBake() { m_Completion = 0.0f; m_BakeState = BakeState.Occluders; m_SerializableOccluders = PortalPrepareUtil.GetOccluderData(); m_BakeState = BakeState.Active; m_Completion = 1.0f; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
public void OnClickBake() { m_Completion = 0.0f; m_BakeState = BakeState.Volumes; m_SerializableVolumes = PortalPrepareUtil.GetVolumeData(m_VolumeMode, m_Subdivisions); m_BakeState = BakeState.Active; m_Completion = 1.0f; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
private IEnumerator GenerateOcclusion() { m_StaticRenderers = Utils.GetStaticRenderers(); // Generate Occluder Data m_BakeState = BakeState.Occluders; ClearOccluderData(); yield return(EditorCoroutines.StartCoroutine(Utils.BuildOccluderProxyGeometry(transform, m_StaticRenderers, value => m_Occluders = value, this, m_OccluderTag), this)); // Generate Volume Data m_BakeState = BakeState.Volumes; ClearVolumeData(); switch (m_VolumeMode) { case VolumeMode.Automatic: // Generate Hierarchical Volume Grid Bounds bounds = Utils.GetSceneBounds(m_StaticRenderers); yield return(EditorCoroutines.StartCoroutine(Utils.BuildHierarchicalVolumeGrid(bounds, m_VolumeDensity, value => m_VolumeData = value, this), this)); break; case VolumeMode.Manual: // Generate Manual Volumes yield return(EditorCoroutines.StartCoroutine(Utils.BuildManualVolumeGrid(m_ManualVolumes, value => m_VolumeData = value), this)); break; } if (m_VolumeData != null) { // Generate Occlusion Data m_BakeState = BakeState.Occlusion; int volumeDensity = m_VolumeMode == VolumeMode.Automatic ? m_VolumeDensity : 1; VolumeData[] smallestVolumes = Utils.GetLowestSubdivisionVolumes(m_VolumeData, volumeDensity); for (int i = 0; i < smallestVolumes.Length; i++) { m_Completion = (float)(i + 1) / (float)smallestVolumes.Length; m_ActiveVolume = smallestVolumes[i]; yield return(EditorCoroutines.StartCoroutine(Utils.BuildOcclusionForVolume(smallestVolumes[i].bounds, m_RayDensity, m_StaticRenderers, m_Occluders, value => smallestVolumes[i].renderers = value, this, m_FilterAngle), this)); } m_BakeState = BakeState.Active; } else { Debug.LogError("Occlusion Bake Failed. Check Settings."); m_BakeState = BakeState.Empty; m_Completion = 0; } m_ActiveVolume = null; yield return(null); }
/// <summary> /// Cancel any active bake and clear all data. Editor only. /// </summary> public void OnClickCancel() { // Abort if in play mode as save actions arent valid if (Application.isPlaying) { Debug.LogWarning("Cannot modifiy Portal data while in Play mode. Aborting."); return; } // Reset all EditorCoroutines.StopAllCoroutines(this); m_BakeState = BakeState.Empty; m_PortalData = null; m_Completion = 0; UnityEditor.SceneView.RepaintAll(); UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty(); }
private IEnumerator GenerateVisibilityTable(SerializableOccluder[] occluders, SerializableVolume[] volumes, Action <List <VisbilityData> > result) { // Abort bake if input data is invalid if (occluders == null || volumes == null) { Debug.LogError("Bake prepare data is invalid. Check bake output and retry."); m_BakeState = BakeState.Empty; m_Completion = 0; yield return(null); } // Setup m_BakeState = BakeState.Visibility; var visibilityTable = new List <VisbilityData>(); int totalRays = 0; int passedRays = 0; int occludedRays = 0; // Get Occluder proxies, volumes and occludees var occluderProxies = PortalPrepareUtil.GetOccluderProxies(occluders); var lowestSubdivisionVolumes = PortalPrepareUtil.FilterVolumeDataNoChildren(volumes); var occludees = PortalPrepareUtil.GetStaticOccludeeRenderers(); // Build Visibility for Volumes for (int v = 0; v < lowestSubdivisionVolumes.Length; v++) { // Setup m_Completion = (float)(v + 1) / (float)lowestSubdivisionVolumes.Length; var volume = lowestSubdivisionVolumes[v]; var passedObjects = new List <GameObject>(); var debugData = new List <VisbilityData.Debug>(); // Iterate random rays based on volume density var rayCount = PortalVisibilityUtil.CalculateRayCount(m_RayDensity, volume.scaleWS); totalRays += rayCount; for (int r = 0; r < rayCount; r++) { // Get a random ray and a list of cone filtered renderers to test var rayPosition = PortalVisibilityUtil.GetRandomPointWithinVolume(volume); var rayDirection = PortalVisibilityUtil.RandomSphericalDistributionVector(); var filteredOccludees = PortalVisibilityUtil.FilterRenderersByConeAngle(occludees, rayPosition, rayDirection, m_ConeAngle); for (int f = 0; f < filteredOccludees.Length; f++) { // Test ray against renderer AABB if (PortalVisibilityUtil.CheckAABBIntersection(rayPosition, rayDirection, filteredOccludees[f].bounds)) { // Test ray against occluders Vector3 hitPos; bool passed = PortalVisibilityUtil.CheckOcclusion(occluderProxies, filteredOccludees[f], rayPosition, rayDirection, out hitPos); switch (passed) { case true: passedObjects.AddIfUnique(filteredOccludees[f].gameObject); passedRays++; break; case false: occludedRays++; break; } // Track visibility debug data debugData.Add(new VisbilityData.Debug() { source = rayPosition, hit = hitPos, direction = rayDirection, distance = Vector3.Distance(rayPosition, filteredOccludees[f].transform.position), isHit = !passed, }); } } } // Add to VisibilityTable visibilityTable.Add(new VisbilityData(volume, passedObjects.ToArray(), debugData.ToArray())); yield return(null); } // Clear Occluder proxies for (int i = 0; i < occluderProxies.Length; i++) { PortalCoreUtil.Destroy(occluderProxies[i].gameObject); } // Save statistics var occludeeCount = PortalCoreUtil.GetUniqueOccludeeCount(visibilityTable); m_OccludeeStatistics = new Vector2(occludeeCount, occludees.Length); m_RayStatistics = new Vector3(passedRays, occludedRays, totalRays); // Finalize result(visibilityTable); }
private IEnumerator CookieBaking() { yield return(null); var resolution = s_resolutionOptions[s_selectedCookieResolution]; // We only want to use GameObjects that are within the outer radius that we have set. So, a quick test // to see if something is within the ball park would be to check if their bounding box insersects with // a bounding box that contains the outer radius. Once that has been done, we can take a closer look at // what's left. var meshRenders = FindObjectsOfType <MeshRenderer>(); var lightCenter = s_currentLightComponent.transform.position; var lightBoundingBox = new Bounds(lightCenter, 2.0f * s_outerRadius * Vector3.one); var intersectingBounds = new List <MeshRenderer>(); foreach (var meshRenderer in meshRenders) { var otherBounds = meshRenderer.bounds; if (otherBounds.Intersects(lightBoundingBox)) { intersectingBounds.Add(meshRenderer); } } yield return(null); // Now, we can limit things a bit more by finding the point within our mesh bounds that is nearset to // the light's center. We then check this point to see if it's within the distance of our outer radius. var intersectingOuterRadius = new List <MeshRenderer>(); foreach (var meshRenderer in intersectingBounds) { var otherBounds = meshRenderer.bounds; var nearsetPointToLight = otherBounds.ClosestPoint(lightCenter); if ((nearsetPointToLight - lightCenter).sqrMagnitude <= (s_outerRadius * s_outerRadius)) { intersectingOuterRadius.Add(meshRenderer); } } yield return(null); var processMeshRenderer = intersectingBounds; var processMeshFilter = new List <MeshFilter>(); // We're reusing the List from intersectingBounds and placing it under a more appropriate name. // Basically, we're reusing a piece of memory that's no longer needed instead of allocating a new List // with a new array. Also, this array shouldn't need to be resized to something larger because it // already a capacity that is greater than or equal to the number of items we will be processing. processMeshRenderer.Clear(); intersectingBounds = null; // Also, while we're at it, lets make sure that we are only baking items that are static. After all, // what's the point of baking the shadow casting item that might not be there? foreach (var meshRender in intersectingOuterRadius) { var gameObject = meshRender.gameObject; // If the gameObject isn't static, than it can be moved. Since we are not updating the cookie at // runtime, having a moving object would be bad. if (!gameObject.isStatic) { continue; } // The mesh for our object is inside the MeshFilter, so we need that to get the mesh. Also, since we're // dealing with static meshes, then we really shouldn't be dealing with any Skinned Mesh Renderers. var meshFilter = gameObject.GetComponent <MeshFilter>(); if (meshFilter == null) { continue; } // If there's no mesh, then what are we even bothering with this? if (meshFilter.sharedMesh == null) { continue; } processMeshRenderer.Add(meshRender); processMeshFilter.Add(meshFilter); } yield return(null); RenderTexture renderTexture = new RenderTexture(resolution, // Width resolution, // Height 0, // Depth buffer (none) RenderTextureFormat.ARGBFloat, // Use a full 32-bit float for each pixel chanel RenderTextureReadWrite.Linear) // Use linear lighting instead of gama { anisoLevel = 0, antiAliasing = 1, autoGenerateMips = false, enableRandomWrite = true, filterMode = FilterMode.Point, memorylessMode = RenderTextureMemoryless.None, // We want to be able to read this back into the system memory, so setting this to not use memory is not an option. wrapMode = TextureWrapMode.Clamp }; renderTexture.Create(); // Todo: With this design, items that use the same mesh will replicate the mesh verts and triangle index // arrays. I need to add a way to check if we have already added a mesh and if so, pull up the triangle // index array information to pass along to the meshRefDatum. var meshObjecRefData = new List <MeshObject>(processMeshRenderer.Count); var indexList = new List <int>(); var vertexList = new List <Vector3>(processMeshRenderer.Count * 50); for (int i = 0; i < processMeshRenderer.Count; i++) { var mesh = processMeshFilter[i].sharedMesh; var meshVerts = mesh.vertices; var meshTriangleIndices = mesh.triangles; var meshRefDatum = new MeshObject() { LocalToWorldMatrix = processMeshRenderer[i].localToWorldMatrix, IndicesOffset = indexList.Count, // The starting index of the vert-index for this object's mesh. IndicesCount = meshTriangleIndices.Length, // The number of indices used to form all of the mesh triangles. VerticesOffset = vertexList.Count }; meshObjecRefData.Add(meshRefDatum); vertexList.AddRange(meshVerts); indexList.AddRange(meshTriangleIndices); } yield return(null); ComputeBuffer objectBuffer = new ComputeBuffer(meshObjecRefData.Count, 76); ComputeBuffer vertexBuffer = new ComputeBuffer(vertexList.Count, 12); ComputeBuffer indexBuffer = new ComputeBuffer(indexList.Count, 4); objectBuffer.SetData(meshObjecRefData); vertexBuffer.SetData(vertexList); indexBuffer.SetData(indexList); yield return(null); // Most of the values will only get set once, so there's no point in storing hash-key value of their // property names. For the few items that will be set quite a few times, storing the hash-key value // will speed things up for us. It's just a tiny bit, but it will be faster. int uvOffsetKey = Shader.PropertyToID("_UvOffset"); s_computeShader.SetVector(uvOffsetKey, new Vector4(0.5f, 0.5f, 0.0f, 0.0f)); s_computeShader.SetFloat("_SampleCount", (float)s_sampleCount); s_computeShader.SetInt("_MaxSegments", s_maxBounceCount); s_computeShader.SetFloat("_SpotLightAngle", s_currentLightComponent.spotAngle / 2.0f); s_computeShader.SetFloat("_ShadowFocusDistance", s_shadowFocusDistance); s_computeShader.SetTexture(0, "Result", renderTexture); s_computeShader.SetVector("_LightPosition", lightCenter.Position()); s_computeShader.SetVector("_LightForwardDir", s_currentLightComponent.transform.forward.Direction()); s_computeShader.SetVector("_LightUpwardDir", s_currentLightComponent.transform.up.Direction()); s_computeShader.SetFloat("_InnerRange", s_innerRadius); s_computeShader.SetFloat("_OuterRange", s_outerRadius); yield return(null); s_computeShader.SetBuffer(0, "_ObjectData", objectBuffer); s_computeShader.SetBuffer(0, "_Vertices", vertexBuffer); s_computeShader.SetBuffer(0, "_Indices", indexBuffer); yield return(null); // I wanted to use Unity's Random class for this, but the comments said that the random floats were // [0.0, 1.0] when what I want is [0.0, 1.0). Using a random function that can generate a 1.0 is bad // for our uv coordinate random sampling. That said, casting a double to a float might also give us a // 1.0 due to rounding from loss of precission. // -FCT System.Random r = new System.Random(0); s_currentBakeState = BakeState.Bake; yield return(null); for (int i = 0; i < s_sampleCount; i++) { s_bakeProgress = i; s_computeShader.Dispatch(0, // We only have the one kernal, so it will have an ID of 0 resolution / 8, // All of our resolution options are divisible by 8, so we don't need to worry about things like resolution / 8, // adding an extra thread group when you have a (resolution % 8) != 0 1); // We only need one thread group for 'Z' because having more won't simplify any of our math. yield return(null); s_computeShader.SetVector(uvOffsetKey, new Vector4(RandomU.value, RandomU.value)); yield return(null); yield return(null); } s_currentBakeState = BakeState.Finalize; yield return(null); objectBuffer.Release(); vertexBuffer.Release(); indexBuffer.Release(); yield return(null); /// /// Code for saving our results into the project and applying them to the light component. /// // Create a Texture2D to place our results into. This Texture2D will be added to the project's assets // and it will be applied to the light source we were raytracing. Texture2D finalResults = new Texture2D(resolution, resolution, TextureFormat.RGBAFloat, false, true) { alphaIsTransparency = true, filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp, name = s_currentLightComponent.name + "_ShadowCookie_" + resolution.ToString() }; yield return(null); var prevActiveRendTexture = RenderTexture.active; // Just in case something was there for some reason. RenderTexture.active = renderTexture; finalResults.ReadPixels(new Rect(0, 0, resolution, resolution), 0, 0, false); finalResults.Apply(); RenderTexture.active = prevActiveRendTexture; yield return(null); // Check for the location where we will be saving the Texture2D. If that location doesn't exist, then // create it. var assetFolderPath = "Assets/Light_Cookies/" + s_currentLightComponent.gameObject.scene.name; if (!Directory.Exists(assetFolderPath)) { if (!Directory.Exists("Assets/Light_Cookies")) { AssetDatabase.CreateFolder("Assets", "Light_Cookies"); yield return(null); } AssetDatabase.CreateFolder("Assets/Light_Cookies", s_currentLightComponent.gameObject.scene.name); } yield return(null); // Save the Texture2D as a project asset. var assetPath = assetFolderPath + "/" + finalResults.name + ".asset"; AssetDatabase.CreateAsset(finalResults, assetPath); yield return(null); // Apply the Texture2D to the light as a cooke, then finish cleaning up. s_currentLightComponent.cookie = finalResults; EditorUtility.SetDirty(s_currentLightComponent.gameObject); s_bakingCoroutine = null; // The coroutines for MonoBehaviors have the option to manipulate them from the outside, which I have // made use of. With a bit of luck, those functions will be added to the EditorCoroutines at some point // in time. // -FCT yield return(null); s_currentBakeState = BakeState.SettingSelection; }
private void DrawSettingSelection() { #region State Checking // // Making sure we have all the valid inputs needed for drawing User Inputs. // if (EditorApplication.isPlaying || EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isUpdating) { GUILayout.Label("Unity Editor is currently busy."); return; } var activeGameObject = Selection.activeGameObject; if (activeGameObject == null) { GUILayout.Label("Please select a valid light source in the scene."); return; } var selectedLightComponent = activeGameObject.GetComponent <Light>(); if (selectedLightComponent == null) { GUILayout.Label("Please select a valid light source in the scene."); return; } switch (selectedLightComponent.type) { case LightType.Spot: break; // I'm planning to support Point lights in the future, so I'm separating this from default. // -FCT case LightType.Point: default: GUILayout.Label("Please select a valid light source in the scene."); return; } // Check some HDRP relectaed things. HDAdditionalLightData additionalLightData = activeGameObject.GetComponent <HDAdditionalLightData>(); if (additionalLightData == null) { // Not an light in HDRP (I think). GUILayout.Label("Please select a valid light source in the scene."); return; } switch (additionalLightData.lightTypeExtent) { case LightTypeExtent.Rectangle: case LightTypeExtent.Tube: GUILayout.Label("Please select a valid light source in the scene."); return; } // I know that at the moment, Spot light is the only light that will make it this far, but I'm planning // to have this plugin work with Point lights too. Doing this now, is one less change I'll need to make // later on. // -FCT if (selectedLightComponent.type == LightType.Spot) { switch (additionalLightData.spotLightShape) { // So, it turns out that the cookie for Cone and Pyramid are used in the exact same way. The only real // difference is that the cone will do less lighting based on the cone shape, but the cookie (which // we're creating) is used in the exact same way. // -FCT case SpotLightShape.Cone: case SpotLightShape.Pyramid: break; default: GUILayout.Label("Please select a valid light source in the scene."); return; } } #endregion CookieBakerEditorWindow.s_currentLightComponent = selectedLightComponent; GUIContent guiContent = null; EditorGUILayout.LabelField("Object Selection:"); EditorGUI.indentLevel++; /// /// Get the range over which we'll be raytracing. /// EditorGUILayout.BeginHorizontal(); guiContent = new GUIContent("Bake Item Range:", "Only items within the selected range can affect the results of the raytracing."); EditorGUILayout.MinMaxSlider(guiContent, ref s_innerRadius, ref s_outerRadius, 0.001f, 1.0f); EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.LabelField("Quality Options:"); EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal(); guiContent = new GUIContent("Max Segment Count:", "This controls the maximum number of times a sample light ray may bounce off of items."); s_maxBounceCount = EditorGUILayout.IntSlider(guiContent, s_maxBounceCount, 1, 16); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); guiContent = new GUIContent("Sample Count:", "This controls the number of samples we take. Higher sample counts lead to better quality and longer bake times."); s_sampleCount = EditorGUILayout.IntSlider(guiContent, s_sampleCount, 1, 500); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); guiContent = new GUIContent("Shadow Focus Distance:", "This is the distance at which we measure if a light sample will add to the cookie-texture."); s_shadowFocusDistance = EditorGUILayout.Slider(guiContent, s_shadowFocusDistance, 1.01f, 2000.0f); EditorGUILayout.EndHorizontal(); /// /// Get the resolution for the generated cookie. /// EditorGUILayout.BeginHorizontal(); guiContent = new GUIContent("Cookie Resolution:"); var resOptions = s_resolutionOptions.Select(res => { return(new GUIContent(res.ToString())); }); s_selectedCookieResolution = EditorGUILayout.Popup(guiContent, s_selectedCookieResolution, resOptions.ToArray()); EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel--; if (GUILayout.Button("Start Baking.")) { s_currentBakeState = BakeState.Prep; s_bakingCoroutine = this.StartCoroutine(CookieBaking()); } }
private IEnumerator CookieBaking() { yield return(null); var resolution = s_resolutionOptions[s_selectedCookieResolution]; // We only want to use GameObjects that are within the outer radius that we have set. So, a quick test // to see if something is within the ball park would be to check if their bounding box insersects with // a bounding box that contains the outer radius. Once that has been done, we can take a closer look at // what's left. var meshRenders = FindObjectsOfType <MeshRenderer>(); var lightCenter = s_currentLightComponent.transform.position; var lightBoundingBox = new UnityEngine.Bounds(lightCenter, 2.0f * s_outerRadius * Vector3.one); var intersectingBounds = new List <MeshRenderer>(); foreach (var meshRenderer in meshRenders) { var otherBounds = meshRenderer.bounds; if (otherBounds.Intersects(lightBoundingBox)) { intersectingBounds.Add(meshRenderer); } } yield return(null); // Now, we can limit things a bit more by finding the point within our mesh bounds that is nearset to // the light's center. We then check this point to see if it's within the distance of our outer radius. var intersectingOuterRadius = new List <MeshRenderer>(); foreach (var meshRenderer in intersectingBounds) { var otherBounds = meshRenderer.bounds; var nearsetPointToLight = otherBounds.ClosestPoint(lightCenter); if ((nearsetPointToLight - lightCenter).sqrMagnitude <= (s_outerRadius * s_outerRadius)) { intersectingOuterRadius.Add(meshRenderer); } } yield return(null); var processMeshRenderer = intersectingBounds; var processMeshFilter = new List <MeshFilter>(); // We're reusing the List from intersectingBounds and placing it under a more appropriate name. // Basically, we're reusing a piece of memory that's no longer needed instead of allocating a new List // with a new array. Also, this array shouldn't need to be resized to something larger because it // already a capacity that is greater than or equal to the number of items we will be processing. processMeshRenderer.Clear(); intersectingBounds = null; // Also, while we're at it, lets make sure that we are only baking items that are static. After all, // what's the point of baking the shadow casting item that might not be there? foreach (var meshRender in intersectingOuterRadius) { var gameObject = meshRender.gameObject; // If the gameObject isn't static, than it can be moved. Since we are not updating the cookie at // runtime, having a moving object would be bad. if (!gameObject.isStatic) { continue; } // The mesh for our object is inside the MeshFilter, so we need that to get the mesh. Also, since we're // dealing with static meshes, then we really shouldn't be dealing with any Skinned Mesh Renderers. var meshFilter = gameObject.GetComponent <MeshFilter>(); if (meshFilter == null) { continue; } // If there's no mesh, then what are we even bothering with this? if (meshFilter.sharedMesh == null) { continue; } processMeshRenderer.Add(meshRender); processMeshFilter.Add(meshFilter); } yield return(null); // Todo: With this design, items that use the same mesh will replicate the mesh verts and triangle index // arrays. I need to add a way to check if we have already added a mesh and if so, pull up the triangle // index array information to pass along to the meshRefDatum. var meshObjecRefData = new List <MeshObjectData>(processMeshRenderer.Count); var indexList = new List <int>(); var vertexList = new List <Vector3>(processMeshRenderer.Count * 50); for (int i = 0; i < processMeshRenderer.Count; i++) { var mesh = processMeshFilter[i].sharedMesh; var meshVerts = mesh.vertices; var meshTriangleIndices = mesh.triangles; var meshRefDatum = new MeshObjectData() { LocalToWorldMatrix = processMeshRenderer[i].localToWorldMatrix, IndicesOffset = indexList.Count, // The starting index of the vert-index for this object's mesh. IndicesCount = meshTriangleIndices.Length, // The number of indices used to form all of the mesh triangles. VerticesOffset = vertexList.Count, Bounds = new Bounds() { Center = processMeshRenderer[i].bounds.center, Extent = processMeshRenderer[i].bounds.extents } }; meshObjecRefData.Add(meshRefDatum); vertexList.AddRange(meshVerts); indexList.AddRange(meshTriangleIndices); } yield return(null); /// /// Try adding tracing code here. /// var backgroundWorkerArgs = new BackgroundWorkerArgs() { Indices = indexList, ObjectData = meshObjecRefData, Vertices = vertexList, LightPosition = lightCenter, LightForward = s_currentLightComponent.transform.forward, LightUpward = s_currentLightComponent.transform.up }; yield return(null); using (var backgroundWorker = new BackgroundWorker()) { backgroundWorker.DoWork += BackgroundWorker_DoWork; backgroundWorker.RunWorkerAsync(backgroundWorkerArgs); while (!backgroundWorkerArgs.Complete) { yield return(new EditorWaitForSeconds(0.15f)); } } s_currentBakeState = BakeState.Finalize; yield return(null); /// /// Code for saving our results into the project and applying them to the light component. /// // Create a Texture2D to place our results into. This Texture2D will be added to the project's assets // and it will be applied to the light source we were raytracing. Texture2D finalResults = new Texture2D(resolution, resolution, TextureFormat.RGBAFloat, false, true) { alphaIsTransparency = true, filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp, name = s_currentLightComponent.name + "_ShadowCookie_" + resolution.ToString() }; yield return(null); //finalResults.SetPixels(threadArgs.Result); yield return(null); // Check for the location where we will be saving the Texture2D. If that location doesn't exist, then // create it. var assetFolderPath = "Assets/Light_Cookies/" + s_currentLightComponent.gameObject.scene.name; if (!Directory.Exists(assetFolderPath)) { if (!Directory.Exists("Assets/Light_Cookies")) { AssetDatabase.CreateFolder("Assets", "Light_Cookies"); yield return(null); } AssetDatabase.CreateFolder("Assets/Light_Cookies", s_currentLightComponent.gameObject.scene.name); } yield return(null); // Save the Texture2D as a project asset. var assetPath = assetFolderPath + "/" + finalResults.name + ".asset"; AssetDatabase.CreateAsset(finalResults, assetPath); yield return(null); // Apply the Texture2D to the light as a cooke, then finish cleaning up. s_currentLightComponent.cookie = finalResults; EditorUtility.SetDirty(s_currentLightComponent.gameObject); s_bakingCoroutine = null; // The coroutines for MonoBehaviors have the option to manipulate them from the outside, which I have // made use of. With a bit of luck, those functions will be added to the EditorCoroutines at some point // in time. // -FCT yield return(null); s_currentBakeState = BakeState.SettingSelection; }
public void ChangeWeather() { #if UNITY_EDITOR if (Bake) { switch (mBakeState) { case BakeState.BakeStop: if (Lightmapping.isRunning != true) { mLightColorMemo = RenderSettings.sun.color; RenderSettings.sun.color = LightColor.gamma; Lightmapping.BakeAsync(); mBakeState = BakeState.Baking; } break; case BakeState.Baking: if (Lightmapping.isRunning == true) { Bake = true; } else { Bake = false; mBakeState = BakeState.BakeStop; RenderSettings.sun.color = mLightColorMemo; } break; default: break; } } #endif //if (Set == true) //GlobalSetting { if (BRDFTex != null) { Shader.SetGlobalTexture("_BRDFTex", BRDFTex); } if (NoiseTex != null) { Shader.SetGlobalTexture("_NoiseTex", NoiseTex); } //Shader.SetGlobalFloat("_Shininess", Shininess); if (CharaLightModelDiff != null) { Shader.SetGlobalTexture("_MatCap", CharaLightModelDiff); } if (CharaLightModel != null) { Shader.SetGlobalTexture("_LightModel", CharaLightModel); } /*if (CharaLightModelSpec != null) * Shader.SetGlobalTexture("_MatCapSpec", CharaLightModelSpec);*/ if (CameraFogStart == false) { Shader.SetGlobalFloat("_StartY", FogStartY); } else { Shader.SetGlobalFloat("_StartY", transform.position.y); } Shader.SetGlobalFloat("_FogMass", FogMass); Shader.SetGlobalFloat("_VFogVariation", VFogVariation1); Shader.SetGlobalFloat("_DFogHeight", DFogHeight); Shader.SetGlobalFloat("_DFogMass", DFogMass); Shader.SetGlobalFloat("_Wetness", Wetness); Shader.SetGlobalFloat("_RainForce", RainForce); Shader.SetGlobalFloat("_EndY", FogHeight); #if UNITY_IOS Shader.SetGlobalFloat("_FinalSaturation", Saturation); #else Shader.SetGlobalFloat("_FinalSaturation", Saturation); #endif Shader.SetGlobalFloat("_FarFogDistance", FarFogDistance); Shader.SetGlobalFloat("_SODarkFresnel", _SODarkFresnel); Shader.SetGlobalFloat("_SODarkFresnelFar", _SODarkFresnelFar); Shader.SetGlobalFloat("_SODarkFresnelFarForce", _SODarkFresnelFarForce); Shader.SetGlobalFloat("_SOLightFresnel", _SOLightFresnel); Shader.SetGlobalFloat("_SOLightFresnelFar", _SOLightFresnelFar); Shader.SetGlobalFloat("_SOLightFresnelFarForce", _SOLightFresnelFarForce); Shader.SetGlobalColor("_FresnelDarkColor", _FresnelDarkColor); Shader.SetGlobalColor("_FresnelLightColor", _FresnelLightColor); if (Player != null) { Shader.SetGlobalVector("_PlayerPos", Player.position); } if (CloudNoiseTex != null) { Shader.SetGlobalTexture("_CloudNoiseTex", CloudNoiseTex); } } if (IsColorSetter) { int timePixel = (int)(42.22f * TimeHour); if (Setters.Length > FirstIndex && Setters.Length > SecondIndex) { mCloudyColor = Color.Lerp(Color.white, LerpColor(timePixel, 362), RainForce * 1.667f); mTmpColor = LerpColor(timePixel, 533); Shader.SetGlobalColor("_LightColorC", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 576); Shader.SetGlobalColor("_ShadowColor", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 619); Shader.SetGlobalColor("_DFogColorFar", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 662); Shader.SetGlobalColor("_DFogColorNear", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 705); Shader.SetGlobalColor("_VFogColorLow", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 748); Shader.SetGlobalColor("_VFogColorHigh", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 791); Shader.SetGlobalColor("_CloudColor", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 834); Shader.SetGlobalColor("_BodyColor", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 877); Shader.SetGlobalColor("_ShadowColor1", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 920); Shader.SetGlobalColor("_ShadowColor2", mTmpColor * mCloudyColor); if (SkyBoxMat != null) { mTmpColor = LerpColor(timePixel, 963); SkyBoxMat.SetColor("_SkyLowColor", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 1006); SkyBoxMat.SetColor("_SkyHighColor", mTmpColor * mCloudyColor); } LerpFloat(); Shader.SetGlobalFloat("_Rotationbbb", RotationSun); Shader.SetGlobalFloat("_RotationeeeX", RotationMoonX); Shader.SetGlobalFloat("_RotationeeeY", RotationMoonY); mTmpColor = IsUiChara ? UiCharaLight : LerpColor(timePixel, 491) * mCloudyColor; Shader.SetGlobalColor("_LightColorMapping", mTmpColor); mTmpColor = IsUiChara ? UiCharaDark : LerpColor(timePixel, 448) * mCloudyColor; Shader.SetGlobalColor("_DarkColorMapping", mTmpColor); mTmpColor = IsUiChara ? UiCharaSkinDark : LerpColor(timePixel, 405) * mCloudyColor; Shader.SetGlobalColor("_SkinDarkColorMapping", mTmpColor); mTmpColor = LerpColor(timePixel, 362); Shader.SetGlobalColor("_GrassColor", mTmpColor * mCloudyColor); mTmpColor = LerpColor(timePixel, 319); Shader.SetGlobalColor("_SMShadowColor", mTmpColor * mCloudyColor); /*Debug Show Color*/ /*LightColor = ColorSelectorTex.GetPixel(timePixel, 533); * ShadowColor = ColorSelectorTex.GetPixel(timePixel, 576); * * FogFar = ColorSelectorTex.GetPixel(timePixel, 619); * FogNear = ColorSelectorTex.GetPixel(timePixel, 662); * FogLow = ColorSelectorTex.GetPixel(timePixel, 705); * FogHigh = ColorSelectorTex.GetPixel(timePixel, 748); * * CloudShadowColor = ColorSelectorTex.GetPixel(timePixel, 791); * * CloudLight = ColorSelectorTex.GetPixel(timePixel, 834); * CloudDark = ColorSelectorTex.GetPixel(timePixel, 877); * CloudDarkControl = ColorSelectorTex.GetPixel(timePixel, 920); * * if (SkyBoxMat != null) * { * SkyLowColor = ColorSelectorTex.GetPixel(timePixel, 963); * SkyHighColor = ColorSelectorTex.GetPixel(timePixel, 1006); * } * * //Shader.SetGlobalColor("_SkyLowColor", ColorSelectorTex.GetPixel(timePixel, 533); * //Shader.SetGlobalColor("_SkyHighColor", ColorSelectorTex.GetPixel(timePixel, 576); * * CharaLight = ColorSelectorTex.GetPixel(timePixel, 491); * CharaDark = ColorSelectorTex.GetPixel(timePixel, 448); * CharaSkinDark = ColorSelectorTex.GetPixel(timePixel, 405);*/ if (!CameraFogOn) { Shader.SetGlobalFloat("_DFogDensity", 0); Shader.SetGlobalFloat("_VFogDensity", 0); } else { DFogDensityValue = LerpList(Setters[FirstIndex].DFogDensityList, Setters[SecondIndex].DFogDensityList); Shader.SetGlobalFloat("_DFogDensity", DFogDensityValue * 0.1f); VFogDensityValue = LerpList(Setters[FirstIndex].VFogDensityList, Setters[SecondIndex].VFogDensityList); Shader.SetGlobalFloat("_VFogDensity", VFogDensityValue * 0.1f); } LightMapSliderValue = LerpList(Setters[FirstIndex].LightMapSliderList, Setters[SecondIndex].LightMapSliderList); Shader.SetGlobalFloat("_HemiSlider", LightMapSliderValue * (1 + Wetness * 0.5f)); BrightnessValue = LerpList(Setters[FirstIndex].BrightnessList, Setters[SecondIndex].BrightnessList); Shader.SetGlobalFloat("_Brightness", BrightnessValue); FogShowSkyValue = LerpList(Setters[FirstIndex].FogShowSkyList, Setters[SecondIndex].FogShowSkyList); Shader.SetGlobalFloat("_ShowSky", FogShowSkyValue); } } else { mCloudyColor = Color.Lerp(Color.white, CloudyColor, RainForce * 1.667f); Shader.SetGlobalColor("_LightColorC", LightColor * mCloudyColor); Shader.SetGlobalColor("_ShadowColor", ShadowColor * mCloudyColor); RenderSettings.ambientLight = ShadowColor; Shader.SetGlobalFloat("_HemiSlider", LightmapSlider * (1 + Wetness * 0.5f)); Shader.SetGlobalColor("_DFogColorNear", FogNear * mCloudyColor); Shader.SetGlobalColor("_DFogColorFar", FogFar * mCloudyColor); Shader.SetGlobalColor("_VFogColorLow", FogLow * mCloudyColor); Shader.SetGlobalColor("_VFogColorHigh", FogHigh * mCloudyColor); Shader.SetGlobalColor("_SDFogColorFar", SencondFogFar * mCloudyColor); if (float.IsNaN(DFogDensity) || DFogDensity < 0) { DFogDensity = 0; } if (!CameraFogOn) { Shader.SetGlobalFloat("_DFogDensity", 0); Shader.SetGlobalFloat("_VFogDensity", 0); Shader.SetGlobalFloat("_SecondLevelFogForce", 0); } else { Shader.SetGlobalFloat("_DFogDensity", DFogDensity * 0.1f); Shader.SetGlobalFloat("_VFogDensity", VFogDensity * 0.1f); Shader.SetGlobalFloat("_SecondLevelFogDistance", SecondLevelFogDistance); Shader.SetGlobalFloat("_SecondLevelFogForce", SecondLevelFogForce); } Shader.SetGlobalFloat("_CloudShadow", CloudShadow); Shader.SetGlobalColor("_BodyColor", CloudLight * mCloudyColor); Shader.SetGlobalColor("_RimColor", CloudLight * mCloudyColor); Shader.SetGlobalColor("_ShadowColor1", CloudDark * mCloudyColor); Shader.SetGlobalColor("_ShadowColor2", CloudDarkControl * mCloudyColor); Shader.SetGlobalFloat("_Coverage", CloudCoverage); Shader.SetGlobalColor("_LightColorMapping", IsUiChara ? UiCharaLight : (CharaLight * mCloudyColor)); Shader.SetGlobalColor("_DarkColorMapping", IsUiChara ? UiCharaDark : (CharaDark * mCloudyColor)); Shader.SetGlobalColor("_SkinDarkColorMapping", IsUiChara ? UiCharaSkinDark : (CharaSkinDark * mCloudyColor)); Shader.SetGlobalColor("_GrassColor", GrassColor * mCloudyColor); Shader.SetGlobalColor("_SMShadowColor", GrassShadowColor * mCloudyColor); Shader.SetGlobalColor("_LmMultiply", LmMultiply * mCloudyColor); Shader.SetGlobalFloat("_BackLight", CharaBackLight); Shader.SetGlobalFloat("_RotDiff", CharaLightRot); if (IsUiChara) { Shader.SetGlobalFloat("_LmShadowForce", 0); Shader.SetGlobalFloat("_LmLightForceInShadow", 0); Shader.SetGlobalFloat("_LmLightForceInLight", 0); } else { Shader.SetGlobalFloat("_LmShadowForce", CharaLmShadowForce); Shader.SetGlobalFloat("_LmLightForceInShadow", LmLightForceInShadow); Shader.SetGlobalFloat("_LmLightForceInLight", LmLightForceInLight); } if (SkyBoxMat != null) { SkyBoxMat.SetColor("_SkyLowColor", SkyLowColor * mCloudyColor); SkyBoxMat.SetColor("_SkyHighColor", SkyHighColor * mCloudyColor); } Shader.SetGlobalFloat("_Rotationbbb", RotationSun); Shader.SetGlobalFloat("_RotationeeeX", RotationMoonX); Shader.SetGlobalFloat("_RotationeeeY", RotationMoonY); Shader.SetGlobalColor("_SkyLowColor", SkyLowColor * mCloudyColor); Shader.SetGlobalColor("_SkyHighColor", SkyHighColor * mCloudyColor); Shader.SetGlobalFloat("_Brightness", Brightness); Shader.SetGlobalFloat("_RtLightOnLm", RealTimeLightOnLightmap); Shader.SetGlobalFloat("_LmShadow", ShadowOnLightmap); Shader.SetGlobalFloat("_ShowSky", FogShowSky); } }