diff --git a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/System/ScreenshotManager.cs b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/System/ScreenshotManager.cs
index 059c034c1..155d162c1 100644
--- a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/System/ScreenshotManager.cs
+++ b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/System/ScreenshotManager.cs
@@ -1,14 +1,13 @@
using UnityEngine;
using System;
-using System.Collections;
using System.IO;
///
/// 스크린샷 캡처 관리.
-/// RenderStreamOutput 이 매 프레임 갱신하는 CaptureTexture/AlphaOutputTexture 를 PNG 로 저장.
-/// captureWidth/Height 가 지정되면 캡처 직전에 카메라 targetTexture 를 임시로 그 해상도로
-/// 변경해 한 프레임 고해상도 렌더 후 원복한다.
-/// 트레이드오프: 그 한 프레임 동안 Spout/NDI 송신도 같은 해상도가 되어 수신측이 잠깐 깜빡임.
+/// RenderStreamOutput.CaptureTexture (후처리 + 알파 합성 결과) 를 PNG 로 저장.
+/// - CaptureScreenshot() : RGB 만 (알파 = 1, 일반 사진)
+/// - CaptureAlphaScreenshot() : RGBA 그대로 (배경 투명, 합성 소스용)
+/// 카메라 해상도 그대로 ReadPixels — 별도 임시 RT/카메라 변경 없음.
///
[Serializable]
public class ScreenshotManager
@@ -22,22 +21,14 @@ public class ScreenshotManager
[Tooltip("파일명 앞에 붙을 접두사")]
public string screenshotFilePrefix = "Screenshot";
- [Header("고해상도 캡처 (0 이면 카메라 해상도 사용)")]
- [Tooltip("캡처 너비. 0 이면 카메라 해상도 그대로")]
- public int captureWidth = 3840;
- [Tooltip("캡처 높이. 0 이면 카메라 해상도 그대로")]
- public int captureHeight = 2160;
-
[Tooltip("(하위 호환) 외부 코드가 .screenshotCamera 로 접근하면 RenderStreamOutput.MainCam 반환")]
public Camera screenshotCamera => renderStream != null ? renderStream.MainCam : null;
- private MonoBehaviour host;
private Action log;
private Action logError;
- public void Initialize(MonoBehaviour host, Action log, Action logError)
+ public void Initialize(Action log, Action logError)
{
- this.host = host;
this.log = log;
this.logError = logError;
@@ -57,78 +48,26 @@ public class ScreenshotManager
}
}
+ /// RGB 만, 알파는 1 로 저장하는 일반 PNG (평범한 사진)
public void CaptureScreenshot()
{
- if (!CanCapture()) return;
- host.StartCoroutine(CaptureCoroutine(alphaOnly: false));
+ if (renderStream == null || renderStream.CaptureTexture == null)
+ {
+ logError?.Invoke("RenderStreamOutput.CaptureTexture 가 준비되지 않았습니다");
+ return;
+ }
+ SaveRtAsPng(renderStream.CaptureTexture, GenerateFileName("png"), TextureFormat.RGB24);
}
+ /// RGBA 모두 저장 — 배경 투명, OBS/합성 소스용
public void CaptureAlphaScreenshot()
{
- if (!CanCapture()) return;
- host.StartCoroutine(CaptureCoroutine(alphaOnly: true));
- }
-
- private bool CanCapture()
- {
- if (host == null) { logError?.Invoke("ScreenshotManager host(MonoBehaviour) 가 없습니다"); return false; }
- if (renderStream == null || renderStream.MainCam == null)
+ if (renderStream == null || renderStream.CaptureTexture == null)
{
- logError?.Invoke("RenderStreamOutput / MainCam 이 준비되지 않았습니다");
- return false;
- }
- return true;
- }
-
- private IEnumerator CaptureCoroutine(bool alphaOnly)
- {
- var cam = renderStream.MainCam;
- bool useTempResolution = captureWidth > 0 && captureHeight > 0;
-
- RenderTexture tempRT = null;
- RenderTexture prevTarget = null;
-
- if (useTempResolution)
- {
- prevTarget = cam.targetTexture;
- var desc = new RenderTextureDescriptor(captureWidth, captureHeight,
- renderStream.TextureFormat, 24)
- {
- msaaSamples = Mathf.Max(1, renderStream.AntiAliasing)
- };
- tempRT = new RenderTexture(desc);
- tempRT.Create();
-
- cam.targetTexture = tempRT;
-
- // 1프레임 — RenderStreamOutput.Update 가 새 pixelWidth 감지 → InitializeTextures(고해상도)
- yield return null;
- // 1프레임 — 고해상도 RT 에 우리 패스 결과 채워짐
- yield return new WaitForEndOfFrame();
- }
-
- var srcRT = alphaOnly ? renderStream.AlphaOutputTexture : renderStream.CaptureTexture;
- if (srcRT != null)
- {
- string fileName = GenerateFileName("png", alphaOnly ? "_Alpha" : "");
- SaveRtAsPng(srcRT, fileName, alphaOnly ? TextureFormat.RGB24 : TextureFormat.RGBA32);
- }
- else
- {
- logError?.Invoke("캡처 RT 가 준비되지 않았습니다");
- }
-
- if (useTempResolution)
- {
- cam.targetTexture = prevTarget;
- if (tempRT != null)
- {
- tempRT.Release();
- UnityEngine.Object.Destroy(tempRT);
- }
- // 한 프레임 더 대기 — RenderStreamOutput.Update 가 원래 해상도로 복귀
- yield return null;
+ logError?.Invoke("RenderStreamOutput.CaptureTexture 가 준비되지 않았습니다");
+ return;
}
+ SaveRtAsPng(renderStream.CaptureTexture, GenerateFileName("png", "_Alpha"), TextureFormat.RGBA32);
}
public void OpenScreenshotFolder()
@@ -148,11 +87,18 @@ public class ScreenshotManager
{
string fullPath = Path.Combine(screenshotSavePath, fileName);
RenderTexture prevActive = RenderTexture.active;
+ RenderTexture sRgbRT = null;
Texture2D tex = null;
try
{
- RenderTexture.active = rt;
+ // HDR/Linear RT → sRGB RT 로 Blit. ReadPixels 는 색공간 변환을 안 하므로 이걸 거치지
+ // 않으면 PNG 가 Linear 값을 sRGB 슬롯에 그대로 담아 OBS(Spout 결과)와 다르게 보임.
+ sRgbRT = RenderTexture.GetTemporary(rt.width, rt.height, 0,
+ RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
+ Graphics.Blit(rt, sRgbRT);
+
+ RenderTexture.active = sRgbRT;
tex = new Texture2D(rt.width, rt.height, format, false);
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
tex.Apply();
@@ -167,6 +113,7 @@ public class ScreenshotManager
finally
{
RenderTexture.active = prevActive;
+ if (sRgbRT != null) RenderTexture.ReleaseTemporary(sRgbRT);
if (tex != null) UnityEngine.Object.Destroy(tex);
}
}
diff --git a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs
index 420acb612..7235661d6 100644
--- a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs
+++ b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/SystemController.cs
@@ -54,7 +54,7 @@ public class SystemController : MonoBehaviour
optiTrack.Initialize(Log, LogError);
facialMotion.Initialize(Log, LogError);
motionRecording.Initialize(optiTrack, Log, LogError);
- screenshot.Initialize(this, Log, LogError);
+ screenshot.Initialize(Log, LogError);
clothSimulation.Initialize(Log, LogError);
avatarHead.Initialize(Log, LogError);
retargetingRemote.Initialize(Log, LogError);
diff --git a/Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/SystemControllerEditor.uxml b/Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/SystemControllerEditor.uxml
index 99eeb3b40..62a7de4be 100644
--- a/Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/SystemControllerEditor.uxml
+++ b/Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/SystemControllerEditor.uxml
@@ -29,12 +29,10 @@
-
+
-
-