From c1eb8742d13db4b8b2a7abb39630f4f6db34fe23 Mon Sep 17 00:00:00 2001 From: swrring Date: Tue, 15 Sep 2026 08:36:54 +0900 Subject: [PATCH] =?UTF-8?q?[WL-816q]=204=C2=B75=ED=9A=8C=EC=B0=A8=20?= =?UTF-8?q?=EC=8B=A4=EC=B8=A1=20=E2=80=94=20=EA=B5=AC=EB=A6=84=20=EC=84=B8?= =?UTF-8?q?=EA=B8=B0=C2=B7=EB=B0=9D=EA=B8=B0=C2=B7=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EC=A0=81=20=EC=83=89=EB=B9=84=20=EC=A0=84=EB=B6=80=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=81,=20=EB=8D=B0=EB=AA=A8=20=EC=9B=90=EA=B0=92=20?= =?UTF-8?q?=EC=9C=A0=EC=A7=80=20=ED=99=95=EC=A0=95=20(#816)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 4회차(구조적 색비): 풀 그림자비를 바닥과 같은 0.3248/0.3416/0.3936 으로 맞추고 알베도만 찾으면 구름 세기가 바뀌어도 안 깨질 것으로 봤으나 실측 최저가 k=1.15 에서 2.3%(S1.0)·4.3%(S1.8) 로 현행 2점 일치(0.43%)보다 나빴다 → 기각. 풀(빌보드)의 램프 입력이 바닥과 상수만큼 다르다는 뜻. - 5회차(세기 재수렴): 세기마다 k 를 0.90~1.30 에서 0.01 씩 다시 찾아 비교. S1.0 단계4 밝기180.2 보이는 풀 1.94% / S1.2 단계5 밝기172.6 3.52% / S1.4 단계5 4.89% / S1.6 단계6 3.94%. 띠를 한 단 얻으면 풀이 1.8~2.5 배 더 드러난다 → **데모 원값 S1.0 유지**. - 3회차(세기×밝기 16점): 어느 조합도 보이는 풀을 1.4% 아래로 못 내렸다(최악 73.8%). 기록만 남긴다. - 스윕 스크립트는 끝에 원값 복구를 넣었다(2회차에 복제본이 씬에 남아 측정이 통째로 오염된 사고). Co-Authored-By: Claude Opus 5 (1M context) --- AgentScripts/WL816q_Scan2.cs | 138 +++++++++++++++++++++++++++ AgentScripts/WL816q_Sweep.cs | 20 ++-- AgentScripts/WL816q_Tune.cs | 175 +++++++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+), 8 deletions(-) create mode 100644 AgentScripts/WL816q_Scan2.cs create mode 100644 AgentScripts/WL816q_Tune.cs diff --git a/AgentScripts/WL816q_Scan2.cs b/AgentScripts/WL816q_Scan2.cs new file mode 100644 index 000000000..ab310160e --- /dev/null +++ b/AgentScripts/WL816q_Scan2.cs @@ -0,0 +1,138 @@ +// WL-816q 4회차 — 「구조적으로」 같은 색 만들기. +// 바닥은 lerp(알베도×0.3248/0.3416/0.3936, 알베도, t). 풀도 **같은 비**를 주고 알베도만 맞추면 +// 모든 램프 단계 t 에서 같은 색이 된다(= 조명·구름 값이 바뀌어도 안 깨진다). +// 지금 채택값은 두 단계에서만 우연히 맞은 것이라 구름 세기를 바꾸면 깨진다(3회차 실측). +public static class WL816q_Scan2 +{ + public static void Start() + { + var go = UnityEngine.GameObject.Find("~WL816qScan2"); + if (go != null) UnityEngine.Object.DestroyImmediate(go); + go = new UnityEngine.GameObject("~WL816qScan2"); + go.AddComponent(); + } +} + +public class WL816q_Scan2Runner : UnityEngine.MonoBehaviour +{ + static System.Text.StringBuilder sb; + const int TS = 512; + static string Dir = "Screenshots_WL/WL816q"; + + 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 < 5; i++) yield return new UnityEngine.WaitForSeconds(1f); + + var g = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); + if (g == null) { L("grass 없음"); Flush(); yield break; } + var rt = UnityEngine.Object.Instantiate(WL.Look.Farm.WLIslandLookSettings.Instance); + 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; rt.viewCullEnabled = 0; + + var topAsset = rt.islandTopMaterial; + var topClone = new UnityEngine.Material(topAsset); topClone.name = topAsset.name + "_s2"; + var rends = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsSortMode.None); + for (int i = 0; i < rends.Length; i++) + { + var ms = rends[i].sharedMaterials; bool hit = false; + for (int m = 0; m < ms.Length; m++) if (ms[m] == topAsset) { ms[m] = topClone; hit = true; } + if (hit) rends[i].sharedMaterials = ms; + } + var grassAsset = arr[0].material; + var gc = new UnityEngine.Material(grassAsset); gc.name = grassAsset.name + "_s2"; + for (int i = 0; i < arr.Length; i++) if (arr[i].material == grassAsset) arr[i].material = gc; + + var gndShd = topAsset.GetColor("_ShadowDiffuseColor"); // 바닥의 그림자/확산 비 + var cur = grassAsset.GetColor("_DiffuseColor"); + L("바닥 비 = (" + gndShd.r.ToString("F4") + "," + gndShd.g.ToString("F4") + "," + gndShd.b.ToString("F4") + ") · 현재 풀 Dif = " + cur); + + var b = g.CalculateInstancesBounds(); + var cam = MakeTop(b.center.x, b.center.z, 6f); + UnityEngine.Time.timeScale = 0f; yield return null; + + float[] strs = { 1.0f, 1.8f }; + float[] ks = { 0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f, 1.40f, 1.50f }; + for (int s = 0; s < strs.Length; s++) + { + topClone.SetFloat("_Cloud_Strength", strs[s]); gc.SetFloat("_Cloud_Strength", strs[s]); + rt.grassEnabled = 0; g.Rebuild(); yield return null; yield return null; + var A = Grab(cam, TS, TS); var apx = A.GetPixels32(); + rt.grassEnabled = 1; + string line = "Strength=" + strs[s].ToString("F1") + " 보이는 풀 % : "; + for (int i = 0; i < ks.Length; i++) + { + var dif = new UnityEngine.Color(cur.r * ks[i], cur.g * ks[i], cur.b * ks[i], cur.a); + gc.SetColor("_DiffuseColor", dif); + gc.SetColor("_ShadowDiffuseColor", new UnityEngine.Color(dif.r * gndShd.r, dif.g * gndShd.g, dif.b * gndShd.b, dif.a)); + g.Rebuild(); yield return null; yield return null; + var B = Grab(cam, TS, TS); + line += ks[i].ToString("F2") + "=" + Cover(apx, B.GetPixels32()).ToString("F1") + " "; + UnityEngine.Object.DestroyImmediate(B); + } + L(line); + UnityEngine.Object.DestroyImmediate(A); + } + // 되돌린다 + topClone.SetFloat("_Cloud_Strength", topAsset.GetFloat("_Cloud_Strength")); + gc.SetFloat("_Cloud_Strength", grassAsset.GetFloat("_Cloud_Strength")); + gc.SetColor("_DiffuseColor", cur); gc.SetColor("_ShadowDiffuseColor", grassAsset.GetColor("_ShadowDiffuseColor")); + g.Rebuild(); + UnityEngine.Time.timeScale = 1f; + Flush(); + } + + static float Cover(UnityEngine.Color32[] a, UnityEngine.Color32[] b) + { + int n = 0, tot = 0; + for (int i = 0; i < a.Length; i++) + { + var p = a[i]; if (!(p.g > p.b + 8 && p.g > 45)) continue; tot++; + var q = b[i]; if (q.g <= q.b + 4) continue; + if (System.Math.Abs(p.r - q.r) + System.Math.Abs(p.g - q.g) + System.Math.Abs(p.b - q.b) > 6) n++; + } + return tot == 0 ? 0f : 100f * n / tot; + } + static UnityEngine.Camera MakeTop(float cx, float cz, float size) + { + var go = UnityEngine.GameObject.Find("~816qTop"); + if (go == null) go = new UnityEngine.GameObject("~816qTop"); + var c = go.GetComponent(); + if (c == null) c = go.AddComponent(); + c.orthographic = true; c.orthographicSize = size; c.nearClipPlane = 0.1f; c.farClipPlane = 200f; + c.transform.rotation = UnityEngine.Quaternion.Euler(90f, 0f, 0f); + c.transform.position = new UnityEngine.Vector3(cx, 60f, cz); + 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/WL816q_SCAN2.txt", sb.ToString()); + UnityEngine.Debug.Log("[816q scan2]\n" + sb.ToString()); + } +} diff --git a/AgentScripts/WL816q_Sweep.cs b/AgentScripts/WL816q_Sweep.cs index 89aab8244..0c85754ab 100644 --- a/AgentScripts/WL816q_Sweep.cs +++ b/AgentScripts/WL816q_Sweep.cs @@ -62,9 +62,9 @@ public class WL816q_SweepRunner : UnityEngine.MonoBehaviour var cam = MakeTop(b.center.x, b.center.z, 6f); UnityEngine.Time.timeScale = 0f; yield return null; - L("목표(데모 참고 x_demo_ground) : 띠단계 8 · LF 16.27 · HF 0.33 · 에지% 1.22"); - float[] strs = { 1f, 1.5f, 2f, 2.5f, 3f, 4f }; - float[] covs = { 0.35f, 0.5f, 0.65f }; + L("목표(데모 참고 x_demo_ground) : 띠단계 8 · LF 16.27 · HF 0.33 · 에지% 1.22 · 밝기 174.2"); + float[] strs = { 1f, 1.4f, 1.8f, 2.2f }; + float[] covs = { 0.25f, 0.9f, 1.6f, 2.4f }; // = _Brightness (밝기 보정) for (int ci = 0; ci < covs.Length; ci++) { for (int si = 0; si < strs.Length; si++) @@ -77,20 +77,24 @@ public class WL816q_SweepRunner : UnityEngine.MonoBehaviour // 풀까지 rt.grassEnabled = 1; g.Rebuild(); yield return null; yield return null; var B = Grab(cam, TS, TS); var bpx = B.GetPixels32(); - L(string.Format("Strength={0:F1} Cover={1:F2} | 바닥만 {2} | 풀포함 {3} | 보이는 풀 {4:F2}%", + L(string.Format("Strength={0:F1} Brightness={1:F2} | 바닥만 {2} | 풀포함 {3} | 보이는 풀 {4:F2}%", strs[si], covs[ci], mg, Metric(bpx, TS, TS), Cover(apx, bpx))); - if (System.Math.Abs(strs[si] - 2f) < 0.01f) - System.IO.File.WriteAllBytes(Dir + "/sweep_s2_c" + covs[ci].ToString("F2") + ".png", UnityEngine.ImageConversion.EncodeToPNG(B)); + System.IO.File.WriteAllBytes(Dir + "/sweep_s" + strs[si].ToString("F1") + "_b" + covs[ci].ToString("F2") + ".png", + UnityEngine.ImageConversion.EncodeToPNG(B)); UnityEngine.Object.DestroyImmediate(A); UnityEngine.Object.DestroyImmediate(B); } } + // 🔴 원래 값으로 되돌린다 — 안 하면 다음 실행이 오염된 씬에서 재기 시작한다(2회차 사고) + Set(topClone, topAsset.GetFloat("_Cloud_Strength"), topAsset.GetFloat("_Brightness")); + Set(grassClone, grassAsset.GetFloat("_Cloud_Strength"), grassAsset.GetFloat("_Brightness")); + g.Rebuild(); UnityEngine.Time.timeScale = 1f; Flush(); } - static void Set(UnityEngine.Material m, float str, float cov) + static void Set(UnityEngine.Material m, float str, float bright) { - m.SetFloat("_Cloud_Strength", str); m.SetFloat("_Cloud_Cover", cov); + m.SetFloat("_Cloud_Strength", str); m.SetFloat("_Brightness", bright); } static float Cover(UnityEngine.Color32[] a, UnityEngine.Color32[] b) diff --git a/AgentScripts/WL816q_Tune.cs b/AgentScripts/WL816q_Tune.cs new file mode 100644 index 000000000..4c66112f2 --- /dev/null +++ b/AgentScripts/WL816q_Tune.cs @@ -0,0 +1,175 @@ +// WL-816q 5회차 — 구름 세기를 올려 띠를 한 단 더 얻을 수 있는가. +// 세기를 바꾸면 풀 색 일치가 깨지므로(3회차 실측) **세기마다 풀 색을 다시 수렴**시켜 비교한다. +// 에셋 무변경(복제본) · 끝나면 원래 값으로 되돌린다. +public static class WL816q_Tune +{ + public static void Start() + { + var go = UnityEngine.GameObject.Find("~WL816qTune"); + if (go != null) UnityEngine.Object.DestroyImmediate(go); + go = new UnityEngine.GameObject("~WL816qTune"); + go.AddComponent(); + } +} + +public class WL816q_TuneRunner : UnityEngine.MonoBehaviour +{ + static System.Text.StringBuilder sb; + const int TS = 512; + static string Dir = "Screenshots_WL/WL816q"; + + 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 < 5; i++) yield return new UnityEngine.WaitForSeconds(1f); + + var g = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); + if (g == null) { L("grass 없음"); Flush(); yield break; } + var rt = UnityEngine.Object.Instantiate(WL.Look.Farm.WLIslandLookSettings.Instance); + 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; rt.viewCullEnabled = 0; + + var topAsset = rt.islandTopMaterial; + var topClone = new UnityEngine.Material(topAsset); topClone.name = topAsset.name + "_tune"; + var rends = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsSortMode.None); + for (int i = 0; i < rends.Length; i++) + { + var ms = rends[i].sharedMaterials; bool hit = false; + for (int m = 0; m < ms.Length; m++) if (ms[m] == topAsset) { ms[m] = topClone; hit = true; } + if (hit) rends[i].sharedMaterials = ms; + } + var grassAsset = arr[0].material; + var gc = new UnityEngine.Material(grassAsset); gc.name = grassAsset.name + "_tune"; + for (int i = 0; i < arr.Length; i++) if (arr[i].material == grassAsset) arr[i].material = gc; + var dif0 = grassAsset.GetColor("_DiffuseColor"); + var shd0 = grassAsset.GetColor("_ShadowDiffuseColor"); + + var b = g.CalculateInstancesBounds(); + var cam = MakeTop(b.center.x, b.center.z, 6f); + UnityEngine.Time.timeScale = 0f; yield return null; + + L("데모 참고 : 띠단계 8 · LF 16.27 · HF 0.33 · 에지% 1.22 · 밝기 174.2"); + float[] strs = { 1.0f, 1.2f, 1.4f, 1.6f }; + for (int s = 0; s < strs.Length; s++) + { + topClone.SetFloat("_Cloud_Strength", strs[s]); gc.SetFloat("_Cloud_Strength", strs[s]); + rt.grassEnabled = 0; g.Rebuild(); yield return null; yield return null; + var A = Grab(cam, TS, TS); var apx = A.GetPixels32(); + string gm = Metric(apx, TS, TS); + rt.grassEnabled = 1; + + // 이 세기에서 풀이 바닥에 녹아드는 배율 k 를 0.90~1.30 에서 0.01 씩 찾는다 + float bestK = 1f, bestC = 999f; string prof = ""; + for (int i = 0; i <= 40; i++) + { + float k = 0.90f + i * 0.01f; + gc.SetColor("_DiffuseColor", new UnityEngine.Color(dif0.r * k, dif0.g * k, dif0.b * k, dif0.a)); + gc.SetColor("_ShadowDiffuseColor", new UnityEngine.Color(shd0.r * k, shd0.g * k, shd0.b * k, shd0.a)); + g.Rebuild(); yield return null; + var B = Grab(cam, TS, TS); + float c = Cover(apx, B.GetPixels32()); + UnityEngine.Object.DestroyImmediate(B); + if (c < bestC) { bestC = c; bestK = k; } + if (c < 5f) prof += k.ToString("F2") + "=" + c.ToString("F1") + " "; + } + gc.SetColor("_DiffuseColor", new UnityEngine.Color(dif0.r * bestK, dif0.g * bestK, dif0.b * bestK, dif0.a)); + gc.SetColor("_ShadowDiffuseColor", new UnityEngine.Color(shd0.r * bestK, shd0.g * bestK, shd0.b * bestK, shd0.a)); + g.Rebuild(); yield return null; yield return null; + var F = Grab(cam, TS, TS); + L(string.Format("Strength={0:F1} | 바닥만 {1} | 최적 k={2:F2} 보이는 풀 {3:F2}% | 풀포함 {4}\n 낮은 구간: {5}", + strs[s], gm, bestK, bestC, Metric(F.GetPixels32(), TS, TS), prof.Length > 0 ? prof : "없음")); + System.IO.File.WriteAllBytes(Dir + "/tune_s" + strs[s].ToString("F1") + ".png", UnityEngine.ImageConversion.EncodeToPNG(F)); + UnityEngine.Object.DestroyImmediate(F); UnityEngine.Object.DestroyImmediate(A); + } + topClone.SetFloat("_Cloud_Strength", topAsset.GetFloat("_Cloud_Strength")); + gc.SetFloat("_Cloud_Strength", grassAsset.GetFloat("_Cloud_Strength")); + gc.SetColor("_DiffuseColor", dif0); gc.SetColor("_ShadowDiffuseColor", shd0); + g.Rebuild(); + UnityEngine.Time.timeScale = 1f; + Flush(); + } + + static float Cover(UnityEngine.Color32[] a, UnityEngine.Color32[] b) + { + int n = 0, tot = 0; + for (int i = 0; i < a.Length; i++) + { + var p = a[i]; if (!Gr(p)) continue; tot++; + var q = b[i]; if (q.g <= q.b + 4) continue; + if (System.Math.Abs(p.r - q.r) + System.Math.Abs(p.g - q.g) + System.Math.Abs(p.b - q.b) > 6) n++; + } + return tot == 0 ? 0f : 100f * n / tot; + } + static string Metric(UnityEngine.Color32[] px, int w, int h) + { + int bs = 8, bw = w / bs, bh = h / bs; + var bm = new float[bw * bh]; var bok = new bool[bw * bh]; + double hf = 0; int hfn = 0; + for (int by = 0; by < bh; by++) for (int bx = 0; bx < bw; bx++) + { + double s = 0; int n = 0; + for (int y = 0; y < bs; y++) for (int x = 0; x < bs; x++) + { var p = px[(by * bs + y) * w + (bx * bs + x)]; if (!Gr(p)) continue; s += Lum(p); n++; } + if (n < bs * bs / 2) continue; + float mean = (float)(s / n); bm[by * bw + bx] = mean; bok[by * bw + bx] = true; + for (int y = 0; y < bs; y++) for (int x = 0; x < bs; x++) + { var p = px[(by * bs + y) * w + (bx * bs + x)]; if (!Gr(p)) continue; hf += System.Math.Abs(Lum(p) - mean); hfn++; } + } + double s1 = 0, s2 = 0; int bn = 0; var lv = new int[40]; + for (int i = 0; i < bm.Length; i++) { if (!bok[i]) continue; s1 += bm[i]; s2 += (double)bm[i] * bm[i]; bn++; int q = (int)(bm[i] / 8f); if (q >= 0 && q < 40) lv[q]++; } + if (bn == 0 || hfn == 0) return "지면 0"; + double mu = s1 / bn, lf = System.Math.Sqrt(System.Math.Max(0, s2 / bn - mu * mu)); + int levels = 0; for (int i = 0; i < 40; i++) if (lv[i] >= bn * 0.005) levels++; + int ed = 0, edn = 0; + for (int y = 0; y < h - 1; y++) for (int x = 0; x < w - 1; x++) + { + var p = px[y * w + x]; if (!Gr(p)) continue; var r = px[y * w + x + 1]; var d = px[(y + 1) * w + x]; edn++; + if ((Gr(r) && System.Math.Abs(Lum(p) - Lum(r)) > 8) || (Gr(d) && System.Math.Abs(Lum(p) - Lum(d)) > 8)) ed++; + } + return string.Format("단계={0} LF={1:F2} HF={2:F2} 에지%={3:F2} 밝기={4:F1}", levels, lf, hf / hfn, 100.0 * ed / System.Math.Max(1, edn), mu); + } + static bool Gr(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 UnityEngine.Camera MakeTop(float cx, float cz, float size) + { + var go = UnityEngine.GameObject.Find("~816qTop"); + if (go == null) go = new UnityEngine.GameObject("~816qTop"); + var c = go.GetComponent(); + if (c == null) c = go.AddComponent(); + c.orthographic = true; c.orthographicSize = size; c.nearClipPlane = 0.1f; c.farClipPlane = 200f; + c.transform.rotation = UnityEngine.Quaternion.Euler(90f, 0f, 0f); + c.transform.position = new UnityEngine.Vector3(cx, 60f, cz); + 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/WL816q_TUNE.txt", sb.ToString()); + UnityEngine.Debug.Log("[816q tune]\n" + sb.ToString()); + } +}