193 lines
10 KiB
C#
193 lines
10 KiB
C#
// WL-816j — ④ 채택값 고르기: 무늬 2.5 m · 흐름 0.8 · 대비 중간 고정 → 거품 띠 3단 · 거품알 3단 · 반대편 가장자리 확인
|
|
// 🔴 자기 완결 파일.
|
|
using System.Collections;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering.Universal;
|
|
|
|
public static class WL816j_Pick
|
|
{
|
|
public const string D = "Screenshots_WL/WL816j/";
|
|
public const float PlaneW = 1000f, Cells = 6f;
|
|
public const string R_Size = "Vector1_07238257334b4a149e675e2451801030";
|
|
public const string R_Speed = "Vector1_8e22a98f75c94b218c49e6c4805e799d";
|
|
public const string R_Strength = "Vector1_99cc56b5c6fd474082f07f00a6df94f9";
|
|
public const string R_NoiseSpeed = "Vector1_ad7e0fcd37f44d68b68de6f06bb43b96";
|
|
public const string R_FoamScale = "Vector1_11671d7a4cdb4d059a6c69e39f3f7b3f";
|
|
public const string R_FoamSpeed = "Vector1_3089b6a325a44c1686907af4ee3b0776";
|
|
public const string R_FoamDistance = "Vector1_101dc4546b684d40bc2ff2fc59ab43d5";
|
|
public const string R_FoamEdge = "Vector1_34f757bec6b8422b9aef3b9d97117a6e";
|
|
public const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
|
public static readonly Color Light2 = new Color(0.80f, 0.90f, 0.96f, 1f);
|
|
|
|
public static void Start()
|
|
{
|
|
var go = GameObject.Find("~WL816jPick");
|
|
if (go != null) Object.DestroyImmediate(go);
|
|
go = new GameObject("~WL816jPick");
|
|
go.AddComponent<WL816j_PickRunner>();
|
|
Debug.Log("[816j] pick 러너 시작");
|
|
}
|
|
|
|
/// <summary>채택 후보 = 무늬 2.5 m · 흐름 0.8 m/s · 대비 중간 · 거품알/띠는 인자로.</summary>
|
|
public static Material Cand(Material src, float foamM, float foamDist, float foamEdge, float churn)
|
|
{
|
|
var m = new Material(src);
|
|
float size = PlaneW / (2.5f * Cells);
|
|
m.SetFloat(R_Size, size);
|
|
m.SetFloat(R_Strength, 0.3085f / size);
|
|
m.SetFloat(R_Speed, 0.8f * size / PlaneW);
|
|
m.SetFloat(R_NoiseSpeed, 0.8f * size / PlaneW);
|
|
m.SetColor(C_Light, Light2);
|
|
float fs = PlaneW / foamM;
|
|
m.SetFloat(R_FoamScale, fs);
|
|
m.SetFloat(R_FoamSpeed, churn * fs / PlaneW);
|
|
m.SetFloat(R_FoamDistance, foamDist);
|
|
m.SetFloat(R_FoamEdge, foamEdge);
|
|
return m;
|
|
}
|
|
public static Camera Make(string n, Vector3 pos, Vector3 look, float fov)
|
|
{
|
|
var go = GameObject.Find(n);
|
|
if (go == null) { go = new GameObject(n); go.hideFlags = HideFlags.DontSave; }
|
|
var c = go.GetComponent<Camera>(); if (c == null) c = go.AddComponent<Camera>();
|
|
c.orthographic = false; c.fieldOfView = fov; c.nearClipPlane = 0.1f; c.farClipPlane = 2000f;
|
|
c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f;
|
|
go.transform.position = pos; go.transform.LookAt(look);
|
|
var a = go.GetComponent<UniversalAdditionalCameraData>();
|
|
if (a == null) a = go.AddComponent<UniversalAdditionalCameraData>();
|
|
a.renderPostProcessing = true;
|
|
return c;
|
|
}
|
|
public static string Shot(Camera cam, string path, int w, int h)
|
|
{
|
|
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
|
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);
|
|
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
|
var px = t.GetPixels32(); int white = 0, n = 0;
|
|
for (int i = 0; i < px.Length; i += 5) { n++; if (px[i].r > 225 && px[i].g > 218 && px[i].b > 218) white++; }
|
|
Object.DestroyImmediate(t);
|
|
return "흰 " + (100f * white / n).ToString("F2") + "% → " + path;
|
|
}
|
|
public static void Strip(string[] paths, string outPath)
|
|
{
|
|
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 += ts[i].width; h = Mathf.Max(h, ts[i].height);
|
|
}
|
|
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 x = 0;
|
|
for (int i = 0; i < ts.Length; i++) { o.SetPixels32(x, 0, ts[i].width, ts[i].height, ts[i].GetPixels32()); x += ts[i].width; }
|
|
o.Apply();
|
|
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
|
|
Object.DestroyImmediate(o);
|
|
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
|
|
}
|
|
}
|
|
|
|
public class WL816j_PickRunner : MonoBehaviour
|
|
{
|
|
static StringBuilder sb;
|
|
static void L(string s) { sb.AppendLine(s); }
|
|
const string D = WL816j_Pick.D;
|
|
|
|
void Start() { StartCoroutine(Co()); }
|
|
|
|
IEnumerator Co()
|
|
{
|
|
sb = new StringBuilder();
|
|
L("=== WL-816j ④ 채택값 고르기 (무늬 2.5 m · 흐름 0.8 · 대비 0.80/0.90/0.96 고정) ===");
|
|
|
|
Renderer water = null;
|
|
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
|
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
|
Camera live = null;
|
|
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("~WL816j")) continue;
|
|
if (live == null || c.depth > live.depth) live = c;
|
|
}
|
|
if (water == null || live == null) { L("🔴 물/카메라 없음"); Done(); yield break; }
|
|
var baseMat = water.sharedMaterial;
|
|
|
|
float zc = -3.78f, shoreX = 0f;
|
|
for (float x = 4f; x < 90f; x += 0.25f)
|
|
{
|
|
RaycastHit h;
|
|
if (Physics.Raycast(new Vector3(x, 60f, zc), Vector3.down, out h, 200f) && h.point.y > -0.9f) shoreX = x;
|
|
}
|
|
var shore = WL816j_Pick.Make("~WL816jS", new Vector3(shoreX + 5.5f, 2.2f, zc + 5.5f), new Vector3(shoreX - 0.5f, -1f, zc - 0.5f), 32f);
|
|
// 게임 카메라와 같은 각도로 섬 전체 — 앞쪽(카메라쪽)·뒤쪽 가장자리를 한 화면에
|
|
var isle = WL816j_Pick.Make("~WL816jI", new Vector3(0f, 14f, -20f), new Vector3(0f, 0f, 2f), 55f);
|
|
L("해안선 x=" + shoreX.ToString("F2") + " · 확대 카메라 " + shore.transform.position + " · 섬 전경 카메라 " + isle.transform.position);
|
|
|
|
// ── 1) 거품 띠 3단 (FoamEdge 1 고정) ────────────────────────
|
|
L("");
|
|
L("1) 거품 띠 3단 — FoamDistance 3 / 6 / 12 (FoamEdge 1 · 거품알 0.75 m · 흐름 0.5 m/s)");
|
|
float[] fd = { 3f, 6f, 12f };
|
|
var sS = new string[4]; var gS = new string[4];
|
|
sS[0] = D + "k_band0_now_shore.png"; gS[0] = D + "k_band0_now_game.png";
|
|
water.sharedMaterial = baseMat; yield return null; yield return null;
|
|
L(" [지금 816h C] 확대 " + WL816j_Pick.Shot(shore, sS[0], 720, 1280) + " · 섬전경 " + WL816j_Pick.Shot(isle, gS[0], 1080, 1920));
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
water.sharedMaterial = WL816j_Pick.Cand(baseMat, 0.75f, fd[i], 1f, 0.5f);
|
|
yield return null; yield return null; yield return new WaitForSeconds(0.2f);
|
|
sS[i + 1] = D + "k_band" + (i + 1) + "_shore.png"; gS[i + 1] = D + "k_band" + (i + 1) + "_game.png";
|
|
L(" [FoamDistance " + fd[i] + "] 확대 " + WL816j_Pick.Shot(shore, sS[i + 1], 720, 1280)
|
|
+ " · 섬전경 " + WL816j_Pick.Shot(isle, gS[i + 1], 1080, 1920));
|
|
}
|
|
WL816j_Pick.Strip(sS, D + "k_band_shore_steps.png");
|
|
WL816j_Pick.Strip(gS, D + "k_band_game_steps.png");
|
|
|
|
// ── 2) 거품알 3단 (FoamDistance 6 고정) ─────────────────────
|
|
L("");
|
|
L("2) 거품알 3단 — 1.5 / 0.75 / 0.35 m (FoamDistance 6 · FoamEdge 1)");
|
|
float[] fc = { 1.5f, 0.75f, 0.35f };
|
|
var cS = new string[3];
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
water.sharedMaterial = WL816j_Pick.Cand(baseMat, fc[i], 6f, 1f, 0.5f);
|
|
yield return null; yield return null; yield return new WaitForSeconds(0.2f);
|
|
cS[i] = D + "l_foamcell" + (i + 1) + ".png";
|
|
L(" [거품알 " + fc[i] + " m] " + WL816j_Pick.Shot(shore, cS[i], 720, 1280));
|
|
}
|
|
WL816j_Pick.Strip(cS, D + "l_foamcell_steps.png");
|
|
|
|
// ── 3) 반대편(카메라 반대쪽) 가장자리도 거품이 생기나 ────────
|
|
L("");
|
|
L("3) 🔴 카메라 반대쪽 가장자리 확인 — 깊이 기반 거품은 「시선이 물을 지나 벽에 닿는 쪽」에만 생긴다");
|
|
water.sharedMaterial = WL816j_Pick.Cand(baseMat, 0.75f, 6f, 1f, 0.5f);
|
|
yield return null; yield return null;
|
|
var back = WL816j_Pick.Make("~WL816jB", new Vector3(shoreX + 5.5f, 2.2f, zc + 5.5f), new Vector3(shoreX + 30f, -1f, zc + 30f), 32f);
|
|
L(" 앞쪽(섬을 보는 쪽) " + WL816j_Pick.Shot(shore, D + "m_edge_front.png", 720, 1280));
|
|
L(" 뒤쪽(바다만) " + WL816j_Pick.Shot(back, D + "m_edge_back.png", 720, 1280));
|
|
var top = WL816j_Pick.Make("~WL816jT", new Vector3(0f, 42f, -12f), new Vector3(0f, 0f, 0f), 55f);
|
|
L(" 섬 위에서(사방 가장자리) " + WL816j_Pick.Shot(top, D + "m_edge_top.png", 1080, 1920));
|
|
WL816j_Pick.Strip(new[] { D + "m_edge_front.png", D + "m_edge_back.png" }, D + "m_edge_pair.png");
|
|
|
|
water.sharedMaterial = baseMat; yield return null;
|
|
Done();
|
|
}
|
|
|
|
void Done()
|
|
{
|
|
System.IO.File.WriteAllText("AgentScripts/WL816j_PICK.txt", sb.ToString());
|
|
Debug.Log("[816j pick]\n" + sb);
|
|
}
|
|
}
|