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);
}
}
}