Project_WL/AgentScripts/WL816r_Ab.cs

218 lines
11 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-816r 후속 — 816q 상태(원본 mat/텍스처) vs 816r 상태(Arena2) 를 **같은 조건**에서 A/B.
// 지표 = 816q 정의: 보이는 풀 %(풀 ON vs OFF 픽셀 차) · 에지 % · HF · 바닥 초록 화면색.
public static class WL816r_Ab
{
public static void Start()
{
var go = UnityEngine.GameObject.Find("~WL816rAb");
if (go != null) UnityEngine.Object.DestroyImmediate(go);
go = new UnityEngine.GameObject("~WL816rAb");
go.AddComponent<WL816r_AbRun>();
}
}
public class WL816r_AbRun : UnityEngine.MonoBehaviour
{
static System.Text.StringBuilder sb;
const int W = 1080, H = 1920;
static string Dir = "Screenshots_WL/WL816r";
static int s_instQ, s_instR;
void Start() { StartCoroutine(Co()); }
System.Collections.IEnumerator Co()
{
sb = new System.Text.StringBuilder();
System.IO.Directory.CreateDirectory(Dir);
if (UnityEngine.SceneManagement.SceneManager.sceneCount < 2)
{
var op = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("Level01", UnityEngine.SceneManagement.LoadSceneMode.Additive);
while (op != null && !op.isDone) yield return null;
}
for (int i = 0; i < 7; i++) yield return new UnityEngine.WaitForSeconds(1f);
var g = UnityEngine.Object.FindFirstObjectByType<WL.Look.Farm.WLIslandGrass>(UnityEngine.FindObjectsInactive.Include);
if (g == null) { L("WLIslandGrass 없음 — 중단"); Flush(); yield break; }
var src = WL.Look.Farm.WLIslandLookSettings.Instance;
var rt = UnityEngine.Object.Instantiate(src); // 에셋 무변경 — 런타임 복제본
if (rt.scatter != null)
{
var arr = new WL.Look.Farm.WLScatterDef[rt.scatter.Length];
for (int i = 0; i < arr.Length; i++)
{
var s = rt.scatter[i];
arr[i] = new WL.Look.Farm.WLScatterDef { enabled_ = s.enabled_, label = s.label, mesh = s.mesh, material = s.material, probability = s.probability, scale = s.scale, normalOffset = s.normalOffset, density = s.density };
}
rt.scatter = arr;
}
g.cfg = rt;
var matR = src.islandTopMaterial; // 816r (Arena2)
var matQ = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Material>(
"Assets/WL/Look/Farm/Materials/Farm_IslandTop_Arena.mat"); // 816q (원본)
L("816r mat=" + (matR ? matR.name : "-") + " tex=" + TexName(matR) + " | 816q mat=" + (matQ ? matQ.name : "-") + " tex=" + TexName(matQ));
if (matQ == null) { L("원본 머티리얼 로드 실패 — 중단"); Flush(); yield break; }
L("머티리얼 값 대조 " + Cmp(matQ, matR));
var topR = new System.Collections.Generic.List<UnityEngine.Renderer>();
foreach (var r in UnityEngine.Object.FindObjectsByType<UnityEngine.Renderer>(UnityEngine.FindObjectsSortMode.None))
foreach (var m in r.sharedMaterials) if (m != null && m == matR) { topR.Add(r); break; }
L("섬윗면 렌더러=" + topR.Count);
var cam = MakePd();
// ── A: 816q 상태 ──────────────────────────────────────────────────
SwapMat(topR, matR, matQ);
yield return null; yield return null;
rt.grassEnabled = 1; g.Rebuild(); yield return null; yield return null; yield return null;
var qOn = Shot(cam); s_instQ = WL.Look.Farm.WLIslandGrass.Instances;
rt.grassEnabled = 0; g.Rebuild(); yield return null; yield return null; yield return null;
var qOff = Shot(cam);
L("[816q] " + Metrics(qOn, qOff) + " · 풀 인스턴스(ON시)=" + s_instQ);
System.IO.File.WriteAllBytes(Dir + "/ab_816q.png", UnityEngine.ImageConversion.EncodeToPNG(ToTex(qOn)));
// ── B: 816r 상태 ──────────────────────────────────────────────────
SwapMat(topR, matQ, matR);
yield return null; yield return null;
rt.grassEnabled = 1; g.Rebuild(); yield return null; yield return null; yield return null;
var rOn = Shot(cam); s_instR = WL.Look.Farm.WLIslandGrass.Instances;
rt.grassEnabled = 0; g.Rebuild(); yield return null; yield return null; yield return null;
var rOff = Shot(cam);
L("[816r] " + Metrics(rOn, rOff) + " · 풀 인스턴스(ON시)=" + s_instR);
System.IO.File.WriteAllBytes(Dir + "/ab_816r.png", UnityEngine.ImageConversion.EncodeToPNG(ToTex(rOn)));
// 풀 다시 켜고 마무리
rt.grassEnabled = 1; g.Rebuild();
Flush();
}
UnityEngine.Color32[] Shot(UnityEngine.Camera cam)
{
var tex = Grab(cam, W, H);
var px = tex.GetPixels32();
UnityEngine.Object.DestroyImmediate(tex);
return px;
}
static UnityEngine.Texture2D ToTex(UnityEngine.Color32[] px)
{
var t = new UnityEngine.Texture2D(W, H, UnityEngine.TextureFormat.RGB24, false);
t.SetPixels32(px); t.Apply();
return t;
}
// 816q 지표
static bool Ground(UnityEngine.Color32 p) { return p.g > p.b + 8 && p.g > 45; }
static float Lum(UnityEngine.Color32 p) { return 0.299f * p.r + 0.587f * p.g + 0.114f * p.b; }
static string Metrics(UnityEngine.Color32[] on, UnityEngine.Color32[] off)
{
int gn = 0, vis = 0;
long rr = 0, gg = 0, bb = 0; int cn = 0;
for (int i = 0; i < off.Length; i++)
{
if (!Ground(off[i])) continue;
gn++;
rr += off[i].r; gg += off[i].g; bb += off[i].b; cn++;
if (System.Math.Abs(Lum(on[i]) - Lum(off[i])) > 8f) vis++;
}
// 에지 % (풀 ON · 지면 픽셀)
int ed = 0, edn = 0;
double hf = 0; int hfn = 0;
for (int y = 0; y < H - 1; y++)
for (int x = 0; x < W - 1; x++)
{
int i = y * W + x;
if (!Ground(on[i])) continue;
edn++;
var r0 = on[i + 1]; var d0 = on[i + W];
if ((Ground(r0) && System.Math.Abs(Lum(on[i]) - Lum(r0)) > 8) || (Ground(d0) && System.Math.Abs(Lum(on[i]) - Lum(d0)) > 8)) ed++;
}
// HF = 8×8 블록 내 편차 평균
int bs = 8;
for (int by = 0; by + bs <= H; by += bs)
for (int bx = 0; bx + bs <= W; bx += bs)
{
double s = 0; int n = 0;
for (int y = 0; y < bs; y++) for (int x = 0; x < bs; x++)
{ var p = on[(by + y) * W + bx + x]; if (!Ground(p)) continue; s += Lum(p); n++; }
if (n < bs * bs / 2) continue;
double mean = s / n;
for (int y = 0; y < bs; y++) for (int x = 0; x < bs; x++)
{ var p = on[(by + y) * W + bx + x]; if (!Ground(p)) continue; hf += System.Math.Abs(Lum(p) - mean); hfn++; }
}
string col = cn == 0 ? "-" : string.Format("#{0:X2}{1:X2}{2:X2}", rr / cn, gg / cn, bb / cn);
return string.Format("지면px(풀off)={0} · 보이는 풀={1:F2}% · 에지%={2:F2} · HF={3:F2} · 바닥초록={4}",
gn, gn == 0 ? 0f : 100f * vis / gn, edn == 0 ? 0f : 100f * ed / edn, hfn == 0 ? 0 : hf / hfn, col);
}
static UnityEngine.Material FindMat(string name)
{
foreach (var m in UnityEngine.Resources.FindObjectsOfTypeAll<UnityEngine.Material>())
if (m != null && m.name == name) return m;
return null;
}
static string TexName(UnityEngine.Material m)
{
if (m == null) return "-";
var t = m.GetTexture("_BaseMap");
return t ? t.name : "-";
}
static string Cmp(UnityEngine.Material a, UnityEngine.Material b)
{
string[] fs = { "_Shades", "_Brightness", "_MinimumDarkness", "_Cloud_Strength", "_Cloud_Density", "_Cloud_Cover", "_Cloud_Change" };
string[] cs = { "_DiffuseColor", "_ShadowDiffuseColor" };
var s = new System.Text.StringBuilder();
int diff = 0;
foreach (var f in fs) { float x = a.GetFloat(f), y = b.GetFloat(f); if (UnityEngine.Mathf.Abs(x - y) > 0.0001f) { diff++; s.Append(" " + f + " " + x + "→" + y); } }
foreach (var c in cs) { var x = a.GetColor(c); var y = b.GetColor(c); if (x != y) { diff++; s.Append(" " + c + " " + x + "→" + y); } }
var ka = string.Join(",", a.shaderKeywords); var kb = string.Join(",", b.shaderKeywords);
if (ka != kb) { diff++; s.Append(" kw [" + ka + "]→[" + kb + "]"); }
// 텍스처 임포트 성질
var ta = a.GetTexture("_BaseMap") as UnityEngine.Texture2D;
var tb = b.GetTexture("_BaseMap") as UnityEngine.Texture2D;
if (ta != null && tb != null)
s.Append(" | tex A " + ta.width + "x" + ta.height + "/" + ta.format + "/" + ta.filterMode + "/mip" + ta.mipmapCount
+ " B " + tb.width + "x" + tb.height + "/" + tb.format + "/" + tb.filterMode + "/mip" + tb.mipmapCount);
return (diff == 0 ? "값 차이 0" : "차이 " + diff + "건:") + s;
}
static void SwapMat(System.Collections.Generic.List<UnityEngine.Renderer> rs, UnityEngine.Material from, UnityEngine.Material to)
{
foreach (var r in rs)
{
var ms = r.sharedMaterials; bool hit = false;
for (int i = 0; i < ms.Length; i++) if (ms[i] == from) { ms[i] = to; hit = true; }
if (hit) r.sharedMaterials = ms;
}
}
static UnityEngine.Camera MakePd()
{
UnityEngine.Vector3 tgt = UnityEngine.Vector3.zero;
var pc = UnityEngine.GameObject.FindGameObjectWithTag("Player"); if (pc != null) tgt = pc.transform.position;
var go = UnityEngine.GameObject.Find("~816rAbPd"); if (go == null) go = new UnityEngine.GameObject("~816rAbPd");
var c = go.GetComponent<UnityEngine.Camera>(); if (c == null) c = go.AddComponent<UnityEngine.Camera>();
c.orthographic = false; c.fieldOfView = 60f; c.nearClipPlane = 0.1f; c.farClipPlane = 300f;
c.transform.rotation = UnityEngine.Quaternion.Euler(45f, 45f, 0f);
c.transform.position = tgt - c.transform.forward * 12f;
c.enabled = false; return c;
}
static UnityEngine.Texture2D Grab(UnityEngine.Camera cam, int w, int h)
{
var rt = new UnityEngine.RenderTexture(w, h, 24, UnityEngine.RenderTextureFormat.ARGB32, UnityEngine.RenderTextureReadWrite.sRGB);
rt.Create(); cam.targetTexture = rt; cam.Render();
var prev = 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 = prev; cam.targetTexture = null;
rt.Release(); UnityEngine.Object.DestroyImmediate(rt);
return tex;
}
static void L(string s) { sb.AppendLine(s); Flush(); }
static void Flush()
{
System.IO.File.WriteAllText("AgentScripts/WL816r_AB.txt", sb.ToString());
UnityEngine.Debug.Log("[816r ab]\n" + sb.ToString());
}
}