Project_WL/AgentScripts/WL814t_Capture.cs

193 lines
8.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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