Project_WL/AgentScripts/WL816f_Cmp.cs

129 lines
6.8 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-816f §2 — 「같은 화각·같은 거리」 바닥 비교용 렌더.
// 표준 바닥 카메라 = 직교 size 5 · euler(30,60,0) · 1080×1920 (814r/816a/816e 화각과 같은 방향)
// 데모는 에디트 모드에서 인스턴싱을 직접 발행해 그린다(데모 씬 Play 금지 · §9).
public static class WL816f_Cmp
{
public const string Dir = "Screenshots_WL/WL816f/";
public const int W = 1080, H = 1920;
// ── 데모 바닥 ──────────────────────────────────────────────────────
public static void Demo()
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
"Assets/3DPixelArtEnvironment/Demo/Demo.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
var sb = new System.Text.StringBuilder();
// 평평한 풀밭 지점을 찾는다(경사가 작고 1층 스플랫이 지배적인 곳)
var terr = UnityEngine.Object.FindFirstObjectByType<UnityEngine.Terrain>();
UnityEngine.Vector3 spot = new UnityEngine.Vector3(130f, 0f, 90f);
if (terr != null)
{
var td = terr.terrainData;
float best = 999f;
for (float x = 40f; x < 180f; x += 10f)
for (float z = 40f; z < 180f; z += 10f)
{
float u = x / td.size.x, v = z / td.size.z;
var nrm = td.GetInterpolatedNormal(u, v);
float slope = 1f - nrm.y;
var c = td.alphamapTextures[0].GetPixelBilinear(u, v);
if (c.r < 0.9f) continue; // 1층(풀)이 지배적인 곳만
if (slope < best) { best = slope; spot = new UnityEngine.Vector3(x, td.GetInterpolatedHeight(u, v) + terr.transform.position.y, z); }
}
sb.AppendLine("데모 바닥 지점 " + spot.ToString("F2") + " slope=" + best.ToString("F4"));
}
var cam = GroundCam(spot, 6f);
int n = WL816f_Inst.Publish(sb);
Shoot(cam, Dir + "x_demo_ground.png", sb);
// 넓은 화각(ortho 10)도 하나
cam = GroundCam(spot, 10f);
WL816f_Inst.Publish(sb);
Shoot(cam, Dir + "x_demo_wide.png", sb);
sb.AppendLine("데모 인스턴싱 구성 " + n);
System.IO.File.WriteAllText("AgentScripts/WL816f_DEMO.txt", sb.ToString());
UnityEngine.Debug.Log(sb.ToString());
}
/// <summary>표준 바닥 카메라 — 지점 spot 을 데모 화각으로 본다.</summary>
public static UnityEngine.Camera GroundCam(UnityEngine.Vector3 spot, float size)
{
var go = UnityEngine.GameObject.Find("~WL816fGroundCam");
if (go == null) { go = new UnityEngine.GameObject("~WL816fGroundCam"); go.hideFlags = UnityEngine.HideFlags.DontSave; }
var c = go.GetComponent<UnityEngine.Camera>();
if (c == null) c = go.AddComponent<UnityEngine.Camera>();
c.orthographic = true; c.orthographicSize = size;
c.nearClipPlane = 0.3f; c.farClipPlane = 500f;
c.clearFlags = UnityEngine.CameraClearFlags.SolidColor;
c.backgroundColor = new UnityEngine.Color(0.192f, 0.302f, 0.475f, 1f);
c.cullingMask = ~0; c.depth = -100f;
var rot = UnityEngine.Quaternion.Euler(30f, 60f, 0f);
go.transform.rotation = rot;
go.transform.position = spot - rot * UnityEngine.Vector3.forward * 60f;
if (go.GetComponent<UnityEngine.Rendering.Universal.UniversalAdditionalCameraData>() == null)
go.AddComponent<UnityEngine.Rendering.Universal.UniversalAdditionalCameraData>();
return c;
}
public static void Shoot(UnityEngine.Camera cam, string path, System.Text.StringBuilder sb)
{
if (cam == null) { if (sb != null) sb.AppendLine("카메라 없음 " + path); return; }
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
var rt = new UnityEngine.RenderTexture(W, H, 24, UnityEngine.RenderTextureFormat.ARGB32, UnityEngine.RenderTextureReadWrite.sRGB);
rt.antiAliasing = 1; rt.Create();
var prevT = cam.targetTexture; var prevA = UnityEngine.RenderTexture.active;
cam.targetTexture = rt; cam.Render();
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();
System.IO.File.WriteAllBytes(path, UnityEngine.ImageConversion.EncodeToPNG(tex));
UnityEngine.RenderTexture.active = prevA; cam.targetTexture = prevT;
UnityEngine.Object.DestroyImmediate(tex);
rt.Release(); UnityEngine.Object.DestroyImmediate(rt);
WL816f_Inst.Free();
if (sb != null) sb.AppendLine("캡처 " + path);
}
}
/// <summary>에디트 모드에서 InstancesBehaviour 가 그릴 것을 이번 프레임에 직접 발행한다(Play 없이).</summary>
public static class WL816f_Inst
{
static readonly System.Collections.Generic.List<Environment.Instancing.InstancingConfiguration> s_pending
= new System.Collections.Generic.List<Environment.Instancing.InstancingConfiguration>();
public static int Publish(System.Text.StringBuilder sb)
{
int n = 0; long inst = 0;
var bs = UnityEngine.Object.FindObjectsByType<Environment.Instancing.InstancesBehaviour>(
UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None);
for (int i = 0; i < bs.Length; i++)
{
var b = bs[i];
System.Collections.Generic.Dictionary<Environment.Instancing.InstancingSettings,
System.Collections.Generic.List<Environment.Instancing.InstanceData>> data = null;
try { data = b.GetInstanceData(); } catch { continue; }
if (data == null) continue;
var bounds = b.CalculateInstancesBounds();
var l2w = b.transform.localToWorldMatrix; l2w.m03 = 0; l2w.m13 = 0; l2w.m23 = 0;
foreach (var kv in data)
{
if (kv.Value == null || kv.Value.Count == 0) continue;
var cfg = new Environment.Instancing.InstancingConfiguration(kv.Key, kv.Value, "_InstanceData");
cfg.MaterialPropertyBlock.SetMatrix("_LocalToWorld", l2w);
UnityEngine.Graphics.DrawMeshInstancedIndirect(cfg.Mesh, 0, cfg.Material, bounds, cfg.CommandBuffer, 0,
cfg.MaterialPropertyBlock, UnityEngine.Rendering.ShadowCastingMode.Off, false, 0);
n++; inst += kv.Value.Count;
s_pending.Add(cfg);
}
}
if (sb != null) sb.AppendLine(" 인스턴스 " + inst + " (구성 " + n + ")");
return n;
}
public static void Free()
{
for (int i = 0; i < s_pending.Count; i++) s_pending[i].FreeMemory();
s_pending.Clear();
}
}