Project_WL/AgentScripts/WL814q_Capture.cs

183 lines
9.3 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-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;
// ⓐ 일반 모드 — 같은 위치·각도 · 퍼스펙티브 · 풀해상도(도트 없음)
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) — 더 가깝고 낮게
cam.transform.position = new UnityEngine.Vector3(0f, 1.15f, 0f)
+ UnityEngine.Quaternion.Euler(0f, 205f, 0f) * new UnityEngine.Vector3(0f, 0f, -4.2f)
+ UnityEngine.Vector3.up * 0.55f;
cam.transform.LookAt(new UnityEngine.Vector3(0f, 0.75f, 0f));
Save(DotA(cam, 2.0f), "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;
// ⓓ 비교용 — 새 아레나(도트A) 렌더를 먼저 잡아 둔다
cam.transform.position = camPos; cam.transform.rotation = camRot;
cam.orthographic = true; cam.orthographicSize = 3.4f;
var mine = DotA(cam, 3.4f);
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채 + Light_Post 일대)을 우리와 같은 내림각 43.61°·도트A 규격으로
var dt = UnityEngine.Object.FindFirstObjectByType<UnityEngine.Terrain>();
var fxz = new UnityEngine.Vector3(94f, 0f, 78f);
float fy = dt != null ? dt.SampleHeight(fxz) + dt.transform.position.y : 4f;
var focus = new UnityEngine.Vector3(fxz.x, fy, fxz.z);
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));
demoCam.transform.position = focus + UnityEngine.Vector3.up * camUp - dir * camHoriz;
demoCam.transform.LookAt(focus + UnityEngine.Vector3.up * 1.06f);
demoCam.orthographic = true; demoCam.orthographicSize = 3.4f;
var d = DotA(demoCam, 3.4f);
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();
}
}