Project_WL/AgentScripts/WL816q_Scan2.cs

139 lines
7.0 KiB
C#
Raw Permalink 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-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<WL816q_Scan2Runner>();
}
}
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<WL.Look.Farm.WLIslandGrass>(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.Renderer>(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<UnityEngine.Camera>();
if (c == null) c = go.AddComponent<UnityEngine.Camera>();
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());
}
}