Project_WL/AgentScripts/WL816k_AltB.cs

232 lines
12 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-816k — ⑤ 대안 ⓑ: 지금 물(ToonWaterU · 814t 톤 유지)에 **얕은 물 그라데이션**을 되살린다.
// 816j2 는 깊이 거품을 껐다(FoamColor=WaterColor) → 섬과 만나는 선에 아무 반응이 없어 「통과하는 느낌」.
// 흰 거품(=PD 가 「안개 같다」) 대신 **물색을 밝힌 색**으로 되살려 얕은 물처럼 보이게 한다. 둘레 띠는 off.
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using WL.Look.Farm;
public static class WL816k_AltB
{
public const string D = "Screenshots_WL/WL816k/";
public const int PW = 1280, PH = 720;
public const string MatDir = "Assets/WL/Look/Farm/Materials/";
public const string C_Foam = "Color_e1f155248d144786a62fc1585ca21e9a";
public const string R_FoamDistance = "Vector1_101dc4546b684d40bc2ff2fc59ab43d5";
public const string R_FoamEdge = "Vector1_34f757bec6b8422b9aef3b9d97117a6e";
public static void Open()
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
"Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
}
public static void Start()
{
var go = GameObject.Find("~WL816kB");
if (go != null) Object.DestroyImmediate(go);
go = new GameObject("~WL816kB");
go.AddComponent<WL816k_AltBRunner>();
}
public static Texture2D Grab(Camera cam, int w, int h)
{
var rt = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
rt.antiAliasing = 1; rt.Create();
var pT = cam.targetTexture; var pA = RenderTexture.active;
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
var t = new Texture2D(w, h, TextureFormat.RGB24, false);
t.ReadPixels(new Rect(0, 0, w, h), 0, 0); t.Apply();
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
return t;
}
static float Lum(Color32 c) { return (0.299f * c.r + 0.587f * c.g + 0.114f * c.b) / 255f; }
public static string Shot(Camera cam, string path, int w, int h, bool shoreMetric, out float shore, out int rmb)
{
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
var t = Grab(cam, w, h);
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
var px = t.GetPixels32();
long r = 0, g = 0, b = 0; int n = 0; double sum = 0, sum2 = 0;
int y0 = 20, y1s = shoreMetric ? 200 : Mathf.Min(320, h);
int x0 = shoreMetric ? 100 : 20, x1s = shoreMetric ? w - 100 : Mathf.Min(340, w);
for (int y = y0; y < y1s; y += 2)
for (int x = x0; x < x1s; x += 2)
{ var c = px[y * w + x]; r += c.r; g += c.g; b += c.b; n++; float l = Lum(c); sum += l; sum2 += l * l; }
double mean = n > 0 ? sum / n : 0;
double sd = n > 0 ? System.Math.Sqrt(System.Math.Max(0, sum2 / n - mean * mean)) : 0;
shore = 0f;
string extra = "";
if (shoreMetric)
{
double a = 0, b2 = 0; int an = 0, bn = 0;
for (int y = 300; y < 350; y++) for (int x = 100; x < w - 100; x += 2) { a += Lum(px[y * w + x]); an++; }
for (int y = 20; y < 70; y++) for (int x = 100; x < w - 100; x += 2) { b2 += Lum(px[y * w + x]); bn++; }
shore = (float)((an > 0 ? a / an : 0) - (bn > 0 ? b2 / bn : 0));
extra = " · 물가Δ " + shore.ToString("F4");
}
// 밝은 픽셀 RB (분홍 방지 · 816j2 ②)
long fr = 0, fb = 0; int fn = 0, tot = 0;
int yh = (int)(h * 0.55f);
for (int y = 0; y < yh; y++) for (int x = 0; x < w; x += 2)
{ var c = px[y * w + x]; tot++; if (c.r > 200 && c.g > 195 && c.b > 195) { fr += c.r; fb += c.b; fn++; } }
rmb = fn == 0 ? 0 : (int)(fr / fn) - (int)(fb / fn);
Object.DestroyImmediate(t);
return "바다 #" + ((int)(r / n)).ToString("X2") + ((int)(g / n)).ToString("X2") + ((int)(b / n)).ToString("X2")
+ " σ=" + sd.ToString("F4") + " · 밝음 " + (100f * fn / tot).ToString("F2") + "%(RB " + rmb + ")" + extra;
}
public static void Strip(string[] paths, string outPath, int div)
{
var ts = new Texture2D[paths.Length]; int w = 0, h = 0;
for (int i = 0; i < paths.Length; i++)
{
if (!System.IO.File.Exists(paths[i])) return;
ts[i] = new Texture2D(2, 2, TextureFormat.RGB24, false);
ts[i].LoadImage(System.IO.File.ReadAllBytes(paths[i]));
w = Mathf.Max(w, ts[i].width / div); h += ts[i].height / div;
}
var o = new Texture2D(w, h, TextureFormat.RGB24, false);
var f = new Color32[w * h];
for (int i = 0; i < f.Length; i++) f[i] = new Color32(24, 24, 28, 255);
o.SetPixels32(f);
int yo = h;
for (int i = 0; i < ts.Length; i++)
{
int sw = ts[i].width / div, sh2 = ts[i].height / div;
var src = ts[i].GetPixels32(); int fw = ts[i].width;
var dst = new Color32[sw * sh2];
for (int y = 0; y < sh2; y++) for (int x = 0; x < sw; x++)
{
int rr = 0, gg = 0, bb = 0;
for (int dy = 0; dy < div; dy++) for (int dx = 0; dx < div; dx++)
{ var c = src[(y * div + dy) * fw + (x * div + dx)]; rr += c.r; gg += c.g; bb += c.b; }
int q = div * div;
dst[y * sw + x] = new Color32((byte)(rr / q), (byte)(gg / q), (byte)(bb / q), 255);
}
yo -= sh2; o.SetPixels32(0, yo, sw, sh2, dst);
}
o.Apply();
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outPath));
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
Object.DestroyImmediate(o);
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
}
}
public class WL816k_AltBRunner : MonoBehaviour
{
static StringBuilder sb;
static void L(string s) { sb.AppendLine(s); }
const string D = WL816k_AltB.D;
const int PW = WL816k_AltB.PW, PH = WL816k_AltB.PH;
Camera live, zoom; Renderer water; MeshRenderer band;
void Start() { StartCoroutine(Co()); }
IEnumerator Co()
{
sb = new StringBuilder();
L("=== WL-816k ⑤ 대안 ⓑ — 지금 물 + 얕은 물 그라데이션 (PD 구도 15 m · 띠 off) ===");
var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive);
while (op != null && !op.isDone) yield return null;
for (int i = 0; i < 8; i++) yield return new WaitForSeconds(1f);
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
if (c.name.StartsWith("~WL816")) continue;
if (live == null || c.depth > live.depth) live = c;
}
var foam = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
band = foam != null ? foam.GetComponent<MeshRenderer>() : null;
if (water == null || live == null) { L("🔴 물/카메라 없음"); Done(); yield break; }
foreach (var mb in live.GetComponents<MonoBehaviour>())
if (mb != null && mb.GetType().Name.Contains("Cinemachine")) mb.enabled = false;
float d = 15f, k = d * 0.70710678f;
live.transform.position = new Vector3(0f, k, -k);
live.transform.rotation = Quaternion.Euler(45f, 0f, 0f);
live.fieldOfView = 60f;
yield return null; yield return new WaitForSeconds(0.3f);
L("카메라 거리 " + live.transform.position.magnitude.ToString("F1") + " m · 각 " + live.transform.eulerAngles.ToString("F0"));
var E = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(WL816k_AltB.MatDir + "Farm_Water_WL_E.mat");
if (E == null) { L("🔴 E 없음"); Done(); yield break; }
var zgo = new GameObject("~WL816kBZ"); zgo.hideFlags = HideFlags.DontSave;
zoom = zgo.AddComponent<Camera>();
zoom.fieldOfView = 34f; zoom.nearClipPlane = 0.1f; zoom.farClipPlane = 2000f;
zoom.clearFlags = CameraClearFlags.Skybox; zoom.cullingMask = ~0; zoom.depth = -100f;
zgo.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
Bounds bb = band != null ? band.bounds : new Bounds(Vector3.zero, new Vector3(16, 1, 16));
zgo.transform.position = new Vector3(bb.center.x, 3.2f, bb.min.z - 9f);
zgo.transform.LookAt(new Vector3(bb.center.x, -1f, bb.min.z + 2f));
float sh; int rmb;
L("");
water.sharedMaterial = E; if (band != null) band.enabled = true;
yield return null; yield return new WaitForSeconds(0.35f);
L("[전] 지금(물 E · 띠 on) 물가 " + WL816k_AltB.Shot(zoom, D + "b_before_zoom.png", PW, PH, true, out sh, out rmb));
if (band != null) band.enabled = false;
yield return null; yield return new WaitForSeconds(0.3f);
L("[전] 띠만 off 물가 " + WL816k_AltB.Shot(zoom, D + "b_bandoff_zoom.png", PW, PH, true, out sh, out rmb));
// 얕은 물 그라데이션 3안 (흰 거품 아님 — 물색을 밝힌 색)
var fc = new[] { new Color(0.62f, 0.82f, 0.90f, 1f), new Color(0.62f, 0.82f, 0.90f, 1f), new Color(0.78f, 0.90f, 0.95f, 1f) };
var fd = new[] { 1.2f, 2.2f, 1.6f };
var fe = new[] { 6f, 3f, 4f };
var zp = new string[3]; var shores = new float[3];
L("");
L("[얕은 물 그라데이션 3안] FoamColor = 물색을 밝힌 색 · 띠 off");
for (int i = 0; i < 3; i++)
{
var m = new Material(E);
m.SetColor(WL816k_AltB.C_Foam, fc[i]);
m.SetFloat(WL816k_AltB.R_FoamDistance, fd[i]);
m.SetFloat(WL816k_AltB.R_FoamEdge, fe[i]);
water.sharedMaterial = m;
yield return null; yield return new WaitForSeconds(0.3f);
zp[i] = D + "b_w" + (i + 1) + "_zoom.png";
L(" w" + (i + 1) + " FoamColor" + fc[i].ToString("F2") + " Dist " + fd[i] + " Edge " + fe[i]);
L(" " + WL816k_AltB.Shot(zoom, zp[i], PW, PH, true, out sh, out rmb));
shores[i] = sh;
L(" PD " + WL816k_AltB.Shot(live, D + "b_w" + (i + 1) + ".png", PW, PH, false, out _, out _));
}
WL816k_AltB.Strip(zp, D + "b_w3_zoom.png", 3);
int best = 0; float bd = -9f;
for (int i = 0; i < 3; i++) if (shores[i] > bd && shores[i] <= 0.09f) { bd = shores[i]; best = i; }
L("");
L("🔴 ⓑ 채택 = w" + (best + 1) + " · FoamColor " + fc[best].ToString("F3") + " · FoamDistance " + fd[best] + " · FoamEdge " + fe[best]
+ " · 물가Δ " + shores[best].ToString("F4"));
System.IO.File.WriteAllText("AgentScripts/WL816k_PICKB.txt",
fc[best].r + "," + fc[best].g + "," + fc[best].b + "|" + fd[best] + "|" + fe[best]);
// 후 = 채택안 PD 구도
var win = new Material(E);
win.SetColor(WL816k_AltB.C_Foam, fc[best]);
win.SetFloat(WL816k_AltB.R_FoamDistance, fd[best]);
win.SetFloat(WL816k_AltB.R_FoamEdge, fe[best]);
water.sharedMaterial = win;
yield return null; yield return new WaitForSeconds(0.35f);
L("[후] PD " + WL816k_AltB.Shot(live, D + "zb_after_pd.png", PW, PH, false, out _, out _));
L("[후] 물가 " + WL816k_AltB.Shot(zoom, D + "zb_after_zoom.png", PW, PH, true, out sh, out rmb));
// 전 PD (띠 on) 도 같은 자리에서
water.sharedMaterial = E; if (band != null) band.enabled = true;
yield return null; yield return new WaitForSeconds(0.35f);
L("[전] PD " + WL816k_AltB.Shot(live, D + "zb_before_pd.png", PW, PH, false, out _, out _));
WL816k_AltB.Strip(new[] { D + "zb_before_pd.png", D + "zb_after_pd.png" }, D + "z_pd_before_after.png", 1);
WL816k_AltB.Strip(new[] { D + "b_before_zoom.png", D + "zb_after_zoom.png" }, D + "z_zoom_shore.png", 1);
Object.DestroyImmediate(zgo);
Done();
}
void Done()
{
System.IO.File.WriteAllText("AgentScripts/WL816k_ALTB.txt", sb.ToString());
Debug.Log("[816k altB]\n" + sb);
}
}