Project_WL/AgentScripts/WL814t_Capture.cs

193 lines
8.6 KiB
C#
Raw Normal View History

// WL-814t 캡처 — 레퍼런스 느낌 4요소 단독/단계/종합 (Play 중 한 프레임 안에서 전부 렌더)
// 한 프레임 안에서 찍는 이유: 구름 그림자(_Time)·포즈가 프레임마다 움직여 세션 간 비교가 노이즈투성이가 된다(814s 미확인⑤).
// run_script --file AgentScripts/WL814t_Capture.cs --entry WL814t_Capture.Run
using System.Collections.Generic;
using UnityEngine;
using WL.Look.Arena;
public static class WL814t_Capture
{
const string Dir = @"E:\NerdNavis\WL_wt\gameplay\Screenshots_WL\WL814t";
const int W = 1080, H = 1920;
const float Close = 3.4f; // 도트A 프리셋과 같은 직교 반높이 = 비교 기준
const float Wide = 10f; // 아레나 씬의 실제 카메라
static Camera s_cam;
static Vector3 s_camPos, s_charCenter;
static float s_camSize;
static System.Text.StringBuilder s_log;
public static string Run()
{
s_log = new System.Text.StringBuilder();
System.IO.Directory.CreateDirectory(Dir);
s_cam = Camera.main;
if (s_cam == null) { var cs = Object.FindObjectsByType<Camera>(FindObjectsSortMode.None); if (cs.Length > 0) s_cam = cs[0]; }
if (s_cam == null) return "no camera";
s_camPos = s_cam.transform.position; s_camSize = s_cam.orthographicSize;
var pc = GameObject.Find("PC_LH_M05");
var rs = pc != null ? pc.GetComponentsInChildren<Renderer>(false) : new Renderer[0];
Bounds b = new Bounds(pc != null ? pc.transform.position : Vector3.zero, Vector3.zero);
bool first = true;
foreach (var r in rs) { if (r == null || !r.enabled) continue; if (first) { b = r.bounds; first = false; } else b.Encapsulate(r.bounds); }
s_charCenter = b.center;
s_log.AppendLine("charCenter=" + s_charCenter.ToString("F3") + " bodyH=" + b.size.y.ToString("F3")
+ " · 화면 캐릭터 키 @ortho3.4 = " + (b.size.y / (2f * Close) * H).ToString("F0") + " px · @ortho10 = " + (b.size.y / (2f * Wide) * H).ToString("F0") + " px");
var cfg = WLReferenceLookSettings.Instance;
if (cfg == null) return "no settings asset";
// ── ⓐ 지금(814s) — 아무것도 안 얹은 상태
Shot2("a_now", Nothing(cfg), Close, 0);
Shot2("a_now_wide", Nothing(cfg), Wide, 0);
Shot2("a_now_pixel", Nothing(cfg), Close, 240);
// ── 4요소 단독
Shot2("b_outline_only", Only(cfg, true, false, false, false), Close, 0);
Shot2("c_contrast_only", Only(cfg, false, true, false, false), Close, 0);
Shot2("d_mood_only", Only(cfg, false, false, true, false), Close, 0);
Shot2("e_rim_only", Only(cfg, false, false, false, true), Close, 0);
// ── Ⓐ 외곽선 4단 (PD: 굵게 · 상한을 올린 2/4/6/8 px)
float[] ws = { 2f, 4f, 6f, 8f };
for (int i = 0; i < ws.Length; i++)
{
var o = Only(cfg, true, false, false, false);
o.outlineWidth = ws[i]; o.outlineWidthBackground = Mathf.Max(1f, ws[i] * 0.45f);
Shot2("o" + (i + 1) + "_outline_" + ws[i].ToString("F0") + "px", o, Close, 0);
}
// 외곽선 색 — 순검정 vs 아주 어두운 보라
{
var o = Only(cfg, true, false, false, false); o.outlineWidth = 6f; o.outlineWidthBackground = 2.7f;
o.outlineColor = Color.black; Shot2("o5_color_pureblack", o, Close, 0);
o.outlineColor = new Color(0.043f, 0.031f, 0.067f, 1f); Shot2("o6_color_darkviolet", o, Close, 0);
}
// ── Ⓑ 대비 3단
float[] mds = { 0.10f, 0.05f, 0.0f };
for (int i = 0; i < mds.Length; i++)
{
var o = Only(cfg, false, true, false, false); o.minimumDarkness = mds[i]; o.charShades = 0;
Shot2("c" + (i + 1) + "_darkness_" + mds[i].ToString("F2"), o, Close, 0);
}
// ── Ⓑ2 캐릭터 색단계 7 / 4 / 3 (레퍼런스2 = 부위당 2~3단)
int[] shades = { 0, 4, 3 };
for (int i = 0; i < shades.Length; i++)
{
var o = Only(cfg, false, true, false, false); o.charShades = shades[i];
Shot2("s" + (i + 1) + "_shades_" + (shades[i] == 0 ? 7 : shades[i]), o, Close, 0);
}
// ── Ⓒ 분위기 3단
float[] ms = { 0.35f, 0.65f, 1.0f };
for (int i = 0; i < ms.Length; i++)
{
var o = Only(cfg, false, false, true, false); o.moodStrength = ms[i];
Shot2("m" + (i + 1) + "_mood_" + ms[i].ToString("F2"), o, Close, 0);
}
// ── Ⓓ 림 3단
float[] rss = { 0.6f, 1.25f, 2.2f };
for (int i = 0; i < rss.Length; i++)
{
var o = Only(cfg, false, false, false, true); o.rimStrength = rss[i];
Shot2("r" + (i + 1) + "_rim_" + rss[i].ToString("F2"), o, Close, 0);
}
// ── ⓕ 종합안 (비픽셀)
var fin = WLReferenceLook.Opt.FromSettings(cfg);
Shot2("f_final", fin, Close, 0);
Shot2("f_final_wide", fin, Wide, 0);
// ── ⓕ2 종합안 + 도트 — 도트A 프리셋(orthoSize 3.4 · pixelHeight 240)
var fp = fin; fp.outlineWidth = cfg.outlineWidthPixelMode; fp.outlineWidthBackground = Mathf.Max(0.5f, cfg.outlineWidthPixelMode * 0.5f);
Shot2("f_final_pixel", fp, Close, 240);
var fp2 = fp; fp2.outlineWidth = cfg.outlineWidthPixelMode * 2f; fp2.outlineWidthBackground = cfg.outlineWidthPixelMode;
Shot2("f_final_pixel_w2", fp2, Close, 240);
Shot2("f_final_pixel_thick", fin, Close, 240); // 비픽셀 두께 그대로 → 저해상도에서 뭉개지는지
// ── 원복 확인
Shot2("z_restored_check", Nothing(cfg), Close, 0);
s_cam.transform.position = s_camPos; s_cam.orthographicSize = s_camSize;
s_log.AppendLine("DONE");
return s_log.ToString();
}
static WLReferenceLook.Opt Nothing(WLReferenceLookSettings cfg)
{
var o = WLReferenceLook.Opt.FromSettings(cfg);
o.outline = false; o.contrast = false; o.mood = false; o.rim = false;
return o;
}
static WLReferenceLook.Opt Only(WLReferenceLookSettings cfg, bool a, bool b, bool c, bool d)
{
var o = WLReferenceLook.Opt.FromSettings(cfg);
o.outline = a; o.contrast = b; o.mood = c; o.rim = d;
return o;
}
/// <summary>카메라를 먼저 맞춘 뒤(줌 비례 두께가 카메라를 읽는다) 적용 → 렌더.</summary>
static void Shot2(string name, WLReferenceLook.Opt o, float orthoSize, int pixelHeight)
{
s_cam.orthographicSize = orthoSize;
s_cam.transform.position = s_charCenter - s_cam.transform.forward * 30f;
WLReferenceLook.Apply(o, WLReferenceLookSettings.Instance);
Shot(name, pixelHeight);
}
/// <summary>한 장 렌더. pixelHeight 0 = 1080×1920 그대로, &gt;0 = 저해상도 RT 로 찍어 점보간 확대(도트).</summary>
static void Shot(string name, int pixelHeight)
{
int rw = W, rh = H;
if (pixelHeight > 0) { rh = pixelHeight; rw = Mathf.RoundToInt(pixelHeight * (float)W / H); }
var rt = new RenderTexture(rw, rh, 24, RenderTextureFormat.ARGB32);
rt.antiAliasing = 1;
rt.filterMode = pixelHeight > 0 ? FilterMode.Point : FilterMode.Bilinear;
rt.Create();
var prevTarget = s_cam.targetTexture;
s_cam.targetTexture = rt;
s_cam.Render();
s_cam.targetTexture = prevTarget;
var prevActive = RenderTexture.active;
RenderTexture.active = rt;
var src = new Texture2D(rw, rh, TextureFormat.RGB24, false);
src.ReadPixels(new Rect(0, 0, rw, rh), 0, 0);
src.Apply();
RenderTexture.active = prevActive;
Texture2D outTex = src;
if (pixelHeight > 0)
{
outTex = new Texture2D(W, H, TextureFormat.RGB24, false);
var sp = src.GetPixels32();
var dp = new Color32[W * H];
for (int y = 0; y < H; y++)
{
int sy = Mathf.Min(rh - 1, y * rh / H);
for (int x = 0; x < W; x++)
{
int sx = Mathf.Min(rw - 1, x * rw / W);
dp[y * W + x] = sp[sy * rw + sx];
}
}
outTex.SetPixels32(dp); outTex.Apply();
}
System.IO.File.WriteAllBytes(System.IO.Path.Combine(Dir, name + ".png"), outTex.EncodeToPNG());
s_log.AppendLine("shot " + name + " " + rw + "x" + rh + " · ortho " + s_cam.orthographicSize.ToString("F2") + " · " + WLReferenceLook.LastLog);
if (outTex != src) Object.Destroy(outTex);
Object.Destroy(src);
rt.Release(); Object.Destroy(rt);
}
}