internal void ReleaseContainer(ShadowContainer container) { if (container == null) { return; } if (--container.RefCount > 0) { return; } RenderTexture.ReleaseTemporary(container.Texture); shadowCache.Remove(container.requestHash); // Debug.Log($"Released container for request\t{container.requestHash}\tTotal Released: {++releasedContainerCount}\t Alive: {createdContainerCount - releasedContainerCount}"); }
// public int createdContainerCount; // public int releasedContainerCount; public void Get(ShadowRenderingRequest request, ref ShadowContainer container) { if (float.IsNaN(request.dimensions.x) || request.dimensions.x < 1 || float.IsNaN(request.dimensions.y) || request.dimensions.y < 1) { ReleaseContainer(container); return; } #if LETAI_TRUESHADOW_DEBUG RenderTexture.ReleaseTemporary(debugTexture); if (request.shadow.alwaysRender) { debugTexture = RenderShadow(request); } #endif // Each request need a coresponding shadow texture // Texture may be shared by multiple elements // Texture are released when no longer used by any element // ShadowContainer keep track of texture and their usage int requestHash = request.GetHashCode(); // Case: requester can keep the same texture if (container?.requestHash == requestHash) { return; } ReleaseContainer(container); if (shadowCache.TryGetValue(requestHash, out var existingContainer)) { // Case: requester got texture from someone else existingContainer.RefCount++; container = existingContainer; } else { // Case: requester got new unique texture container = shadowCache[requestHash] = new ShadowContainer(RenderShadow(request), request); // Debug.Log($"Created new container for request\t{requestHash}\tTotal Created: {++createdContainerCount}\t Alive: {createdContainerCount - releasedContainerCount}"); } }
void BakeShadows() { #if UNITY_EDITOR ShadowContainer container = null; ShadowFactory.Instance.Get(new ShadowRenderingRequest(this), ref container); var renderTexture = container.Texture; Debug.Assert(renderTexture); var texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false); var activeTexture = RenderTexture.active; RenderTexture.active = renderTexture; texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); RenderTexture.active = activeTexture; var textureName = $"{SceneManager.GetActiveScene().name} - {gameObject.name} @{size}.png"; var texturePath = BAKED_SHADOWS_PATH + textureName; Directory.CreateDirectory(BAKED_SHADOWS_PATH); File.WriteAllBytes(texturePath, texture.EncodeToPNG()); AssetDatabase.Refresh(ImportAssetOptions.DontDownloadFromCacheServer); var importer = (TextureImporter)AssetImporter.GetAtPath(texturePath); TextureImporterSettings importSettings = new TextureImporterSettings(); importer.ReadTextureSettings(importSettings); importSettings.textureType = TextureImporterType.Sprite; importSettings.spriteMeshType = SpriteMeshType.Tight; importSettings.spriteGenerateFallbackPhysicsShape = false; importSettings.alphaSource = TextureImporterAlphaSource.FromInput; importSettings.alphaIsTransparency = true; importSettings.mipmapEnabled = false; importer.SetTextureSettings(importSettings); importer.SaveAndReimport(); var bakedSprite = AssetDatabase.LoadAssetAtPath <Sprite>(texturePath); bakedShadows.Add(bakedSprite); if (Graphic is Image image) { SpriteAtlasCache.AddToSameAtlas(bakedSprite, image.sprite); } shadowRenderer.SetSprite(bakedSprite); #endif }