183 lines
9.3 KiB
C#
183 lines
9.3 KiB
C#
// 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();
|
||
}
|
||
}
|