Project_WL/AgentScripts/WL814q_Capture.cs

198 lines
10 KiB
C#
Raw Permalink 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-814q — 캡처 4장(+개요) · 1080×1920 · Screenshots_WL/WL814q/
public static class WL814q_Capture
{
const string Out = "Screenshots_WL/WL814q/";
const string ScenePath = "Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity";
const string DemoPath = "Assets/3DPixelArtEnvironment/Demo/Demo.unity";
const int W = 1080, H = 1920;
static UnityEngine.Texture2D Shot(UnityEngine.Camera cam, int w, int h)
{
var rt = new UnityEngine.RenderTexture(w, h, 24, UnityEngine.RenderTextureFormat.ARGB32,
UnityEngine.RenderTextureReadWrite.sRGB);
rt.filterMode = UnityEngine.FilterMode.Point;
rt.antiAliasing = 1;
rt.Create();
var prev = cam.targetTexture;
cam.targetTexture = rt;
cam.Render();
var oldActive = UnityEngine.RenderTexture.active;
UnityEngine.RenderTexture.active = rt;
var tex = new UnityEngine.Texture2D(w, h, UnityEngine.TextureFormat.RGB24, false);
tex.ReadPixels(new UnityEngine.Rect(0, 0, w, h), 0, 0);
tex.Apply();
UnityEngine.RenderTexture.active = oldActive;
cam.targetTexture = prev;
rt.Release();
UnityEngine.Object.DestroyImmediate(rt);
return tex;
}
/// <summary>점(Point) 확대 — 도트 격자를 그대로 키운다.</summary>
static UnityEngine.Texture2D Upscale(UnityEngine.Texture2D src, int w, int h)
{
var d = new UnityEngine.Texture2D(w, h, UnityEngine.TextureFormat.RGB24, false);
var sp = src.GetPixels32();
var dp = new UnityEngine.Color32[w * h];
for (int y = 0; y < h; y++)
{
int sy = y * src.height / h; if (sy >= src.height) sy = src.height - 1;
for (int x = 0; x < w; x++)
{
int sx = x * src.width / w; if (sx >= src.width) sx = src.width - 1;
dp[y * w + x] = sp[sy * src.width + sx];
}
}
d.SetPixels32(dp); d.Apply();
return d;
}
static void Save(UnityEngine.Texture2D t, string name)
{
var dir = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), Out);
System.IO.Directory.CreateDirectory(dir);
System.IO.File.WriteAllBytes(System.IO.Path.Combine(dir, name), UnityEngine.ImageConversion.EncodeToPNG(t));
UnityEngine.Object.DestroyImmediate(t);
}
/// <summary>도트A: pixelHeight 240 저해상도 렌더 → 점 확대.</summary>
static UnityEngine.Texture2D DotA(UnityEngine.Camera cam, float orthoSize)
{
bool o = cam.orthographic; float os = cam.orthographicSize;
cam.orthographic = true; cam.orthographicSize = orthoSize;
int ph = 240, pw = UnityEngine.Mathf.RoundToInt(240f * W / H); // 135×240
var small = Shot(cam, pw, ph);
var big = Upscale(small, W, H);
UnityEngine.Object.DestroyImmediate(small);
cam.orthographic = o; cam.orthographicSize = os;
return big;
}
static UnityEngine.Texture2D SideBySide(UnityEngine.Texture2D a, UnityEngine.Texture2D b, int gap)
{
int w = a.width + gap + b.width, h = UnityEngine.Mathf.Max(a.height, b.height);
var d = new UnityEngine.Texture2D(w, h, UnityEngine.TextureFormat.RGB24, false);
var px = new UnityEngine.Color32[w * h];
for (int i = 0; i < px.Length; i++) px[i] = new UnityEngine.Color32(18, 18, 22, 255);
d.SetPixels32(px); d.Apply();
UnityEngine.Graphics.CopyTexture(a, 0, 0, 0, 0, a.width, a.height, d, 0, 0, 0, 0);
UnityEngine.Graphics.CopyTexture(b, 0, 0, 0, 0, b.width, b.height, d, 0, 0, a.width + gap, 0);
return d;
}
public static string Run()
{
var sb = new System.Text.StringBuilder();
var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(ScenePath,
UnityEditor.SceneManagement.OpenSceneMode.Single);
// 🔴 Water_Plane 프리팹의 PlanarReflectionProbe 도 Camera 다 — 이름으로 고른다
UnityEngine.Camera cam = null;
foreach (var c in UnityEngine.Object.FindObjectsByType<UnityEngine.Camera>(
UnityEngine.FindObjectsSortMode.None))
if (c.gameObject.name == "Main Camera") cam = c;
if (cam == null) return "NO CAMERA";
var camPos = cam.transform.position;
var camRot = cam.transform.rotation;
// 🔴 씬을 연 직후 첫 렌더는 터레인 머티리얼/스플랫이 아직 안 붙는다 — 버리는 렌더 2장으로 예열
for (int i = 0; i < 2; i++) UnityEngine.Object.DestroyImmediate(Shot(cam, 64, 64));
// ⓐ 일반 모드 — 같은 위치·각도 · 퍼스펙티브 · 풀해상도(도트 없음)
cam.orthographic = false;
// 주시점까지 거리에서 세로 화각이 ortho 3.4 와 같아지도록 FOV 를 맞춘다(같은 구도 유지)
float dist = UnityEngine.Vector3.Distance(camPos, new UnityEngine.Vector3(0f, 1.06f, 0f));
cam.fieldOfView = 2f * UnityEngine.Mathf.Atan2(3.4f, dist) * UnityEngine.Mathf.Rad2Deg;
var a = Shot(cam, W, H);
Save(a, "a_normal_1080x1920.png");
sb.AppendLine("a_normal: perspective fov=" + cam.fieldOfView.ToString("F2") + " dist=" + dist.ToString("F3"));
cam.orthographic = true; cam.orthographicSize = 3.4f;
// ⓑ 도트A — 같은 구도 · orthoSize 3.4 · pixelHeight 240
Save(DotA(cam, 3.4f), "b_dotA_1080x1920.png");
sb.AppendLine("b_dotA: ortho 3.4 · 135x240 -> point x8");
// ⓒ 캐릭터가 보이는 눈높이 구도(도트A) — 더 가깝고 낮게
// 캐릭터를 크게 — 도트A 각도(43.61°) 유지 · orthoSize 만 줄이고 주시점을 앞으로 밀어 캐릭터를 아래쪽에
cam.transform.position = camPos; cam.transform.rotation = camRot;
var fwd = cam.transform.forward; fwd.y = 0f; fwd.Normalize();
cam.transform.position = camPos + fwd * 1.9f;
Save(DotA(cam, 2.2f), "c_dotA_eye_1080x1920.png");
sb.AppendLine("c_dotA_eye: ortho 2.0 · 135x240 -> point x8 · pos=" + cam.transform.position);
// 개요(참고) — 아레나 전체 + 연못 + 풍차 (퍼스펙티브 3/4 뷰)
cam.orthographic = false;
cam.fieldOfView = 40f;
cam.transform.position = new UnityEngine.Vector3(30f, 20f, -33f);
cam.transform.LookAt(new UnityEngine.Vector3(1f, 1.5f, -1f));
Save(Shot(cam, W, H), "e_overview_1080x1920.png");
sb.AppendLine("e_overview: perspective fov40 @" + cam.transform.position);
cam.orthographic = true; cam.orthographicSize = 3.4f;
// ⓓ 비교용 — 데모의 부품은 우리보다 5~6배 크다(House 9.2 m · Tree 13.5 m vs 캐릭터 1.19 m).
// 도트A(ortho 3.4)로 데모를 찍으면 집 벽 한 조각만 나온다 → 두 씬 모두 ortho 10 · 같은 내림각 43.61° 로 맞춘다.
const float CmpOrtho = 10f;
float kk = CmpOrtho / 3.4f; // 각도 유지 · 카메라만 뒤로(near 0.3 에 잘리지 않게)
cam.transform.position = camPos * kk; cam.transform.rotation = camRot;
cam.orthographic = true; cam.orthographicSize = CmpOrtho;
var mine = DotA(cam, CmpOrtho);
var mineHalf = Upscale(mine, W / 2, H / 2);
UnityEngine.Object.DestroyImmediate(mine);
// 텍스처를 씬 전환에서 지키기
mineHalf.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
// 데모 씬 — 같은 규격(도트A)으로. 🔴 저장하지 않는다.
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(DemoPath,
UnityEditor.SceneManagement.OpenSceneMode.Single);
UnityEngine.Camera demoCam = null;
foreach (var c in UnityEngine.Object.FindObjectsByType<UnityEngine.Camera>(
UnityEngine.FindObjectsSortMode.None))
if (c.gameObject.name == "Main Camera") demoCam = c;
UnityEngine.Texture2D demoHalf = null;
if (demoCam != null)
{
// 데모의 집 앞(House (2))을 기준점으로 — 오브젝트 바운즈에서 직접 발밑을 잡는다(지형 추정 금지)
var focus = new UnityEngine.Vector3(94f, 4f, 78f);
var hg = UnityEngine.GameObject.Find("House (2)");
if (hg == null) hg = UnityEngine.GameObject.Find("Light_Post");
if (hg != null)
{
var hr = hg.GetComponentInChildren<UnityEngine.Renderer>();
if (hr != null)
{
var hb = hr.bounds;
focus = new UnityEngine.Vector3(hb.center.x, hb.min.y, hb.center.z);
sb.AppendLine("demo focus = " + hg.name + " bounds " + hb.size + " @ " + focus);
}
}
float camUp = 5.4335f, camHoriz = 4.5911f;
float yaw = 215f;
var dir = new UnityEngine.Vector3(UnityEngine.Mathf.Sin(yaw * UnityEngine.Mathf.Deg2Rad), 0f,
UnityEngine.Mathf.Cos(yaw * UnityEngine.Mathf.Deg2Rad));
float k = CmpOrtho / 3.4f; // 같은 각도를 유지한 채 카메라만 뒤로
demoCam.transform.position = focus + UnityEngine.Vector3.up * camUp * k - dir * camHoriz * k;
demoCam.transform.LookAt(focus + UnityEngine.Vector3.up * 1.06f);
demoCam.orthographic = true; demoCam.orthographicSize = CmpOrtho;
var d = DotA(demoCam, CmpOrtho);
demoHalf = Upscale(d, W / 2, H / 2);
demoHalf.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
UnityEngine.Object.DestroyImmediate(d);
sb.AppendLine("demo shot ok @" + demoCam.transform.position);
}
else sb.AppendLine("DEMO CAMERA NOT FOUND");
if (demoHalf != null)
{
var cmp = SideBySide(demoHalf, mineHalf, 16);
Save(cmp, "d_compare_demo_vs_arena.png");
sb.AppendLine("d_compare: left=Critter Demo · right=WL_ArenaProto (both dotA 240p)");
UnityEngine.Object.DestroyImmediate(demoHalf);
}
UnityEngine.Object.DestroyImmediate(mineHalf);
// 🔴 데모 씬은 저장하지 않고 원래 씬으로 되돌린다
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(ScenePath,
UnityEditor.SceneManagement.OpenSceneMode.Single);
sb.AppendLine("OUT " + System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), Out));
return sb.ToString();
}
}