using UnityEngine; using System; using System.IO; /// /// 스크린샷 캡처 관리 (RGB + 알파채널) /// [Serializable] public class ScreenshotManager { [Tooltip("스크린샷 해상도 (기본: 4K)")] public int screenshotWidth = 3840; [Tooltip("스크린샷 해상도 (기본: 4K)")] public int screenshotHeight = 2160; [Tooltip("스크린샷 저장 경로 (비어있으면 바탕화면)")] public string screenshotSavePath = ""; [Tooltip("파일명 앞에 붙을 접두사")] public string screenshotFilePrefix = "Screenshot"; [Tooltip("알파 채널 추출용 셰이더")] public Shader alphaShader; [Tooltip("NiloToon Prepass 버퍼 텍스처 이름")] public string niloToonPrepassBufferName = "_NiloToonPrepassBufferTex"; [Tooltip("촬영할 카메라 (비어있으면 메인 카메라 사용)")] public Camera screenshotCamera; [Tooltip("알파 채널 블러 반경 (0 = 블러 없음, 1.0 = 약한 블러)")] [Range(0f, 3f)] public float alphaBlurRadius = 1.0f; [NonSerialized] private Material alphaMaterial; private Action log; private Action logError; public void Initialize(Action log, Action logError) { this.log = log; this.logError = logError; if (screenshotCamera == null) { screenshotCamera = Camera.main; } if (alphaShader == null) { alphaShader = Shader.Find("Hidden/AlphaFromNiloToon"); if (alphaShader == null) { logError?.Invoke("알파 셰이더를 찾을 수 없습니다: Hidden/AlphaFromNiloToon"); } } if (string.IsNullOrEmpty(screenshotSavePath)) { screenshotSavePath = Path.Combine(Application.dataPath, "..", "Screenshots"); } if (!Directory.Exists(screenshotSavePath)) { Directory.CreateDirectory(screenshotSavePath); log?.Invoke($"Screenshots 폴더 생성됨: {screenshotSavePath}"); } } public void CaptureScreenshot() { if (screenshotCamera == null) { logError?.Invoke("촬영할 카메라가 설정되지 않았습니다!"); return; } string fileName = GenerateFileName("png"); string fullPath = Path.Combine(screenshotSavePath, fileName); try { RenderTexture rt = new RenderTexture(screenshotWidth, screenshotHeight, 24); RenderTexture currentRT = screenshotCamera.targetTexture; screenshotCamera.targetTexture = rt; screenshotCamera.Render(); RenderTexture.active = rt; Texture2D screenshot = new Texture2D(screenshotWidth, screenshotHeight, TextureFormat.RGB24, false); screenshot.ReadPixels(new Rect(0, 0, screenshotWidth, screenshotHeight), 0, 0); screenshot.Apply(); byte[] bytes = screenshot.EncodeToPNG(); File.WriteAllBytes(fullPath, bytes); screenshotCamera.targetTexture = currentRT; RenderTexture.active = null; rt.Release(); UnityEngine.Object.Destroy(rt); UnityEngine.Object.Destroy(screenshot); log?.Invoke($"스크린샷 저장 완료: {fullPath}"); } catch (Exception e) { logError?.Invoke($"스크린샷 촬영 실패: {e.Message}"); } } public void CaptureAlphaScreenshot() { if (screenshotCamera == null) { logError?.Invoke("촬영할 카메라가 설정되지 않았습니다!"); return; } if (alphaShader == null) { logError?.Invoke("알파 셰이더가 설정되지 않았습니다!"); return; } string fileName = GenerateFileName("png", "_Alpha"); string fullPath = Path.Combine(screenshotSavePath, fileName); try { RenderTexture rt = new RenderTexture(screenshotWidth, screenshotHeight, 24); RenderTexture currentRT = screenshotCamera.targetTexture; screenshotCamera.targetTexture = rt; screenshotCamera.Render(); Texture niloToonPrepassBuffer = Shader.GetGlobalTexture(niloToonPrepassBufferName); if (niloToonPrepassBuffer == null) { logError?.Invoke($"NiloToon Prepass 버퍼를 찾을 수 없습니다: {niloToonPrepassBufferName}"); screenshotCamera.targetTexture = currentRT; UnityEngine.Object.Destroy(rt); return; } if (alphaMaterial == null) { alphaMaterial = new Material(alphaShader); } RenderTexture alphaRT = new RenderTexture(screenshotWidth, screenshotHeight, 0, RenderTextureFormat.ARGB32); alphaMaterial.SetTexture("_MainTex", rt); alphaMaterial.SetTexture("_AlphaTex", niloToonPrepassBuffer); alphaMaterial.SetFloat("_BlurRadius", alphaBlurRadius); Graphics.Blit(rt, alphaRT, alphaMaterial); RenderTexture.active = alphaRT; Texture2D screenshot = new Texture2D(screenshotWidth, screenshotHeight, TextureFormat.RGBA32, false); screenshot.ReadPixels(new Rect(0, 0, screenshotWidth, screenshotHeight), 0, 0); screenshot.Apply(); byte[] bytes = screenshot.EncodeToPNG(); File.WriteAllBytes(fullPath, bytes); screenshotCamera.targetTexture = currentRT; RenderTexture.active = null; rt.Release(); UnityEngine.Object.Destroy(rt); alphaRT.Release(); UnityEngine.Object.Destroy(alphaRT); UnityEngine.Object.Destroy(screenshot); log?.Invoke($"알파 스크린샷 저장 완료: {fullPath}"); } catch (Exception e) { logError?.Invoke($"알파 스크린샷 촬영 실패: {e.Message}"); } } public void OpenScreenshotFolder() { if (Directory.Exists(screenshotSavePath)) { System.Diagnostics.Process.Start(screenshotSavePath); log?.Invoke($"저장 폴더 열기: {screenshotSavePath}"); } else { logError?.Invoke($"저장 폴더가 존재하지 않습니다: {screenshotSavePath}"); } } private string GenerateFileName(string extension, string suffix = "") { string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); return $"{screenshotFilePrefix}{suffix}_{timestamp}.{extension}"; } public void Cleanup() { if (alphaMaterial != null) { UnityEngine.Object.Destroy(alphaMaterial); } } }