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